]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
crash: add a new kexec flag for hotplug support
authorSourabh Jain <sourabhjain@linux.ibm.com>
Tue, 26 Mar 2024 05:54:09 +0000 (11:24 +0530)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 23 Apr 2024 04:59:01 +0000 (14:59 +1000)
Commit a72bbec70da2 ("crash: hotplug support for kexec_load()")
introduced a new kexec flag, `KEXEC_UPDATE_ELFCOREHDR`. Kexec tool uses
this flag to indicate to the kernel that it is safe to modify the
elfcorehdr of the kdump image loaded using the kexec_load system call.

However, it is possible that architectures may need to update kexec
segments other then elfcorehdr. For example, FDT (Flatten Device Tree)
on PowerPC. Introducing a new kexec flag for every new kexec segment
may not be a good solution. Hence, a generic kexec flag bit,
`KEXEC_CRASH_HOTPLUG_SUPPORT`, is introduced to share the CPU/Memory
hotplug support intent between the kexec tool and the kernel for the
kexec_load system call.

Now we have two kexec flags that enables crash hotplug support for
kexec_load system call. First is KEXEC_UPDATE_ELFCOREHDR (only used in
x86), and second is KEXEC_CRASH_HOTPLUG_SUPPORT (for all architectures).

To simplify the process of finding and reporting the crash hotplug
support the following changes are introduced.

1. Define arch specific function to process the kexec flags and
   determine crash hotplug support

2. Rename the @update_elfcorehdr member of struct kimage to
   @hotplug_support and populate it for both kexec_load and
   kexec_file_load syscalls, because architecture can update more than
   one kexec segment

3. Let generic function crash_check_hotplug_support report hotplug
   support for loaded kdump image based on value of @hotplug_support

To bring the x86 crash hotplug support in line with the above points,
the following changes have been made:

- Introduce the arch_crash_hotplug_support function to process kexec
  flags and determine crash hotplug support

- Remove the arch_crash_hotplug_[cpu|memory]_support functions

Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Acked-by: Baoquan He <bhe@redhat.com>
Acked-by: Hari Bathini <hbathini@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20240326055413.186534-3-sourabhjain@linux.ibm.com
arch/x86/include/asm/kexec.h
arch/x86/kernel/crash.c
drivers/base/cpu.c
drivers/base/memory.c
include/linux/crash_core.h
include/linux/kexec.h
include/uapi/linux/kexec.h
kernel/crash_core.c
kernel/kexec.c
kernel/kexec_file.c

index cb1320ebbc2353a2ae885b4519e8de3652c32226..ae5482a2f0ca0e0a68f127f98184f620b1df380e 100644 (file)
@@ -210,15 +210,8 @@ extern void kdump_nmi_shootdown_cpus(void);
 void arch_crash_handle_hotplug_event(struct kimage *image, void *arg);
 #define arch_crash_handle_hotplug_event arch_crash_handle_hotplug_event
 
-#ifdef CONFIG_HOTPLUG_CPU
-int arch_crash_hotplug_cpu_support(void);
-#define crash_hotplug_cpu_support arch_crash_hotplug_cpu_support
-#endif
-
-#ifdef CONFIG_MEMORY_HOTPLUG
-int arch_crash_hotplug_memory_support(void);
-#define crash_hotplug_memory_support arch_crash_hotplug_memory_support
-#endif
+int arch_crash_hotplug_support(struct kimage *image, unsigned long kexec_flags);
+#define arch_crash_hotplug_support arch_crash_hotplug_support
 
 unsigned int arch_crash_get_elfcorehdr_size(void);
 #define crash_get_elfcorehdr_size arch_crash_get_elfcorehdr_size
index 2a682fe8635281b0e05b94049cdb50d783a7c6eb..f06501445cd9818572a525f054bd83d86ce9a0e7 100644 (file)
@@ -402,20 +402,26 @@ int crash_load_segments(struct kimage *image)
 #undef pr_fmt
 #define pr_fmt(fmt) "crash hp: " fmt
 
-/* These functions provide the value for the sysfs crash_hotplug nodes */
-#ifdef CONFIG_HOTPLUG_CPU
-int arch_crash_hotplug_cpu_support(void)
+int arch_crash_hotplug_support(struct kimage *image, unsigned long kexec_flags)
 {
-       return crash_check_update_elfcorehdr();
-}
-#endif
 
-#ifdef CONFIG_MEMORY_HOTPLUG
-int arch_crash_hotplug_memory_support(void)
-{
-       return crash_check_update_elfcorehdr();
-}
+#ifdef CONFIG_KEXEC_FILE
+       if (image->file_mode)
+               return 1;
 #endif
+       /*
+        * Initially, crash hotplug support for kexec_load was added
+        * with the KEXEC_UPDATE_ELFCOREHDR flag. Later, this
+        * functionality was expanded to accommodate multiple kexec
+        * segment updates, leading to the introduction of the
+        * KEXEC_CRASH_HOTPLUG_SUPPORT kexec flag bit. Consequently,
+        * when the kexec tool sends either of these flags, it indicates
+        * that the required kexec segment (elfcorehdr) is excluded from
+        * the SHA calculation.
+        */
+       return (kexec_flags & KEXEC_UPDATE_ELFCOREHDR ||
+               kexec_flags & KEXEC_CRASH_HOTPLUG_SUPPORT);
+}
 
 unsigned int arch_crash_get_elfcorehdr_size(void)
 {
index 56fba44ba391adb432ca0b85e552b3ee95ddbad6..c61ecb0c2ae2900a641c74b358d076357b36131d 100644 (file)
@@ -306,7 +306,7 @@ static ssize_t crash_hotplug_show(struct device *dev,
                                     struct device_attribute *attr,
                                     char *buf)
 {
-       return sysfs_emit(buf, "%d\n", crash_hotplug_cpu_support());
+       return sysfs_emit(buf, "%d\n", crash_check_hotplug_support());
 }
 static DEVICE_ATTR_ADMIN_RO(crash_hotplug);
 #endif
index c0436f46cfb7012ee651cec0c1f2b7af66570c0b..67858eeb92ed286d7e141c9a10abba4e18891f63 100644 (file)
@@ -535,7 +535,7 @@ static DEVICE_ATTR_RW(auto_online_blocks);
 static ssize_t crash_hotplug_show(struct device *dev,
                                       struct device_attribute *attr, char *buf)
 {
-       return sysfs_emit(buf, "%d\n", crash_hotplug_memory_support());
+       return sysfs_emit(buf, "%d\n", crash_check_hotplug_support());
 }
 static DEVICE_ATTR_RO(crash_hotplug);
 #endif
index 647e928efee8264c6856c2c0d3ea1517f943e1dc..44305336314eb45c15ceea452f9acbc0b26f2a86 100644 (file)
@@ -40,14 +40,13 @@ static inline void arch_kexec_unprotect_crashkres(void) { }
 static inline void arch_crash_handle_hotplug_event(struct kimage *image, void *arg) { }
 #endif
 
-int crash_check_update_elfcorehdr(void);
+int crash_check_hotplug_support(void);
 
-#ifndef crash_hotplug_cpu_support
-static inline int crash_hotplug_cpu_support(void) { return 0; }
-#endif
-
-#ifndef crash_hotplug_memory_support
-static inline int crash_hotplug_memory_support(void) { return 0; }
+#ifndef arch_crash_hotplug_support
+static inline int arch_crash_hotplug_support(struct kimage *image, unsigned long kexec_flags)
+{
+       return 0;
+}
 #endif
 
 #ifndef crash_get_elfcorehdr_size
index 060835bb82d52f0fff68b9bf7a8fd50f27ae5d25..5b93a5767413a561302331740e217e4819595247 100644 (file)
@@ -319,8 +319,10 @@ struct kimage {
        /* If set, we are using file mode kexec syscall */
        unsigned int file_mode:1;
 #ifdef CONFIG_CRASH_HOTPLUG
-       /* If set, allow changes to elfcorehdr of kexec_load'd image */
-       unsigned int update_elfcorehdr:1;
+       /* If set, it is safe to update kexec segments that are
+        * excluded from SHA calculation.
+        */
+       unsigned int hotplug_support:1;
 #endif
 
 #ifdef ARCH_HAS_KIMAGE_ARCH
@@ -391,9 +393,10 @@ bool kexec_load_permitted(int kexec_image_type);
 
 /* List of defined/legal kexec flags */
 #ifndef CONFIG_KEXEC_JUMP
-#define KEXEC_FLAGS    (KEXEC_ON_CRASH | KEXEC_UPDATE_ELFCOREHDR)
+#define KEXEC_FLAGS    (KEXEC_ON_CRASH | KEXEC_UPDATE_ELFCOREHDR | KEXEC_CRASH_HOTPLUG_SUPPORT)
 #else
-#define KEXEC_FLAGS    (KEXEC_ON_CRASH | KEXEC_PRESERVE_CONTEXT | KEXEC_UPDATE_ELFCOREHDR)
+#define KEXEC_FLAGS    (KEXEC_ON_CRASH | KEXEC_PRESERVE_CONTEXT | KEXEC_UPDATE_ELFCOREHDR | \
+                       KEXEC_CRASH_HOTPLUG_SUPPORT)
 #endif
 
 /* List of defined/legal kexec file flags */
index c17bb096ea68576026666f7c4bac07c0c5612501..5ae1741ea8ea07b29ce483f54299fb5b481b7dbb 100644 (file)
@@ -13,6 +13,7 @@
 #define KEXEC_ON_CRASH         0x00000001
 #define KEXEC_PRESERVE_CONTEXT 0x00000002
 #define KEXEC_UPDATE_ELFCOREHDR        0x00000004
+#define KEXEC_CRASH_HOTPLUG_SUPPORT 0x00000008
 #define KEXEC_ARCH_MASK                0xffff0000
 
 /*
index 70fa8111a9d6f664914332a53c04e5899aa85e1f..394db3ebe8353543f1dc7ffdba7fe2c6f06a9271 100644 (file)
@@ -493,10 +493,10 @@ static DEFINE_MUTEX(__crash_hotplug_lock);
 
 /*
  * This routine utilized when the crash_hotplug sysfs node is read.
- * It reflects the kernel's ability/permission to update the crash
- * elfcorehdr directly.
+ * It reflects the kernel's ability/permission to update the kdump
+ * image directly.
  */
-int crash_check_update_elfcorehdr(void)
+int crash_check_hotplug_support(void)
 {
        int rc = 0;
 
@@ -508,10 +508,7 @@ int crash_check_update_elfcorehdr(void)
                return 0;
        }
        if (kexec_crash_image) {
-               if (kexec_crash_image->file_mode)
-                       rc = 1;
-               else
-                       rc = kexec_crash_image->update_elfcorehdr;
+               rc = kexec_crash_image->hotplug_support;
        }
        /* Release lock now that update complete */
        kexec_unlock();
@@ -552,8 +549,8 @@ static void crash_handle_hotplug_event(unsigned int hp_action, unsigned int cpu,
 
        image = kexec_crash_image;
 
-       /* Check that updating elfcorehdr is permitted */
-       if (!(image->file_mode || image->update_elfcorehdr))
+       /* Check that kexec segments update is permitted */
+       if (!image->hotplug_support)
                goto out;
 
        if (hp_action == KEXEC_CRASH_HP_ADD_CPU ||
index bab542fc1463d24bda47efd22b6f60a8b066fe9e..a6b3f96bb50c87f2f9f37a39f5616d4aee788ce6 100644 (file)
@@ -135,8 +135,8 @@ static int do_kexec_load(unsigned long entry, unsigned long nr_segments,
                image->preserve_context = 1;
 
 #ifdef CONFIG_CRASH_HOTPLUG
-       if (flags & KEXEC_UPDATE_ELFCOREHDR)
-               image->update_elfcorehdr = 1;
+       if ((flags & KEXEC_ON_CRASH) && arch_crash_hotplug_support(image, flags))
+               image->hotplug_support = 1;
 #endif
 
        ret = machine_kexec_prepare(image);
index 2d1db05fbf04f35d20bf941314ea9b591e0c220d..3d64290d24c9a2158c257b3bfa8bc2b3dd68606c 100644 (file)
@@ -376,6 +376,11 @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,
        if (ret)
                goto out;
 
+#ifdef CONFIG_CRASH_HOTPLUG
+       if ((flags & KEXEC_FILE_ON_CRASH) && arch_crash_hotplug_support(image, flags))
+               image->hotplug_support = 1;
+#endif
+
        ret = machine_kexec_prepare(image);
        if (ret)
                goto out;