Older 32-bit Linux VMs (including Ubuntu 16.10) have issues with the
64-bit pci io window, failing during boot with errors like:
virtio_balloon virtio2: virtio: device uses modern interface but does not have
VIRTIO_F_VERSION_19734-565debf7b362
virtio_net virtio0: virtio: device uses modern interface but does not have
VIRTIO_F_VERSION_1
Virtio_scsi virtio1: virtio: device uses modern interface but does not have
VIRTIO_F_VERSION_1
Gave up waiting for root device. Common problems:
- Boot args (cat /proc/cmdline)
- Check rootdelay= (did the system wait long enough?)
- Check root= (did the system wait for the right device?)
- Missing modules (cat /proc/modules; ls /dev)
ALERT! /dev/disk/by-uuid/86859879-3f17-443d-a226-077c435291e2 does not exist.
Dropping to a shell!
Be a bit more conservative, and only enable the window by default when
the ram size extends beyond 64G - a 32-bit guest using PAE cannot
address beyond that anyway. Due to the mmio window this translates
to an effective working configuration limit of 62G/63G, depending on
machine type.
Fixes: 96a8d130 ("be less conservative with the 64bit pci io window")
Signed-off-by: John Levon <[email protected]>
---
src/fw/paravirt.c | 28 ++++++++++++++++++++++++----
src/fw/paravirt.h | 1 +
src/fw/pciinit.c | 6 +++++-
3 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c
index 3ad9094b..5b0f191b 100644
--- a/src/fw/paravirt.c
+++ b/src/fw/paravirt.c
@@ -29,11 +29,14 @@
#include "stacks.h" // yield
#define MEM_4G (0x100000000ULL)
+#define MEM_64G (16 * 0x100000000ULL)
// Amount of continuous ram under 4Gig
u32 RamSize;
// Amount of continuous ram >4Gig
u64 RamSizeOver4G;
+// Amount of continuous ram >64Gig
+u64 RamSizeOver64G;
// physical address space bits
u8 CPUPhysBits;
// 64bit processor
@@ -591,8 +594,12 @@ qemu_cfg_e820(void)
| ((u32)rtc_read(CMOS_MEM_HIGHMEM_MID) << 24)
| ((u64)rtc_read(CMOS_MEM_HIGHMEM_HIGH) << 32));
RamSizeOver4G = high;
+ RamSizeOver64G = 0;
+ if (high + MEM_4G > MEM_64G)
+ RamSizeOver64G = high + MEM_4G - MEM_64G;
e820_add(MEM_4G, high, E820_RAM);
dprintf(1, "RamSizeOver4G: 0x%016llx [cmos]\n", RamSizeOver4G);
+ dprintf(1, "RamSizeOver64G: 0x%016llx [cmos]\n", RamSizeOver64G);
}
// Populate romfile entries for legacy fw_cfg ports (that predate the
@@ -774,19 +781,32 @@ static int qemu_early_e820(void)
e820_add(table.address, table.length, table.type);
dprintf(1, "qemu/e820: addr 0x%016llx len 0x%016llx [RAM]\n",
table.address, table.length);
+ // address below 4g?
if (table.address < MEM_4G) {
- // below 4g
if (RamSize < table.address + table.length)
RamSize = table.address + table.length;
} else {
- // above 4g
- if (RamSizeOver4G < table.address + table.length - MEM_4G)
- RamSizeOver4G = table.address + table.length - MEM_4G;
+ u64 table_end = table.address + table.length;
+
+ /*
+ * Note that this would ignore any span that crosses the 4G
+ * boundary. For RamSizeOver64G, we do account for any spans
+ * that cross the 64G boundary.
+ */
+ if (RamSizeOver4G < table_end - MEM_4G)
+ RamSizeOver4G = table_end - MEM_4G;
+
+ // crosses 64G ?
+ if (table_end > MEM_64G) {
+ if (RamSizeOver64G < table_end - MEM_64G)
+ RamSizeOver64G = table_end - MEM_64G;
+ }
}
}
}
dprintf(1, "qemu/e820: RamSize: 0x%08x\n", RamSize);
dprintf(1, "qemu/e820: RamSizeOver4G: 0x%016llx\n", RamSizeOver4G);
+ dprintf(1, "qemu/e820: RamSizeOver64G: 0x%016llx\n", RamSizeOver64G);
return 1;
}
diff --git a/src/fw/paravirt.h b/src/fw/paravirt.h
index 62a2cd07..b56e96e8 100644
--- a/src/fw/paravirt.h
+++ b/src/fw/paravirt.h
@@ -30,6 +30,7 @@ typedef struct QemuCfgDmaAccess {
extern u32 RamSize;
extern u64 RamSizeOver4G;
+extern u64 RamSizeOver64G;
extern int PlatformRunningOn;
extern u8 CPUPhysBits;
extern u8 CPULongMode;
diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index 0395fdbf..1247eb12 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -1197,7 +1197,11 @@ pci_setup(void)
}
}
- if (CPUPhysBits >= 36 && CPULongMode && RamSizeOver4G) {
+ /*
+ * Only enable this if we exceed 64G, as some older 32-bit Linux VMs cannot
+ * handle the 64-bit window correctly.
+ */
+ if (CPUPhysBits >= 36 && CPULongMode && RamSizeOver64G) {
dprintf(1, "enabling 64-bit pci mmio window\n");
pci_pad_mem64 = 1;
}
--
2.34.1
_______________________________________________
SeaBIOS mailing list -- [email protected]
To unsubscribe send an email to [email protected]