Kernel KVM virtualization development
 help / color / mirror / Atom feed
From: Sriram Nambakam <snambakam@linux.microsoft.com>
To: kvm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Subject: [RFC PATCH v1 09/42] Activate the VM Planes through the Hypervisor - Using KVM as the VMM
Date: Wed,  5 Aug 2026 04:02:51 -0700	[thread overview]
Message-ID: <20260805110324.25067-10-snambakam@linux.microsoft.com> (raw)
In-Reply-To: <20260805110324.25067-1-snambakam@linux.microsoft.com>

---
 arch/x86/include/asm/cpu.h   |   3 +-
 arch/x86/kernel/cpu/common.c |  39 ++++++--
 include/linux/vm_planes.h    |   4 +-
 init/vm_planes.c             | 179 ++++++++++++++++++++++++++++++++++-
 4 files changed, 212 insertions(+), 13 deletions(-)

diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index 8ab76adf14a9..52e80c6ac8f0 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -13,8 +13,9 @@
 #ifdef CONFIG_VM_PLANES
 struct vm_plane_config;
 
-void __init alloc_vm_planes(unsigned int plane_count,
+int __init alloc_vm_planes(unsigned int plane_count,
 			    struct vm_plane_config *plane_cfg);
+int __init activate_vm_planes(unsigned int plane_count);
 #endif
 
 #ifndef CONFIG_SMP
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 166597204739..9912208d2010 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -82,7 +82,9 @@
 
 #ifdef CONFIG_VM_PLANES
 /* Private hypercall number for early VM plane configuration. */
-#define KVM_HC_VM_PLANES_CONFIG	0x1000
+#define KVM_HC_VM_PLANES_CONFIG		0x1000
+/* Private hypercall number to activate all configured planes. */
+#define KVM_HC_VM_PLANES_ACTIVATE	0x1001
 #endif
 
 DEFINE_PER_CPU_READ_MOSTLY(struct cpuinfo_x86, cpu_info);
@@ -2674,31 +2676,56 @@ void __init arch_cpu_finalize_init(void)
 }
 
 #ifdef CONFIG_VM_PLANES
-void __init alloc_vm_planes(unsigned int plane_count,
+int __init alloc_vm_planes(unsigned int plane_count,
 			    struct vm_plane_config *plane_cfg)
 {
 	phys_addr_t phys;
 	long ret;
 
 	if (!plane_count || !plane_cfg)
-		return;
+		return -EINVAL;
 
 	if (!kvm_para_available()) {
 		pr_warn("vm_planes: hypercall interface unavailable\n");
-		return;
+		return -ENODEV;
 	}
 
 	phys = virt_to_phys((void *)plane_cfg);
 
 	if (sizeof(unsigned long) < sizeof(phys_addr_t) && phys > ULONG_MAX) {
 		pr_warn("vm_planes: shared config address exceeds hypercall register width\n");
-		return;
+		return -EOVERFLOW;
 	}
 
 	ret = kvm_hypercall2(KVM_HC_VM_PLANES_CONFIG,
 			     (unsigned long)phys,
 			     plane_count);
-	if (ret < 0)
+	if (ret < 0) {
 		pr_warn("vm_planes: hypercall failed: %ld\n", ret);
+		return (int)ret;
+	}
+
+	return 0;
+}
+
+int __init activate_vm_planes(unsigned int plane_count)
+{
+	long ret;
+
+	if (!plane_count)
+		return -EINVAL;
+
+	if (!kvm_para_available()) {
+		pr_warn("vm_planes: hypercall interface unavailable\n");
+		return -ENODEV;
+	}
+
+	ret = kvm_hypercall1(KVM_HC_VM_PLANES_ACTIVATE, plane_count);
+	if (ret < 0) {
+		pr_warn("vm_planes: activate hypercall failed: %ld\n", ret);
+		return (int)ret;
+	}
+
+	return 0;
 }
 #endif
diff --git a/include/linux/vm_planes.h b/include/linux/vm_planes.h
index 6d0066f70349..5850c9e0d097 100644
--- a/include/linux/vm_planes.h
+++ b/include/linux/vm_planes.h
@@ -24,8 +24,8 @@ struct vm_plane_config {
 };
 
 void __init arch_init_vm_planes(void);
-void __init load_vm_plane_kernels(unsigned int plane_count,
-				  struct vm_plane_config *plane_cfg);
+int __init load_vm_plane_kernels(unsigned int plane_count,
+				 struct vm_plane_config *plane_cfg);
 
 #endif /* CONFIG_VM_PLANES */
 
diff --git a/init/vm_planes.c b/init/vm_planes.c
index da9c17de4a44..6fac52af4b77 100644
--- a/init/vm_planes.c
+++ b/init/vm_planes.c
@@ -11,7 +11,7 @@
 #include <linux/elf.h>
 #include <asm/cpu.h>
 #include <asm/kvm_para.h>
-#include <asm/io.h>
+#include <asm-generic/early_ioremap.h>
 
 #ifdef CONFIG_VM_PLANES
 static bool __initdata enable_vm_planes_requested;
@@ -405,6 +405,159 @@ static int __init vm_planes_get_cfg_from_initrd(unsigned int *plane_count,
 	return -ENOENT;
 }
 
+static int __init find_initrd_file(const char *filename,
+				   const u8 **out_data, u32 *out_size)
+{
+	const u8 *p = (const u8 *)(unsigned long)initrd_start;
+	const u8 *end = (const u8 *)(unsigned long)initrd_end;
+
+	if (!initrd_start || !initrd_end || initrd_end <= initrd_start)
+		return -ENOENT;
+
+	while (p + sizeof(struct cpio_newc_header) <= end) {
+		const struct cpio_newc_header *hdr;
+		const char *name;
+		const u8 *data;
+		u32 namesize, filesize;
+		u32 name_align, data_align;
+		int ret;
+
+		hdr = (const struct cpio_newc_header *)p;
+		if (memcmp(hdr->c_magic, "070701", 6) &&
+		    memcmp(hdr->c_magic, "070702", 6))
+			return -EINVAL;
+
+		ret = parse_hex_field(hdr->c_namesize,
+				      sizeof(hdr->c_namesize), &namesize);
+		if (ret)
+			return ret;
+
+		ret = parse_hex_field(hdr->c_filesize,
+				      sizeof(hdr->c_filesize), &filesize);
+		if (ret)
+			return ret;
+
+		if (!namesize)
+			return -EINVAL;
+
+		p += sizeof(*hdr);
+		if (p + namesize > end)
+			return -EINVAL;
+
+		name = (const char *)p;
+		name_align = ALIGN(namesize, 4);
+		if (p + name_align > end)
+			return -EINVAL;
+
+		data = p + name_align;
+		if (data + filesize > end)
+			return -EINVAL;
+
+		if (!strcmp(name, "TRAILER!!!"))
+			break;
+
+		if (cpio_name_match(name, namesize, filename)) {
+			*out_data = data;
+			*out_size = filesize;
+			return 0;
+		}
+
+		data_align = ALIGN(filesize, 4);
+		if (data + data_align < data || data + data_align > end)
+			return -EINVAL;
+
+		p = data + data_align;
+	}
+
+	return -ENOENT;
+}
+
+static int __init copy_to_early_mem(phys_addr_t dest, const void *src,
+				    unsigned long size)
+{
+	unsigned long slop, clen;
+	char *p;
+
+	while (size) {
+		slop = offset_in_page(dest);
+		clen = size;
+		if (clen > PAGE_SIZE - slop)
+			clen = PAGE_SIZE - slop;
+		p = early_memremap(dest & PAGE_MASK, clen + slop);
+		if (!p)
+			return -ENOMEM;
+		memcpy(p + slop, src, clen);
+		early_memunmap(p, clen + slop);
+		dest += clen;
+		src += clen;
+		size -= clen;
+	}
+	return 0;
+}
+
+static int __init load_plane_kernel_raw(const u8 *data, u32 size,
+					struct vm_plane_config *cfg)
+{
+	if (size > cfg->memory_size) {
+		pr_err("vm_planes: raw kernel image (%u bytes) exceeds plane memory (%llu bytes)\n",
+		       size, (unsigned long long)cfg->memory_size);
+		return -ENOMEM;
+	}
+
+	return copy_to_early_mem(cfg->load_offset, data, size);
+}
+
+int __init load_vm_plane_kernels(unsigned int plane_count,
+				 struct vm_plane_config *plane_cfg)
+{
+	unsigned int i;
+	int err = 0;
+
+	for (i = 1; i < plane_count; i++) {
+		const u8 *data;
+		u32 size;
+		int ret;
+
+		ret = find_initrd_file(plane_cfg[i].kernel, &data, &size);
+		if (ret) {
+			pr_err("vm_planes: plane %u: kernel image '%s' not found in initrd\n",
+			       i, plane_cfg[i].kernel);
+			err = ret;
+			continue;
+		}
+
+		switch (plane_cfg[i].kernel_format) {
+		case VM_PLANE_KFMT_RAW:
+			ret = load_plane_kernel_raw(data, size,
+						    &plane_cfg[i]);
+			break;
+		case VM_PLANE_KFMT_BZIMAGE:
+		case VM_PLANE_KFMT_ELF:
+			pr_err("vm_planes: plane %u: kernel format not yet supported\n",
+			       i);
+			err = -ENOSYS;
+			continue;
+		default:
+			pr_err("vm_planes: plane %u: unknown kernel format %u\n",
+			       i, plane_cfg[i].kernel_format);
+			err = -EINVAL;
+			continue;
+		}
+
+		if (ret) {
+			pr_err("vm_planes: plane %u: failed to load kernel image: %d\n",
+			       i, ret);
+			err = ret;
+		} else {
+			pr_info("vm_planes: plane %u: loaded '%s' (%u bytes) at 0x%llx\n",
+				i, plane_cfg[i].kernel,
+				size, (unsigned long long)plane_cfg[i].load_offset);
+		}
+	}
+
+	return err;
+}
+
 static int __init parse_enable_vm_planes(char *str)
 {
 	bool enable;
@@ -423,13 +576,16 @@ static int __init parse_enable_vm_planes(char *str)
 
 early_param("enable-vm-planes", parse_enable_vm_planes);
 
-void __init __weak alloc_vm_planes(unsigned int plane_count,
-				   struct vm_plane_config *plane_cfg) { }
+int __init __weak alloc_vm_planes(unsigned int plane_count,
+				   struct vm_plane_config *plane_cfg) { return -ENOSYS; }
+
+int __init __weak activate_vm_planes(unsigned int plane_count) { return -ENOSYS; }
 
 void __init arch_init_vm_planes(void)
 {
 	unsigned int plane_count = VM_PLANES_DEFAULT_COUNT;
 	struct vm_plane_config *plane_cfg;
+	int ret;
 
 	if (!enable_vm_planes_requested)
 		return;
@@ -445,7 +601,22 @@ void __init arch_init_vm_planes(void)
 
 	pr_info("vm_planes: enabling %u planes (ids 0..%u)\n",
 		plane_count, plane_count - 1);
-	alloc_vm_planes(plane_count, plane_cfg);
+
+	ret = alloc_vm_planes(plane_count, plane_cfg);
+	if (ret) {
+		pr_err("vm_planes: failed to allocate planes: %d\n", ret);
+		return;
+	}
+
+	ret = load_vm_plane_kernels(plane_count, plane_cfg);
+	if (ret) {
+		pr_err("vm_planes: failed to load plane kernels: %d\n", ret);
+		return;
+	}
+
+	ret = activate_vm_planes(plane_count);
+	if (ret)
+		pr_err("vm_planes: failed to activate planes: %d\n", ret);
 }
 
 #endif /* CONFIG_VM_PLANES */
-- 
2.55.0


  parent reply	other threads:[~2026-08-05 11:03 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-05 11:02 [RFC PATCH v1 00/42] VBS/VSM-on-KVM: VBS integration for KVM VM planes Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 01/42] Fix merge issue - Remove duplicate definition for kvm_arch_has_irq_bypass Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 02/42] Fix compilation Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 03/42] Fix compile error Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 04/42] Fix compile errors Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 05/42] Initial support for VM Planes - Add kernel config for CONFIG_VM_PLANES - Parse vm plane config from initrd for plane configuration - Make hypercalls to allocate memory for the vm planes Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 06/42] Use vcpu count from the plane configuration Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 07/42] skip processing plane configuration for plane 0 - plane 0 is the boot plane Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 08/42] Add plane config param to specify kernel image format Sriram Nambakam
2026-08-05 11:02 ` Sriram Nambakam [this message]
2026-08-05 11:02 ` [RFC PATCH v1 10/42] allow the command line to be specified for kernels in other planes Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 11/42] Various changes to support VM Planes Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 12/42] Add a Virtualization Based Security (VBS) framework. - Add backends for AMD SEV-SNP, Intel TDX, Arm CCA and KVM Planes. - Support VTL on Hyper-V in addition to Planes on KVM Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 13/42] Add a inter-plane communication mechanism through KVM. - model this to use a single page similar to SEV-SNP Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 14/42] KVM: Add per-plane memory attribute support for cross-plane EPT protection Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 15/42] KVM: x86: Add KVM_HC_VBS_VTL_CALL hypercall for VBS inter-plane calls Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 16/42] vbs: Add HEKI kernel sealing and fix KVM plane memory attribute guards Sriram Nambakam
2026-08-05 11:02 ` [RFC PATCH v1 17/42] vbs: Add module authentication via VBS/HEKI Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 18/42] vbs: Add kexec validation and make module auth non-fatal Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 19/42] Merge branch 'master' into vm-planes Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 20/42] kvm: x86: fix merged plane API/stat build regressions Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 21/42] KVM: x86: exit VM planes and VBS hypercalls to userspace Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 22/42] kexec: block legacy kexec_load when VBS is active Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 23/42] kvm: x86: fix merged plane API/stat build regressions Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 24/42] KVM: planes: expose memory-attribute setting to in-kernel callers Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 25/42] vm_planes: drop unused per-plane vcpu_count Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 26/42] drivers/virt: add VBS secure-plane park loop Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 27/42] KVM: planes: add arch-neutral in-kernel plane switch helper Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 28/42] KVM: x86: add VBS VTL call/return and cross-plane set-mem-attrs hypercalls Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 29/42] init/vm_planes: set up planes from rootfs_initcall and load ELF payloads Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 30/42] security/vbs: run backend probe and HEKI seal at rootfs_initcall Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 31/42] security/vbs: pin the VTL call hypercall to CPU0 Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 32/42] security/vbs: add secure-plane monitor backend Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 33/42] drivers/virt: rename VBS park loop to secure_monitor Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 34/42] x86/realmode: skip the sub-1M trampoline for the VBS secure plane Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 35/42] KVM: x86: deny normal-plane access to secure-plane memory Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 36/42] KVM: plane: handle KVM_CHECK_EXTENSION on the plane fd Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 37/42] KVM: selftests: run plane tests with a split IRQ chip Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 38/42] kvm: x86: drop obsolete kvm_cache_regs.h Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 39/42] kvm: arch: finalize plane hooks and kvm_arch_vcpu_create signature Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 40/42] kvm: x86: use kvm_vcpu scheduling-state accessors and struct stat fields Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 41/42] kvm: x86: finalize per-plane APIC state and CPUID placement Sriram Nambakam
2026-08-05 11:03 ` [RFC PATCH v1 42/42] kvm: planes: reconcile core plane state, UAPI and hypercall exit Sriram Nambakam

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260805110324.25067-10-snambakam@linux.microsoft.com \
    --to=snambakam@linux.microsoft.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox