[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen stable-4.19] xen/device-tree: Allow region overlapping with /memreserve/ ranges



commit 6f7af8383f51f6e4f0588a12ff945d22d7375ae6
Author:     Luca Fancellu <luca.fancellu@xxxxxxx>
AuthorDate: Mon Dec 16 13:31:23 2024 +0100
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Mon Dec 16 13:31:23 2024 +0100

    xen/device-tree: Allow region overlapping with /memreserve/ ranges
    
    There are some cases where the device tree exposes a memory range
    in both /memreserve/ and reserved-memory node, in this case the
    current code will stop Xen to boot since it will find that the
    latter range is clashing with the already recorded /memreserve/
    ranges.
    
    Furthermore, u-boot lists boot modules ranges, such as ramdisk,
    in the /memreserve/ part and even in this case this will prevent
    Xen to boot since it will see that the module memory range that
    it is going to add in 'add_boot_module' clashes with a /memreserve/
    range.
    
    When Xen populate the data structure that tracks the memory ranges,
    it also adds a memory type described in 'enum membank_type', so
    in order to fix this behavior, allow overlapping with the /memreserve/
    ranges in the 'check_reserved_regions_overlap' function when a flag
    is set.
    
    In order to implement this solution, there is a distinction between
    the 'struct membanks *' handled by meminfo_overlap_check(...) that
    needs to be done, because the static shared memory banks doesn't have
    a usable bank[].type field and so it can't be accessed, hence now
    the 'struct membanks_hdr' have a 'enum region_type type' field in order
    to be able to identify static shared memory banks in 
meminfo_overlap_check(...).
    
    While there, set a type for the memory recorded using meminfo_add_bank()
    from efi-boot.h.
    
    Fixes: 53dc37829c31 ("xen/arm: Add DT reserve map regions to 
bootinfo.reserved_mem")
    Reported-by: Shawn Anastasio <sanastasio@xxxxxxxxxxxxxxxxxxxxx>
    Reported-by: Grygorii Strashko <grygorii_strashko@xxxxxxxx>
    Signed-off-by: Luca Fancellu <luca.fancellu@xxxxxxx>
    Tested-by: Grygorii Strashko <grygorii_strashko@xxxxxxxx>
    Reviewed-by: Julien Grall <jgrall@xxxxxxxxxx>
    
    bootfdt: Add missing trailing commas in BOOTINFO_{ACPI,SHMEM}_INIT
    
    Commit a14593e3995a extended BOOTINFO_{ACPI,SHMEM}_INIT initializers
    list with a new 'type' member but forgot to add trailing commas (they
    were present before). This results in a build failure when building
    with CONFIG_ACPI=y and CONFIG_STATIC_SHM=y:
    ./include/xen/bootfdt.h:155:5: error: request for member 'shmem' in 
something not a structure or union
      155 |     .shmem.common.max_banks = NR_SHMEM_BANKS,       \
          |     ^
    ./include/xen/bootfdt.h:168:5: note: in expansion of macro 
'BOOTINFO_SHMEM_INIT'
      168 |     BOOTINFO_SHMEM_INIT                             \
          |     ^~~~~~~~~~~~~~~~~~~
    common/device-tree/bootinfo.c:22:39: note: in expansion of macro 
'BOOTINFO_INIT'
       22 | struct bootinfo __initdata bootinfo = BOOTINFO_INIT;
    
    Fixes: a14593e3995a ("xen/device-tree: Allow region overlapping with 
/memreserve/ ranges")
    Signed-off-by: Michal Orzel <michal.orzel@xxxxxxx>
    Reviewed-by: Bertrand Marquis <bertrand.marquis@xxxxxxx>
    Reviewed-by: Luca Fancellu <luca.fancellu@xxxxxxx>
    master commit: a14593e3995afc74bf4efe91116e34894e0ea49a
    master date: 2024-11-28 18:57:21 +0000
    master commit: 5a455a52eae1420619df14c8e55fd17ced70538e
    master date: 2024-12-03 12:20:41 +0000
---
 xen/arch/arm/bootfdt.c           |  9 ++++++++-
 xen/arch/arm/efi/efi-boot.h      |  3 ++-
 xen/arch/arm/include/asm/setup.h | 20 +++++++++++++++++---
 xen/arch/arm/setup.c             | 39 +++++++++++++++++++++++++++++----------
 xen/arch/arm/static-shmem.c      |  2 +-
 5 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/xen/arch/arm/bootfdt.c b/xen/arch/arm/bootfdt.c
index 6e060111d9..1a766a2c4b 100644
--- a/xen/arch/arm/bootfdt.c
+++ b/xen/arch/arm/bootfdt.c
@@ -148,8 +148,15 @@ static int __init device_tree_get_meminfo(const void *fdt, 
int node,
     for ( i = 0; i < banks && mem->nr_banks < mem->max_banks; i++ )
     {
         device_tree_get_reg(&cell, address_cells, size_cells, &start, &size);
+        /*
+         * Some valid device trees, such as those generated by OpenPOWER
+         * skiboot firmware, expose all reserved memory regions in the
+         * FDT memory reservation block AND in the reserved-memory node which
+         * has already been parsed. Thus, any matching overlaps in the
+         * reserved_mem banks should be ignored.
+         */
         if ( mem == bootinfo_get_reserved_mem() &&
-             check_reserved_regions_overlap(start, size) )
+             check_reserved_regions_overlap(start, size, true) )
             return -EINVAL;
         /* Some DT may describe empty bank, ignore them */
         if ( !size )
diff --git a/xen/arch/arm/efi/efi-boot.h b/xen/arch/arm/efi/efi-boot.h
index 199f526022..a80a5a7ab3 100644
--- a/xen/arch/arm/efi/efi-boot.h
+++ b/xen/arch/arm/efi/efi-boot.h
@@ -167,13 +167,14 @@ static bool __init meminfo_add_bank(struct membanks *mem,
     if ( mem->nr_banks >= mem->max_banks )
         return false;
 #ifdef CONFIG_ACPI
-    if ( check_reserved_regions_overlap(start, size) )
+    if ( check_reserved_regions_overlap(start, size, false) )
         return false;
 #endif
 
     bank = &mem->bank[mem->nr_banks];
     bank->start = start;
     bank->size = size;
+    bank->type = MEMBANK_DEFAULT;
 
     mem->nr_banks++;
 
diff --git a/xen/arch/arm/include/asm/setup.h b/xen/arch/arm/include/asm/setup.h
index c34179da93..ea2e8503dc 100644
--- a/xen/arch/arm/include/asm/setup.h
+++ b/xen/arch/arm/include/asm/setup.h
@@ -49,6 +49,12 @@ enum membank_type {
     MEMBANK_FDT_RESVMEM,
 };
 
+enum region_type {
+    MEMORY,
+    RESERVED_MEMORY,
+    STATIC_SHARED_MEMORY
+};
+
 /* Indicates the maximum number of characters(\0 included) for shm_id */
 #define MAX_SHM_ID_LENGTH 16
 
@@ -72,6 +78,7 @@ struct membanks {
     __struct_group(membanks_hdr, common, ,
         unsigned int nr_banks;
         unsigned int max_banks;
+        enum region_type type;
     );
     struct membank bank[];
 };
@@ -137,13 +144,17 @@ struct bootinfo {
 };
 
 #ifdef CONFIG_ACPI
-#define BOOTINFO_ACPI_INIT .acpi.common.max_banks = NR_MEM_BANKS,
+#define BOOTINFO_ACPI_INIT                          \
+    .acpi.common.max_banks = NR_MEM_BANKS,          \
+    .acpi.common.type = MEMORY,
 #else
 #define BOOTINFO_ACPI_INIT
 #endif
 
 #ifdef CONFIG_STATIC_SHM
-#define BOOTINFO_SHMEM_INIT .shmem.common.max_banks = NR_SHMEM_BANKS,
+#define BOOTINFO_SHMEM_INIT                         \
+    .shmem.common.max_banks = NR_SHMEM_BANKS,       \
+    .shmem.common.type = STATIC_SHARED_MEMORY,
 #else
 #define BOOTINFO_SHMEM_INIT
 #endif
@@ -151,7 +162,9 @@ struct bootinfo {
 #define BOOTINFO_INIT                               \
 {                                                   \
     .mem.common.max_banks = NR_MEM_BANKS,           \
+    .mem.common.type = MEMORY,                      \
     .reserved_mem.common.max_banks = NR_MEM_BANKS,  \
+    .reserved_mem.common.type = RESERVED_MEMORY,    \
     BOOTINFO_ACPI_INIT                              \
     BOOTINFO_SHMEM_INIT                             \
 }
@@ -223,7 +236,8 @@ void fw_unreserved_regions(paddr_t s, paddr_t e,
 size_t boot_fdt_info(const void *fdt, paddr_t paddr);
 const char *boot_fdt_cmdline(const void *fdt);
 
-bool check_reserved_regions_overlap(paddr_t region_start, paddr_t region_size);
+bool check_reserved_regions_overlap(paddr_t region_start, paddr_t region_size,
+                                    bool allow_memreserve_overlap);
 
 struct bootmodule *add_boot_module(bootmodule_kind kind,
                                    paddr_t start, paddr_t size, bool domU);
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 0c2fdaceaf..d0533cb715 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -268,7 +268,8 @@ static void __init dt_unreserved_regions(paddr_t s, paddr_t 
e,
  */
 static bool __init meminfo_overlap_check(const struct membanks *mem,
                                          paddr_t region_start,
-                                         paddr_t region_size)
+                                         paddr_t region_size,
+                                         bool allow_memreserve_overlap)
 {
     paddr_t bank_start = INVALID_PADDR, bank_end = 0;
     paddr_t region_end = region_start + region_size;
@@ -282,12 +283,23 @@ static bool __init meminfo_overlap_check(const struct 
membanks *mem,
         if ( INVALID_PADDR == bank_start || region_end <= bank_start ||
              region_start >= bank_end )
             continue;
-        else
-        {
-            printk("Region: [%#"PRIpaddr", %#"PRIpaddr") overlapping with 
bank[%u]: [%#"PRIpaddr", %#"PRIpaddr")\n",
-                   region_start, region_end, i, bank_start, bank_end);
-            return true;
-        }
+
+        /*
+         * If allow_memreserve_overlap is set, this check allows a region to be
+         * included in a MEMBANK_FDT_RESVMEM bank, but struct membanks *mem of
+         * type STATIC_SHARED_MEMORY don't set the bank[].type field because
+         * that is declared in a union with a field that is instead used,
+         * in any case this restriction is ok since STATIC_SHARED_MEMORY banks
+         * are not meant to clash with FDT /memreserve/ ranges.
+         */
+        if ( allow_memreserve_overlap && mem->type != STATIC_SHARED_MEMORY &&
+             region_start >= bank_start && region_end <= bank_end &&
+             mem->bank[i].type == MEMBANK_FDT_RESVMEM )
+            continue;
+
+        printk("Region: [%#"PRIpaddr", %#"PRIpaddr") overlapping with 
bank[%u]: [%#"PRIpaddr", %#"PRIpaddr")\n",
+                region_start, region_end, i, bank_start, bank_end);
+        return true;
     }
 
     return false;
@@ -340,7 +352,8 @@ void __init fw_unreserved_regions(paddr_t s, paddr_t e,
  * existing reserved memory regions, otherwise false.
  */
 bool __init check_reserved_regions_overlap(paddr_t region_start,
-                                           paddr_t region_size)
+                                           paddr_t region_size,
+                                           bool allow_memreserve_overlap)
 {
     const struct membanks *mem_banks[] = {
         bootinfo_get_reserved_mem(),
@@ -359,7 +372,8 @@ bool __init check_reserved_regions_overlap(paddr_t 
region_start,
      * shared memory banks (when static shared memory feature is enabled)
      */
     for ( i = 0; i < ARRAY_SIZE(mem_banks); i++ )
-        if ( meminfo_overlap_check(mem_banks[i], region_start, region_size) )
+        if ( meminfo_overlap_check(mem_banks[i], region_start, region_size,
+                                   allow_memreserve_overlap) )
             return true;
 
     /* Check if input region is overlapping with bootmodules */
@@ -385,7 +399,12 @@ struct bootmodule __init *add_boot_module(bootmodule_kind 
kind,
         return NULL;
     }
 
-    if ( check_reserved_regions_overlap(start, size) )
+    /*
+     * u-boot adds boot module such as ramdisk to the /memreserve/, since these
+     * ranges are saved in reserved_mem at this stage, allow an eventual exact
+     * match with MEMBANK_FDT_RESVMEM banks.
+     */
+    if ( check_reserved_regions_overlap(start, size, true) )
         return NULL;
 
     for ( i = 0 ; i < mods->nr_mods ; i++ )
diff --git a/xen/arch/arm/static-shmem.c b/xen/arch/arm/static-shmem.c
index aa80756c3c..66088a4267 100644
--- a/xen/arch/arm/static-shmem.c
+++ b/xen/arch/arm/static-shmem.c
@@ -696,7 +696,7 @@ int __init process_shm_node(const void *fdt, int node, 
uint32_t address_cells,
         if (i < mem->max_banks)
         {
             if ( (paddr != INVALID_PADDR) &&
-                 check_reserved_regions_overlap(paddr, size) )
+                 check_reserved_regions_overlap(paddr, size, false) )
                 return -EINVAL;
 
             /* Static shared memory shall be reserved from any other use. */
--
generated by git-patchbot for /home/xen/git/xen.git#stable-4.19



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.