The Linux Kernel Mailing List
 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 28/42] KVM: x86: add VBS VTL call/return and cross-plane set-mem-attrs hypercalls
Date: Wed,  5 Aug 2026 04:03:10 -0700	[thread overview]
Message-ID: <20260805110324.25067-29-snambakam@linux.microsoft.com> (raw)
In-Reply-To: <20260805110324.25067-1-snambakam@linux.microsoft.com>

Add the in-kernel handling for the VBS secure-plane hypercalls so the
plane switch happens without bouncing through userspace:

 - KVM_HC_VBS_VTL_CALL: the normal plane (plane 0) records the
   calling-area GPA and switches to the secure plane. While the secure
   plane is still booting the call is parked (vtl_call_pending) and
   delivered once the plane parks itself; once ready (vtl_plane_ready)
   the GPA is delivered directly via kvm_vcpu_switch_plane().

 - KVM_HC_VBS_VTL_RETURN: the secure plane parks and hands control back
   to plane 0, marking itself ready and delivering any pending call.

 - KVM_HC_VBS_SET_MEM_ATTRS: the secure plane applies cross-plane EPT
   restrictions to a lower plane via kvm_vm_set_mem_attributes()
   (rejected from plane 0).

Track the per-CPU bootstrap state (vtl_plane_ready, vtl_call_pending,
vtl_call_ca) in kvm_vcpu_common and assign the new hypercall numbers
KVM_HC_VBS_VTL_RETURN (16) and KVM_HC_VBS_SET_MEM_ATTRS (17).

Signed-off-by: Sriram Nambakam <snambakam@linux.microsoft.com>
---
 arch/x86/kvm/x86.c            | 139 +++++++++++++++++++++++++++++++++-
 include/linux/kvm_host.h      |  17 +++++
 include/uapi/linux/kvm_para.h |   2 +
 3 files changed, 156 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index eb82dde62399..3c73ab1dcfe8 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -10588,9 +10588,145 @@ int ____kvm_emulate_hypercall(struct kvm_vcpu *vcpu, int cpl,
 		vcpu->arch.complete_userspace_io = complete_hypercall;
 		return 0;
 	}
+	case KVM_HC_VBS_VTL_CALL:
+#ifdef CONFIG_VM_PLANES
+		/*
+		 * Runtime VBS/VTL call from the normal world (plane 0) into the
+		 * secure plane.  Serviced in-kernel by switching to the secure
+		 * plane (plane 1) — no userspace round trip.  This is
+		 * arch-neutral: it works for both Intel (VMX) and AMD (SVM), and
+		 * mirrors the SEV-SNP in-kernel VMPL switch.  a0 carries the
+		 * guest-physical address of the shared calling area.
+		 *
+		 * Two cases:
+		 *  - Secure plane already booted and parked in its dispatch loop
+		 *    (vtl_plane_ready): deliver the calling-area GPA directly in
+		 *    RAX (its pending VTL return value) and switch to it.
+		 *  - Secure plane not booted yet (bootstrap): record the call as
+		 *    pending and switch to the secure plane so it boots; it will
+		 *    pick up the pending GPA when it reaches its first VTL return.
+		 *
+		 * If there is no secure plane configured at all, fall through to
+		 * the userspace path so QEMU can service the call.
+		 */
+		if (vcpu->plane_level == 0) {
+			struct kvm_vcpu_common *common = vcpu->common;
+			struct kvm_vcpu *secure = common->vcpus[1];
+
+			if (secure) {
+				common->vtl_call_ca = a0;
+
+				if (common->vtl_plane_ready) {
+					/* Parked in vtl_return: deliver now. */
+					kvm_rax_write(secure, a0);
+					common->vtl_call_pending = false;
+				} else {
+					/* Still booting: deliver on readiness. */
+					common->vtl_call_pending = true;
+				}
+
+				if (kvm_vcpu_switch_plane(vcpu, secure) == 1) {
+					ret = 0;
+					goto out;
+				}
+				ret = -KVM_EINVAL;
+				goto out;
+			}
+		}
+#endif /* CONFIG_VM_PLANES */
+		goto vtl_userspace_exit;
+	case KVM_HC_VBS_VTL_RETURN:
+#ifdef CONFIG_VM_PLANES
+		/*
+		 * The secure plane (plane >0) hands control back to plane 0
+		 * in-kernel.  This covers three situations:
+		 *  - Bootstrap "ready": the secure plane has just booted and is
+		 *    issuing its first VTL return to announce it is parked.
+		 *  - Normal completion: it has finished servicing a VTL call;
+		 *    the result is already in the shared calling area.
+		 *  - A call that arrived while the secure plane was still booting
+		 *    is now delivered (vtl_call_pending) by returning its
+		 *    calling-area GPA in RAX and keeping the secure plane running.
+		 * a0 is an optional status carried for tracing only.
+		 */
+		if (vcpu->plane_level == 0) {
+			ret = -KVM_EPERM;
+			goto out;
+		} else {
+			struct kvm_vcpu_common *common = vcpu->common;
+
+			common->vtl_plane_ready = true;
+
+			if (common->vtl_call_pending) {
+				/*
+				 * Deliver the call that triggered the secure
+				 * plane's boot: return its calling-area GPA and
+				 * stay in the secure plane to service it.  The
+				 * GPA is delivered as this hypercall's return
+				 * value (RAX) via the normal completion path; do
+				 * not write RAX directly here, as the completion
+				 * handler would overwrite it with hypercall.ret.
+				 */
+				common->vtl_call_pending = false;
+				ret = common->vtl_call_ca;
+				goto out;
+			}
+
+			if (kvm_vcpu_switch_plane(vcpu, common->vcpus[0]) == 1) {
+				ret = 0;
+				goto out;
+			}
+		}
+#endif /* CONFIG_VM_PLANES */
+		ret = -KVM_EINVAL;
+		goto out;
+	case KVM_HC_VBS_SET_MEM_ATTRS:
+#if defined(CONFIG_VM_PLANES) && defined(CONFIG_KVM_GENERIC_MEMORY_ATTRIBUTES)
+		/*
+		 * The secure plane (plane >0) enforces EPT permissions on the
+		 * normal plane's memory.  It cannot issue the host
+		 * KVM_SET_MEMORY_ATTRIBUTES ioctl, so it asks KVM to do it via
+		 * this hypercall.  Only a higher-privilege plane may call it.
+		 *
+		 *   a0 = guest-physical address (page aligned)
+		 *   a1 = region size in bytes  (page aligned)
+		 *   a2 = access bits to retain for lower planes:
+		 *        bit0 read (implicit), bit1 write, bit2 exec
+		 *        (matches VBS_MEM_READ/WRITE/EXEC)
+		 */
+		if (vcpu->plane_level == 0) {
+			ret = -KVM_EPERM;
+			goto out;
+		}
+
+		if (!PAGE_ALIGNED(a0) || !PAGE_ALIGNED(a1) || a1 == 0 ||
+		    a0 + a1 < a0) {
+			ret = -KVM_EINVAL;
+			goto out;
+		} else {
+			unsigned long attrs = 0;
+			gfn_t start = a0 >> PAGE_SHIFT;
+			gfn_t end = (a0 + a1) >> PAGE_SHIFT;
+
+			if (!(a2 & BIT(1)))
+				attrs |= KVM_MEMORY_ATTRIBUTE_NO_WRITE;
+			if (!(a2 & BIT(2)))
+				attrs |= KVM_MEMORY_ATTRIBUTE_NO_EXEC;
+
+			if (kvm_vm_set_mem_attributes(vcpu->kvm, start, end,
+						      attrs))
+				ret = -KVM_EINVAL;
+			else
+				ret = 0;
+			goto out;
+		}
+#else
+		ret = -KVM_ENOSYS;
+		goto out;
+#endif /* CONFIG_VM_PLANES && CONFIG_KVM_GENERIC_MEMORY_ATTRIBUTES */
 	case KVM_HC_VM_PLANES_CONFIG:
 	case KVM_HC_VM_PLANES_ACTIVATE:
-	case KVM_HC_VBS_VTL_CALL: {
+	vtl_userspace_exit:
 		ret = -KVM_ENOSYS;
 		if (!user_exit_on_hypercall(vcpu->kvm, nr))
 			break;
@@ -10609,7 +10745,6 @@ int ____kvm_emulate_hypercall(struct kvm_vcpu *vcpu, int cpl,
 		WARN_ON_ONCE(vcpu->run->hypercall.flags & KVM_EXIT_HYPERCALL_MBZ);
 		vcpu->arch.complete_userspace_io = complete_hypercall;
 		return 0;
-	}
 	default:
 		ret = -KVM_ENOSYS;
 		break;
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index c6cf2b6c0076..f14d78fd8cd3 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -386,6 +386,23 @@ struct kvm_vcpu_common {
 
 	bool plane_switch;
 
+#ifdef CONFIG_VM_PLANES
+	/*
+	 * VBS/VTL secure-plane bootstrap state (per logical CPU).
+	 *
+	 * @vtl_plane_ready: the secure plane has booted and parked itself in
+	 *                   its dispatch loop (issued its first VTL return).
+	 * @vtl_call_pending: a normal-plane VTL call has been registered but
+	 *                    not yet delivered to the secure plane (used while
+	 *                    the secure plane is still booting).
+	 * @vtl_call_ca:      guest-physical address of the pending call's
+	 *                    shared calling area.
+	 */
+	bool vtl_plane_ready;
+	bool vtl_call_pending;
+	u64 vtl_call_ca;
+#endif
+
 	struct kvm_vcpu_arch_common arch;
 };
 
diff --git a/include/uapi/linux/kvm_para.h b/include/uapi/linux/kvm_para.h
index 1703238952fb..eec4fce6b33a 100644
--- a/include/uapi/linux/kvm_para.h
+++ b/include/uapi/linux/kvm_para.h
@@ -33,6 +33,8 @@
 #define KVM_HC_VM_PLANES_CONFIG		13
 #define KVM_HC_VM_PLANES_ACTIVATE	14
 #define KVM_HC_VBS_VTL_CALL		15
+#define KVM_HC_VBS_VTL_RETURN		16
+#define KVM_HC_VBS_SET_MEM_ATTRS	17
 
 /*
  * hypercalls use architecture specific
-- 
2.55.0


  parent reply	other threads:[~2026-08-05 11:04 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 ` [RFC PATCH v1 09/42] Activate the VM Planes through the Hypervisor - Using KVM as the VMM Sriram Nambakam
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 ` Sriram Nambakam [this message]
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-29-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