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 them as disabled.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
hw/arm/virt.c | 34 ++++++++++++++++++++++++++++------
1 file changed, 28 insertions(+), 6 deletions(-)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index db4b0636e1..70b4773b3e 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1711,21 +1711,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 = MAX(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;
--
2.30.2
Hi Marc,
On 1/7/22 5:33 PM, Marc Zyngier wrote:
> 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 them as disabled.
s/them them/them
>
> Signed-off-by: Marc Zyngier <maz@kernel.org>
> ---
> hw/arm/virt.c | 34 ++++++++++++++++++++++++++++------
> 1 file changed, 28 insertions(+), 6 deletions(-)
>
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index db4b0636e1..70b4773b3e 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -1711,21 +1711,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 = MAX(vms->highest_gpa, base + size - 1);
why do you need the MAX()?
> + }
> + 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;
Eric
On Mon, 10 Jan 2022 17:12:50 +0000,
Eric Auger <eric.auger@redhat.com> wrote:
>
> Hi Marc,
>
> On 1/7/22 5:33 PM, Marc Zyngier wrote:
> > 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 them as disabled.
> s/them them/them
> >
> > Signed-off-by: Marc Zyngier <maz@kernel.org>
> > ---
> > hw/arm/virt.c | 34 ++++++++++++++++++++++++++++------
> > 1 file changed, 28 insertions(+), 6 deletions(-)
> >
> > diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> > index db4b0636e1..70b4773b3e 100644
> > --- a/hw/arm/virt.c
> > +++ b/hw/arm/virt.c
> > @@ -1711,21 +1711,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 = MAX(vms->highest_gpa, base + size - 1);
> why do you need the MAX()?
Well spotted, I don't. Since we build the memmap by moving base
upward, I can directly use 'base + size - 1' as the new highest_gpa
value.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
© 2016 - 2026 Red Hat, Inc.