lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20251019061631.2235405-10-xiyou.wangcong@gmail.com>
Date: Sat, 18 Oct 2025 23:16:23 -0700
From: Cong Wang <xiyou.wangcong@...il.com>
To: linux-kernel@...r.kernel.org
Cc: jiri@...nulli.us,
	stefanha@...hat.com,
	multikernel@...ts.linux.dev,
	pasha.tatashin@...een.com,
	Cong Wang <cwang@...tikernel.io>,
	Andrew Morton <akpm@...ux-foundation.org>,
	Baoquan He <bhe@...hat.com>,
	Alexander Graf <graf@...zon.com>,
	Mike Rapoport <rppt@...nel.org>,
	Changyuan Lyu <changyuanl@...gle.com>,
	kexec@...ts.infradead.org,
	linux-mm@...ck.org
Subject: [RFC Patch v2 09/16] kexec: Integrate multikernel instance management with kexec subsystem

From: Cong Wang <cwang@...tikernel.io>

Establish bidirectional integration between the kexec subsystem and
multikernel instance management, enabling proper lifecycle tracking
and resource coordination for multikernel operations.

This commit introduces:

* Enhanced kimage structure with multikernel-specific fields including
  mk_id for unique multikernel identification and mk_instance pointer
  for cross-referencing with the multikernel instance management
  system, enabling proper state synchronization.

* UAPI extensions in include/uapi/linux/kexec.h that define multikernel
  ID encoding within kexec flags using KEXEC_MK_ID_MASK and
  KEXEC_MK_ID_SHIFT, providing up to 2047 unique multikernel instances
  with proper bit field management macros.

* Multikernel image lookup infrastructure through kimage_find_by_id()
  that leverages the mk_instance system for efficient image retrieval
  by multikernel ID, replacing CPU-based lookup with proper instance
  management.

* Refactored multikernel_kexec() interface from CPU-based to ID-based
  operation (multikernel_kexec_by_id()) that uses instance CPU
  assignments from device tree configuration rather than manual CPU
  specification, improving safety and consistency.

* Proper resource lifecycle management in kimage_free() that clears
  cross-references, updates instance states, and handles reference
  counting when multikernel images are freed, preventing resource
  leaks and dangling pointers.

* Updated reboot syscall interface that accepts multikernel instance
  IDs instead of CPU numbers in LINUX_REBOOT_CMD_MULTIKERNEL,
  providing a more intuitive and safer user interface.

Signed-off-by: Cong Wang <cwang@...tikernel.io>
---
 include/linux/kexec.h       | 10 ++++-
 include/linux/multikernel.h |  3 ++
 include/uapi/linux/kexec.h  |  4 ++
 kernel/kexec_core.c         | 75 +++++++++++++++++++++++++++++++++----
 kernel/reboot.c             |  4 +-
 5 files changed, 85 insertions(+), 11 deletions(-)

diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 69877db5360b..5e9e9ad1dfeb 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -132,6 +132,7 @@ struct purgatory_info {
 };
 
 struct kimage;
+struct mk_instance;
 
 typedef int (kexec_probe_t)(const char *kernel_buf, unsigned long kernel_size);
 typedef void *(kexec_load_t)(struct kimage *image, char *kernel_buf,
@@ -434,6 +435,12 @@ struct kimage {
 
 	/* For multikernel support: linked list node */
 	struct list_head list;
+
+	/* Multikernel unique ID (0 = current kernel, >0 = multikernel images) */
+	int mk_id;
+
+	/* Multikernel instance cross-reference */
+	struct mk_instance *mk_instance;
 };
 
 /* kexec interface functions */
@@ -441,7 +448,8 @@ extern void machine_kexec(struct kimage *image);
 extern int machine_kexec_prepare(struct kimage *image);
 extern void machine_kexec_cleanup(struct kimage *image);
 extern int kernel_kexec(void);
-extern int multikernel_kexec(int cpu);
+extern int multikernel_kexec_by_id(int mk_id);
+extern struct kimage *kimage_find_by_id(int mk_id);
 extern struct page *kimage_alloc_control_pages(struct kimage *image,
 						unsigned int order);
 
diff --git a/include/linux/multikernel.h b/include/linux/multikernel.h
index 75cbb316d565..c65d39a66b84 100644
--- a/include/linux/multikernel.h
+++ b/include/linux/multikernel.h
@@ -102,6 +102,9 @@ struct mk_instance {
 	void *dtb_data;                 /* Device tree blob data */
 	size_t dtb_size;                /* Size of DTB */
 
+	/* Kexec integration */
+	struct kimage *kimage;          /* Associated kimage object */
+
 	/* Sysfs representation */
 	struct kernfs_node *kn;            /* Kernfs node for this instance */
 
diff --git a/include/uapi/linux/kexec.h b/include/uapi/linux/kexec.h
index 346e0ff4e663..82a562ae6ac1 100644
--- a/include/uapi/linux/kexec.h
+++ b/include/uapi/linux/kexec.h
@@ -15,6 +15,10 @@
 #define KEXEC_UPDATE_ELFCOREHDR	0x00000004
 #define KEXEC_CRASH_HOTPLUG_SUPPORT 0x00000008
 #define KEXEC_MULTIKERNEL	0x00000010
+#define KEXEC_MK_ID_MASK	0x0000ffe0
+#define KEXEC_MK_ID_SHIFT	5
+#define KEXEC_MK_ID(id)		(((id) << KEXEC_MK_ID_SHIFT) & KEXEC_MK_ID_MASK)
+#define KEXEC_GET_MK_ID(flags)	(((flags) & KEXEC_MK_ID_MASK) >> KEXEC_MK_ID_SHIFT)
 #define KEXEC_ARCH_MASK		0xffff0000
 
 /*
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index 449096060fe8..ed5c97b4531e 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -40,6 +40,7 @@
 #include <linux/hugetlb.h>
 #include <linux/objtool.h>
 #include <linux/kmsg_dump.h>
+#include <linux/multikernel.h>
 #include <linux/dma-map-ops.h>
 #include <linux/memblock.h>
 
@@ -255,6 +256,12 @@ struct kimage *do_kimage_alloc_init(void)
 	/* Initialize the list node for multikernel support */
 	INIT_LIST_HEAD(&image->list);
 
+	/* Initialize multikernel ID (0 = current kernel, will be assigned later for multikernel) */
+	image->mk_id = 0;
+
+	/* Initialize multikernel instance cross-reference */
+	image->mk_instance = NULL;
+
 #ifdef CONFIG_CRASH_HOTPLUG
 	image->hp_action = KEXEC_CRASH_HP_NONE;
 	image->elfcorehdr_index = -1;
@@ -594,6 +601,16 @@ void kimage_free(struct kimage *image)
 	else if (image == kexec_crash_image)
 		kimage_update_compat_pointers(NULL, KEXEC_TYPE_CRASH);
 
+	/* Remove from IDR if it's a multikernel image */
+	if (image->type == KEXEC_TYPE_MULTIKERNEL && image->mk_instance) {
+		/* Clear cross-reference and update state */
+		image->mk_instance->kimage = NULL;
+		mk_instance_set_state(image->mk_instance, MK_STATE_READY);
+		mk_instance_put(image->mk_instance);
+		image->mk_instance = NULL;
+		pr_info("Freed multikernel ID %d\n", image->mk_id);
+	}
+
 #ifdef CONFIG_CRASH_DUMP
 	if (image->vmcoreinfo_data_copy) {
 		crash_update_vmcoreinfo_safecopy(NULL);
@@ -1393,26 +1410,68 @@ int kernel_kexec(void)
 	return error;
 }
 
-int multikernel_kexec(int cpu)
+/*
+ * Find a multikernel image by ID using mk_instance lookup
+ */
+struct kimage *kimage_find_by_id(int mk_id)
 {
-	int rc;
+	struct mk_instance *instance;
+	struct kimage *image = NULL;
 
-	pr_info("multikernel kexec: cpu %d\n", cpu);
+	if (mk_id <= 0)
+		return NULL;
 
-	if (cpu_online(cpu)) {
-		pr_err("The CPU is currently running with this kernel instance.");
-		return -EBUSY;
+	/* Use mk_instance system to find the associated kimage */
+	instance = mk_instance_find(mk_id);
+	if (instance) {
+		image = instance->kimage;
+		mk_instance_put(instance); /* Release reference from find */
 	}
 
+	return image;
+}
+
+int multikernel_kexec_by_id(int mk_id)
+{
+	struct kimage *mk_image;
+	struct mk_instance *instance;
+	int cpu = -1;
+	int rc;
+
 	if (!kexec_trylock())
 		return -EBUSY;
-	if (!kexec_image) {
+
+	mk_image = kimage_find_by_id(mk_id);
+	if (!mk_image) {
+		pr_err("No multikernel image found with ID %d\n", mk_id);
 		rc = -EINVAL;
 		goto unlock;
 	}
 
+	instance = mk_image->mk_instance;
+	if (instance->cpus_valid && !cpumask_empty(instance->cpus)) {
+		cpu = cpumask_first(instance->cpus);
+		pr_info("multikernel kexec: using assigned CPU %d from instance cpumask %*pbl\n",
+			cpu, cpumask_pr_args(instance->cpus));
+	} else {
+		pr_err("No CPU assignment found for multikernel instance %d - CPU assignment is required\n",
+		       mk_id);
+		rc = -EINVAL;
+		goto unlock;
+	}
+
+	if (cpu_online(cpu)) {
+		pr_err("CPU %d is currently online and cannot be used for multikernel instance %d\n",
+		       cpu, mk_id);
+		rc = -EBUSY;
+		goto unlock;
+	}
+
+	pr_info("Using multikernel image with ID %d (entry point: 0x%lx) on CPU %d\n",
+		mk_image->mk_id, mk_image->start, cpu);
+
 	cpus_read_lock();
-	rc = multikernel_kick_ap(cpu, kexec_image->start);
+	rc = multikernel_kick_ap(cpu, mk_image->start);
 	cpus_read_unlock();
 
 unlock:
diff --git a/kernel/reboot.c b/kernel/reboot.c
index f3ac703c4695..bff6d3603a17 100644
--- a/kernel/reboot.c
+++ b/kernel/reboot.c
@@ -718,7 +718,7 @@ EXPORT_SYMBOL_GPL(kernel_power_off);
 DEFINE_MUTEX(system_transition_mutex);
 
 struct multikernel_boot_args {
-	int cpu;
+	int mk_id;
 };
 
 /*
@@ -807,7 +807,7 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
 	case LINUX_REBOOT_CMD_MULTIKERNEL:
 		if (copy_from_user(&boot_args, arg, sizeof(boot_args)))
 			return -EFAULT;
-		ret = multikernel_kexec(boot_args.cpu);
+		ret = multikernel_kexec_by_id(boot_args.mk_id);
 		break;
 #endif
 
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ