efi: x86: Move EFI runtime map sysfs code to arch/x86
authorArd Biesheuvel <ardb@kernel.org>
Mon, 7 Nov 2022 08:17:16 +0000 (09:17 +0100)
committerArd Biesheuvel <ardb@kernel.org>
Fri, 18 Nov 2022 08:14:09 +0000 (09:14 +0100)
The EFI runtime map code is only wired up on x86, which is the only
architecture that has a need for it in its implementation of kexec.

So let's move this code under arch/x86 and drop all references to it
from generic code. To ensure that the efi_runtime_map_init() is invoked
at the appropriate time use a 'sync' subsys_initcall() that will be
called right after the EFI initcall made from generic code where the
original invocation of efi_runtime_map_init() resided.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Dave Young <dyoung@redhat.com>
arch/x86/Kconfig
arch/x86/include/asm/efi.h
arch/x86/platform/efi/Makefile
arch/x86/platform/efi/runtime-map.c [new file with mode: 0644]
drivers/firmware/efi/Kconfig
drivers/firmware/efi/Makefile
drivers/firmware/efi/efi.c
drivers/firmware/efi/runtime-map.c [deleted file]
include/linux/efi.h

index e2f89a7495d28fdf240edcede692fe2133f42471..eaf84759482e8bd73ca0f4b5f06150451efd5221 100644 (file)
@@ -2014,6 +2014,17 @@ config EFI_MAX_FAKE_MEM
          Ranges can be set up to this value using comma-separated list.
          The default value is 8.
 
+config EFI_RUNTIME_MAP
+       bool "Export EFI runtime maps to sysfs" if EXPERT
+       depends on EFI
+       default KEXEC_CORE
+       help
+         Export EFI runtime memory regions to /sys/firmware/efi/runtime-map.
+         That memory map is required by the 2nd kernel to set up EFI virtual
+         mappings after kexec, but can also be used for debugging purposes.
+
+         See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map.
+
 source "kernel/Kconfig.hz"
 
 config KEXEC
index f29d1450edf4b50534664c23d38d62148f9a6ecf..a63154e049d789545b1099d4f64d5e0836071a59 100644 (file)
@@ -432,4 +432,26 @@ extern void __init efi_memmap_insert(struct efi_memory_map *old_memmap,
 #define arch_ima_efi_boot_mode \
        ({ extern struct boot_params boot_params; boot_params.secure_boot; })
 
+#ifdef CONFIG_EFI_RUNTIME_MAP
+int efi_get_runtime_map_size(void);
+int efi_get_runtime_map_desc_size(void);
+int efi_runtime_map_copy(void *buf, size_t bufsz);
+#else
+static inline int efi_get_runtime_map_size(void)
+{
+       return 0;
+}
+
+static inline int efi_get_runtime_map_desc_size(void)
+{
+       return 0;
+}
+
+static inline int efi_runtime_map_copy(void *buf, size_t bufsz)
+{
+       return 0;
+}
+
+#endif
+
 #endif /* _ASM_X86_EFI_H */
index ed5502a5185d4eadd0a456d7f4b63b997bcf7537..543df9a1379d121c2c84124a14450567f9450d05 100644 (file)
@@ -6,3 +6,4 @@ obj-$(CONFIG_EFI)               += memmap.o quirks.o efi.o efi_$(BITS).o \
                                   efi_stub_$(BITS).o
 obj-$(CONFIG_EFI_MIXED)                += efi_thunk_$(BITS).o
 obj-$(CONFIG_EFI_FAKE_MEMMAP)  += fake_mem.o
+obj-$(CONFIG_EFI_RUNTIME_MAP)  += runtime-map.o
diff --git a/arch/x86/platform/efi/runtime-map.c b/arch/x86/platform/efi/runtime-map.c
new file mode 100644 (file)
index 0000000..bbee682
--- /dev/null
@@ -0,0 +1,194 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2013 Red Hat, Inc., Dave Young <dyoung@redhat.com>
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/efi.h>
+#include <linux/slab.h>
+
+#include <asm/efi.h>
+#include <asm/setup.h>
+
+struct efi_runtime_map_entry {
+       efi_memory_desc_t md;
+       struct kobject kobj;   /* kobject for each entry */
+};
+
+static struct efi_runtime_map_entry **map_entries;
+
+struct map_attribute {
+       struct attribute attr;
+       ssize_t (*show)(struct efi_runtime_map_entry *entry, char *buf);
+};
+
+static inline struct map_attribute *to_map_attr(struct attribute *attr)
+{
+       return container_of(attr, struct map_attribute, attr);
+}
+
+static ssize_t type_show(struct efi_runtime_map_entry *entry, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "0x%x\n", entry->md.type);
+}
+
+#define EFI_RUNTIME_FIELD(var) entry->md.var
+
+#define EFI_RUNTIME_U64_ATTR_SHOW(name) \
+static ssize_t name##_show(struct efi_runtime_map_entry *entry, char *buf) \
+{ \
+       return snprintf(buf, PAGE_SIZE, "0x%llx\n", EFI_RUNTIME_FIELD(name)); \
+}
+
+EFI_RUNTIME_U64_ATTR_SHOW(phys_addr);
+EFI_RUNTIME_U64_ATTR_SHOW(virt_addr);
+EFI_RUNTIME_U64_ATTR_SHOW(num_pages);
+EFI_RUNTIME_U64_ATTR_SHOW(attribute);
+
+static inline struct efi_runtime_map_entry *to_map_entry(struct kobject *kobj)
+{
+       return container_of(kobj, struct efi_runtime_map_entry, kobj);
+}
+
+static ssize_t map_attr_show(struct kobject *kobj, struct attribute *attr,
+                             char *buf)
+{
+       struct efi_runtime_map_entry *entry = to_map_entry(kobj);
+       struct map_attribute *map_attr = to_map_attr(attr);
+
+       return map_attr->show(entry, buf);
+}
+
+static struct map_attribute map_type_attr = __ATTR_RO_MODE(type, 0400);
+static struct map_attribute map_phys_addr_attr = __ATTR_RO_MODE(phys_addr, 0400);
+static struct map_attribute map_virt_addr_attr = __ATTR_RO_MODE(virt_addr, 0400);
+static struct map_attribute map_num_pages_attr = __ATTR_RO_MODE(num_pages, 0400);
+static struct map_attribute map_attribute_attr = __ATTR_RO_MODE(attribute, 0400);
+
+/*
+ * These are default attributes that are added for every memmap entry.
+ */
+static struct attribute *def_attrs[] = {
+       &map_type_attr.attr,
+       &map_phys_addr_attr.attr,
+       &map_virt_addr_attr.attr,
+       &map_num_pages_attr.attr,
+       &map_attribute_attr.attr,
+       NULL
+};
+ATTRIBUTE_GROUPS(def);
+
+static const struct sysfs_ops map_attr_ops = {
+       .show = map_attr_show,
+};
+
+static void map_release(struct kobject *kobj)
+{
+       struct efi_runtime_map_entry *entry;
+
+       entry = to_map_entry(kobj);
+       kfree(entry);
+}
+
+static struct kobj_type __refdata map_ktype = {
+       .sysfs_ops      = &map_attr_ops,
+       .default_groups = def_groups,
+       .release        = map_release,
+};
+
+static struct kset *map_kset;
+
+static struct efi_runtime_map_entry *
+add_sysfs_runtime_map_entry(struct kobject *kobj, int nr,
+                           efi_memory_desc_t *md)
+{
+       int ret;
+       struct efi_runtime_map_entry *entry;
+
+       if (!map_kset) {
+               map_kset = kset_create_and_add("runtime-map", NULL, kobj);
+               if (!map_kset)
+                       return ERR_PTR(-ENOMEM);
+       }
+
+       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+       if (!entry) {
+               kset_unregister(map_kset);
+               map_kset = NULL;
+               return ERR_PTR(-ENOMEM);
+       }
+
+       memcpy(&entry->md, md, sizeof(efi_memory_desc_t));
+
+       kobject_init(&entry->kobj, &map_ktype);
+       entry->kobj.kset = map_kset;
+       ret = kobject_add(&entry->kobj, NULL, "%d", nr);
+       if (ret) {
+               kobject_put(&entry->kobj);
+               kset_unregister(map_kset);
+               map_kset = NULL;
+               return ERR_PTR(ret);
+       }
+
+       return entry;
+}
+
+int efi_get_runtime_map_size(void)
+{
+       return efi.memmap.nr_map * efi.memmap.desc_size;
+}
+
+int efi_get_runtime_map_desc_size(void)
+{
+       return efi.memmap.desc_size;
+}
+
+int efi_runtime_map_copy(void *buf, size_t bufsz)
+{
+       size_t sz = efi_get_runtime_map_size();
+
+       if (sz > bufsz)
+               sz = bufsz;
+
+       memcpy(buf, efi.memmap.map, sz);
+       return 0;
+}
+
+static int __init efi_runtime_map_init(void)
+{
+       int i, j, ret = 0;
+       struct efi_runtime_map_entry *entry;
+       efi_memory_desc_t *md;
+
+       if (!efi_enabled(EFI_MEMMAP) || !efi_kobj)
+               return 0;
+
+       map_entries = kcalloc(efi.memmap.nr_map, sizeof(entry), GFP_KERNEL);
+       if (!map_entries) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       i = 0;
+       for_each_efi_memory_desc(md) {
+               entry = add_sysfs_runtime_map_entry(efi_kobj, i, md);
+               if (IS_ERR(entry)) {
+                       ret = PTR_ERR(entry);
+                       goto out_add_entry;
+               }
+               *(map_entries + i++) = entry;
+       }
+
+       return 0;
+out_add_entry:
+       for (j = i - 1; j >= 0; j--) {
+               entry = *(map_entries + j);
+               kobject_put(&entry->kobj);
+       }
+out:
+       return ret;
+}
+subsys_initcall_sync(efi_runtime_map_init);
index 552512f211a1f5e7535a5de83e24a8f1739e872f..08ed88e49ea307b0d1a9b81b8f29445108fd4d87 100644 (file)
@@ -26,17 +26,6 @@ config EFI_VARS_PSTORE_DEFAULT_DISABLE
          backend for pstore by default. This setting can be overridden
          using the efivars module's pstore_disable parameter.
 
-config EFI_RUNTIME_MAP
-       bool "Export EFI runtime maps to sysfs" if EXPERT
-       depends on X86 && EFI
-       default KEXEC_CORE
-       help
-         Export EFI runtime memory regions to /sys/firmware/efi/runtime-map.
-         That memory map is required by the 2nd kernel to set up EFI virtual
-         mappings after kexec, but can also be used for debugging purposes.
-
-         See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map.
-
 config EFI_SOFT_RESERVE
        bool "Reserve EFI Specific Purpose Memory"
        depends on EFI && EFI_STUB && ACPI_HMAT
index 8e4f0d5b26e542c36819c1cf69c63597183abcea..7d3b08cc8c5a28134b5db3c5f6ae3999555c9179 100644 (file)
@@ -20,7 +20,6 @@ obj-$(CONFIG_EFI_PARAMS_FROM_FDT)     += fdtparams.o
 obj-$(CONFIG_EFI_ESRT)                 += esrt.o
 obj-$(CONFIG_EFI_VARS_PSTORE)          += efi-pstore.o
 obj-$(CONFIG_UEFI_CPER)                        += cper.o
-obj-$(CONFIG_EFI_RUNTIME_MAP)          += runtime-map.o
 obj-$(CONFIG_EFI_RUNTIME_WRAPPERS)     += runtime-wrappers.o
 subdir-$(CONFIG_EFI_STUB)              += libstub
 obj-$(CONFIG_EFI_BOOTLOADER_CONTROL)   += efibc.o
index 951a42d27cf431cc5f639103c0dc69e94f065300..dfdbbc702da0cc720f8a65cfeec2e7a45214d2da 100644 (file)
@@ -396,10 +396,6 @@ static int __init efisubsys_init(void)
                goto err_unregister;
        }
 
-       error = efi_runtime_map_init(efi_kobj);
-       if (error)
-               goto err_remove_group;
-
        /* and the standard mountpoint for efivarfs */
        error = sysfs_create_mount_point(efi_kobj, "efivars");
        if (error) {
@@ -425,6 +421,7 @@ err_unregister:
                generic_ops_unregister();
 err_put:
        kobject_put(efi_kobj);
+       efi_kobj = NULL;
        destroy_workqueue(efi_rts_wq);
        return error;
 }
diff --git a/drivers/firmware/efi/runtime-map.c b/drivers/firmware/efi/runtime-map.c
deleted file mode 100644 (file)
index 92a3d45..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * linux/drivers/efi/runtime-map.c
- * Copyright (C) 2013 Red Hat, Inc., Dave Young <dyoung@redhat.com>
- */
-
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/efi.h>
-#include <linux/slab.h>
-
-#include <asm/setup.h>
-
-struct efi_runtime_map_entry {
-       efi_memory_desc_t md;
-       struct kobject kobj;   /* kobject for each entry */
-};
-
-static struct efi_runtime_map_entry **map_entries;
-
-struct map_attribute {
-       struct attribute attr;
-       ssize_t (*show)(struct efi_runtime_map_entry *entry, char *buf);
-};
-
-static inline struct map_attribute *to_map_attr(struct attribute *attr)
-{
-       return container_of(attr, struct map_attribute, attr);
-}
-
-static ssize_t type_show(struct efi_runtime_map_entry *entry, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "0x%x\n", entry->md.type);
-}
-
-#define EFI_RUNTIME_FIELD(var) entry->md.var
-
-#define EFI_RUNTIME_U64_ATTR_SHOW(name) \
-static ssize_t name##_show(struct efi_runtime_map_entry *entry, char *buf) \
-{ \
-       return snprintf(buf, PAGE_SIZE, "0x%llx\n", EFI_RUNTIME_FIELD(name)); \
-}
-
-EFI_RUNTIME_U64_ATTR_SHOW(phys_addr);
-EFI_RUNTIME_U64_ATTR_SHOW(virt_addr);
-EFI_RUNTIME_U64_ATTR_SHOW(num_pages);
-EFI_RUNTIME_U64_ATTR_SHOW(attribute);
-
-static inline struct efi_runtime_map_entry *to_map_entry(struct kobject *kobj)
-{
-       return container_of(kobj, struct efi_runtime_map_entry, kobj);
-}
-
-static ssize_t map_attr_show(struct kobject *kobj, struct attribute *attr,
-                             char *buf)
-{
-       struct efi_runtime_map_entry *entry = to_map_entry(kobj);
-       struct map_attribute *map_attr = to_map_attr(attr);
-
-       return map_attr->show(entry, buf);
-}
-
-static struct map_attribute map_type_attr = __ATTR_RO_MODE(type, 0400);
-static struct map_attribute map_phys_addr_attr = __ATTR_RO_MODE(phys_addr, 0400);
-static struct map_attribute map_virt_addr_attr = __ATTR_RO_MODE(virt_addr, 0400);
-static struct map_attribute map_num_pages_attr = __ATTR_RO_MODE(num_pages, 0400);
-static struct map_attribute map_attribute_attr = __ATTR_RO_MODE(attribute, 0400);
-
-/*
- * These are default attributes that are added for every memmap entry.
- */
-static struct attribute *def_attrs[] = {
-       &map_type_attr.attr,
-       &map_phys_addr_attr.attr,
-       &map_virt_addr_attr.attr,
-       &map_num_pages_attr.attr,
-       &map_attribute_attr.attr,
-       NULL
-};
-ATTRIBUTE_GROUPS(def);
-
-static const struct sysfs_ops map_attr_ops = {
-       .show = map_attr_show,
-};
-
-static void map_release(struct kobject *kobj)
-{
-       struct efi_runtime_map_entry *entry;
-
-       entry = to_map_entry(kobj);
-       kfree(entry);
-}
-
-static struct kobj_type __refdata map_ktype = {
-       .sysfs_ops      = &map_attr_ops,
-       .default_groups = def_groups,
-       .release        = map_release,
-};
-
-static struct kset *map_kset;
-
-static struct efi_runtime_map_entry *
-add_sysfs_runtime_map_entry(struct kobject *kobj, int nr,
-                           efi_memory_desc_t *md)
-{
-       int ret;
-       struct efi_runtime_map_entry *entry;
-
-       if (!map_kset) {
-               map_kset = kset_create_and_add("runtime-map", NULL, kobj);
-               if (!map_kset)
-                       return ERR_PTR(-ENOMEM);
-       }
-
-       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
-       if (!entry) {
-               kset_unregister(map_kset);
-               map_kset = NULL;
-               return ERR_PTR(-ENOMEM);
-       }
-
-       memcpy(&entry->md, md, sizeof(efi_memory_desc_t));
-
-       kobject_init(&entry->kobj, &map_ktype);
-       entry->kobj.kset = map_kset;
-       ret = kobject_add(&entry->kobj, NULL, "%d", nr);
-       if (ret) {
-               kobject_put(&entry->kobj);
-               kset_unregister(map_kset);
-               map_kset = NULL;
-               return ERR_PTR(ret);
-       }
-
-       return entry;
-}
-
-int efi_get_runtime_map_size(void)
-{
-       return efi.memmap.nr_map * efi.memmap.desc_size;
-}
-
-int efi_get_runtime_map_desc_size(void)
-{
-       return efi.memmap.desc_size;
-}
-
-int efi_runtime_map_copy(void *buf, size_t bufsz)
-{
-       size_t sz = efi_get_runtime_map_size();
-
-       if (sz > bufsz)
-               sz = bufsz;
-
-       memcpy(buf, efi.memmap.map, sz);
-       return 0;
-}
-
-int __init efi_runtime_map_init(struct kobject *efi_kobj)
-{
-       int i, j, ret = 0;
-       struct efi_runtime_map_entry *entry;
-       efi_memory_desc_t *md;
-
-       if (!efi_enabled(EFI_MEMMAP))
-               return 0;
-
-       map_entries = kcalloc(efi.memmap.nr_map, sizeof(entry), GFP_KERNEL);
-       if (!map_entries) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       i = 0;
-       for_each_efi_memory_desc(md) {
-               entry = add_sysfs_runtime_map_entry(efi_kobj, i, md);
-               if (IS_ERR(entry)) {
-                       ret = PTR_ERR(entry);
-                       goto out_add_entry;
-               }
-               *(map_entries + i++) = entry;
-       }
-
-       return 0;
-out_add_entry:
-       for (j = i - 1; j >= 0; j--) {
-               entry = *(map_entries + j);
-               kobject_put(&entry->kobj);
-       }
-out:
-       return ret;
-}
index 6a0bdef8375d319b8b3c54877d2b5036c5886ab2..400edf77bb12098242bc274742c16088decc0f59 100644 (file)
@@ -1089,34 +1089,6 @@ extern int efi_capsule_update(efi_capsule_header_t *capsule,
 static inline bool efi_capsule_pending(int *reset_type) { return false; }
 #endif
 
-#ifdef CONFIG_EFI_RUNTIME_MAP
-int efi_runtime_map_init(struct kobject *);
-int efi_get_runtime_map_size(void);
-int efi_get_runtime_map_desc_size(void);
-int efi_runtime_map_copy(void *buf, size_t bufsz);
-#else
-static inline int efi_runtime_map_init(struct kobject *kobj)
-{
-       return 0;
-}
-
-static inline int efi_get_runtime_map_size(void)
-{
-       return 0;
-}
-
-static inline int efi_get_runtime_map_desc_size(void)
-{
-       return 0;
-}
-
-static inline int efi_runtime_map_copy(void *buf, size_t bufsz)
-{
-       return 0;
-}
-
-#endif
-
 #ifdef CONFIG_EFI
 extern bool efi_runtime_disabled(void);
 #else