]> git.ipfire.org Git - people/ms/linux.git/commitdiff
x86/boot: Add setup_indirect support in early_memremap_is_setup_data()
authorRoss Philipson <ross.philipson@oracle.com>
Thu, 24 Feb 2022 02:07:36 +0000 (21:07 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 16 Mar 2022 13:23:45 +0000 (14:23 +0100)
commit 445c1470b6ef96440e7cfc42dfc160f5004fd149 upstream.

The x86 boot documentation describes the setup_indirect structures and
how they are used. Only one of the two functions in ioremap.c that needed
to be modified to be aware of the introduction of setup_indirect
functionality was updated. Adds comparable support to the other function
where it was missing.

Fixes: b3c72fc9a78e ("x86/boot: Introduce setup_indirect")
Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/1645668456-22036-3-git-send-email-ross.philipson@oracle.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/x86/mm/ioremap.c

index 5831cb7751a3c1e2b3fa12296e8d7e0e01b895aa..7ce9b8dd875773bc480a7cbd26bb1ebfa4c97ccd 100644 (file)
@@ -675,22 +675,51 @@ static bool memremap_is_setup_data(resource_size_t phys_addr,
 static bool __init early_memremap_is_setup_data(resource_size_t phys_addr,
                                                unsigned long size)
 {
+       struct setup_indirect *indirect;
        struct setup_data *data;
        u64 paddr, paddr_next;
 
        paddr = boot_params.hdr.setup_data;
        while (paddr) {
-               unsigned int len;
+               unsigned int len, size;
 
                if (phys_addr == paddr)
                        return true;
 
                data = early_memremap_decrypted(paddr, sizeof(*data));
+               if (!data) {
+                       pr_warn("failed to early memremap setup_data entry\n");
+                       return false;
+               }
+
+               size = sizeof(*data);
 
                paddr_next = data->next;
                len = data->len;
 
-               early_memunmap(data, sizeof(*data));
+               if ((phys_addr > paddr) && (phys_addr < (paddr + len))) {
+                       early_memunmap(data, sizeof(*data));
+                       return true;
+               }
+
+               if (data->type == SETUP_INDIRECT) {
+                       size += len;
+                       early_memunmap(data, sizeof(*data));
+                       data = early_memremap_decrypted(paddr, size);
+                       if (!data) {
+                               pr_warn("failed to early memremap indirect setup_data\n");
+                               return false;
+                       }
+
+                       indirect = (struct setup_indirect *)data->data;
+
+                       if (indirect->type != SETUP_INDIRECT) {
+                               paddr = indirect->addr;
+                               len = indirect->len;
+                       }
+               }
+
+               early_memunmap(data, size);
 
                if ((phys_addr > paddr) && (phys_addr < (paddr + len)))
                        return true;