Blame SOURCES/kvm-hw-arm-virt-Improve-high-memory-region-address-assig.patch

7f1c5b
From 1c7fad3776a14ca35b24dc2fdb262d4ddf40d6eb Mon Sep 17 00:00:00 2001
7f1c5b
From: Gavin Shan <gshan@redhat.com>
7f1c5b
Date: Wed, 21 Dec 2022 08:48:45 +0800
7f1c5b
Subject: [PATCH 5/8] hw/arm/virt: Improve high memory region address
7f1c5b
 assignment
7f1c5b
7f1c5b
RH-Author: Gavin Shan <gshan@redhat.com>
7f1c5b
RH-MergeRequest: 126: hw/arm/virt: Optimize high memory region address assignment
7f1c5b
RH-Bugzilla: 2113840
7f1c5b
RH-Acked-by: Eric Auger <eric.auger@redhat.com>
7f1c5b
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
7f1c5b
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
7f1c5b
RH-Commit: [5/8] 4d77fa78b5258a1bd8d30405cec5ba3311d42f92
7f1c5b
7f1c5b
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2113840
7f1c5b
7f1c5b
There are three high memory regions, which are VIRT_HIGH_REDIST2,
7f1c5b
VIRT_HIGH_PCIE_ECAM and VIRT_HIGH_PCIE_MMIO. Their base addresses
7f1c5b
are floating on highest RAM address. However, they can be disabled
7f1c5b
in several cases.
7f1c5b
7f1c5b
(1) One specific high memory region is likely to be disabled by
7f1c5b
    code by toggling vms->highmem_{redists, ecam, mmio}.
7f1c5b
7f1c5b
(2) VIRT_HIGH_PCIE_ECAM region is disabled on machine, which is
7f1c5b
    'virt-2.12' or ealier than it.
7f1c5b
7f1c5b
(3) VIRT_HIGH_PCIE_ECAM region is disabled when firmware is loaded
7f1c5b
    on 32-bits system.
7f1c5b
7f1c5b
(4) One specific high memory region is disabled when it breaks the
7f1c5b
    PA space limit.
7f1c5b
7f1c5b
The current implementation of virt_set_{memmap, high_memmap}() isn't
7f1c5b
optimized because the high memory region's PA space is always reserved,
7f1c5b
regardless of whatever the actual state in the corresponding
7f1c5b
vms->highmem_{redists, ecam, mmio} flag. In the code, 'base' and
7f1c5b
'vms->highest_gpa' are always increased for case (1), (2) and (3).
7f1c5b
It's unnecessary since the assigned PA space for the disabled high
7f1c5b
memory region won't be used afterwards.
7f1c5b
7f1c5b
Improve the address assignment for those three high memory region by
7f1c5b
skipping the address assignment for one specific high memory region if
7f1c5b
it has been disabled in case (1), (2) and (3). The memory layout may
7f1c5b
be changed after the improvement is applied, which leads to potential
7f1c5b
migration breakage. So 'vms->highmem_compact' is added to control if
7f1c5b
the improvement should be applied. For now, 'vms->highmem_compact' is
7f1c5b
set to false, meaning that we don't have memory layout change until it
7f1c5b
becomes configurable through property 'compact-highmem' in next patch.
7f1c5b
7f1c5b
Signed-off-by: Gavin Shan <gshan@redhat.com>
7f1c5b
Reviewed-by: Eric Auger <eric.auger@redhat.com>
7f1c5b
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
7f1c5b
Reviewed-by: Marc Zyngier <maz@kernel.org>
7f1c5b
Tested-by: Zhenyu Zhang <zhenyzha@redhat.com>
7f1c5b
Message-id: 20221029224307.138822-6-gshan@redhat.com
7f1c5b
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7f1c5b
(cherry picked from commit 4a4ff9edc6a8fdc76082af5b41b059217138c09b)
7f1c5b
Signed-off-by: Gavin Shan <gshan@redhat.com>
7f1c5b
---
7f1c5b
 hw/arm/virt.c         | 15 ++++++++++-----
7f1c5b
 include/hw/arm/virt.h |  1 +
7f1c5b
 2 files changed, 11 insertions(+), 5 deletions(-)
7f1c5b
7f1c5b
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
7f1c5b
index 6e3b9fc060..6896e0ca0f 100644
7f1c5b
--- a/hw/arm/virt.c
7f1c5b
+++ b/hw/arm/virt.c
7f1c5b
@@ -1768,18 +1768,23 @@ static void virt_set_high_memmap(VirtMachineState *vms,
7f1c5b
         vms->memmap[i].size = region_size;
7f1c5b
 
7f1c5b
         /*
7f1c5b
-         * Check each device to see if they fit in the PA space,
7f1c5b
-         * moving highest_gpa as we go.
7f1c5b
+         * Check each device to see if it fits in the PA space,
7f1c5b
+         * moving highest_gpa as we go. For compatibility, move
7f1c5b
+         * highest_gpa for disabled fitting devices as well, if
7f1c5b
+         * the compact layout has been disabled.
7f1c5b
          *
7f1c5b
          * For each device that doesn't fit, disable it.
7f1c5b
          */
7f1c5b
         fits = (region_base + region_size) <= BIT_ULL(pa_bits);
7f1c5b
-        if (fits) {
7f1c5b
-            vms->highest_gpa = region_base + region_size - 1;
7f1c5b
+        *region_enabled &= fits;
7f1c5b
+        if (vms->highmem_compact && !*region_enabled) {
7f1c5b
+            continue;
7f1c5b
         }
7f1c5b
 
7f1c5b
-        *region_enabled &= fits;
7f1c5b
         base = region_base + region_size;
7f1c5b
+        if (fits) {
7f1c5b
+            vms->highest_gpa = base - 1;
7f1c5b
+        }
7f1c5b
     }
7f1c5b
 }
7f1c5b
 
7f1c5b
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
7f1c5b
index 22b54ec510..15bd291311 100644
7f1c5b
--- a/include/hw/arm/virt.h
7f1c5b
+++ b/include/hw/arm/virt.h
7f1c5b
@@ -144,6 +144,7 @@ struct VirtMachineState {
7f1c5b
     PFlashCFI01 *flash[2];
7f1c5b
     bool secure;
7f1c5b
     bool highmem;
7f1c5b
+    bool highmem_compact;
7f1c5b
     bool highmem_ecam;
7f1c5b
     bool highmem_mmio;
7f1c5b
     bool highmem_redists;
7f1c5b
-- 
7f1c5b
2.31.1
7f1c5b