diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 892bae4f3a..9596c7c7f1 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -29,6 +29,7 @@ */ #include "qemu/osdep.h" +#include "qemu/units.h" #include "qapi/error.h" #include "hw/sysbus.h" #include "hw/arm/arm.h" @@ -121,7 +122,7 @@ * Note that devices should generally be placed at multiples of 0x10000, * to accommodate guests using 64K pages. */ -static const MemMapEntry a15memmap[] = { +static const MemMapEntry base_memmap[] = { /* Space up to 0x8000000 is reserved for a boot ROM */ [VIRT_FLASH] = { 0, 0x08000000 }, [VIRT_CPUPERIPHS] = { 0x08000000, 0x00020000 }, @@ -149,11 +150,24 @@ static const MemMapEntry a15memmap[] = { [VIRT_PCIE_PIO] = { 0x3eff0000, 0x00010000 }, [VIRT_PCIE_ECAM] = { 0x3f000000, 0x01000000 }, [VIRT_MEM] = { 0x40000000, RAMLIMIT_BYTES }, +}; + +/* + * 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. + * 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). + */ +static MemMapEntry extended_memmap[] = { /* Additional 64 MB redist region (can contain up to 512 redistributors) */ - [VIRT_HIGH_GIC_REDIST2] = { 0x4000000000ULL, 0x4000000 }, - [VIRT_HIGH_PCIE_ECAM] = { 0x4010000000ULL, 0x10000000 }, - /* Second PCIe window, 512GB wide at the 512GB boundary */ - [VIRT_HIGH_PCIE_MMIO] = { 0x8000000000ULL, 0x8000000000ULL }, + [VIRT_HIGH_GIC_REDIST2] = { 0x0, 64 * MiB }, + [VIRT_HIGH_PCIE_ECAM] = { 0x0, 256 * MiB }, + /* Second PCIe window */ + [VIRT_HIGH_PCIE_MMIO] = { 0x0, 512 * GiB }, }; static const int a15irqmap[] = { @@ -1354,6 +1368,29 @@ static uint64_t virt_cpu_mp_affinity(VirtMachineState *vms, int idx) return arm_cpu_mp_affinity(idx, clustersz); } +static void virt_set_memmap(VirtMachineState *vms) +{ + hwaddr base; + int i; + + vms->memmap = extended_memmap; + + for (i = 0; i < ARRAY_SIZE(base_memmap); i++) { + vms->memmap[i] = base_memmap[i]; + } + + base = 256 * GiB; /* Top of the legacy initial RAM region */ + + for (i = VIRT_LOWMEMMAP_LAST; i < ARRAY_SIZE(extended_memmap); i++) { + hwaddr size = extended_memmap[i].size; + + base = ROUND_UP(base, size); + vms->memmap[i].base = base; + vms->memmap[i].size = size; + base += size; + } +} + static void machvirt_init(MachineState *machine) { VirtMachineState *vms = VIRT_MACHINE(machine); @@ -1368,6 +1405,8 @@ static void machvirt_init(MachineState *machine) bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0); bool aarch64 = true; + virt_set_memmap(vms); + /* We can probe only here because during property set * KVM is not available yet */ @@ -1845,7 +1884,6 @@ static void virt_instance_init(Object *obj) "Valid values are none and smmuv3", NULL); - vms->memmap = a15memmap; vms->irqmap = a15irqmap; } diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index a27086d524..f3f7fae4ac 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -64,7 +64,6 @@ enum { VIRT_GIC_VCPU, VIRT_GIC_ITS, VIRT_GIC_REDIST, - VIRT_HIGH_GIC_REDIST2, VIRT_SMMU, VIRT_UART, VIRT_MMIO, @@ -74,12 +73,18 @@ enum { VIRT_PCIE_MMIO, VIRT_PCIE_PIO, VIRT_PCIE_ECAM, - VIRT_HIGH_PCIE_ECAM, VIRT_PLATFORM_BUS, - VIRT_HIGH_PCIE_MMIO, VIRT_GPIO, VIRT_SECURE_UART, VIRT_SECURE_MEM, + VIRT_LOWMEMMAP_LAST, +}; + +/* indices of IO regions located after the RAM */ +enum { + VIRT_HIGH_GIC_REDIST2 = VIRT_LOWMEMMAP_LAST, + VIRT_HIGH_PCIE_ECAM, + VIRT_HIGH_PCIE_MMIO, }; typedef enum VirtIOMMUType { @@ -116,7 +121,7 @@ typedef struct { int32_t gic_version; VirtIOMMUType iommu; struct arm_boot_info bootinfo; - const MemMapEntry *memmap; + MemMapEntry *memmap; const int *irqmap; int smp_cpus; void *fdt;