* [PATCH 1/3] kexec_load: Use new kexec flag for hotplug support
@ 2024-05-22 13:13 Sourabh Jain
2024-05-22 13:13 ` [PATCH 2/3] powerpc/kexec_load: add " Sourabh Jain
` (3 more replies)
0 siblings, 4 replies; 12+ messages in thread
From: Sourabh Jain @ 2024-05-22 13:13 UTC (permalink / raw)
To: kexec
Cc: Sourabh Jain, Aditya Gupta, Baoquan He, Coiby Xu, Hari Bathini,
Mahesh Salgaonkar
Kernel commit 79365026f869 (crash: add a new kexec flag for hotplug
support) has introduced a new kexec flag to generalize hotplug support.
The newly introduced kexec flags for hotplug allow architectures to
exclude all the required kexec segments from SHA calculation so that
the kernel can update them on hotplug events. This was not possible
earlier with the KEXEC_UPDATE_ELFCOREHDR kexec flags since it was added
only for the elfcorehdr segment.
To enable architectures to control the list of kexec segments to exclude
when hotplug support is enabled, add a new architecture-specific
function named arch_do_exclude_segment. During the SHA calculation, this
function gets called to let the architecture decide whether a specific
kexec segment should be considered for SHA calculation or not.
Given that the KEXEC_UPDATE_ELFCOREHDR is no longer required and was
colliding with the KEXEC_LIVE_UPDATE update flag, it is removed.
Cc: Aditya Gupta <adityag@linux.ibm.com>
Cc: Baoquan He <bhe@redhat.com>
Cc: Coiby Xu <coxu@redhat.com>
Cc: Hari Bathini <hbathini@linux.ibm.com>
Cc: Mahesh Salgaonkar <mahesh@linux.ibm.com>
Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
---
kexec/arch/arm/kexec-arm.c | 5 +++++
kexec/arch/arm64/kexec-arm64.c | 4 ++++
kexec/arch/cris/kexec-cris.c | 4 ++++
kexec/arch/hppa/kexec-hppa.c | 5 +++++
kexec/arch/i386/kexec-x86.c | 8 ++++++++
kexec/arch/ia64/kexec-ia64.c | 4 ++++
kexec/arch/loongarch/kexec-loongarch.c | 5 +++++
kexec/arch/m68k/kexec-m68k.c | 5 +++++
kexec/arch/mips/kexec-mips.c | 4 ++++
kexec/arch/ppc/kexec-ppc.c | 4 ++++
kexec/arch/ppc64/kexec-ppc64.c | 5 +++++
kexec/arch/s390/kexec-s390.c | 5 +++++
kexec/arch/sh/kexec-sh.c | 5 +++++
kexec/arch/x86_64/kexec-x86_64.c | 5 +++++
kexec/kexec-syscall.h | 2 +-
kexec/kexec.c | 14 ++++++++------
kexec/kexec.h | 2 ++
17 files changed, 79 insertions(+), 7 deletions(-)
diff --git a/kexec/arch/arm/kexec-arm.c b/kexec/arch/arm/kexec-arm.c
index 49f35b1..34531f9 100644
--- a/kexec/arch/arm/kexec-arm.c
+++ b/kexec/arch/arm/kexec-arm.c
@@ -148,3 +148,8 @@ int have_sysfs_fdt(void)
{
return !access(SYSFS_FDT, F_OK);
}
+
+int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
+{
+ return 0;
+}
diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index 4a67b0d..9d052b0 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -1363,3 +1363,7 @@ void arch_reuse_initrd(void)
void arch_update_purgatory(struct kexec_info *UNUSED(info))
{
}
+int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
+{
+ return 0;
+}
diff --git a/kexec/arch/cris/kexec-cris.c b/kexec/arch/cris/kexec-cris.c
index 3b69709..7f09121 100644
--- a/kexec/arch/cris/kexec-cris.c
+++ b/kexec/arch/cris/kexec-cris.c
@@ -109,3 +109,7 @@ unsigned long add_buffer(struct kexec_info *info, const void *buf,
buf_min, buf_max, buf_end, 1);
}
+int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
+{
+ return 0;
+}
diff --git a/kexec/arch/hppa/kexec-hppa.c b/kexec/arch/hppa/kexec-hppa.c
index 77c9739..a64dc3d 100644
--- a/kexec/arch/hppa/kexec-hppa.c
+++ b/kexec/arch/hppa/kexec-hppa.c
@@ -146,3 +146,8 @@ unsigned long virt_to_phys(unsigned long addr)
{
return addr - phys_offset;
}
+
+int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
+{
+ return 0;
+}
diff --git a/kexec/arch/i386/kexec-x86.c b/kexec/arch/i386/kexec-x86.c
index 444cb69..b4947a0 100644
--- a/kexec/arch/i386/kexec-x86.c
+++ b/kexec/arch/i386/kexec-x86.c
@@ -208,3 +208,11 @@ void arch_update_purgatory(struct kexec_info *info)
elf_rel_set_symbol(&info->rhdr, "panic_kernel",
&panic_kernel, sizeof(panic_kernel));
}
+
+int arch_do_exclude_segment(struct kexec_segment *seg_ptr, struct kexec_info *info)
+{
+ if (info->elfcorehdr == (unsigned long) seg_ptr->mem)
+ return 1;
+
+ return 0;
+}
diff --git a/kexec/arch/ia64/kexec-ia64.c b/kexec/arch/ia64/kexec-ia64.c
index 418d997..8d9c1f3 100644
--- a/kexec/arch/ia64/kexec-ia64.c
+++ b/kexec/arch/ia64/kexec-ia64.c
@@ -245,3 +245,7 @@ void arch_update_purgatory(struct kexec_info *UNUSED(info))
{
}
+int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
+{
+ return 0;
+}
diff --git a/kexec/arch/loongarch/kexec-loongarch.c b/kexec/arch/loongarch/kexec-loongarch.c
index 32a42d2..9a50ff6 100644
--- a/kexec/arch/loongarch/kexec-loongarch.c
+++ b/kexec/arch/loongarch/kexec-loongarch.c
@@ -378,3 +378,8 @@ unsigned long add_buffer(struct kexec_info *info, const void *buf,
return add_buffer_phys_virt(info, buf, bufsz, memsz, buf_align,
buf_min, buf_max, buf_end, 1);
}
+
+int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
+{
+ return 0;
+}
diff --git a/kexec/arch/m68k/kexec-m68k.c b/kexec/arch/m68k/kexec-m68k.c
index cb54927..0c7dbaf 100644
--- a/kexec/arch/m68k/kexec-m68k.c
+++ b/kexec/arch/m68k/kexec-m68k.c
@@ -108,3 +108,8 @@ void add_segment(struct kexec_info *info, const void *buf, size_t bufsz,
{
add_segment_phys_virt(info, buf, bufsz, base, memsz, 1);
}
+
+int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
+{
+ return 0;
+}
diff --git a/kexec/arch/mips/kexec-mips.c b/kexec/arch/mips/kexec-mips.c
index d8cbea8..94224ee 100644
--- a/kexec/arch/mips/kexec-mips.c
+++ b/kexec/arch/mips/kexec-mips.c
@@ -189,3 +189,7 @@ unsigned long add_buffer(struct kexec_info *info, const void *buf,
buf_min, buf_max, buf_end, 1);
}
+int arch_do_exclude_segment(const void *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
+{
+ return 0;
+}
diff --git a/kexec/arch/ppc/kexec-ppc.c b/kexec/arch/ppc/kexec-ppc.c
index 03bec36..c8af870 100644
--- a/kexec/arch/ppc/kexec-ppc.c
+++ b/kexec/arch/ppc/kexec-ppc.c
@@ -966,3 +966,7 @@ void arch_update_purgatory(struct kexec_info *UNUSED(info))
{
}
+int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
+{
+ return 0;
+}
diff --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c
index bd5274c..fb27b6b 100644
--- a/kexec/arch/ppc64/kexec-ppc64.c
+++ b/kexec/arch/ppc64/kexec-ppc64.c
@@ -967,3 +967,8 @@ int arch_compat_trampoline(struct kexec_info *UNUSED(info))
void arch_update_purgatory(struct kexec_info *UNUSED(info))
{
}
+
+int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
+{
+ return 0;
+}
diff --git a/kexec/arch/s390/kexec-s390.c b/kexec/arch/s390/kexec-s390.c
index 33ba6b9..0561ee7 100644
--- a/kexec/arch/s390/kexec-s390.c
+++ b/kexec/arch/s390/kexec-s390.c
@@ -267,3 +267,8 @@ int get_crash_kernel_load_range(uint64_t *start, uint64_t *end)
{
return parse_iomem_single("Crash kernel\n", start, end);
}
+
+int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
+{
+ return 0;
+}
diff --git a/kexec/arch/sh/kexec-sh.c b/kexec/arch/sh/kexec-sh.c
index ce341c8..f84c40c 100644
--- a/kexec/arch/sh/kexec-sh.c
+++ b/kexec/arch/sh/kexec-sh.c
@@ -257,3 +257,8 @@ unsigned long add_buffer(struct kexec_info *info, const void *buf,
return add_buffer_phys_virt(info, buf, bufsz, memsz, buf_align,
buf_min, buf_max, buf_end, 1);
}
+
+int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
+{
+ return 0;
+}
diff --git a/kexec/arch/x86_64/kexec-x86_64.c b/kexec/arch/x86_64/kexec-x86_64.c
index ffd84f0..42af90a 100644
--- a/kexec/arch/x86_64/kexec-x86_64.c
+++ b/kexec/arch/x86_64/kexec-x86_64.c
@@ -188,3 +188,8 @@ void arch_update_purgatory(struct kexec_info *info)
elf_rel_set_symbol(&info->rhdr, "panic_kernel",
&panic_kernel, sizeof(panic_kernel));
}
+
+int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
+{
+ return 0;
+}
diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h
index 73e5254..4675c46 100644
--- a/kexec/kexec-syscall.h
+++ b/kexec/kexec-syscall.h
@@ -112,7 +112,7 @@ static inline long kexec_file_load(int kernel_fd, int initrd_fd,
#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
/* Flags for kexec file based system call */
diff --git a/kexec/kexec.c b/kexec/kexec.c
index 222f79e..034cea6 100644
--- a/kexec/kexec.c
+++ b/kexec/kexec.c
@@ -701,10 +701,13 @@ static void update_purgatory(struct kexec_info *info)
continue;
}
- /* Don't include elfcorehdr in the checksum, if hotplug
- * support enabled.
+ /*
+ * Let architecture decide which segments to exclude from checksum
+ * if hotplug support is enabled.
*/
- if (do_hotplug && (info->segment[i].mem == (void *)info->elfcorehdr)) {
+ if (do_hotplug && arch_do_exclude_segment(&info->segment[i], info)) {
+ dbgprintf("Skipping segment mem: 0x%lx from SHA calculation\n",
+ (unsigned long)info->segment[i].mem);
continue;
}
@@ -1651,7 +1654,6 @@ int main(int argc, char *argv[])
die("--load-live-update can only be used with xen\n");
}
- /* NOTE: Xen KEXEC_LIVE_UPDATE and KEXEC_UPDATE_ELFCOREHDR collide */
if (do_hotplug) {
const char *ces = "/sys/kernel/crash_elfcorehdr_size";
char *buf, *endptr = NULL;
@@ -1665,8 +1667,8 @@ int main(int argc, char *argv[])
if (!elfcorehdrsz || (endptr && *endptr != '\0'))
die("Path %s does not exist, the kernel needs CONFIG_CRASH_HOTPLUG\n", ces);
dbgprintf("ELFCOREHDR_SIZE %lu\n", elfcorehdrsz);
- /* Indicate to the kernel it is ok to modify the elfcorehdr */
- kexec_flags |= KEXEC_UPDATE_ELFCOREHDR;
+ /* Indicate to the kernel it is ok to modify the relevant kexec segments */
+ kexec_flags |= KEXEC_CRASH_HOTPLUG_SUPPORT;
}
fileind = optind;
diff --git a/kexec/kexec.h b/kexec/kexec.h
index 1004aff..2d758c9 100644
--- a/kexec/kexec.h
+++ b/kexec/kexec.h
@@ -307,6 +307,8 @@ extern int do_hotplug;
#define BOOTLOADER_VERSION PACKAGE_VERSION
void arch_usage(void);
+/* Return non-zero if segment needs to be excluded from SHA calculation, else 0. */
+int arch_do_exclude_segment(struct kexec_segment *seg_ptr, struct kexec_info *info);
int arch_process_options(int argc, char **argv);
int arch_compat_trampoline(struct kexec_info *info);
void arch_update_purgatory(struct kexec_info *info);
--
2.44.0
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/3] powerpc/kexec_load: add hotplug support
2024-05-22 13:13 [PATCH 1/3] kexec_load: Use new kexec flag for hotplug support Sourabh Jain
@ 2024-05-22 13:13 ` Sourabh Jain
2024-06-10 9:38 ` Hari Bathini
2024-05-22 13:13 ` [PATCH 3/3] doc/hotplug: update man and --help Sourabh Jain
` (2 subsequent siblings)
3 siblings, 1 reply; 12+ messages in thread
From: Sourabh Jain @ 2024-05-22 13:13 UTC (permalink / raw)
To: kexec
Cc: Sourabh Jain, Aditya Gupta, Baoquan He, Coiby Xu, Hari Bathini,
Mahesh Salgaonkar
Kernel commits b741092d5976 ("powerpc/crash: add crash CPU hotplug
support") and 849599b702ef ("powerpc/crash: add crash memory hotplug
support") added crash CPU/Memory hotplug support on PowerPC. This patch
extends that support for the kexec_load syscall.
During CPU/Memory hotplug events on PowerPC, two kexec segments,
elfcorehdr, and FDT, get updated by the kernel. To ensure the kernel
can safely update these two kexec segments for the kdump image loaded
using the kexec_load system call, the following changes are made:
1. Extra size is allocated for both elfcorehdr and FDT to accommodate
additional resources in the future. For the elfcorehdr, the size hint
is taken from /sys/kernel/crash_elfcorehdr_size sysfs, while for FDT,
extra size is allocated to hold possible CPU nodes.
2. Both elfcorehdr and FDT are skipped from SHA calculation.
Cc: Aditya Gupta <adityag@linux.ibm.com>
Cc: Baoquan He <bhe@redhat.com>
Cc: Coiby Xu <coxu@redhat.com>
Cc: Hari Bathini <hbathini@linux.ibm.com>
Cc: Mahesh Salgaonkar <mahesh@linux.ibm.com>
Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
---
kexec/arch/ppc64/crashdump-ppc64.c | 16 ++-
kexec/arch/ppc64/fdt.c | 200 +++++++++++++++++++++++++++-
kexec/arch/ppc64/include/arch/fdt.h | 2 +-
kexec/arch/ppc64/kexec-elf-ppc64.c | 2 +-
kexec/arch/ppc64/kexec-ppc64.c | 12 +-
5 files changed, 225 insertions(+), 7 deletions(-)
diff --git a/kexec/arch/ppc64/crashdump-ppc64.c b/kexec/arch/ppc64/crashdump-ppc64.c
index 6d47898..c14b593 100644
--- a/kexec/arch/ppc64/crashdump-ppc64.c
+++ b/kexec/arch/ppc64/crashdump-ppc64.c
@@ -476,7 +476,7 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
uint64_t max_addr, unsigned long min_base)
{
void *tmp;
- unsigned long sz;
+ unsigned long sz, memsz;
uint64_t elfcorehdr;
int nr_ranges, align = 1024, i;
unsigned long long end;
@@ -531,8 +531,18 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
}
}
- elfcorehdr = add_buffer(info, tmp, sz, sz, align, min_base,
- max_addr, 1);
+ memsz = sz;
+ /* To support --hotplug, replace the calculated minimum size with the
+ * value from /sys/kernel/crash_elfcorehdr_size and align it correctly.
+ */
+ if (do_hotplug) {
+ if (elfcorehdrsz > sz)
+ memsz = _ALIGN(elfcorehdrsz, align);
+ }
+
+ /* Record the location of the elfcorehdr for hotplug handling */
+ info->elfcorehdr = elfcorehdr = add_buffer(info, tmp, sz, memsz, align,
+ min_base, max_addr, 1);
reserve(elfcorehdr, sz);
/* modify and store the cmdline in a global array. This is later
* read by flatten_device_tree and modified if required
diff --git a/kexec/arch/ppc64/fdt.c b/kexec/arch/ppc64/fdt.c
index 8bc6d2d..10abc29 100644
--- a/kexec/arch/ppc64/fdt.c
+++ b/kexec/arch/ppc64/fdt.c
@@ -17,6 +17,13 @@
#include <libfdt.h>
#include <stdio.h>
#include <stdlib.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <dirent.h>
+#include <sys/stat.h>
+
+#include "../../kexec.h"
+#include "../../kexec-syscall.h"
/*
* Let the kernel know it booted from kexec, as some things (e.g.
@@ -46,17 +53,208 @@ static int fixup_kexec_prop(void *fdt)
return 0;
}
+static inline bool is_dot_dir(char * d_path)
+{
+ return d_path[0] == '.';
+}
+
+/*
+ * Returns size of files including file name size under the given
+ * @cpu_node_path.
+ */
+static unsigned int get_cpu_node_size(char *cpu_node_path)
+{
+ DIR *d;
+ struct dirent *de;
+ struct stat statbuf;
+ unsigned int cpu_node_size = 0;
+ char cpu_prop_path[2 * PATH_MAX];
+
+ d = opendir(cpu_node_path);
+ if (!d)
+ return 0;
+
+ while ((de = readdir(d)) != NULL) {
+ if (de->d_type != DT_REG)
+ continue;
+
+ memset(cpu_prop_path, '\0', PATH_MAX);
+ snprintf(cpu_prop_path, 2 * PATH_MAX, "%s/%s", cpu_node_path, de->d_name);
+
+ if (stat(cpu_prop_path, &statbuf))
+ continue;
+
+ cpu_node_size += statbuf.st_size;
+ cpu_node_size += strlen(de->d_name);
+ }
+
+ return cpu_node_size;
+}
+
+/*
+ * Checks if the node specified by the given @path represents a CPU node.
+ *
+ * Returns true if the @path has a "device_type" file containing "cpu";
+ * otherwise, returns false.
+ */
+static bool is_cpu_node(char *path)
+{
+ FILE *file;
+ bool ret = false;
+ char device_type[4];
+
+ file = fopen(path, "r");
+ if (!file)
+ return false;
+
+ memset(device_type, '\0', 4);
+ if (fread(device_type, 1, 3, file) < 3)
+ goto out;
+
+ if (strcmp(device_type, "cpu"))
+ goto out;
+
+ ret = true;
+
+out:
+ fclose(file);
+ return ret;
+}
+
+static unsigned int get_threads_per_cpu(char *path)
+{
+ struct stat statbuf;
+ if (stat(path, &statbuf))
+ return 0;
+
+ return statbuf.st_size / 4;
+}
+
+/*
+ * Finds the following CPU attributes:
+ *
+ * cpus_in_system: Currently available CPU nodes present under
+ * /proc/device-tree/cpus.
+ * threads_per_cpu: Number of threads per CPU, based on the device tree entry
+ * /proc/device-tree/cpus/<cpu_node>/ibm,ppc-interrupt-server#s.
+ * cpu_node_size: Size of files including file name size under a CPU node.
+ *
+ * Returns 0 on success, else -1.
+ */
+static unsigned int get_cpu_info(int *_cpus_in_system, int *_threads_per_cpu,
+ int *_cpu_node_size)
+{
+ DIR *d;
+ struct dirent *de;
+ int first_cpu = 1;
+ char path[PATH_MAX];
+ char *cpus_node_path = "/proc/device-tree/cpus";
+ int cpus_in_system = 0, threads_per_cpu = 0, cpu_node_size = 0;
+
+ d = opendir(cpus_node_path);
+ if (!d)
+ return -1;
+
+ while ((de = readdir(d)) != NULL) {
+ if ((de->d_type != DT_DIR) || is_dot_dir(de->d_name))
+ continue;
+
+ memset(path, '\0', PATH_MAX);
+ snprintf(path, PATH_MAX, "%s/%s/%s", cpus_node_path,
+ de->d_name, "device_type");
+
+ /* Skip nodes with device_type != "cpu" */
+ if (!is_cpu_node(path))
+ continue;
+
+ /*
+ * Found the first node under /proc/device-tree/cpus with
+ * device_type == "cpu"
+ */
+ if (first_cpu) {
+ memset(path, '\0', PATH_MAX);
+ snprintf(path, PATH_MAX, "%s/%s", cpus_node_path, de->d_name);
+ cpu_node_size = get_cpu_node_size(path);
+
+ memset(path, '\0', PATH_MAX);
+ snprintf(path, PATH_MAX, "%s/%s/%s", cpus_node_path,
+ de->d_name, "ibm,ppc-interrupt-server#s");
+ threads_per_cpu = get_threads_per_cpu(path);
+
+ first_cpu = 0;
+ }
+
+ cpus_in_system++;
+ }
+
+ closedir(d);
+
+ dbgprintf("cpus_in_system: %d, threads_per_cpus: %d, cpu_node_size: %d\n",
+ cpus_in_system, threads_per_cpu, cpu_node_size);
+
+ if (!(cpus_in_system && threads_per_cpu && cpu_node_size))
+ return -1;
+
+ *_cpus_in_system = cpus_in_system;
+ *_threads_per_cpu = threads_per_cpu;
+ *_cpu_node_size = cpu_node_size;
+
+ return 0;
+}
+
+/*
+ * Calculates the extra size needed for the flattened device tree (FDT) based
+ * on the difference between the possible number of CPU nodes and the number
+ * of CPU nodes present under /proc/device-tree/cpus.
+ */
+static unsigned int kdump_fdt_extra_size(void)
+{
+ unsigned int extra_size = 0;
+ int cpus_in_system = 0, threads_per_cpu = 0, cpu_node_size = 0;
+ int possible_cpus;
+
+ /* ALL possible CPUs are present in FDT so no extra size required */
+ if (sysconf(_SC_NPROCESSORS_ONLN) == sysconf(_SC_NPROCESSORS_CONF))
+ return 0;
+
+ if (get_cpu_info(&cpus_in_system, &threads_per_cpu, &cpu_node_size)) {
+ die("Failed to get cpu info\n");
+ }
+
+ /*
+ * Maximum number of CPU nodes with device_type = "cpu" possible under
+ * /proc/device-tree/cpus/
+ */
+ possible_cpus = sysconf(_SC_NPROCESSORS_CONF) / threads_per_cpu;
+
+ if (cpus_in_system > possible_cpus)
+ die("Possible CPU nodes can't be less than active CPU nodes\n");
+
+
+ extra_size = (possible_cpus - cpus_in_system) * cpu_node_size;
+ dbgprintf("kdump fdt extra size: %u\n", extra_size);
+
+ return extra_size;
+}
/*
* For now, assume that the added content fits in the file.
* This should be the case when flattening from /proc/device-tree,
* and when passing in a dtb, dtc can be told to add padding.
*/
-int fixup_dt(char **fdt, off_t *size)
+int fixup_dt(char **fdt, off_t *size, unsigned long kexec_flags)
{
int ret;
*size += 4096;
+
+ /* To support --hotplug option for the kexec_load syscall, consider
+ * adding extra buffer to FDT so that the kernel can add CPU nodes
+ * of hot-added CPUs.
+ */
+ if (do_hotplug && (kexec_flags & KEXEC_ON_CRASH))
+ *size += kdump_fdt_extra_size();
+
*fdt = realloc(*fdt, *size);
if (!*fdt) {
fprintf(stderr, "%s: out of memory\n", __func__);
diff --git a/kexec/arch/ppc64/include/arch/fdt.h b/kexec/arch/ppc64/include/arch/fdt.h
index b19f185..5f340b0 100644
--- a/kexec/arch/ppc64/include/arch/fdt.h
+++ b/kexec/arch/ppc64/include/arch/fdt.h
@@ -3,6 +3,6 @@
#include <sys/types.h>
-int fixup_dt(char **fdt, off_t *size);
+int fixup_dt(char **fdt, off_t *size, unsigned long kexec_flags);
#endif
diff --git a/kexec/arch/ppc64/kexec-elf-ppc64.c b/kexec/arch/ppc64/kexec-elf-ppc64.c
index bdcfd20..858c994 100644
--- a/kexec/arch/ppc64/kexec-elf-ppc64.c
+++ b/kexec/arch/ppc64/kexec-elf-ppc64.c
@@ -345,7 +345,7 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
create_flatten_tree(&seg_buf, &seg_size, cmdline);
}
- result = fixup_dt(&seg_buf, &seg_size);
+ result = fixup_dt(&seg_buf, &seg_size, info->kexec_flags);
if (result < 0)
return result;
diff --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c
index fb27b6b..f27d76b 100644
--- a/kexec/arch/ppc64/kexec-ppc64.c
+++ b/kexec/arch/ppc64/kexec-ppc64.c
@@ -24,6 +24,7 @@
#include <errno.h>
#include <stdint.h>
#include <string.h>
+#include <libfdt.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
@@ -968,7 +969,16 @@ void arch_update_purgatory(struct kexec_info *UNUSED(info))
{
}
-int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
+int arch_do_exclude_segment(struct kexec_segment *seg_ptr, struct kexec_info *info)
{
+ if (!seg_ptr)
+ return 0;
+
+ if (info->elfcorehdr == (unsigned long) seg_ptr->mem)
+ return 1;
+
+ if (seg_ptr->buf && fdt_magic(seg_ptr->buf) == FDT_MAGIC)
+ return 1;
+
return 0;
}
--
2.44.0
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 3/3] doc/hotplug: update man and --help
2024-05-22 13:13 [PATCH 1/3] kexec_load: Use new kexec flag for hotplug support Sourabh Jain
2024-05-22 13:13 ` [PATCH 2/3] powerpc/kexec_load: add " Sourabh Jain
@ 2024-05-22 13:13 ` Sourabh Jain
2024-06-10 9:19 ` Hari Bathini
2024-05-28 11:33 ` [PATCH 1/3] kexec_load: Use new kexec flag for hotplug support Aditya Gupta
2024-06-10 8:52 ` Hari Bathini
3 siblings, 1 reply; 12+ messages in thread
From: Sourabh Jain @ 2024-05-22 13:13 UTC (permalink / raw)
To: kexec
Cc: Sourabh Jain, Aditya Gupta, Baoquan He, Coiby Xu, Hari Bathini,
Mahesh Salgaonkar
Update the man page and --help option to make the description of the
--hotplug option easier to understand.
Cc: Aditya Gupta <adityag@linux.ibm.com>
Cc: Baoquan He <bhe@redhat.com>
Cc: Coiby Xu <coxu@redhat.com>
Cc: Hari Bathini <hbathini@linux.ibm.com>
Cc: Mahesh Salgaonkar <mahesh@linux.ibm.com>
Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
---
kexec/kexec.8 | 8 ++++----
kexec/kexec.c | 3 ++-
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/kexec/kexec.8 b/kexec/kexec.8
index 9e995fe..7dddae9 100644
--- a/kexec/kexec.8
+++ b/kexec/kexec.8
@@ -140,10 +140,10 @@ Open a help file for
.BR kexec .
.TP
.B \-\-hotplug
-Setup for kernel modification of the elfcorehdr. This option performs
-the steps needed to support kernel updates to the elfcorehdr in the
-presence of hot un/plug and/or on/offline events. This option only
-useful for KEXEC_LOAD syscall.
+Helps avoid kdump kernel reload on CPU/Memory hotplug or on/offline events.
+If this option is enabled, the kexec segments will be set up in a way that
+the kernel can safely update them on CPU/memory hotplug and/or on/offline
+events. This option is only useful for the KEXEC_LOAD syscall.
.TP
.B \-i\ (\-\-no-checks)
Fast reboot, no memory integrity checks.
diff --git a/kexec/kexec.c b/kexec/kexec.c
index 034cea6..2b06438 100644
--- a/kexec/kexec.c
+++ b/kexec/kexec.c
@@ -1093,7 +1093,8 @@ void usage(void)
" back to the compatibility syscall when file based\n"
" syscall is not supported or the kernel did not\n"
" understand the image (default)\n"
- " --hotplug Setup for kernel modification of elfcorehdr.\n"
+ " --hotplug Helps avoid kdump kernel reload on CPU/Memory hotplug\n"
+ " or on/offline events.\n"
" -d, --debug Enable debugging to help spot a failure.\n"
" -S, --status Return 1 if the type (by default crash) is loaded,\n"
" 0 if not.\n"
--
2.44.0
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] kexec_load: Use new kexec flag for hotplug support
2024-05-22 13:13 [PATCH 1/3] kexec_load: Use new kexec flag for hotplug support Sourabh Jain
2024-05-22 13:13 ` [PATCH 2/3] powerpc/kexec_load: add " Sourabh Jain
2024-05-22 13:13 ` [PATCH 3/3] doc/hotplug: update man and --help Sourabh Jain
@ 2024-05-28 11:33 ` Aditya Gupta
2024-05-29 13:13 ` Sourabh Jain
2024-06-10 8:52 ` Hari Bathini
3 siblings, 1 reply; 12+ messages in thread
From: Aditya Gupta @ 2024-05-28 11:33 UTC (permalink / raw)
To: Sourabh Jain; +Cc: kexec, Baoquan He, Coiby Xu, Hari Bathini, Mahesh Salgaonkar
Hello sourabh,
On Wed, May 22, 2024 at 06:43:51PM GMT, Sourabh Jain wrote:
> Kernel commit 79365026f869 (crash: add a new kexec flag for hotplug
> support) has introduced a new kexec flag to generalize hotplug support.
> The newly introduced kexec flags for hotplug allow architectures to
> exclude all the required kexec segments from SHA calculation so that
> the kernel can update them on hotplug events. This was not possible
> earlier with the KEXEC_UPDATE_ELFCOREHDR kexec flags since it was added
> only for the elfcorehdr segment.
>
> To enable architectures to control the list of kexec segments to exclude
> when hotplug support is enabled, add a new architecture-specific
> function named arch_do_exclude_segment. During the SHA calculation, this
> function gets called to let the architecture decide whether a specific
> kexec segment should be considered for SHA calculation or not.
>
> Given that the KEXEC_UPDATE_ELFCOREHDR is no longer required and was
> colliding with the KEXEC_LIVE_UPDATE update flag, it is removed.
>
> Cc: Aditya Gupta <adityag@linux.ibm.com>
> Cc: Baoquan He <bhe@redhat.com>
> Cc: Coiby Xu <coxu@redhat.com>
> Cc: Hari Bathini <hbathini@linux.ibm.com>
> Cc: Mahesh Salgaonkar <mahesh@linux.ibm.com>
> Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
> ---
> kexec/arch/arm/kexec-arm.c | 5 +++++
> kexec/arch/arm64/kexec-arm64.c | 4 ++++
> kexec/arch/cris/kexec-cris.c | 4 ++++
> kexec/arch/hppa/kexec-hppa.c | 5 +++++
> kexec/arch/i386/kexec-x86.c | 8 ++++++++
> kexec/arch/ia64/kexec-ia64.c | 4 ++++
> kexec/arch/loongarch/kexec-loongarch.c | 5 +++++
> kexec/arch/m68k/kexec-m68k.c | 5 +++++
> kexec/arch/mips/kexec-mips.c | 4 ++++
> kexec/arch/ppc/kexec-ppc.c | 4 ++++
> kexec/arch/ppc64/kexec-ppc64.c | 5 +++++
> kexec/arch/s390/kexec-s390.c | 5 +++++
> kexec/arch/sh/kexec-sh.c | 5 +++++
> kexec/arch/x86_64/kexec-x86_64.c | 5 +++++
> kexec/kexec-syscall.h | 2 +-
> kexec/kexec.c | 14 ++++++++------
> kexec/kexec.h | 2 ++
> 17 files changed, 79 insertions(+), 7 deletions(-)
>
> diff --git a/kexec/arch/arm/kexec-arm.c b/kexec/arch/arm/kexec-arm.c
> index 49f35b1..34531f9 100644
> --- a/kexec/arch/arm/kexec-arm.c
> +++ b/kexec/arch/arm/kexec-arm.c
> @@ -148,3 +148,8 @@ int have_sysfs_fdt(void)
> {
> return !access(SYSFS_FDT, F_OK);
> }
> +
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
> index 4a67b0d..9d052b0 100644
> --- a/kexec/arch/arm64/kexec-arm64.c
> +++ b/kexec/arch/arm64/kexec-arm64.c
> @@ -1363,3 +1363,7 @@ void arch_reuse_initrd(void)
> void arch_update_purgatory(struct kexec_info *UNUSED(info))
> {
> }
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/cris/kexec-cris.c b/kexec/arch/cris/kexec-cris.c
> index 3b69709..7f09121 100644
> --- a/kexec/arch/cris/kexec-cris.c
> +++ b/kexec/arch/cris/kexec-cris.c
> @@ -109,3 +109,7 @@ unsigned long add_buffer(struct kexec_info *info, const void *buf,
> buf_min, buf_max, buf_end, 1);
> }
>
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/hppa/kexec-hppa.c b/kexec/arch/hppa/kexec-hppa.c
> index 77c9739..a64dc3d 100644
> --- a/kexec/arch/hppa/kexec-hppa.c
> +++ b/kexec/arch/hppa/kexec-hppa.c
> @@ -146,3 +146,8 @@ unsigned long virt_to_phys(unsigned long addr)
> {
> return addr - phys_offset;
> }
> +
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/i386/kexec-x86.c b/kexec/arch/i386/kexec-x86.c
> index 444cb69..b4947a0 100644
> --- a/kexec/arch/i386/kexec-x86.c
> +++ b/kexec/arch/i386/kexec-x86.c
> @@ -208,3 +208,11 @@ void arch_update_purgatory(struct kexec_info *info)
> elf_rel_set_symbol(&info->rhdr, "panic_kernel",
> &panic_kernel, sizeof(panic_kernel));
> }
> +
> +int arch_do_exclude_segment(struct kexec_segment *seg_ptr, struct kexec_info *info)
> +{
> + if (info->elfcorehdr == (unsigned long) seg_ptr->mem)
> + return 1;
> +
> + return 0;
> +}
> diff --git a/kexec/arch/ia64/kexec-ia64.c b/kexec/arch/ia64/kexec-ia64.c
> index 418d997..8d9c1f3 100644
> --- a/kexec/arch/ia64/kexec-ia64.c
> +++ b/kexec/arch/ia64/kexec-ia64.c
> @@ -245,3 +245,7 @@ void arch_update_purgatory(struct kexec_info *UNUSED(info))
> {
> }
>
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/loongarch/kexec-loongarch.c b/kexec/arch/loongarch/kexec-loongarch.c
> index 32a42d2..9a50ff6 100644
> --- a/kexec/arch/loongarch/kexec-loongarch.c
> +++ b/kexec/arch/loongarch/kexec-loongarch.c
> @@ -378,3 +378,8 @@ unsigned long add_buffer(struct kexec_info *info, const void *buf,
> return add_buffer_phys_virt(info, buf, bufsz, memsz, buf_align,
> buf_min, buf_max, buf_end, 1);
> }
> +
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/m68k/kexec-m68k.c b/kexec/arch/m68k/kexec-m68k.c
> index cb54927..0c7dbaf 100644
> --- a/kexec/arch/m68k/kexec-m68k.c
> +++ b/kexec/arch/m68k/kexec-m68k.c
> @@ -108,3 +108,8 @@ void add_segment(struct kexec_info *info, const void *buf, size_t bufsz,
> {
> add_segment_phys_virt(info, buf, bufsz, base, memsz, 1);
> }
> +
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/mips/kexec-mips.c b/kexec/arch/mips/kexec-mips.c
> index d8cbea8..94224ee 100644
> --- a/kexec/arch/mips/kexec-mips.c
> +++ b/kexec/arch/mips/kexec-mips.c
> @@ -189,3 +189,7 @@ unsigned long add_buffer(struct kexec_info *info, const void *buf,
> buf_min, buf_max, buf_end, 1);
> }
>
> +int arch_do_exclude_segment(const void *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/ppc/kexec-ppc.c b/kexec/arch/ppc/kexec-ppc.c
> index 03bec36..c8af870 100644
> --- a/kexec/arch/ppc/kexec-ppc.c
> +++ b/kexec/arch/ppc/kexec-ppc.c
> @@ -966,3 +966,7 @@ void arch_update_purgatory(struct kexec_info *UNUSED(info))
> {
> }
>
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c
> index bd5274c..fb27b6b 100644
> --- a/kexec/arch/ppc64/kexec-ppc64.c
> +++ b/kexec/arch/ppc64/kexec-ppc64.c
> @@ -967,3 +967,8 @@ int arch_compat_trampoline(struct kexec_info *UNUSED(info))
> void arch_update_purgatory(struct kexec_info *UNUSED(info))
> {
> }
> +
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/s390/kexec-s390.c b/kexec/arch/s390/kexec-s390.c
> index 33ba6b9..0561ee7 100644
> --- a/kexec/arch/s390/kexec-s390.c
> +++ b/kexec/arch/s390/kexec-s390.c
> @@ -267,3 +267,8 @@ int get_crash_kernel_load_range(uint64_t *start, uint64_t *end)
> {
> return parse_iomem_single("Crash kernel\n", start, end);
> }
> +
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/sh/kexec-sh.c b/kexec/arch/sh/kexec-sh.c
> index ce341c8..f84c40c 100644
> --- a/kexec/arch/sh/kexec-sh.c
> +++ b/kexec/arch/sh/kexec-sh.c
> @@ -257,3 +257,8 @@ unsigned long add_buffer(struct kexec_info *info, const void *buf,
> return add_buffer_phys_virt(info, buf, bufsz, memsz, buf_align,
> buf_min, buf_max, buf_end, 1);
> }
> +
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/x86_64/kexec-x86_64.c b/kexec/arch/x86_64/kexec-x86_64.c
> index ffd84f0..42af90a 100644
> --- a/kexec/arch/x86_64/kexec-x86_64.c
> +++ b/kexec/arch/x86_64/kexec-x86_64.c
> @@ -188,3 +188,8 @@ void arch_update_purgatory(struct kexec_info *info)
> elf_rel_set_symbol(&info->rhdr, "panic_kernel",
> &panic_kernel, sizeof(panic_kernel));
> }
> +
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
Should all arch_do_exclude_segment return 1 for elfcorehdr ? Please
refer my below comment.
> diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h
> index 73e5254..4675c46 100644
> --- a/kexec/kexec-syscall.h
> +++ b/kexec/kexec-syscall.h
> @@ -112,7 +112,7 @@ static inline long kexec_file_load(int kernel_fd, int initrd_fd,
>
> #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
>
> /* Flags for kexec file based system call */
> diff --git a/kexec/kexec.c b/kexec/kexec.c
> index 222f79e..034cea6 100644
> --- a/kexec/kexec.c
> +++ b/kexec/kexec.c
> @@ -701,10 +701,13 @@ static void update_purgatory(struct kexec_info *info)
> continue;
> }
>
> - /* Don't include elfcorehdr in the checksum, if hotplug
> - * support enabled.
> + /*
> + * Let architecture decide which segments to exclude from checksum
> + * if hotplug support is enabled.
> */
> - if (do_hotplug && (info->segment[i].mem == (void *)info->elfcorehdr)) {
> + if (do_hotplug && arch_do_exclude_segment(&info->segment[i], info)) {
> + dbgprintf("Skipping segment mem: 0x%lx from SHA calculation\n",
> + (unsigned long)info->segment[i].mem);
> continue;
> }
Current behaviour seems to skip elfcorehdr segment in all architectures.
But now as all architectures are returning 0 in arch_do_exclude_segment,
will elfcorehdr still be skipped ?
Rest all looks good to me.
Thanks,
Aditya Gupta
>
> @@ -1651,7 +1654,6 @@ int main(int argc, char *argv[])
> die("--load-live-update can only be used with xen\n");
> }
>
> - /* NOTE: Xen KEXEC_LIVE_UPDATE and KEXEC_UPDATE_ELFCOREHDR collide */
> if (do_hotplug) {
> const char *ces = "/sys/kernel/crash_elfcorehdr_size";
> char *buf, *endptr = NULL;
> @@ -1665,8 +1667,8 @@ int main(int argc, char *argv[])
> if (!elfcorehdrsz || (endptr && *endptr != '\0'))
> die("Path %s does not exist, the kernel needs CONFIG_CRASH_HOTPLUG\n", ces);
> dbgprintf("ELFCOREHDR_SIZE %lu\n", elfcorehdrsz);
> - /* Indicate to the kernel it is ok to modify the elfcorehdr */
> - kexec_flags |= KEXEC_UPDATE_ELFCOREHDR;
> + /* Indicate to the kernel it is ok to modify the relevant kexec segments */
> + kexec_flags |= KEXEC_CRASH_HOTPLUG_SUPPORT;
> }
>
> fileind = optind;
> diff --git a/kexec/kexec.h b/kexec/kexec.h
> index 1004aff..2d758c9 100644
> --- a/kexec/kexec.h
> +++ b/kexec/kexec.h
> @@ -307,6 +307,8 @@ extern int do_hotplug;
> #define BOOTLOADER_VERSION PACKAGE_VERSION
>
> void arch_usage(void);
> +/* Return non-zero if segment needs to be excluded from SHA calculation, else 0. */
> +int arch_do_exclude_segment(struct kexec_segment *seg_ptr, struct kexec_info *info);
> int arch_process_options(int argc, char **argv);
> int arch_compat_trampoline(struct kexec_info *info);
> void arch_update_purgatory(struct kexec_info *info);
> --
> 2.44.0
>
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] kexec_load: Use new kexec flag for hotplug support
2024-05-28 11:33 ` [PATCH 1/3] kexec_load: Use new kexec flag for hotplug support Aditya Gupta
@ 2024-05-29 13:13 ` Sourabh Jain
2024-05-30 6:23 ` Aditya Gupta
0 siblings, 1 reply; 12+ messages in thread
From: Sourabh Jain @ 2024-05-29 13:13 UTC (permalink / raw)
To: Aditya Gupta; +Cc: kexec, Baoquan He, Coiby Xu, Hari Bathini, Mahesh Salgaonkar
Hello Aditya,
On 28/05/24 17:03, Aditya Gupta wrote:
> Hello sourabh,
>
> On Wed, May 22, 2024 at 06:43:51PM GMT, Sourabh Jain wrote:
>> Kernel commit 79365026f869 (crash: add a new kexec flag for hotplug
>> support) has introduced a new kexec flag to generalize hotplug support.
>> The newly introduced kexec flags for hotplug allow architectures to
>> exclude all the required kexec segments from SHA calculation so that
>> the kernel can update them on hotplug events. This was not possible
>> earlier with the KEXEC_UPDATE_ELFCOREHDR kexec flags since it was added
>> only for the elfcorehdr segment.
>>
>> To enable architectures to control the list of kexec segments to exclude
>> when hotplug support is enabled, add a new architecture-specific
>> function named arch_do_exclude_segment. During the SHA calculation, this
>> function gets called to let the architecture decide whether a specific
>> kexec segment should be considered for SHA calculation or not.
>>
>> Given that the KEXEC_UPDATE_ELFCOREHDR is no longer required and was
>> colliding with the KEXEC_LIVE_UPDATE update flag, it is removed.
>>
>> Cc: Aditya Gupta <adityag@linux.ibm.com>
>> Cc: Baoquan He <bhe@redhat.com>
>> Cc: Coiby Xu <coxu@redhat.com>
>> Cc: Hari Bathini <hbathini@linux.ibm.com>
>> Cc: Mahesh Salgaonkar <mahesh@linux.ibm.com>
>> Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
>> ---
>> kexec/arch/arm/kexec-arm.c | 5 +++++
>> kexec/arch/arm64/kexec-arm64.c | 4 ++++
>> kexec/arch/cris/kexec-cris.c | 4 ++++
>> kexec/arch/hppa/kexec-hppa.c | 5 +++++
>> kexec/arch/i386/kexec-x86.c | 8 ++++++++
>> kexec/arch/ia64/kexec-ia64.c | 4 ++++
>> kexec/arch/loongarch/kexec-loongarch.c | 5 +++++
>> kexec/arch/m68k/kexec-m68k.c | 5 +++++
>> kexec/arch/mips/kexec-mips.c | 4 ++++
>> kexec/arch/ppc/kexec-ppc.c | 4 ++++
>> kexec/arch/ppc64/kexec-ppc64.c | 5 +++++
>> kexec/arch/s390/kexec-s390.c | 5 +++++
>> kexec/arch/sh/kexec-sh.c | 5 +++++
>> kexec/arch/x86_64/kexec-x86_64.c | 5 +++++
>> kexec/kexec-syscall.h | 2 +-
>> kexec/kexec.c | 14 ++++++++------
>> kexec/kexec.h | 2 ++
>> 17 files changed, 79 insertions(+), 7 deletions(-)
>>
>> diff --git a/kexec/arch/arm/kexec-arm.c b/kexec/arch/arm/kexec-arm.c
>> index 49f35b1..34531f9 100644
>> --- a/kexec/arch/arm/kexec-arm.c
>> +++ b/kexec/arch/arm/kexec-arm.c
>> @@ -148,3 +148,8 @@ int have_sysfs_fdt(void)
>> {
>> return !access(SYSFS_FDT, F_OK);
>> }
>> +
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
>> index 4a67b0d..9d052b0 100644
>> --- a/kexec/arch/arm64/kexec-arm64.c
>> +++ b/kexec/arch/arm64/kexec-arm64.c
>> @@ -1363,3 +1363,7 @@ void arch_reuse_initrd(void)
>> void arch_update_purgatory(struct kexec_info *UNUSED(info))
>> {
>> }
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/cris/kexec-cris.c b/kexec/arch/cris/kexec-cris.c
>> index 3b69709..7f09121 100644
>> --- a/kexec/arch/cris/kexec-cris.c
>> +++ b/kexec/arch/cris/kexec-cris.c
>> @@ -109,3 +109,7 @@ unsigned long add_buffer(struct kexec_info *info, const void *buf,
>> buf_min, buf_max, buf_end, 1);
>> }
>>
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/hppa/kexec-hppa.c b/kexec/arch/hppa/kexec-hppa.c
>> index 77c9739..a64dc3d 100644
>> --- a/kexec/arch/hppa/kexec-hppa.c
>> +++ b/kexec/arch/hppa/kexec-hppa.c
>> @@ -146,3 +146,8 @@ unsigned long virt_to_phys(unsigned long addr)
>> {
>> return addr - phys_offset;
>> }
>> +
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/i386/kexec-x86.c b/kexec/arch/i386/kexec-x86.c
>> index 444cb69..b4947a0 100644
>> --- a/kexec/arch/i386/kexec-x86.c
>> +++ b/kexec/arch/i386/kexec-x86.c
>> @@ -208,3 +208,11 @@ void arch_update_purgatory(struct kexec_info *info)
>> elf_rel_set_symbol(&info->rhdr, "panic_kernel",
>> &panic_kernel, sizeof(panic_kernel));
>> }
>> +
>> +int arch_do_exclude_segment(struct kexec_segment *seg_ptr, struct kexec_info *info)
>> +{
>> + if (info->elfcorehdr == (unsigned long) seg_ptr->mem)
>> + return 1;
>> +
>> + return 0;
>> +}
>> diff --git a/kexec/arch/ia64/kexec-ia64.c b/kexec/arch/ia64/kexec-ia64.c
>> index 418d997..8d9c1f3 100644
>> --- a/kexec/arch/ia64/kexec-ia64.c
>> +++ b/kexec/arch/ia64/kexec-ia64.c
>> @@ -245,3 +245,7 @@ void arch_update_purgatory(struct kexec_info *UNUSED(info))
>> {
>> }
>>
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/loongarch/kexec-loongarch.c b/kexec/arch/loongarch/kexec-loongarch.c
>> index 32a42d2..9a50ff6 100644
>> --- a/kexec/arch/loongarch/kexec-loongarch.c
>> +++ b/kexec/arch/loongarch/kexec-loongarch.c
>> @@ -378,3 +378,8 @@ unsigned long add_buffer(struct kexec_info *info, const void *buf,
>> return add_buffer_phys_virt(info, buf, bufsz, memsz, buf_align,
>> buf_min, buf_max, buf_end, 1);
>> }
>> +
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/m68k/kexec-m68k.c b/kexec/arch/m68k/kexec-m68k.c
>> index cb54927..0c7dbaf 100644
>> --- a/kexec/arch/m68k/kexec-m68k.c
>> +++ b/kexec/arch/m68k/kexec-m68k.c
>> @@ -108,3 +108,8 @@ void add_segment(struct kexec_info *info, const void *buf, size_t bufsz,
>> {
>> add_segment_phys_virt(info, buf, bufsz, base, memsz, 1);
>> }
>> +
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/mips/kexec-mips.c b/kexec/arch/mips/kexec-mips.c
>> index d8cbea8..94224ee 100644
>> --- a/kexec/arch/mips/kexec-mips.c
>> +++ b/kexec/arch/mips/kexec-mips.c
>> @@ -189,3 +189,7 @@ unsigned long add_buffer(struct kexec_info *info, const void *buf,
>> buf_min, buf_max, buf_end, 1);
>> }
>>
>> +int arch_do_exclude_segment(const void *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/ppc/kexec-ppc.c b/kexec/arch/ppc/kexec-ppc.c
>> index 03bec36..c8af870 100644
>> --- a/kexec/arch/ppc/kexec-ppc.c
>> +++ b/kexec/arch/ppc/kexec-ppc.c
>> @@ -966,3 +966,7 @@ void arch_update_purgatory(struct kexec_info *UNUSED(info))
>> {
>> }
>>
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c
>> index bd5274c..fb27b6b 100644
>> --- a/kexec/arch/ppc64/kexec-ppc64.c
>> +++ b/kexec/arch/ppc64/kexec-ppc64.c
>> @@ -967,3 +967,8 @@ int arch_compat_trampoline(struct kexec_info *UNUSED(info))
>> void arch_update_purgatory(struct kexec_info *UNUSED(info))
>> {
>> }
>> +
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/s390/kexec-s390.c b/kexec/arch/s390/kexec-s390.c
>> index 33ba6b9..0561ee7 100644
>> --- a/kexec/arch/s390/kexec-s390.c
>> +++ b/kexec/arch/s390/kexec-s390.c
>> @@ -267,3 +267,8 @@ int get_crash_kernel_load_range(uint64_t *start, uint64_t *end)
>> {
>> return parse_iomem_single("Crash kernel\n", start, end);
>> }
>> +
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/sh/kexec-sh.c b/kexec/arch/sh/kexec-sh.c
>> index ce341c8..f84c40c 100644
>> --- a/kexec/arch/sh/kexec-sh.c
>> +++ b/kexec/arch/sh/kexec-sh.c
>> @@ -257,3 +257,8 @@ unsigned long add_buffer(struct kexec_info *info, const void *buf,
>> return add_buffer_phys_virt(info, buf, bufsz, memsz, buf_align,
>> buf_min, buf_max, buf_end, 1);
>> }
>> +
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/x86_64/kexec-x86_64.c b/kexec/arch/x86_64/kexec-x86_64.c
>> index ffd84f0..42af90a 100644
>> --- a/kexec/arch/x86_64/kexec-x86_64.c
>> +++ b/kexec/arch/x86_64/kexec-x86_64.c
>> @@ -188,3 +188,8 @@ void arch_update_purgatory(struct kexec_info *info)
>> elf_rel_set_symbol(&info->rhdr, "panic_kernel",
>> &panic_kernel, sizeof(panic_kernel));
>> }
>> +
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
> Should all arch_do_exclude_segment return 1 for elfcorehdr ? Please
> refer my below comment.
No they shouldn't until they have CRASH_HTOPLUG support in the kernel.
>
>> diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h
>> index 73e5254..4675c46 100644
>> --- a/kexec/kexec-syscall.h
>> +++ b/kexec/kexec-syscall.h
>> @@ -112,7 +112,7 @@ static inline long kexec_file_load(int kernel_fd, int initrd_fd,
>>
>> #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
>>
>> /* Flags for kexec file based system call */
>> diff --git a/kexec/kexec.c b/kexec/kexec.c
>> index 222f79e..034cea6 100644
>> --- a/kexec/kexec.c
>> +++ b/kexec/kexec.c
>> @@ -701,10 +701,13 @@ static void update_purgatory(struct kexec_info *info)
>> continue;
>> }
>>
>> - /* Don't include elfcorehdr in the checksum, if hotplug
>> - * support enabled.
>> + /*
>> + * Let architecture decide which segments to exclude from checksum
>> + * if hotplug support is enabled.
>> */
>> - if (do_hotplug && (info->segment[i].mem == (void *)info->elfcorehdr)) {
>> + if (do_hotplug && arch_do_exclude_segment(&info->segment[i], info)) {
>> + dbgprintf("Skipping segment mem: 0x%lx from SHA calculation\n",
>> + (unsigned long)info->segment[i].mem);
>> continue;
>> }
> Current behaviour seems to skip elfcorehdr segment in all architectures.
>
> But now as all architectures are returning 0 in arch_do_exclude_segment,
> will elfcorehdr still be skipped ?
Skipping elfcorehdr for architectures that don't support CRASH_HOTPLUG
is, I think, incorrect.
Therefore, I believe the proposed approach in this patch, which asks the
architecture which
segments to exclude, is better.
> Rest all looks good to me.
Thanks for the review.
- Sourabh Jain
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] kexec_load: Use new kexec flag for hotplug support
2024-05-29 13:13 ` Sourabh Jain
@ 2024-05-30 6:23 ` Aditya Gupta
0 siblings, 0 replies; 12+ messages in thread
From: Aditya Gupta @ 2024-05-30 6:23 UTC (permalink / raw)
To: Sourabh Jain; +Cc: kexec, Baoquan He, Coiby Xu, Hari Bathini, Mahesh Salgaonkar
Hello sourabh,
On 29/05/24 18:43, Sourabh Jain wrote:
> Hello Aditya,
>
>
> On 28/05/24 17:03, Aditya Gupta wrote:
>>
>>> diff --git a/kexec/arch/arm/kexec-arm.c b/kexec/arch/arm/kexec-arm.c
>>> index 49f35b1..34531f9 100644
>>> --- a/kexec/arch/arm/kexec-arm.c
>>> +++ b/kexec/arch/arm/kexec-arm.c
>>> @@ -148,3 +148,8 @@ int have_sysfs_fdt(void)
>>> {
>>> return !access(SYSFS_FDT, F_OK);
>>> }
>>> +
>>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>>> struct kexec_info *UNUSED(info))
>>> +{
>>> + return 0;
>>> +}
>>> diff --git a/kexec/arch/arm64/kexec-arm64.c
>>> b/kexec/arch/arm64/kexec-arm64.c
>>> index 4a67b0d..9d052b0 100644
>>> --- a/kexec/arch/arm64/kexec-arm64.c
>>> +++ b/kexec/arch/arm64/kexec-arm64.c
>>> @@ -1363,3 +1363,7 @@ void arch_reuse_initrd(void)
>>> void arch_update_purgatory(struct kexec_info *UNUSED(info))
>>> {
>>> }
>>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>>> struct kexec_info *UNUSED(info))
>>> +{
>>> + return 0;
>>> +}
>>> diff --git a/kexec/arch/cris/kexec-cris.c
>>> b/kexec/arch/cris/kexec-cris.c
>>> index 3b69709..7f09121 100644
>>> --- a/kexec/arch/cris/kexec-cris.c
>>> +++ b/kexec/arch/cris/kexec-cris.c
>>> @@ -109,3 +109,7 @@ unsigned long add_buffer(struct kexec_info
>>> *info, const void *buf,
>>> buf_min, buf_max, buf_end, 1);
>>> }
>>> +int arch_do_exclude_segment(struct kexec_segment
>>> *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
>>> +{
>>> + return 0;
>>> +}
>>> diff --git a/kexec/arch/hppa/kexec-hppa.c
>>> b/kexec/arch/hppa/kexec-hppa.c
>>> index 77c9739..a64dc3d 100644
>>> --- a/kexec/arch/hppa/kexec-hppa.c
>>> +++ b/kexec/arch/hppa/kexec-hppa.c
>>> @@ -146,3 +146,8 @@ unsigned long virt_to_phys(unsigned long addr)
>>> {
>>> return addr - phys_offset;
>>> }
>>> +
>>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>>> struct kexec_info *UNUSED(info))
>>> +{
>>> + return 0;
>>> +}
>>> diff --git a/kexec/arch/i386/kexec-x86.c b/kexec/arch/i386/kexec-x86.c
>>> index 444cb69..b4947a0 100644
>>> --- a/kexec/arch/i386/kexec-x86.c
>>> +++ b/kexec/arch/i386/kexec-x86.c
>>> @@ -208,3 +208,11 @@ void arch_update_purgatory(struct kexec_info
>>> *info)
>>> elf_rel_set_symbol(&info->rhdr, "panic_kernel",
>>> &panic_kernel, sizeof(panic_kernel));
>>> }
>>> +
>>> +int arch_do_exclude_segment(struct kexec_segment *seg_ptr, struct
>>> kexec_info *info)
>>> +{
>>> + if (info->elfcorehdr == (unsigned long) seg_ptr->mem)
>>> + return 1;
>>> +
>>> + return 0;
>>> +}
>>> diff --git a/kexec/arch/ia64/kexec-ia64.c
>>> b/kexec/arch/ia64/kexec-ia64.c
>>> index 418d997..8d9c1f3 100644
>>> --- a/kexec/arch/ia64/kexec-ia64.c
>>> +++ b/kexec/arch/ia64/kexec-ia64.c
>>> @@ -245,3 +245,7 @@ void arch_update_purgatory(struct kexec_info
>>> *UNUSED(info))
>>> {
>>> }
>>> +int arch_do_exclude_segment(struct kexec_segment
>>> *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
>>> +{
>>> + return 0;
>>> +}
>>> diff --git a/kexec/arch/loongarch/kexec-loongarch.c
>>> b/kexec/arch/loongarch/kexec-loongarch.c
>>> index 32a42d2..9a50ff6 100644
>>> --- a/kexec/arch/loongarch/kexec-loongarch.c
>>> +++ b/kexec/arch/loongarch/kexec-loongarch.c
>>> @@ -378,3 +378,8 @@ unsigned long add_buffer(struct kexec_info
>>> *info, const void *buf,
>>> return add_buffer_phys_virt(info, buf, bufsz, memsz, buf_align,
>>> buf_min, buf_max, buf_end, 1);
>>> }
>>> +
>>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>>> struct kexec_info *UNUSED(info))
>>> +{
>>> + return 0;
>>> +}
>>> diff --git a/kexec/arch/m68k/kexec-m68k.c
>>> b/kexec/arch/m68k/kexec-m68k.c
>>> index cb54927..0c7dbaf 100644
>>> --- a/kexec/arch/m68k/kexec-m68k.c
>>> +++ b/kexec/arch/m68k/kexec-m68k.c
>>> @@ -108,3 +108,8 @@ void add_segment(struct kexec_info *info, const
>>> void *buf, size_t bufsz,
>>> {
>>> add_segment_phys_virt(info, buf, bufsz, base, memsz, 1);
>>> }
>>> +
>>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>>> struct kexec_info *UNUSED(info))
>>> +{
>>> + return 0;
>>> +}
>>> diff --git a/kexec/arch/mips/kexec-mips.c
>>> b/kexec/arch/mips/kexec-mips.c
>>> index d8cbea8..94224ee 100644
>>> --- a/kexec/arch/mips/kexec-mips.c
>>> +++ b/kexec/arch/mips/kexec-mips.c
>>> @@ -189,3 +189,7 @@ unsigned long add_buffer(struct kexec_info
>>> *info, const void *buf,
>>> buf_min, buf_max, buf_end, 1);
>>> }
>>> +int arch_do_exclude_segment(const void *UNUSED(seg_ptr), struct
>>> kexec_info *UNUSED(info))
>>> +{
>>> + return 0;
>>> +}
>>> diff --git a/kexec/arch/ppc/kexec-ppc.c b/kexec/arch/ppc/kexec-ppc.c
>>> index 03bec36..c8af870 100644
>>> --- a/kexec/arch/ppc/kexec-ppc.c
>>> +++ b/kexec/arch/ppc/kexec-ppc.c
>>> @@ -966,3 +966,7 @@ void arch_update_purgatory(struct kexec_info
>>> *UNUSED(info))
>>> {
>>> }
>>> +int arch_do_exclude_segment(struct kexec_segment
>>> *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
>>> +{
>>> + return 0;
>>> +}
>>> diff --git a/kexec/arch/ppc64/kexec-ppc64.c
>>> b/kexec/arch/ppc64/kexec-ppc64.c
>>> index bd5274c..fb27b6b 100644
>>> --- a/kexec/arch/ppc64/kexec-ppc64.c
>>> +++ b/kexec/arch/ppc64/kexec-ppc64.c
>>> @@ -967,3 +967,8 @@ int arch_compat_trampoline(struct kexec_info
>>> *UNUSED(info))
>>> void arch_update_purgatory(struct kexec_info *UNUSED(info))
>>> {
>>> }
>>> +
>>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>>> struct kexec_info *UNUSED(info))
>>> +{
>>> + return 0;
>>> +}
>>> diff --git a/kexec/arch/s390/kexec-s390.c
>>> b/kexec/arch/s390/kexec-s390.c
>>> index 33ba6b9..0561ee7 100644
>>> --- a/kexec/arch/s390/kexec-s390.c
>>> +++ b/kexec/arch/s390/kexec-s390.c
>>> @@ -267,3 +267,8 @@ int get_crash_kernel_load_range(uint64_t *start,
>>> uint64_t *end)
>>> {
>>> return parse_iomem_single("Crash kernel\n", start, end);
>>> }
>>> +
>>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>>> struct kexec_info *UNUSED(info))
>>> +{
>>> + return 0;
>>> +}
>>> diff --git a/kexec/arch/sh/kexec-sh.c b/kexec/arch/sh/kexec-sh.c
>>> index ce341c8..f84c40c 100644
>>> --- a/kexec/arch/sh/kexec-sh.c
>>> +++ b/kexec/arch/sh/kexec-sh.c
>>> @@ -257,3 +257,8 @@ unsigned long add_buffer(struct kexec_info
>>> *info, const void *buf,
>>> return add_buffer_phys_virt(info, buf, bufsz, memsz, buf_align,
>>> buf_min, buf_max, buf_end, 1);
>>> }
>>> +
>>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>>> struct kexec_info *UNUSED(info))
>>> +{
>>> + return 0;
>>> +}
>>> diff --git a/kexec/arch/x86_64/kexec-x86_64.c
>>> b/kexec/arch/x86_64/kexec-x86_64.c
>>> index ffd84f0..42af90a 100644
>>> --- a/kexec/arch/x86_64/kexec-x86_64.c
>>> +++ b/kexec/arch/x86_64/kexec-x86_64.c
>>> @@ -188,3 +188,8 @@ void arch_update_purgatory(struct kexec_info *info)
>>> elf_rel_set_symbol(&info->rhdr, "panic_kernel",
>>> &panic_kernel, sizeof(panic_kernel));
>>> }
>>> +
>>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>>> struct kexec_info *UNUSED(info))
>>> +{
>>> + return 0;
>>> +}
>> Should all arch_do_exclude_segment return 1 for elfcorehdr ? Please
>> refer my below comment.
>
> No they shouldn't until they have CRASH_HTOPLUG support in the kernel.
>
>
>>
>>> diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h
>>> index 73e5254..4675c46 100644
>>> --- a/kexec/kexec-syscall.h
>>> +++ b/kexec/kexec-syscall.h
>>> @@ -112,7 +112,7 @@ static inline long kexec_file_load(int
>>> kernel_fd, int initrd_fd,
>>> #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
>>> /* Flags for kexec file based system call */
>>> diff --git a/kexec/kexec.c b/kexec/kexec.c
>>> index 222f79e..034cea6 100644
>>> --- a/kexec/kexec.c
>>> +++ b/kexec/kexec.c
>>> @@ -701,10 +701,13 @@ static void update_purgatory(struct kexec_info
>>> *info)
>>> continue;
>>> }
>>> - /* Don't include elfcorehdr in the checksum, if hotplug
>>> - * support enabled.
>>> + /*
>>> + * Let architecture decide which segments to exclude from
>>> checksum
>>> + * if hotplug support is enabled.
>>> */
>>> - if (do_hotplug && (info->segment[i].mem == (void
>>> *)info->elfcorehdr)) {
>>> + if (do_hotplug &&
>>> arch_do_exclude_segment(&info->segment[i], info)) {
>>> + dbgprintf("Skipping segment mem: 0x%lx from SHA
>>> calculation\n",
>>> + (unsigned long)info->segment[i].mem);
>>> continue;
>>> }
>> Current behaviour seems to skip elfcorehdr segment in all architectures.
>>
>> But now as all architectures are returning 0 in arch_do_exclude_segment,
>> will elfcorehdr still be skipped ?
>
> Skipping elfcorehdr for architectures that don't support CRASH_HOTPLUG
> is, I think, incorrect.
> Therefore, I believe the proposed approach in this patch, which asks
> the architecture which
> segments to exclude, is better.
>
Got it, makes sense to me. Thanks for the explanation sourabh.
- Aditya Gupta
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] kexec_load: Use new kexec flag for hotplug support
2024-05-22 13:13 [PATCH 1/3] kexec_load: Use new kexec flag for hotplug support Sourabh Jain
` (2 preceding siblings ...)
2024-05-28 11:33 ` [PATCH 1/3] kexec_load: Use new kexec flag for hotplug support Aditya Gupta
@ 2024-06-10 8:52 ` Hari Bathini
2024-06-10 11:42 ` Sourabh Jain
3 siblings, 1 reply; 12+ messages in thread
From: Hari Bathini @ 2024-06-10 8:52 UTC (permalink / raw)
To: Sourabh Jain, kexec; +Cc: Aditya Gupta, Baoquan He, Coiby Xu, Mahesh Salgaonkar
On 22/05/24 6:43 pm, Sourabh Jain wrote:
> Kernel commit 79365026f869 (crash: add a new kexec flag for hotplug
> support) has introduced a new kexec flag to generalize hotplug support.
> The newly introduced kexec flags for hotplug allow architectures to
> exclude all the required kexec segments from SHA calculation so that
> the kernel can update them on hotplug events. This was not possible
> earlier with the KEXEC_UPDATE_ELFCOREHDR kexec flags since it was added
> only for the elfcorehdr segment.
>
> To enable architectures to control the list of kexec segments to exclude
> when hotplug support is enabled, add a new architecture-specific
> function named arch_do_exclude_segment. During the SHA calculation, this
> function gets called to let the architecture decide whether a specific
> kexec segment should be considered for SHA calculation or not.
>
> Given that the KEXEC_UPDATE_ELFCOREHDR is no longer required and was
> colliding with the KEXEC_LIVE_UPDATE update flag, it is removed.
>
> Cc: Aditya Gupta <adityag@linux.ibm.com>
> Cc: Baoquan He <bhe@redhat.com>
> Cc: Coiby Xu <coxu@redhat.com>
> Cc: Hari Bathini <hbathini@linux.ibm.com>
> Cc: Mahesh Salgaonkar <mahesh@linux.ibm.com>
> Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
> ---
> kexec/arch/arm/kexec-arm.c | 5 +++++
> kexec/arch/arm64/kexec-arm64.c | 4 ++++
> kexec/arch/cris/kexec-cris.c | 4 ++++
> kexec/arch/hppa/kexec-hppa.c | 5 +++++
> kexec/arch/i386/kexec-x86.c | 8 ++++++++
> kexec/arch/ia64/kexec-ia64.c | 4 ++++
> kexec/arch/loongarch/kexec-loongarch.c | 5 +++++
> kexec/arch/m68k/kexec-m68k.c | 5 +++++
> kexec/arch/mips/kexec-mips.c | 4 ++++
> kexec/arch/ppc/kexec-ppc.c | 4 ++++
> kexec/arch/ppc64/kexec-ppc64.c | 5 +++++
> kexec/arch/s390/kexec-s390.c | 5 +++++
> kexec/arch/sh/kexec-sh.c | 5 +++++
> kexec/arch/x86_64/kexec-x86_64.c | 5 +++++
> kexec/kexec-syscall.h | 2 +-
> kexec/kexec.c | 14 ++++++++------
> kexec/kexec.h | 2 ++
> 17 files changed, 79 insertions(+), 7 deletions(-)
>
> diff --git a/kexec/arch/arm/kexec-arm.c b/kexec/arch/arm/kexec-arm.c
> index 49f35b1..34531f9 100644
> --- a/kexec/arch/arm/kexec-arm.c
> +++ b/kexec/arch/arm/kexec-arm.c
> @@ -148,3 +148,8 @@ int have_sysfs_fdt(void)
> {
> return !access(SYSFS_FDT, F_OK);
> }
> +
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
> index 4a67b0d..9d052b0 100644
> --- a/kexec/arch/arm64/kexec-arm64.c
> +++ b/kexec/arch/arm64/kexec-arm64.c
> @@ -1363,3 +1363,7 @@ void arch_reuse_initrd(void)
> void arch_update_purgatory(struct kexec_info *UNUSED(info))
> {
> }
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/cris/kexec-cris.c b/kexec/arch/cris/kexec-cris.c
> index 3b69709..7f09121 100644
> --- a/kexec/arch/cris/kexec-cris.c
> +++ b/kexec/arch/cris/kexec-cris.c
> @@ -109,3 +109,7 @@ unsigned long add_buffer(struct kexec_info *info, const void *buf,
> buf_min, buf_max, buf_end, 1);
> }
>
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/hppa/kexec-hppa.c b/kexec/arch/hppa/kexec-hppa.c
> index 77c9739..a64dc3d 100644
> --- a/kexec/arch/hppa/kexec-hppa.c
> +++ b/kexec/arch/hppa/kexec-hppa.c
> @@ -146,3 +146,8 @@ unsigned long virt_to_phys(unsigned long addr)
> {
> return addr - phys_offset;
> }
> +
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/i386/kexec-x86.c b/kexec/arch/i386/kexec-x86.c
> index 444cb69..b4947a0 100644
> --- a/kexec/arch/i386/kexec-x86.c
> +++ b/kexec/arch/i386/kexec-x86.c
> @@ -208,3 +208,11 @@ void arch_update_purgatory(struct kexec_info *info)
> elf_rel_set_symbol(&info->rhdr, "panic_kernel",
> &panic_kernel, sizeof(panic_kernel));
> }
> +
> +int arch_do_exclude_segment(struct kexec_segment *seg_ptr, struct kexec_info *info)
> +{
> + if (info->elfcorehdr == (unsigned long) seg_ptr->mem)
> + return 1;
> +
> + return 0;
> +}
> diff --git a/kexec/arch/ia64/kexec-ia64.c b/kexec/arch/ia64/kexec-ia64.c
> index 418d997..8d9c1f3 100644
> --- a/kexec/arch/ia64/kexec-ia64.c
> +++ b/kexec/arch/ia64/kexec-ia64.c
> @@ -245,3 +245,7 @@ void arch_update_purgatory(struct kexec_info *UNUSED(info))
> {
> }
>
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/loongarch/kexec-loongarch.c b/kexec/arch/loongarch/kexec-loongarch.c
> index 32a42d2..9a50ff6 100644
> --- a/kexec/arch/loongarch/kexec-loongarch.c
> +++ b/kexec/arch/loongarch/kexec-loongarch.c
> @@ -378,3 +378,8 @@ unsigned long add_buffer(struct kexec_info *info, const void *buf,
> return add_buffer_phys_virt(info, buf, bufsz, memsz, buf_align,
> buf_min, buf_max, buf_end, 1);
> }
> +
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/m68k/kexec-m68k.c b/kexec/arch/m68k/kexec-m68k.c
> index cb54927..0c7dbaf 100644
> --- a/kexec/arch/m68k/kexec-m68k.c
> +++ b/kexec/arch/m68k/kexec-m68k.c
> @@ -108,3 +108,8 @@ void add_segment(struct kexec_info *info, const void *buf, size_t bufsz,
> {
> add_segment_phys_virt(info, buf, bufsz, base, memsz, 1);
> }
> +
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/mips/kexec-mips.c b/kexec/arch/mips/kexec-mips.c
> index d8cbea8..94224ee 100644
> --- a/kexec/arch/mips/kexec-mips.c
> +++ b/kexec/arch/mips/kexec-mips.c
> @@ -189,3 +189,7 @@ unsigned long add_buffer(struct kexec_info *info, const void *buf,
> buf_min, buf_max, buf_end, 1);
> }
>
> +int arch_do_exclude_segment(const void *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/ppc/kexec-ppc.c b/kexec/arch/ppc/kexec-ppc.c
> index 03bec36..c8af870 100644
> --- a/kexec/arch/ppc/kexec-ppc.c
> +++ b/kexec/arch/ppc/kexec-ppc.c
> @@ -966,3 +966,7 @@ void arch_update_purgatory(struct kexec_info *UNUSED(info))
> {
> }
>
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c
> index bd5274c..fb27b6b 100644
> --- a/kexec/arch/ppc64/kexec-ppc64.c
> +++ b/kexec/arch/ppc64/kexec-ppc64.c
> @@ -967,3 +967,8 @@ int arch_compat_trampoline(struct kexec_info *UNUSED(info))
> void arch_update_purgatory(struct kexec_info *UNUSED(info))
> {
> }
> +
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/s390/kexec-s390.c b/kexec/arch/s390/kexec-s390.c
> index 33ba6b9..0561ee7 100644
> --- a/kexec/arch/s390/kexec-s390.c
> +++ b/kexec/arch/s390/kexec-s390.c
> @@ -267,3 +267,8 @@ int get_crash_kernel_load_range(uint64_t *start, uint64_t *end)
> {
> return parse_iomem_single("Crash kernel\n", start, end);
> }
> +
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/sh/kexec-sh.c b/kexec/arch/sh/kexec-sh.c
> index ce341c8..f84c40c 100644
> --- a/kexec/arch/sh/kexec-sh.c
> +++ b/kexec/arch/sh/kexec-sh.c
> @@ -257,3 +257,8 @@ unsigned long add_buffer(struct kexec_info *info, const void *buf,
> return add_buffer_phys_virt(info, buf, bufsz, memsz, buf_align,
> buf_min, buf_max, buf_end, 1);
> }
> +
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
> + return 0;
> +}
> diff --git a/kexec/arch/x86_64/kexec-x86_64.c b/kexec/arch/x86_64/kexec-x86_64.c
> index ffd84f0..42af90a 100644
> --- a/kexec/arch/x86_64/kexec-x86_64.c
> +++ b/kexec/arch/x86_64/kexec-x86_64.c
> @@ -188,3 +188,8 @@ void arch_update_purgatory(struct kexec_info *info)
> elf_rel_set_symbol(&info->rhdr, "panic_kernel",
> &panic_kernel, sizeof(panic_kernel));
> }
> +
> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +{
This should also be similar to i386, no?
Except for that, rest looks good..
Acked-by: Hari Bathini <hbathini@linux.ibm.com>
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/3] doc/hotplug: update man and --help
2024-05-22 13:13 ` [PATCH 3/3] doc/hotplug: update man and --help Sourabh Jain
@ 2024-06-10 9:19 ` Hari Bathini
2024-06-10 12:24 ` Sourabh Jain
0 siblings, 1 reply; 12+ messages in thread
From: Hari Bathini @ 2024-06-10 9:19 UTC (permalink / raw)
To: Sourabh Jain, kexec; +Cc: Aditya Gupta, Baoquan He, Coiby Xu, Mahesh Salgaonkar
On 22/05/24 6:43 pm, Sourabh Jain wrote:
> Update the man page and --help option to make the description of the
> --hotplug option easier to understand.
>
> Cc: Aditya Gupta <adityag@linux.ibm.com>
> Cc: Baoquan He <bhe@redhat.com>
> Cc: Coiby Xu <coxu@redhat.com>
> Cc: Hari Bathini <hbathini@linux.ibm.com>
> Cc: Mahesh Salgaonkar <mahesh@linux.ibm.com>
> Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
> ---
> kexec/kexec.8 | 8 ++++----
> kexec/kexec.c | 3 ++-
> 2 files changed, 6 insertions(+), 5 deletions(-)
>
> diff --git a/kexec/kexec.8 b/kexec/kexec.8
> index 9e995fe..7dddae9 100644
> --- a/kexec/kexec.8
> +++ b/kexec/kexec.8
> @@ -140,10 +140,10 @@ Open a help file for
> .BR kexec .
> .TP
> .B \-\-hotplug
Can we have the description changed like:
> -Setup for kernel modification of the elfcorehdr. This option performs
> -the steps needed to support kernel updates to the elfcorehdr in the
> -presence of hot un/plug and/or on/offline events. This option only
> -useful for KEXEC_LOAD syscall.
> +Helps avoid kdump kernel reload on CPU/Memory hotplug or on/offline events.
> +If this option is enabled, the kexec segments will be set up in a way that
> +the kernel can safely update them on CPU/memory hotplug and/or on/offline
> +events. This option is only useful for the KEXEC_LOAD syscall.
"Setup kexec segments such that kernel can safely update them on
CPU/Memory hot add/remove events. If this option is enabled, kernel does
in-kernel update of kexec segments on CPU/Memory hot add/remove events.
Helps avoid the need to reload kdump kernel."
> .TP
> .B \-i\ (\-\-no-checks)
> Fast reboot, no memory integrity checks.
> diff --git a/kexec/kexec.c b/kexec/kexec.c
> index 034cea6..2b06438 100644
> --- a/kexec/kexec.c
> +++ b/kexec/kexec.c
> @@ -1093,7 +1093,8 @@ void usage(void)
> " back to the compatibility syscall when file based\n"
> " syscall is not supported or the kernel did not\n"
> " understand the image (default)\n"
> - " --hotplug Setup for kernel modification of elfcorehdr.\n"
> + " --hotplug Helps avoid kdump kernel reload on CPU/Memory hotplug\n"
> + " or on/offline events.\n"
"Do in-kernel update of kexec segments on CPU/Memory hot add/remove
events. This avoids the need to reload kdump kernel."
- Hari
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/3] powerpc/kexec_load: add hotplug support
2024-05-22 13:13 ` [PATCH 2/3] powerpc/kexec_load: add " Sourabh Jain
@ 2024-06-10 9:38 ` Hari Bathini
2024-06-10 12:19 ` Sourabh Jain
0 siblings, 1 reply; 12+ messages in thread
From: Hari Bathini @ 2024-06-10 9:38 UTC (permalink / raw)
To: Sourabh Jain, kexec; +Cc: Aditya Gupta, Baoquan He, Coiby Xu, Mahesh Salgaonkar
On 22/05/24 6:43 pm, Sourabh Jain wrote:
> Kernel commits b741092d5976 ("powerpc/crash: add crash CPU hotplug
> support") and 849599b702ef ("powerpc/crash: add crash memory hotplug
> support") added crash CPU/Memory hotplug support on PowerPC. This patch
> extends that support for the kexec_load syscall.
>
> During CPU/Memory hotplug events on PowerPC, two kexec segments,
> elfcorehdr, and FDT, get updated by the kernel. To ensure the kernel
> can safely update these two kexec segments for the kdump image loaded
> using the kexec_load system call, the following changes are made:
>
> 1. Extra size is allocated for both elfcorehdr and FDT to accommodate
> additional resources in the future. For the elfcorehdr, the size hint
> is taken from /sys/kernel/crash_elfcorehdr_size sysfs, while for FDT,
> extra size is allocated to hold possible CPU nodes.
>
> 2. Both elfcorehdr and FDT are skipped from SHA calculation.
>
> Cc: Aditya Gupta <adityag@linux.ibm.com>
> Cc: Baoquan He <bhe@redhat.com>
> Cc: Coiby Xu <coxu@redhat.com>
> Cc: Hari Bathini <hbathini@linux.ibm.com>
> Cc: Mahesh Salgaonkar <mahesh@linux.ibm.com>
> Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
> ---
> kexec/arch/ppc64/crashdump-ppc64.c | 16 ++-
> kexec/arch/ppc64/fdt.c | 200 +++++++++++++++++++++++++++-
> kexec/arch/ppc64/include/arch/fdt.h | 2 +-
> kexec/arch/ppc64/kexec-elf-ppc64.c | 2 +-
> kexec/arch/ppc64/kexec-ppc64.c | 12 +-
> 5 files changed, 225 insertions(+), 7 deletions(-)
>
> diff --git a/kexec/arch/ppc64/crashdump-ppc64.c b/kexec/arch/ppc64/crashdump-ppc64.c
> index 6d47898..c14b593 100644
> --- a/kexec/arch/ppc64/crashdump-ppc64.c
> +++ b/kexec/arch/ppc64/crashdump-ppc64.c
> @@ -476,7 +476,7 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
> uint64_t max_addr, unsigned long min_base)
> {
> void *tmp;
> - unsigned long sz;
> + unsigned long sz, memsz;
> uint64_t elfcorehdr;
> int nr_ranges, align = 1024, i;
> unsigned long long end;
> @@ -531,8 +531,18 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
> }
> }
>
> - elfcorehdr = add_buffer(info, tmp, sz, sz, align, min_base,
> - max_addr, 1);
> + memsz = sz;
> + /* To support --hotplug, replace the calculated minimum size with the
> + * value from /sys/kernel/crash_elfcorehdr_size and align it correctly.
> + */
> + if (do_hotplug) {
> + if (elfcorehdrsz > sz)
> + memsz = _ALIGN(elfcorehdrsz, align);
> + }
> +
> + /* Record the location of the elfcorehdr for hotplug handling */
> + info->elfcorehdr = elfcorehdr = add_buffer(info, tmp, sz, memsz, align,
> + min_base, max_addr, 1);
> reserve(elfcorehdr, sz);
> /* modify and store the cmdline in a global array. This is later
> * read by flatten_device_tree and modified if required
> diff --git a/kexec/arch/ppc64/fdt.c b/kexec/arch/ppc64/fdt.c
> index 8bc6d2d..10abc29 100644
> --- a/kexec/arch/ppc64/fdt.c
> +++ b/kexec/arch/ppc64/fdt.c
> @@ -17,6 +17,13 @@
> #include <libfdt.h>
> #include <stdio.h>
> #include <stdlib.h>
> +#include <limits.h>
> +#include <stdbool.h>
> +#include <dirent.h>
> +#include <sys/stat.h>
> +
> +#include "../../kexec.h"
> +#include "../../kexec-syscall.h"
>
> /*
> * Let the kernel know it booted from kexec, as some things (e.g.
> @@ -46,17 +53,208 @@ static int fixup_kexec_prop(void *fdt)
> return 0;
> }
>
> +static inline bool is_dot_dir(char * d_path)
> +{
> + return d_path[0] == '.';
> +}
> +
> +/*
> + * Returns size of files including file name size under the given
> + * @cpu_node_path.
> + */
> +static unsigned int get_cpu_node_size(char *cpu_node_path)
> +{
> + DIR *d;
> + struct dirent *de;
> + struct stat statbuf;
> + unsigned int cpu_node_size = 0;
> + char cpu_prop_path[2 * PATH_MAX];
> +
> + d = opendir(cpu_node_path);
> + if (!d)
> + return 0;
> +
> + while ((de = readdir(d)) != NULL) {
> + if (de->d_type != DT_REG)
> + continue;
> +
> + memset(cpu_prop_path, '\0', PATH_MAX);
> + snprintf(cpu_prop_path, 2 * PATH_MAX, "%s/%s", cpu_node_path, de->d_name);
> +
> + if (stat(cpu_prop_path, &statbuf))
> + continue;
> +
> + cpu_node_size += statbuf.st_size;
> + cpu_node_size += strlen(de->d_name);
> + }
> +
> + return cpu_node_size;
> +}
> +
> +/*
> + * Checks if the node specified by the given @path represents a CPU node.
> + *
> + * Returns true if the @path has a "device_type" file containing "cpu";
> + * otherwise, returns false.
> + */
> +static bool is_cpu_node(char *path)
> +{
> + FILE *file;
> + bool ret = false;
> + char device_type[4];
> +
> + file = fopen(path, "r");
> + if (!file)
> + return false;
> +
> + memset(device_type, '\0', 4);
> + if (fread(device_type, 1, 3, file) < 3)
> + goto out;
> +
> + if (strcmp(device_type, "cpu"))
> + goto out;
> +
> + ret = true;
> +
> +out:
> + fclose(file);
> + return ret;
> +}
> +
> +static unsigned int get_threads_per_cpu(char *path)
> +{
> + struct stat statbuf;
> + if (stat(path, &statbuf))
> + return 0;
> +
> + return statbuf.st_size / 4;
> +}
> +
> +/*
> + * Finds the following CPU attributes:
> + *
> + * cpus_in_system: Currently available CPU nodes present under
> + * /proc/device-tree/cpus.
> + * threads_per_cpu: Number of threads per CPU, based on the device tree entry
> + * /proc/device-tree/cpus/<cpu_node>/ibm,ppc-interrupt-server#s.
> + * cpu_node_size: Size of files including file name size under a CPU node.
> + *
> + * Returns 0 on success, else -1.
> + */
> +static unsigned int get_cpu_info(int *_cpus_in_system, int *_threads_per_cpu,
> + int *_cpu_node_size)
> +{
> + DIR *d;
> + struct dirent *de;
> + int first_cpu = 1;
> + char path[PATH_MAX];
> + char *cpus_node_path = "/proc/device-tree/cpus";
> + int cpus_in_system = 0, threads_per_cpu = 0, cpu_node_size = 0;
> +
> + d = opendir(cpus_node_path);
> + if (!d)
> + return -1;
> +
> + while ((de = readdir(d)) != NULL) {
> + if ((de->d_type != DT_DIR) || is_dot_dir(de->d_name))
> + continue;
> +
> + memset(path, '\0', PATH_MAX);
> + snprintf(path, PATH_MAX, "%s/%s/%s", cpus_node_path,
> + de->d_name, "device_type");
> +
> + /* Skip nodes with device_type != "cpu" */
> + if (!is_cpu_node(path))
> + continue;
> +
> + /*
> + * Found the first node under /proc/device-tree/cpus with
> + * device_type == "cpu"
> + */
> + if (first_cpu) {
> + memset(path, '\0', PATH_MAX);
> + snprintf(path, PATH_MAX, "%s/%s", cpus_node_path, de->d_name);
> + cpu_node_size = get_cpu_node_size(path);
> +
> + memset(path, '\0', PATH_MAX);
> + snprintf(path, PATH_MAX, "%s/%s/%s", cpus_node_path,
> + de->d_name, "ibm,ppc-interrupt-server#s");
> + threads_per_cpu = get_threads_per_cpu(path);
> +
> + first_cpu = 0;
> + }
> +
> + cpus_in_system++;
> + }
> +
> + closedir(d);
> +
> + dbgprintf("cpus_in_system: %d, threads_per_cpus: %d, cpu_node_size: %d\n",
> + cpus_in_system, threads_per_cpu, cpu_node_size);
> +
> + if (!(cpus_in_system && threads_per_cpu && cpu_node_size))
> + return -1;
> +
> + *_cpus_in_system = cpus_in_system;
> + *_threads_per_cpu = threads_per_cpu;
> + *_cpu_node_size = cpu_node_size;
> +
> + return 0;
> +}
> +
> +/*
> + * Calculates the extra size needed for the flattened device tree (FDT) based
> + * on the difference between the possible number of CPU nodes and the number
> + * of CPU nodes present under /proc/device-tree/cpus.
> + */
> +static unsigned int kdump_fdt_extra_size(void)
> +{
> + unsigned int extra_size = 0;
> + int cpus_in_system = 0, threads_per_cpu = 0, cpu_node_size = 0;
> + int possible_cpus;
> +
> + /* ALL possible CPUs are present in FDT so no extra size required */
> + if (sysconf(_SC_NPROCESSORS_ONLN) == sysconf(_SC_NPROCESSORS_CONF))
> + return 0;
> +
> + if (get_cpu_info(&cpus_in_system, &threads_per_cpu, &cpu_node_size)) {
Is (sysconf(_SC_NPROCESSORS_ONLN) / threads_per_cpu) not the same as
'cpus_in_system'? If they are same, should be able to get cpu_node_size
& threads_per_cpu by examining a single core instead of going through
all cores on the system??
> + die("Failed to get cpu info\n");
> + }
> +
> + /*
> + * Maximum number of CPU nodes with device_type = "cpu" possible under
> + * /proc/device-tree/cpus/
> + */
> + possible_cpus = sysconf(_SC_NPROCESSORS_CONF) / threads_per_cpu;
> +
> + if (cpus_in_system > possible_cpus)
> + die("Possible CPU nodes can't be less than active CPU nodes\n");
> +
> +
> + extra_size = (possible_cpus - cpus_in_system) * cpu_node_size;
> + dbgprintf("kdump fdt extra size: %u\n", extra_size);
> +
> + return extra_size;
> +}
>
> /*
> * For now, assume that the added content fits in the file.
> * This should be the case when flattening from /proc/device-tree,
> * and when passing in a dtb, dtc can be told to add padding.
> */
> -int fixup_dt(char **fdt, off_t *size)
> +int fixup_dt(char **fdt, off_t *size, unsigned long kexec_flags)
> {
> int ret;
>
> *size += 4096;
> +
> + /* To support --hotplug option for the kexec_load syscall, consider
> + * adding extra buffer to FDT so that the kernel can add CPU nodes
> + * of hot-added CPUs.
> + */
> + if (do_hotplug && (kexec_flags & KEXEC_ON_CRASH))
> + *size += kdump_fdt_extra_size();
> +
> *fdt = realloc(*fdt, *size);
> if (!*fdt) {
> fprintf(stderr, "%s: out of memory\n", __func__);
> diff --git a/kexec/arch/ppc64/include/arch/fdt.h b/kexec/arch/ppc64/include/arch/fdt.h
> index b19f185..5f340b0 100644
> --- a/kexec/arch/ppc64/include/arch/fdt.h
> +++ b/kexec/arch/ppc64/include/arch/fdt.h
> @@ -3,6 +3,6 @@
>
> #include <sys/types.h>
>
> -int fixup_dt(char **fdt, off_t *size);
> +int fixup_dt(char **fdt, off_t *size, unsigned long kexec_flags);
>
> #endif
> diff --git a/kexec/arch/ppc64/kexec-elf-ppc64.c b/kexec/arch/ppc64/kexec-elf-ppc64.c
> index bdcfd20..858c994 100644
> --- a/kexec/arch/ppc64/kexec-elf-ppc64.c
> +++ b/kexec/arch/ppc64/kexec-elf-ppc64.c
> @@ -345,7 +345,7 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
> create_flatten_tree(&seg_buf, &seg_size, cmdline);
> }
>
> - result = fixup_dt(&seg_buf, &seg_size);
> + result = fixup_dt(&seg_buf, &seg_size, info->kexec_flags);
> if (result < 0)
> return result;
>
> diff --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c
> index fb27b6b..f27d76b 100644
> --- a/kexec/arch/ppc64/kexec-ppc64.c
> +++ b/kexec/arch/ppc64/kexec-ppc64.c
> @@ -24,6 +24,7 @@
> #include <errno.h>
> #include <stdint.h>
> #include <string.h>
> +#include <libfdt.h>
> #include <sys/stat.h>
> #include <sys/types.h>
> #include <dirent.h>
> @@ -968,7 +969,16 @@ void arch_update_purgatory(struct kexec_info *UNUSED(info))
> {
> }
>
> -int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr), struct kexec_info *UNUSED(info))
> +int arch_do_exclude_segment(struct kexec_segment *seg_ptr, struct kexec_info *info)
> {
> + if (!seg_ptr)
When can this be true? If this is a possiblilty, why do we not have the
same thing for i386?
- Hari
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] kexec_load: Use new kexec flag for hotplug support
2024-06-10 8:52 ` Hari Bathini
@ 2024-06-10 11:42 ` Sourabh Jain
0 siblings, 0 replies; 12+ messages in thread
From: Sourabh Jain @ 2024-06-10 11:42 UTC (permalink / raw)
To: Hari Bathini, kexec; +Cc: Aditya Gupta, Baoquan He, Coiby Xu, Mahesh Salgaonkar
Hello Hari,
On 10/06/24 14:22, Hari Bathini wrote:
>
>
> On 22/05/24 6:43 pm, Sourabh Jain wrote:
>> Kernel commit 79365026f869 (crash: add a new kexec flag for hotplug
>> support) has introduced a new kexec flag to generalize hotplug support.
>> The newly introduced kexec flags for hotplug allow architectures to
>> exclude all the required kexec segments from SHA calculation so that
>> the kernel can update them on hotplug events. This was not possible
>> earlier with the KEXEC_UPDATE_ELFCOREHDR kexec flags since it was added
>> only for the elfcorehdr segment.
>>
>> To enable architectures to control the list of kexec segments to exclude
>> when hotplug support is enabled, add a new architecture-specific
>> function named arch_do_exclude_segment. During the SHA calculation, this
>> function gets called to let the architecture decide whether a specific
>> kexec segment should be considered for SHA calculation or not.
>>
>> Given that the KEXEC_UPDATE_ELFCOREHDR is no longer required and was
>> colliding with the KEXEC_LIVE_UPDATE update flag, it is removed.
>>
>> Cc: Aditya Gupta <adityag@linux.ibm.com>
>> Cc: Baoquan He <bhe@redhat.com>
>> Cc: Coiby Xu <coxu@redhat.com>
>> Cc: Hari Bathini <hbathini@linux.ibm.com>
>> Cc: Mahesh Salgaonkar <mahesh@linux.ibm.com>
>> Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
>> ---
>> kexec/arch/arm/kexec-arm.c | 5 +++++
>> kexec/arch/arm64/kexec-arm64.c | 4 ++++
>> kexec/arch/cris/kexec-cris.c | 4 ++++
>> kexec/arch/hppa/kexec-hppa.c | 5 +++++
>> kexec/arch/i386/kexec-x86.c | 8 ++++++++
>> kexec/arch/ia64/kexec-ia64.c | 4 ++++
>> kexec/arch/loongarch/kexec-loongarch.c | 5 +++++
>> kexec/arch/m68k/kexec-m68k.c | 5 +++++
>> kexec/arch/mips/kexec-mips.c | 4 ++++
>> kexec/arch/ppc/kexec-ppc.c | 4 ++++
>> kexec/arch/ppc64/kexec-ppc64.c | 5 +++++
>> kexec/arch/s390/kexec-s390.c | 5 +++++
>> kexec/arch/sh/kexec-sh.c | 5 +++++
>> kexec/arch/x86_64/kexec-x86_64.c | 5 +++++
>> kexec/kexec-syscall.h | 2 +-
>> kexec/kexec.c | 14 ++++++++------
>> kexec/kexec.h | 2 ++
>> 17 files changed, 79 insertions(+), 7 deletions(-)
>>
>> diff --git a/kexec/arch/arm/kexec-arm.c b/kexec/arch/arm/kexec-arm.c
>> index 49f35b1..34531f9 100644
>> --- a/kexec/arch/arm/kexec-arm.c
>> +++ b/kexec/arch/arm/kexec-arm.c
>> @@ -148,3 +148,8 @@ int have_sysfs_fdt(void)
>> {
>> return !access(SYSFS_FDT, F_OK);
>> }
>> +
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>> struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/arm64/kexec-arm64.c
>> b/kexec/arch/arm64/kexec-arm64.c
>> index 4a67b0d..9d052b0 100644
>> --- a/kexec/arch/arm64/kexec-arm64.c
>> +++ b/kexec/arch/arm64/kexec-arm64.c
>> @@ -1363,3 +1363,7 @@ void arch_reuse_initrd(void)
>> void arch_update_purgatory(struct kexec_info *UNUSED(info))
>> {
>> }
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>> struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/cris/kexec-cris.c b/kexec/arch/cris/kexec-cris.c
>> index 3b69709..7f09121 100644
>> --- a/kexec/arch/cris/kexec-cris.c
>> +++ b/kexec/arch/cris/kexec-cris.c
>> @@ -109,3 +109,7 @@ unsigned long add_buffer(struct kexec_info *info,
>> const void *buf,
>> buf_min, buf_max, buf_end, 1);
>> }
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>> struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/hppa/kexec-hppa.c b/kexec/arch/hppa/kexec-hppa.c
>> index 77c9739..a64dc3d 100644
>> --- a/kexec/arch/hppa/kexec-hppa.c
>> +++ b/kexec/arch/hppa/kexec-hppa.c
>> @@ -146,3 +146,8 @@ unsigned long virt_to_phys(unsigned long addr)
>> {
>> return addr - phys_offset;
>> }
>> +
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>> struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/i386/kexec-x86.c b/kexec/arch/i386/kexec-x86.c
>> index 444cb69..b4947a0 100644
>> --- a/kexec/arch/i386/kexec-x86.c
>> +++ b/kexec/arch/i386/kexec-x86.c
>> @@ -208,3 +208,11 @@ void arch_update_purgatory(struct kexec_info *info)
>> elf_rel_set_symbol(&info->rhdr, "panic_kernel",
>> &panic_kernel, sizeof(panic_kernel));
>> }
>> +
>> +int arch_do_exclude_segment(struct kexec_segment *seg_ptr, struct
>> kexec_info *info)
>> +{
>> + if (info->elfcorehdr == (unsigned long) seg_ptr->mem)
>> + return 1;
>> +
>> + return 0;
>> +}
>> diff --git a/kexec/arch/ia64/kexec-ia64.c b/kexec/arch/ia64/kexec-ia64.c
>> index 418d997..8d9c1f3 100644
>> --- a/kexec/arch/ia64/kexec-ia64.c
>> +++ b/kexec/arch/ia64/kexec-ia64.c
>> @@ -245,3 +245,7 @@ void arch_update_purgatory(struct kexec_info
>> *UNUSED(info))
>> {
>> }
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>> struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/loongarch/kexec-loongarch.c
>> b/kexec/arch/loongarch/kexec-loongarch.c
>> index 32a42d2..9a50ff6 100644
>> --- a/kexec/arch/loongarch/kexec-loongarch.c
>> +++ b/kexec/arch/loongarch/kexec-loongarch.c
>> @@ -378,3 +378,8 @@ unsigned long add_buffer(struct kexec_info *info,
>> const void *buf,
>> return add_buffer_phys_virt(info, buf, bufsz, memsz, buf_align,
>> buf_min, buf_max, buf_end, 1);
>> }
>> +
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>> struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/m68k/kexec-m68k.c b/kexec/arch/m68k/kexec-m68k.c
>> index cb54927..0c7dbaf 100644
>> --- a/kexec/arch/m68k/kexec-m68k.c
>> +++ b/kexec/arch/m68k/kexec-m68k.c
>> @@ -108,3 +108,8 @@ void add_segment(struct kexec_info *info, const
>> void *buf, size_t bufsz,
>> {
>> add_segment_phys_virt(info, buf, bufsz, base, memsz, 1);
>> }
>> +
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>> struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/mips/kexec-mips.c b/kexec/arch/mips/kexec-mips.c
>> index d8cbea8..94224ee 100644
>> --- a/kexec/arch/mips/kexec-mips.c
>> +++ b/kexec/arch/mips/kexec-mips.c
>> @@ -189,3 +189,7 @@ unsigned long add_buffer(struct kexec_info *info,
>> const void *buf,
>> buf_min, buf_max, buf_end, 1);
>> }
>> +int arch_do_exclude_segment(const void *UNUSED(seg_ptr), struct
>> kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/ppc/kexec-ppc.c b/kexec/arch/ppc/kexec-ppc.c
>> index 03bec36..c8af870 100644
>> --- a/kexec/arch/ppc/kexec-ppc.c
>> +++ b/kexec/arch/ppc/kexec-ppc.c
>> @@ -966,3 +966,7 @@ void arch_update_purgatory(struct kexec_info
>> *UNUSED(info))
>> {
>> }
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>> struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/ppc64/kexec-ppc64.c
>> b/kexec/arch/ppc64/kexec-ppc64.c
>> index bd5274c..fb27b6b 100644
>> --- a/kexec/arch/ppc64/kexec-ppc64.c
>> +++ b/kexec/arch/ppc64/kexec-ppc64.c
>> @@ -967,3 +967,8 @@ int arch_compat_trampoline(struct kexec_info
>> *UNUSED(info))
>> void arch_update_purgatory(struct kexec_info *UNUSED(info))
>> {
>> }
>> +
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>> struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/s390/kexec-s390.c b/kexec/arch/s390/kexec-s390.c
>> index 33ba6b9..0561ee7 100644
>> --- a/kexec/arch/s390/kexec-s390.c
>> +++ b/kexec/arch/s390/kexec-s390.c
>> @@ -267,3 +267,8 @@ int get_crash_kernel_load_range(uint64_t *start,
>> uint64_t *end)
>> {
>> return parse_iomem_single("Crash kernel\n", start, end);
>> }
>> +
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>> struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>> diff --git a/kexec/arch/sh/kexec-sh.c b/kexec/arch/sh/kexec-sh.c
>> index ce341c8..f84c40c 100644
>> --- a/kexec/arch/sh/kexec-sh.c
>> +++ b/kexec/arch/sh/kexec-sh.c
>> @@ -257,3 +257,8 @@ unsigned long add_buffer(struct kexec_info *info,
>> const void *buf,
>> return add_buffer_phys_virt(info, buf, bufsz, memsz, buf_align,
>> buf_min, buf_max, buf_end, 1);
>> }
>> +
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>> struct kexec_info *UNUSED(info))
>> +{
>> + return 0;
>> +}
>
>> diff --git a/kexec/arch/x86_64/kexec-x86_64.c
>> b/kexec/arch/x86_64/kexec-x86_64.c
>> index ffd84f0..42af90a 100644
>> --- a/kexec/arch/x86_64/kexec-x86_64.c
>> +++ b/kexec/arch/x86_64/kexec-x86_64.c
>> @@ -188,3 +188,8 @@ void arch_update_purgatory(struct kexec_info *info)
>> elf_rel_set_symbol(&info->rhdr, "panic_kernel",
>> &panic_kernel, sizeof(panic_kernel));
>> }
>> +
>> +int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>> struct kexec_info *UNUSED(info))
>> +{
>
> This should also be similar to i386, no?
> Except for that, rest looks good..
In kexec tools, hotplug support for the kexec_load syscall is not yet
enabled for x86_64.
Hence, the function returns 0.
>
> Acked-by: Hari Bathini <hbathini@linux.ibm.com>
Thank you for reviewing and giving an Ack to the patch.
- Sourabh Jain
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/3] powerpc/kexec_load: add hotplug support
2024-06-10 9:38 ` Hari Bathini
@ 2024-06-10 12:19 ` Sourabh Jain
0 siblings, 0 replies; 12+ messages in thread
From: Sourabh Jain @ 2024-06-10 12:19 UTC (permalink / raw)
To: Hari Bathini, kexec; +Cc: Aditya Gupta, Baoquan He, Coiby Xu, Mahesh Salgaonkar
Hello Hari,
On 10/06/24 15:08, Hari Bathini wrote:
>
>
> On 22/05/24 6:43 pm, Sourabh Jain wrote:
>> Kernel commits b741092d5976 ("powerpc/crash: add crash CPU hotplug
>> support") and 849599b702ef ("powerpc/crash: add crash memory hotplug
>> support") added crash CPU/Memory hotplug support on PowerPC. This patch
>> extends that support for the kexec_load syscall.
>>
>> During CPU/Memory hotplug events on PowerPC, two kexec segments,
>> elfcorehdr, and FDT, get updated by the kernel. To ensure the kernel
>> can safely update these two kexec segments for the kdump image loaded
>> using the kexec_load system call, the following changes are made:
>>
>> 1. Extra size is allocated for both elfcorehdr and FDT to accommodate
>> additional resources in the future. For the elfcorehdr, the size
>> hint
>> is taken from /sys/kernel/crash_elfcorehdr_size sysfs, while for
>> FDT,
>> extra size is allocated to hold possible CPU nodes.
>>
>> 2. Both elfcorehdr and FDT are skipped from SHA calculation.
>>
>> Cc: Aditya Gupta <adityag@linux.ibm.com>
>> Cc: Baoquan He <bhe@redhat.com>
>> Cc: Coiby Xu <coxu@redhat.com>
>> Cc: Hari Bathini <hbathini@linux.ibm.com>
>> Cc: Mahesh Salgaonkar <mahesh@linux.ibm.com>
>> Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
>> ---
>> kexec/arch/ppc64/crashdump-ppc64.c | 16 ++-
>> kexec/arch/ppc64/fdt.c | 200 +++++++++++++++++++++++++++-
>> kexec/arch/ppc64/include/arch/fdt.h | 2 +-
>> kexec/arch/ppc64/kexec-elf-ppc64.c | 2 +-
>> kexec/arch/ppc64/kexec-ppc64.c | 12 +-
>> 5 files changed, 225 insertions(+), 7 deletions(-)
>>
>> diff --git a/kexec/arch/ppc64/crashdump-ppc64.c
>> b/kexec/arch/ppc64/crashdump-ppc64.c
>> index 6d47898..c14b593 100644
>> --- a/kexec/arch/ppc64/crashdump-ppc64.c
>> +++ b/kexec/arch/ppc64/crashdump-ppc64.c
>> @@ -476,7 +476,7 @@ int load_crashdump_segments(struct kexec_info
>> *info, char* mod_cmdline,
>> uint64_t max_addr, unsigned long min_base)
>> {
>> void *tmp;
>> - unsigned long sz;
>> + unsigned long sz, memsz;
>> uint64_t elfcorehdr;
>> int nr_ranges, align = 1024, i;
>> unsigned long long end;
>> @@ -531,8 +531,18 @@ int load_crashdump_segments(struct kexec_info
>> *info, char* mod_cmdline,
>> }
>> }
>> - elfcorehdr = add_buffer(info, tmp, sz, sz, align, min_base,
>> - max_addr, 1);
>> + memsz = sz;
>> + /* To support --hotplug, replace the calculated minimum size
>> with the
>> + * value from /sys/kernel/crash_elfcorehdr_size and align it
>> correctly.
>> + */
>> + if (do_hotplug) {
>> + if (elfcorehdrsz > sz)
>> + memsz = _ALIGN(elfcorehdrsz, align);
>> + }
>> +
>> + /* Record the location of the elfcorehdr for hotplug handling */
>> + info->elfcorehdr = elfcorehdr = add_buffer(info, tmp, sz, memsz,
>> align,
>> + min_base, max_addr, 1);
>> reserve(elfcorehdr, sz);
>> /* modify and store the cmdline in a global array. This is later
>> * read by flatten_device_tree and modified if required
>> diff --git a/kexec/arch/ppc64/fdt.c b/kexec/arch/ppc64/fdt.c
>> index 8bc6d2d..10abc29 100644
>> --- a/kexec/arch/ppc64/fdt.c
>> +++ b/kexec/arch/ppc64/fdt.c
>> @@ -17,6 +17,13 @@
>> #include <libfdt.h>
>> #include <stdio.h>
>> #include <stdlib.h>
>> +#include <limits.h>
>> +#include <stdbool.h>
>> +#include <dirent.h>
>> +#include <sys/stat.h>
>> +
>> +#include "../../kexec.h"
>> +#include "../../kexec-syscall.h"
>> /*
>> * Let the kernel know it booted from kexec, as some things (e.g.
>> @@ -46,17 +53,208 @@ static int fixup_kexec_prop(void *fdt)
>> return 0;
>> }
>> +static inline bool is_dot_dir(char * d_path)
>> +{
>> + return d_path[0] == '.';
>> +}
>> +
>> +/*
>> + * Returns size of files including file name size under the given
>> + * @cpu_node_path.
>> + */
>> +static unsigned int get_cpu_node_size(char *cpu_node_path)
>> +{
>> + DIR *d;
>> + struct dirent *de;
>> + struct stat statbuf;
>> + unsigned int cpu_node_size = 0;
>> + char cpu_prop_path[2 * PATH_MAX];
>> +
>> + d = opendir(cpu_node_path);
>> + if (!d)
>> + return 0;
>> +
>> + while ((de = readdir(d)) != NULL) {
>> + if (de->d_type != DT_REG)
>> + continue;
>> +
>> + memset(cpu_prop_path, '\0', PATH_MAX);
>> + snprintf(cpu_prop_path, 2 * PATH_MAX, "%s/%s",
>> cpu_node_path, de->d_name);
>> +
>> + if (stat(cpu_prop_path, &statbuf))
>> + continue;
>> +
>> + cpu_node_size += statbuf.st_size;
>> + cpu_node_size += strlen(de->d_name);
>> + }
>> +
>> + return cpu_node_size;
>> +}
>> +
>> +/*
>> + * Checks if the node specified by the given @path represents a CPU
>> node.
>> + *
>> + * Returns true if the @path has a "device_type" file containing "cpu";
>> + * otherwise, returns false.
>> + */
>> +static bool is_cpu_node(char *path)
>> +{
>> + FILE *file;
>> + bool ret = false;
>> + char device_type[4];
>> +
>> + file = fopen(path, "r");
>> + if (!file)
>> + return false;
>> +
>> + memset(device_type, '\0', 4);
>> + if (fread(device_type, 1, 3, file) < 3)
>> + goto out;
>> +
>> + if (strcmp(device_type, "cpu"))
>> + goto out;
>> +
>> + ret = true;
>> +
>> +out:
>> + fclose(file);
>> + return ret;
>> +}
>> +
>> +static unsigned int get_threads_per_cpu(char *path)
>> +{
>> + struct stat statbuf;
>> + if (stat(path, &statbuf))
>> + return 0;
>> +
>> + return statbuf.st_size / 4;
>> +}
>> +
>> +/*
>> + * Finds the following CPU attributes:
>> + *
>> + * cpus_in_system: Currently available CPU nodes present under
>> + * /proc/device-tree/cpus.
>> + * threads_per_cpu: Number of threads per CPU, based on the device
>> tree entry
>> + * /proc/device-tree/cpus/<cpu_node>/ibm,ppc-interrupt-server#s.
>> + * cpu_node_size: Size of files including file name size under a CPU
>> node.
>> + *
>> + * Returns 0 on success, else -1.
>> + */
>> +static unsigned int get_cpu_info(int *_cpus_in_system, int
>> *_threads_per_cpu,
>> + int *_cpu_node_size)
>> +{
>> + DIR *d;
>> + struct dirent *de;
>> + int first_cpu = 1;
>> + char path[PATH_MAX];
>> + char *cpus_node_path = "/proc/device-tree/cpus";
>> + int cpus_in_system = 0, threads_per_cpu = 0, cpu_node_size = 0;
>> +
>> + d = opendir(cpus_node_path);
>> + if (!d)
>> + return -1;
>> +
>> + while ((de = readdir(d)) != NULL) {
>> + if ((de->d_type != DT_DIR) || is_dot_dir(de->d_name))
>> + continue;
>> +
>> + memset(path, '\0', PATH_MAX);
>> + snprintf(path, PATH_MAX, "%s/%s/%s", cpus_node_path,
>> + de->d_name, "device_type");
>> +
>> + /* Skip nodes with device_type != "cpu" */
>> + if (!is_cpu_node(path))
>> + continue;
>> +
>> + /*
>> + * Found the first node under /proc/device-tree/cpus with
>> + * device_type == "cpu"
>> + */
>> + if (first_cpu) {
>> + memset(path, '\0', PATH_MAX);
>> + snprintf(path, PATH_MAX, "%s/%s", cpus_node_path,
>> de->d_name);
>> + cpu_node_size = get_cpu_node_size(path);
>> +
>> + memset(path, '\0', PATH_MAX);
>> + snprintf(path, PATH_MAX, "%s/%s/%s", cpus_node_path,
>> + de->d_name, "ibm,ppc-interrupt-server#s");
>> + threads_per_cpu = get_threads_per_cpu(path);
>> +
>> + first_cpu = 0;
>> + }
>> +
>> + cpus_in_system++;
>> + }
>> +
>> + closedir(d);
>> +
>> + dbgprintf("cpus_in_system: %d, threads_per_cpus: %d,
>> cpu_node_size: %d\n",
>> + cpus_in_system, threads_per_cpu, cpu_node_size);
>> +
>> + if (!(cpus_in_system && threads_per_cpu && cpu_node_size))
>> + return -1;
>> +
>> + *_cpus_in_system = cpus_in_system;
>> + *_threads_per_cpu = threads_per_cpu;
>> + *_cpu_node_size = cpu_node_size;
>> +
>> + return 0;
>> +}
>> +
>> +/*
>> + * Calculates the extra size needed for the flattened device tree
>> (FDT) based
>> + * on the difference between the possible number of CPU nodes and
>> the number
>> + * of CPU nodes present under /proc/device-tree/cpus.
>> + */
>> +static unsigned int kdump_fdt_extra_size(void)
>> +{
>> + unsigned int extra_size = 0;
>> + int cpus_in_system = 0, threads_per_cpu = 0, cpu_node_size = 0;
>> + int possible_cpus;
>> +
>> + /* ALL possible CPUs are present in FDT so no extra size
>> required */
>> + if (sysconf(_SC_NPROCESSORS_ONLN) == sysconf(_SC_NPROCESSORS_CONF))
>> + return 0;
>> +
>> + if (get_cpu_info(&cpus_in_system, &threads_per_cpu,
>> &cpu_node_size)) {
>
> Is (sysconf(_SC_NPROCESSORS_ONLN) / threads_per_cpu) not the same as
> 'cpus_in_system'? If they are same, should be able to get cpu_node_size
> & threads_per_cpu by examining a single core instead of going through
> all cores on the system??
Agree we can avoid traversing all cpu nodes. I will include the above
suggestion
in next version.
>
>> + die("Failed to get cpu info\n");
>> + }
>> +
>> + /*
>> + * Maximum number of CPU nodes with device_type = "cpu" possible
>> under
>> + * /proc/device-tree/cpus/
>> + */
>> + possible_cpus = sysconf(_SC_NPROCESSORS_CONF) / threads_per_cpu;
>> +
>> + if (cpus_in_system > possible_cpus)
>> + die("Possible CPU nodes can't be less than active CPU
>> nodes\n");
>> +
>> +
>> + extra_size = (possible_cpus - cpus_in_system) * cpu_node_size;
>> + dbgprintf("kdump fdt extra size: %u\n", extra_size);
>> +
>> + return extra_size;
>> +}
>> /*
>> * For now, assume that the added content fits in the file.
>> * This should be the case when flattening from /proc/device-tree,
>> * and when passing in a dtb, dtc can be told to add padding.
>> */
>> -int fixup_dt(char **fdt, off_t *size)
>> +int fixup_dt(char **fdt, off_t *size, unsigned long kexec_flags)
>> {
>> int ret;
>> *size += 4096;
>> +
>> + /* To support --hotplug option for the kexec_load syscall, consider
>> + * adding extra buffer to FDT so that the kernel can add CPU nodes
>> + * of hot-added CPUs.
>> + */
>> + if (do_hotplug && (kexec_flags & KEXEC_ON_CRASH))
>> + *size += kdump_fdt_extra_size();
>> +
>> *fdt = realloc(*fdt, *size);
>> if (!*fdt) {
>> fprintf(stderr, "%s: out of memory\n", __func__);
>> diff --git a/kexec/arch/ppc64/include/arch/fdt.h
>> b/kexec/arch/ppc64/include/arch/fdt.h
>> index b19f185..5f340b0 100644
>> --- a/kexec/arch/ppc64/include/arch/fdt.h
>> +++ b/kexec/arch/ppc64/include/arch/fdt.h
>> @@ -3,6 +3,6 @@
>> #include <sys/types.h>
>> -int fixup_dt(char **fdt, off_t *size);
>> +int fixup_dt(char **fdt, off_t *size, unsigned long kexec_flags);
>> #endif
>> diff --git a/kexec/arch/ppc64/kexec-elf-ppc64.c
>> b/kexec/arch/ppc64/kexec-elf-ppc64.c
>> index bdcfd20..858c994 100644
>> --- a/kexec/arch/ppc64/kexec-elf-ppc64.c
>> +++ b/kexec/arch/ppc64/kexec-elf-ppc64.c
>> @@ -345,7 +345,7 @@ int elf_ppc64_load(int argc, char **argv, const
>> char *buf, off_t len,
>> create_flatten_tree(&seg_buf, &seg_size, cmdline);
>> }
>> - result = fixup_dt(&seg_buf, &seg_size);
>> + result = fixup_dt(&seg_buf, &seg_size, info->kexec_flags);
>> if (result < 0)
>> return result;
>> diff --git a/kexec/arch/ppc64/kexec-ppc64.c
>> b/kexec/arch/ppc64/kexec-ppc64.c
>> index fb27b6b..f27d76b 100644
>> --- a/kexec/arch/ppc64/kexec-ppc64.c
>> +++ b/kexec/arch/ppc64/kexec-ppc64.c
>> @@ -24,6 +24,7 @@
>> #include <errno.h>
>> #include <stdint.h>
>> #include <string.h>
>> +#include <libfdt.h>
>> #include <sys/stat.h>
>> #include <sys/types.h>
>> #include <dirent.h>
>> @@ -968,7 +969,16 @@ void arch_update_purgatory(struct kexec_info
>> *UNUSED(info))
>> {
>> }
>> -int arch_do_exclude_segment(struct kexec_segment *UNUSED(seg_ptr),
>> struct kexec_info *UNUSED(info))
>> +int arch_do_exclude_segment(struct kexec_segment *seg_ptr, struct
>> kexec_info *info)
>> {
>
>> + if (!seg_ptr)
>
> When can this be true? If this is a possiblilty, why do we not have the
> same thing for i386?
I agree that seg_ptr can't be NULL, which makes the above check unnecessary.
I will remove it in the next version.
Thanks,
Sourabh Jain
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/3] doc/hotplug: update man and --help
2024-06-10 9:19 ` Hari Bathini
@ 2024-06-10 12:24 ` Sourabh Jain
0 siblings, 0 replies; 12+ messages in thread
From: Sourabh Jain @ 2024-06-10 12:24 UTC (permalink / raw)
To: Hari Bathini, kexec; +Cc: Aditya Gupta, Baoquan He, Coiby Xu, Mahesh Salgaonkar
Hello Hari,
On 10/06/24 14:49, Hari Bathini wrote:
>
>
> On 22/05/24 6:43 pm, Sourabh Jain wrote:
>> Update the man page and --help option to make the description of the
>> --hotplug option easier to understand.
>>
>> Cc: Aditya Gupta <adityag@linux.ibm.com>
>> Cc: Baoquan He <bhe@redhat.com>
>> Cc: Coiby Xu <coxu@redhat.com>
>> Cc: Hari Bathini <hbathini@linux.ibm.com>
>> Cc: Mahesh Salgaonkar <mahesh@linux.ibm.com>
>> Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
>> ---
>> kexec/kexec.8 | 8 ++++----
>> kexec/kexec.c | 3 ++-
>> 2 files changed, 6 insertions(+), 5 deletions(-)
>>
>> diff --git a/kexec/kexec.8 b/kexec/kexec.8
>> index 9e995fe..7dddae9 100644
>> --- a/kexec/kexec.8
>> +++ b/kexec/kexec.8
>> @@ -140,10 +140,10 @@ Open a help file for
>> .BR kexec .
>> .TP
>> .B \-\-hotplug
>
> Can we have the description changed like:
>
>> -Setup for kernel modification of the elfcorehdr. This option performs
>> -the steps needed to support kernel updates to the elfcorehdr in the
>> -presence of hot un/plug and/or on/offline events. This option only
>> -useful for KEXEC_LOAD syscall.
>> +Helps avoid kdump kernel reload on CPU/Memory hotplug or on/offline
>> events.
>> +If this option is enabled, the kexec segments will be set up in a
>> way that
>> +the kernel can safely update them on CPU/memory hotplug and/or
>> on/offline
>> +events. This option is only useful for the KEXEC_LOAD syscall.
>
> "Setup kexec segments such that kernel can safely update them on
> CPU/Memory hot add/remove events. If this option is enabled, kernel does
> in-kernel update of kexec segments on CPU/Memory hot add/remove events.
> Helps avoid the need to reload kdump kernel."
>
>
>> .TP
>> .B \-i\ (\-\-no-checks)
>> Fast reboot, no memory integrity checks.
>> diff --git a/kexec/kexec.c b/kexec/kexec.c
>> index 034cea6..2b06438 100644
>> --- a/kexec/kexec.c
>> +++ b/kexec/kexec.c
>> @@ -1093,7 +1093,8 @@ void usage(void)
>> " back to the compatibility syscall
>> when file based\n"
>> " syscall is not supported or the
>> kernel did not\n"
>> " understand the image (default)\n"
>> - " --hotplug Setup for kernel modification of
>> elfcorehdr.\n"
>
>> + " --hotplug Helps avoid kdump kernel reload on
>> CPU/Memory hotplug\n"
>> + " or on/offline events.\n"
>
> "Do in-kernel update of kexec segments on CPU/Memory hot add/remove
> events. This avoids the need to reload kdump kernel."
The suggested descriptions look good to me. I will update them in the
next version.
Thanks,
Sourabh Jain
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2024-06-10 12:25 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-05-22 13:13 [PATCH 1/3] kexec_load: Use new kexec flag for hotplug support Sourabh Jain
2024-05-22 13:13 ` [PATCH 2/3] powerpc/kexec_load: add " Sourabh Jain
2024-06-10 9:38 ` Hari Bathini
2024-06-10 12:19 ` Sourabh Jain
2024-05-22 13:13 ` [PATCH 3/3] doc/hotplug: update man and --help Sourabh Jain
2024-06-10 9:19 ` Hari Bathini
2024-06-10 12:24 ` Sourabh Jain
2024-05-28 11:33 ` [PATCH 1/3] kexec_load: Use new kexec flag for hotplug support Aditya Gupta
2024-05-29 13:13 ` Sourabh Jain
2024-05-30 6:23 ` Aditya Gupta
2024-06-10 8:52 ` Hari Bathini
2024-06-10 11:42 ` Sourabh Jain
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox