aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Zyngier <maz@kernel.org>2022-01-14 14:07:40 +0000
committerPeter Maydell <peter.maydell@linaro.org>2022-01-20 11:47:53 +0000
commitd9afe24c29a0985b29d7535b2f1615affbd1a888 (patch)
tree1d7e33949ec7626e71337e4d8b47fd2199a4c6cc
parent3715c251cc781b263fbd7f7c535fde7a4da401c3 (diff)
hw/arm/virt: Disable highmem devices that don't fit in the PA range
In order to only keep the highmem devices that actually fit in the PA range, check their location against the range and update highest_gpa if they fit. If they don't, mark them as disabled. Signed-off-by: Marc Zyngier <maz@kernel.org> Reviewed-by: Eric Auger <eric.auger@redhat.com> Message-id: 20220114140741.1358263-6-maz@kernel.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/arm/virt.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 8627f5ab95..8d02c2267d 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1719,21 +1719,43 @@ static void virt_set_memmap(VirtMachineState *vms, int pa_bits)
base = vms->memmap[VIRT_MEM].base + LEGACY_RAMLIMIT_BYTES;
}
+ /* We know for sure that at least the memory fits in the PA space */
+ vms->highest_gpa = memtop - 1;
+
for (i = VIRT_LOWMEMMAP_LAST; i < ARRAY_SIZE(extended_memmap); i++) {
hwaddr size = extended_memmap[i].size;
+ bool fits;
base = ROUND_UP(base, size);
vms->memmap[i].base = base;
vms->memmap[i].size = size;
+
+ /*
+ * Check each device to see if they fit in the PA space,
+ * moving highest_gpa as we go.
+ *
+ * For each device that doesn't fit, disable it.
+ */
+ fits = (base + size) <= BIT_ULL(pa_bits);
+ if (fits) {
+ vms->highest_gpa = base + size - 1;
+ }
+
+ switch (i) {
+ case VIRT_HIGH_GIC_REDIST2:
+ vms->highmem_redists &= fits;
+ break;
+ case VIRT_HIGH_PCIE_ECAM:
+ vms->highmem_ecam &= fits;
+ break;
+ case VIRT_HIGH_PCIE_MMIO:
+ vms->highmem_mmio &= fits;
+ break;
+ }
+
base += size;
}
- /*
- * If base fits within pa_bits, all good. If it doesn't, limit it
- * to the end of RAM, which is guaranteed to fit within pa_bits.
- */
- vms->highest_gpa = (base <= BIT_ULL(pa_bits) ? base : memtop) - 1;
-
if (device_memory_size > 0) {
ms->device_memory = g_malloc0(sizeof(*ms->device_memory));
ms->device_memory->base = device_memory_base;