diff -Nru seabios-1.16.2/.version seabios-1.16.3/.version --- seabios-1.16.2/.version 2023-03-16 09:56:04.000000000 +0000 +++ seabios-1.16.3/.version 2023-11-28 07:35:31.000000000 +0000 @@ -1 +1 @@ -1.16.2 +1.16.3 diff -Nru seabios-1.16.2/Makefile seabios-1.16.3/Makefile --- seabios-1.16.2/Makefile 2023-02-02 01:14:39.000000000 +0000 +++ seabios-1.16.3/Makefile 2023-11-13 12:49:59.000000000 +0000 @@ -71,6 +71,7 @@ COMMONCFLAGS += $(call cc-option,$(CC),-fno-stack-protector-all,) COMMONCFLAGS += $(call cc-option,$(CC),-fstack-check=no,) COMMONCFLAGS += $(call cc-option,$(CC),-Wno-address-of-packed-member,) +COMMONCFLAGS += $(call cc-option,$(CC),-Wno-array-bounds,) COMMONCFLAGS += $(call cc-option,$(CC),-fcf-protection=none,) COMMA := , diff -Nru seabios-1.16.2/debian/changelog seabios-1.16.3/debian/changelog --- seabios-1.16.2/debian/changelog 2023-04-11 13:08:25.000000000 +0000 +++ seabios-1.16.3/debian/changelog 2023-11-30 17:20:26.000000000 +0000 @@ -1,3 +1,23 @@ +seabios (1.16.3-2) unstable; urgency=medium + + * d/rules: turn off LSI_SCSI and DEBUG_IO for 128k bios variant. + these are probably the last bits which can be turned off before + we will start breaking old versions of qemu. upstream qemu + turned off all pci devices for 128k bios variant, leaving only + stuff needed for -M isapc, since it dropped <1.7 machines + compatibility + + -- Michael Tokarev Thu, 30 Nov 2023 20:20:26 +0300 + +seabios (1.16.3-1) unstable; urgency=medium + + * new upstream release (rel-1.16.3) + this brings up a few fixes, including `ahci: handle TFES irq correctly' + which is needed for qemu 8.2+ with `D2H FIS when processing NCQ command' + commit, esp-scsi fixes, and more. + + -- Michael Tokarev Tue, 28 Nov 2023 12:05:35 +0300 + seabios (1.16.2-1) unstable; urgency=medium * sync with upstream stable 1.16.2 release (rel-1.16.2 tag): diff -Nru seabios-1.16.2/debian/rules seabios-1.16.3/debian/rules --- seabios-1.16.2/debian/rules 2022-11-18 17:13:21.000000000 +0000 +++ seabios-1.16.3/debian/rules 2023-11-30 17:16:29.000000000 +0000 @@ -40,7 +40,8 @@ echo "EXTRAVERSION=-debian-$$(dpkg-parsechangelog -SVersion)" > $@ # A stripped-down version of bios, to fit in 128Kb, for qemu <= 1.7 -bios-config = QEMU=y ROM_SIZE=128 PVSCSI=n ATA_DMA=n BOOTSPLASH=n XEN=n USB_OHCI=n USB_XHCI=n USB_UAS=n SDCARD=n TCGBIOS=n MPT_SCSI=n ESP_SCSI=n MEGASAS=n NVME=n USE_SMM=n VGAHOOKS=n HOST_BIOS_GEOMETRY=n ACPI_PARSE=n +bios-config = QEMU=y ROM_SIZE=128 PVSCSI=n ATA_DMA=n BOOTSPLASH=n XEN=n USB_OHCI=n USB_XHCI=n USB_UAS=n SDCARD=n TCGBIOS=n MPT_SCSI=n ESP_SCSI=n MEGASAS=n NVME=n USE_SMM=n VGAHOOKS=n HOST_BIOS_GEOMETRY=n ACPI_PARSE=n \ + LSI_SCSI=n DEBUG_IO=n bios-256k-config = QEMU=y ROM_SIZE=256 bios-microvm-config = QEMU=y ROM_SIZE=128 XEN=n BOOTSPLASH=n ATA=n AHCI=n SDCARD=n PVSCSI=n ESP_SCSI=n LSI_SCSI=n MEGASAS=n MPT_SCSI=n FLOPPY=n FLASH_FLOPPY=n NVME=n PS2PORT=n USB=n LPT=n RTC_TIMER=n USE_SMM=n PMTIMER=n TCGBIOS=n HARDWARE_IRQ=n ACPI_PARSE=y diff -Nru seabios-1.16.2/src/config.h seabios-1.16.3/src/config.h --- seabios-1.16.2/src/config.h 2023-02-02 01:14:39.000000000 +0000 +++ seabios-1.16.3/src/config.h 2023-11-13 12:49:59.000000000 +0000 @@ -15,7 +15,7 @@ #define BUILD_APPNAME4 "BXPC" // Maximum number of map entries in the e820 map -#define BUILD_MAX_E820 32 +#define BUILD_MAX_E820 128 // Space to reserve in high-memory for tables #define BUILD_MIN_HIGHTABLE (256*1024) #define BUILD_MAX_HIGHTABLE (16*1024*1024) diff -Nru seabios-1.16.2/src/e820map.c seabios-1.16.3/src/e820map.c --- seabios-1.16.2/src/e820map.c 2023-02-02 01:14:39.000000000 +0000 +++ seabios-1.16.3/src/e820map.c 2023-11-13 12:49:59.000000000 +0000 @@ -150,3 +150,18 @@ { dump_map(); } + +int +e820_is_used(u64 start, u64 size) +{ + int i; + for (i=0; istart) + continue; + if (start >= e->start + e->size) + continue; + return 1; + } + return 0; +} diff -Nru seabios-1.16.2/src/e820map.h seabios-1.16.3/src/e820map.h --- seabios-1.16.2/src/e820map.h 2023-02-02 01:14:39.000000000 +0000 +++ seabios-1.16.3/src/e820map.h 2023-11-13 12:49:59.000000000 +0000 @@ -18,6 +18,7 @@ void e820_add(u64 start, u64 size, u32 type); void e820_remove(u64 start, u64 size); void e820_prepboot(void); +int e820_is_used(u64 start, u64 size); // e820 map storage extern struct e820entry e820_list[]; diff -Nru seabios-1.16.2/src/fw/csm.c seabios-1.16.3/src/fw/csm.c --- seabios-1.16.2/src/fw/csm.c 2023-02-02 01:14:39.000000000 +0000 +++ seabios-1.16.3/src/fw/csm.c 2023-11-13 12:49:59.000000000 +0000 @@ -150,9 +150,9 @@ for (i=0; i < csm_compat_table.E820Length / sizeof(struct e820entry); i++) e820_add(p[i].start, p[i].size, p[i].type); - if (csm_init_table->HiPmmMemorySizeInBytes > BUILD_MAX_HIGHTABLE) { + if (csm_init_table->HiPmmMemorySizeInBytes > BUILD_MIN_HIGHTABLE) { u32 hi_pmm_end = csm_init_table->HiPmmMemory + csm_init_table->HiPmmMemorySizeInBytes; - e820_add(hi_pmm_end - BUILD_MAX_HIGHTABLE, BUILD_MAX_HIGHTABLE, E820_RESERVED); + e820_add(hi_pmm_end - BUILD_MIN_HIGHTABLE, BUILD_MIN_HIGHTABLE, E820_RESERVED); } // For PCIBIOS 1ab10e diff -Nru seabios-1.16.2/src/fw/paravirt.c seabios-1.16.3/src/fw/paravirt.c --- seabios-1.16.2/src/fw/paravirt.c 2023-02-02 01:14:39.000000000 +0000 +++ seabios-1.16.3/src/fw/paravirt.c 2023-11-13 12:49:59.000000000 +0000 @@ -32,6 +32,10 @@ u32 RamSize; // Amount of continuous ram >4Gig u64 RamSizeOver4G; +// physical address space bits +u8 CPUPhysBits; +// 64bit processor +u8 CPULongMode; // Type of emulator platform. int PlatformRunningOn VARFSEG; // cfg enabled @@ -53,23 +57,35 @@ * should be used to determine that a VM is running under KVM. */ #define KVM_CPUID_SIGNATURE 0x40000000 +static unsigned int kvm_cpuid_base = 0; static void kvm_detect(void) { + unsigned int i, max = 0; unsigned int eax, ebx, ecx, edx; char signature[13]; - cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx); - memcpy(signature + 0, &ebx, 4); - memcpy(signature + 4, &ecx, 4); - memcpy(signature + 8, &edx, 4); - signature[12] = 0; + for (i = KVM_CPUID_SIGNATURE;; i += 0x100) { + eax = 0; + cpuid(i, &eax, &ebx, &ecx, &edx); + if (eax < i) + break; + memcpy(signature + 0, &ebx, 4); + memcpy(signature + 4, &ecx, 4); + memcpy(signature + 8, &edx, 4); + signature[12] = 0; + dprintf(1, "cpuid 0x%x: eax %x, signature '%s'\n", i, eax, signature); + if (strcmp(signature, "KVMKVMKVM") == 0) { + kvm_cpuid_base = i; + max = eax; + } + } - if (strcmp(signature, "KVMKVMKVM") == 0) { + if (kvm_cpuid_base) { dprintf(1, "Running on KVM\n"); PlatformRunningOn |= PF_KVM; - if (eax >= KVM_CPUID_SIGNATURE + 0x10) { - cpuid(KVM_CPUID_SIGNATURE + 0x10, &eax, &ebx, &ecx, &edx); + if (max >= kvm_cpuid_base + 0x10) { + cpuid(kvm_cpuid_base + 0x10, &eax, &ebx, &ecx, &edx); dprintf(1, "kvm: have invtsc, freq %u kHz\n", eax); tsctimer_setfreq(eax, "invtsc"); } @@ -93,7 +109,7 @@ if (!runningOnKVM()) return; - cpuid(KVM_CPUID_SIGNATURE + 0x01, &eax, &ebx, &ecx, &edx); + cpuid(kvm_cpuid_base + 0x01, &eax, &ebx, &ecx, &edx); if (eax & (1 << KVM_FEATURE_CLOCKSOURCE2)) msr = MSR_KVM_SYSTEM_TIME_NEW; else if (eax & (1 << KVM_FEATURE_CLOCKSOURCE)) @@ -118,6 +134,58 @@ tsctimer_setfreq(MHz * 1000, "kvmclock"); } +static void physbits(int qemu_quirk) +{ + unsigned int max, eax, ebx, ecx, edx; + unsigned int physbits; + char signature[13]; + int pae = 0, valid = 0; + + cpuid(0, &eax, &ebx, &ecx, &edx); + memcpy(signature + 0, &ebx, 4); + memcpy(signature + 4, &edx, 4); + memcpy(signature + 8, &ecx, 4); + signature[12] = 0; + if (eax >= 1) { + cpuid(1, &eax, &ebx, &ecx, &edx); + pae = (edx & (1 << 6)); + } + + cpuid(0x80000000, &eax, &ebx, &ecx, &edx); + max = eax; + + if (max >= 0x80000001) { + cpuid(0x80000001, &eax, &ebx, &ecx, &edx); + CPULongMode = !!(edx & (1 << 29)); + } + + if (pae && CPULongMode && max >= 0x80000008) { + cpuid(0x80000008, &eax, &ebx, &ecx, &edx); + physbits = (u8)eax; + if (!qemu_quirk) { + valid = 1; + } else if (physbits >= 41) { + valid = 1; + } else if (strcmp(signature, "GenuineIntel") == 0) { + if ((physbits == 36) || (physbits == 39)) + valid = 1; + } else if (strcmp(signature, "AuthenticAMD") == 0) { + if (physbits == 40) + valid = 1; + } + } else { + physbits = pae ? 36 : 32; + valid = 1; + } + + dprintf(1, "%s: signature=\"%s\", pae=%s, lm=%s, phys-bits=%d, valid=%s\n", + __func__, signature, pae ? "yes" : "no", CPULongMode ? "yes" : "no", + physbits, valid ? "yes" : "no"); + + if (valid) + CPUPhysBits = physbits; +} + static void qemu_detect(void) { if (!CONFIG_QEMU_HARDWARE) @@ -150,6 +218,7 @@ dprintf(1, "Running on QEMU (unknown nb: %04x:%04x)\n", v, d); break; } + physbits(1); } static int qemu_early_e820(void); @@ -696,7 +765,7 @@ switch (table.type) { case E820_RESERVED: e820_add(table.address, table.length, table.type); - dprintf(3, "qemu/e820: addr 0x%016llx len 0x%016llx [reserved]\n", + dprintf(1, "qemu/e820: addr 0x%016llx len 0x%016llx [reserved]\n", table.address, table.length); break; case E820_RAM: diff -Nru seabios-1.16.2/src/fw/paravirt.h seabios-1.16.3/src/fw/paravirt.h --- seabios-1.16.2/src/fw/paravirt.h 2023-02-02 01:14:39.000000000 +0000 +++ seabios-1.16.3/src/fw/paravirt.h 2023-11-13 12:49:59.000000000 +0000 @@ -31,6 +31,8 @@ extern u32 RamSize; extern u64 RamSizeOver4G; extern int PlatformRunningOn; +extern u8 CPUPhysBits; +extern u8 CPULongMode; static inline int runningOnQEMU(void) { return CONFIG_QEMU || ( diff -Nru seabios-1.16.2/src/fw/pciinit.c seabios-1.16.3/src/fw/pciinit.c --- seabios-1.16.2/src/fw/pciinit.c 2023-02-02 01:14:39.000000000 +0000 +++ seabios-1.16.3/src/fw/pciinit.c 2023-11-13 12:49:59.000000000 +0000 @@ -46,11 +46,16 @@ [ PCI_REGION_TYPE_PREFMEM ] = "prefmem", }; +// Memory ranges exported to legacy ACPI type table generation u64 pcimem_start = BUILD_PCIMEM_START; u64 pcimem_end = BUILD_PCIMEM_END; u64 pcimem64_start = BUILD_PCIMEM64_START; u64 pcimem64_end = BUILD_PCIMEM64_END; -u64 pci_io_low_end = 0xa000; + +// Resource allocation limits +static u64 pci_io_low_end = 0xa000; +static u64 pci_mem64_top = 0; +static u32 pci_pad_mem64 = 0; struct pci_region_entry { struct pci_device *dev; @@ -960,10 +965,15 @@ if (pci_region_align(&s->r[type]) > align) align = pci_region_align(&s->r[type]); u64 sum = pci_region_sum(&s->r[type]); + int is64 = pci_bios_bridge_region_is64(&s->r[type], + s->bus_dev, type); int resource_optional = 0; if (hotplug_support == HOTPLUG_PCIE) resource_optional = pcie_cap && (type == PCI_REGION_TYPE_IO); - if (!sum && hotplug_support && !resource_optional) + if (hotplug_support && pci_pad_mem64 && is64 + && (type == PCI_REGION_TYPE_PREFMEM)) + align = pci_mem64_top >> 11; + if (align > sum && hotplug_support && !resource_optional) sum = align; /* reserve min size for hot-plug */ if (size > sum) { dprintf(1, "PCI: QEMU resource reserve cap: " @@ -975,8 +985,6 @@ } else { size = ALIGN(sum, align); } - int is64 = pci_bios_bridge_region_is64(&s->r[type], - s->bus_dev, type); // entry->bar is -1 if the entry represents a bridge region struct pci_region_entry *entry = pci_region_create_entry( parent, s->bus_dev, -1, size, align, type, is64); @@ -1108,7 +1116,7 @@ panic("PCI: out of I/O address space\n"); dprintf(1, "PCI: 32: %016llx - %016llx\n", pcimem_start, pcimem_end); - if (pci_bios_init_root_regions_mem(busses)) { + if (pci_pad_mem64 || pci_bios_init_root_regions_mem(busses)) { struct pci_region r64_mem, r64_pref; r64_mem.list.first = NULL; r64_pref.list.first = NULL; @@ -1128,6 +1136,17 @@ r64_mem.base = le64_to_cpu(romfile_loadint("etc/reserved-memory-end", 0)); if (r64_mem.base < 0x100000000LL + RamSizeOver4G) r64_mem.base = 0x100000000LL + RamSizeOver4G; + if (pci_mem64_top) { + u64 size = (ALIGN(sum_mem, (1LL<<30)) + + ALIGN(sum_pref, (1LL<<30))); + if (pci_pad_mem64) + size = ALIGN(size, pci_mem64_top >> 3); + if (r64_mem.base < pci_mem64_top - size) { + r64_mem.base = pci_mem64_top - size; + } + if (e820_is_used(r64_mem.base, size)) + r64_mem.base -= size; + } r64_mem.base = ALIGN(r64_mem.base, align_mem); r64_mem.base = ALIGN(r64_mem.base, (1LL<<30)); // 1G hugepage r64_pref.base = r64_mem.base + sum_mem; @@ -1166,6 +1185,19 @@ dprintf(3, "pci setup\n"); + if (CPUPhysBits) { + pci_mem64_top = 1LL << CPUPhysBits; + if (CPUPhysBits > 46) { + // Old linux kernels have trouble dealing with more than 46 + // phys-bits, so avoid that for now. Seems to be a bug in the + // virtio-pci driver. Reported: centos-7, ubuntu-18.04 + pci_mem64_top = 1LL << 46; + } + } + + if (CPUPhysBits >= 36 && CPULongMode && RamSizeOver4G) + pci_pad_mem64 = 1; + dprintf(1, "=== PCI bus & bridge init ===\n"); if (pci_probe_host() != 0) { return; diff -Nru seabios-1.16.2/src/hw/ahci.c seabios-1.16.3/src/hw/ahci.c --- seabios-1.16.2/src/hw/ahci.c 2023-02-02 01:14:39.000000000 +0000 +++ seabios-1.16.3/src/hw/ahci.c 2023-11-13 12:49:59.000000000 +0000 @@ -138,6 +138,12 @@ intbits = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT); if (intbits) { ahci_port_writel(ctrl, pnr, PORT_IRQ_STAT, intbits); + if (intbits & 0x40000000) { + u32 tf = ahci_port_readl(ctrl, pnr, PORT_TFDATA); + status = tf & 0xff; + error = (tf & 0xff00) >> 8; + break; + } if (intbits & 0x02) { status = GET_LOWFLAT(fis->psfis[2]); error = GET_LOWFLAT(fis->psfis[3]); diff -Nru seabios-1.16.2/src/hw/esp-scsi.c seabios-1.16.3/src/hw/esp-scsi.c --- seabios-1.16.2/src/hw/esp-scsi.c 2023-02-02 01:14:39.000000000 +0000 +++ seabios-1.16.3/src/hw/esp-scsi.c 2023-11-13 12:49:59.000000000 +0000 @@ -46,6 +46,7 @@ #define ESP_DMA_WMAC 0x58c #define ESP_CMD_DMA 0x80 +#define ESP_CMD_FLUSH 0x01 #define ESP_CMD_RESET 0x02 #define ESP_CMD_TI 0x10 #define ESP_CMD_ICCS 0x11 @@ -56,6 +57,8 @@ #define ESP_STAT_MSG 0x04 #define ESP_STAT_TC 0x10 +#define ESP_INTR_FC 0x08 +#define ESP_INTR_BS 0x10 #define ESP_INTR_DC 0x20 struct esp_lun_s { @@ -96,6 +99,10 @@ outb(target, iobase + ESP_WBUSID); + /* Clear FIFO and interrupts before sending command. */ + outb(ESP_CMD_FLUSH, iobase + ESP_CMD); + inb(iobase + ESP_RINTR); + /* * We need to pass the LUN at the beginning of the command, and the FIFO * is only 16 bytes, so we cannot support 16-byte CDBs. The alternative @@ -111,33 +118,47 @@ for (state = 0;;) { u8 stat = inb(iobase + ESP_RSTAT); + u8 intr; - /* Detect disconnected device. */ - if (state == 0 && (inb(iobase + ESP_RINTR) & ESP_INTR_DC)) { - return DISK_RET_ENOTREADY; - } + if (state == 0) { + intr = inb(iobase + ESP_RINTR); - /* HBA reads command, clears CD, sets TC -> do DMA if needed. */ - if (state == 0 && (stat & ESP_STAT_TC)) { - state++; - if (op->count && blocksize) { - /* Data phase. */ - u32 count = (u32)op->count * blocksize; - esp_scsi_dma(iobase, (u32)op->buf_fl, count, scsi_is_read(op)); - outb(ESP_CMD_TI | ESP_CMD_DMA, iobase + ESP_CMD); - continue; + /* Detect disconnected device. */ + if (intr & ESP_INTR_DC) { + return DISK_RET_ENOTREADY; + } + + /* HBA reads command, executes it, sets BS/FC -> do DMA if needed. */ + if (intr & (ESP_INTR_BS | ESP_INTR_FC)) { + state++; + if (op->count && blocksize) { + /* Data phase. */ + u32 count = (u32)op->count * blocksize; + esp_scsi_dma(iobase, (u32)op->buf_fl, count, scsi_is_read(op)); + outb(ESP_CMD_TI | ESP_CMD_DMA, iobase + ESP_CMD); + continue; + } else { + /* No data phase. */ + state++; + } } } /* At end of DMA TC is set again -> complete command. */ if (state == 1 && (stat & ESP_STAT_TC)) { state++; + continue; + } + + /* Request message in data. */ + if (state == 2) { + state++; outb(ESP_CMD_ICCS, iobase + ESP_CMD); continue; } /* Finally read data from the message in phase. */ - if (state == 2 && (stat & ESP_STAT_MSG)) { + if (state == 3 && (stat & ESP_STAT_MSG)) { state++; status = inb(iobase + ESP_FIFO); inb(iobase + ESP_FIFO); diff -Nru seabios-1.16.2/src/hw/virtio-blk.c seabios-1.16.3/src/hw/virtio-blk.c --- seabios-1.16.2/src/hw/virtio-blk.c 2023-02-02 01:14:39.000000000 +0000 +++ seabios-1.16.3/src/hw/virtio-blk.c 2023-11-13 12:49:59.000000000 +0000 @@ -92,7 +92,7 @@ u16 blk_num_max; if (vdrive->drive.blksize != 0 && max_io_size != 0) - blk_num_max = (u16)(max_io_size / vdrive->drive.blksize); + blk_num_max = (u16) min(max_io_size / vdrive->drive.blksize, 0xffff); else /* default blk_num_max if hardware doesnot advise a proper value */ blk_num_max = 64; diff -Nru seabios-1.16.2/src/malloc.c seabios-1.16.3/src/malloc.c --- seabios-1.16.2/src/malloc.c 2023-02-02 01:14:39.000000000 +0000 +++ seabios-1.16.3/src/malloc.c 2023-11-13 12:49:59.000000000 +0000 @@ -460,10 +460,10 @@ { ASSERT32FLAT(); - if (hi_pmm_size > BUILD_MAX_HIGHTABLE) { + if (hi_pmm_size > BUILD_MIN_HIGHTABLE) { u32 hi_pmm_end = hi_pmm + hi_pmm_size; - alloc_add(&ZoneTmpHigh, hi_pmm, hi_pmm_end - BUILD_MAX_HIGHTABLE); - alloc_add(&ZoneHigh, hi_pmm_end - BUILD_MAX_HIGHTABLE, hi_pmm_end); + alloc_add(&ZoneTmpHigh, hi_pmm, hi_pmm_end - BUILD_MIN_HIGHTABLE); + alloc_add(&ZoneHigh, hi_pmm_end - BUILD_MIN_HIGHTABLE, hi_pmm_end); } else { alloc_add(&ZoneTmpHigh, hi_pmm, hi_pmm + hi_pmm_size); }