require sufficient space in the ECAM region. However, the Highmem ECAM
region did not fit in the limited PA space on the hardware, and the ECAM
region size was limited to 16 MiB. If virt-install had added more than
16 devices to the root bridge, the region overflowed, which prevented
edk2-stable202505 from scanning PCI devices, including the boot disk,
causing boot failures.
Ideally, a virtual machine with more than 16 devices added to the root
bridge should just work so that users and management layers do not have
to care whether they use constrained hardware.
The base address of the Highmem IO Regions was fixed when commit
f90747c4e8fb ("hw/arm/virt: GICv3 DT node with one or two redistributor
regions") added the first Highmem IO Region. Later, commit 957e32cffa57
("hw/arm/virt: Dynamic memory map depending on RAM requirements")
allowed moving the Highmem IO Regions to higher addresses to accommodate
RAM more than 255 GiB, but the lower bound remained to keep the legacy
memory map.
Remove the lower bound for the latest machine version to accommodate
more devices with the root bridge. Keeping the lower bound for the old
machine versions ensures the compatibility is still maintained.
The hardcoded memory map in tests/qtest/libqos/generic-pcihost.c is also
updated.
Signed-off-by: Akihiko Odaki <[email protected]>
Reviewed-by: Eric Auger <[email protected]>
---
include/hw/arm/virt.h | 1 +
hw/arm/virt.c | 17 +++++++++++------
tests/qtest/libqos/generic-pcihost.c | 2 +-
3 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 3ba33b4bd274..6c8ba8f3185b 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -142,6 +142,7 @@ typedef enum VirtGICType {
struct VirtMachineClass {
MachineClass parent;
+ hwaddr min_highmem_base;
bool no_tcg_its;
bool no_highmem_compact;
bool no_kvm_steal_time;
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index b090233893c5..78a85a966ad7 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -229,8 +229,7 @@ static const MemMapEntry base_memmap[] = {
* Highmem IO Regions: This memory map is floating, located after the RAM.
* Each MemMapEntry base (GPA) will be dynamically computed, depending on the
* top of the RAM, so that its base get the same alignment as the size,
- * ie. a 512GiB entry will be aligned on a 512GiB boundary. If there is
- * less than 256GiB of RAM, the floating area starts at the 256GiB mark.
+ * ie. a 512GiB entry will be aligned on a 512GiB boundary.
* Note the extended_memmap is sized so that it eventually also includes the
* base_memmap entries (VIRT_HIGH_GIC_REDIST2 index is greater than the last
* index of base_memmap).
@@ -2479,6 +2478,7 @@ static void virt_set_high_memmap(VirtMachineState *vms,
static void virt_set_memmap(VirtMachineState *vms, int pa_bits)
{
MachineState *ms = MACHINE(vms);
+ VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
hwaddr base, device_memory_base, device_memory_size, memtop;
int i;
@@ -2505,8 +2505,7 @@ static void virt_set_memmap(VirtMachineState *vms, int pa_bits)
/*
* We compute the base of the high IO region depending on the
* amount of initial and device memory. The device memory start/size
- * is aligned on 1GiB. We never put the high IO region below 256GiB
- * so that if maxram_size is < 255GiB we keep the legacy memory map.
+ * is aligned on 1GiB.
* The device region size assumes 1GiB page max alignment per slot.
*/
device_memory_base =
@@ -2524,8 +2523,8 @@ static void virt_set_memmap(VirtMachineState *vms, int
pa_bits)
error_report("maxmem/slots too huge");
exit(EXIT_FAILURE);
}
- if (base < vms->memmap[VIRT_MEM].base + LEGACY_RAMLIMIT_BYTES) {
- base = vms->memmap[VIRT_MEM].base + LEGACY_RAMLIMIT_BYTES;
+ if (base < vmc->min_highmem_base) {
+ base = vmc->min_highmem_base;
}
/* We know for sure that at least the memory fits in the PA space */
@@ -4367,6 +4366,12 @@ static void virt_machine_11_0_options(MachineClass *mc)
virt_machine_11_1_options(mc);
compat_props_add(mc->compat_props, hw_compat_11_0, hw_compat_11_0_len);
vmc->hvf_no_kernel_irqchip_default = true;
+
+ /*
+ * Do not put the high IO region below 256GiB so that if maxram_size is
+ * < 255GiB we keep the legacy memory map.
+ */
+ vmc->min_highmem_base = base_memmap[VIRT_MEM].base + LEGACY_RAMLIMIT_BYTES;
}
DEFINE_VIRT_MACHINE(11, 0)
diff --git a/tests/qtest/libqos/generic-pcihost.c b/tests/qtest/libqos/generic-pcihost.c
index b77617524cac..287e8445ec5b 100644
--- a/tests/qtest/libqos/generic-pcihost.c
+++ b/tests/qtest/libqos/generic-pcihost.c
@@ -210,7 +210,7 @@ void qpci_init_generic(QGenericPCIBus *qpci, QTestState
*qts,
qpci->bus.pio_limit = 0x10000;
qpci->bus.mmio_alloc_ptr = 0x10000000;
qpci->bus.mmio_limit = 0x2eff0000;
- qpci->ecam_alloc_ptr = 0x4010000000;
+ qpci->ecam_alloc_ptr = 0x90000000;
qpci->obj.get_driver = qpci_generic_get_driver;
}