[RFC PATCH v2 4/4] KVM: x86: handle VBS VTL call/return via in-kernel plane switch

Sriram Nambakam <[email protected]>
Newsgroups org.kernel.vger.kvm,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Service the VBS inter-plane hypercalls in-kernel, with no userspace round
trip, by switching planes:

  KVM_HC_VBS_VTL_CALL   - the normal plane (0) calls into the secure plane
                          (1).  a0 is the guest-physical address of the
                          shared calling area; deliver it to the secure
                          plane's pending VTL return (or mark it pending if
                          the secure plane is still booting) and switch.
  KVM_HC_VBS_VTL_RETURN - the secure plane (>0) hands control back to plane
                          0, announcing readiness and delivering any call
                          that arrived while it was booting.

The switch reuses the per-plane scheduling (kvm_vcpu_set_plane_runnable/
stopped + KVM_REQ_PLANE_RESCHED).
---
 arch/x86/kvm/x86.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 3b21c72fc9e0..35fbe0776a3e 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -10562,6 +10562,65 @@ 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: {
+		/*
+		 * Runtime VBS call from the normal plane (0) into the secure
+		 * plane (1), serviced in-kernel by switching planes.  a0 is the
+		 * guest-physical address of the shared calling area.  If the
+		 * secure plane is parked in its VTL return, deliver the GPA as
+		 * that return's value now; otherwise mark it pending so the
+		 * secure plane picks it up on its first return.
+		 */
+		struct kvm_vcpu_common *common = vcpu->common;
+		struct kvm_vcpu *secure;
+
+		if (vcpu->plane_level != 0)
+			break;
+
+		secure = common->vcpus[1];
+		if (!secure)
+			break;
+
+		common->vtl_call_ca = a0;
+		if (common->vtl_plane_ready) {
+			kvm_rax_write_raw(secure, a0);
+			common->vtl_call_pending = false;
+		} else {
+			common->vtl_call_pending = true;
+		}
+
+		kvm_vcpu_set_plane_runnable(secure);
+		kvm_vcpu_set_plane_stopped(vcpu);
+		ret = 0;
+		break;
+	}
+	case KVM_HC_VBS_VTL_RETURN: {
+		/*
+		 * The secure plane (>0) hands control back to plane 0.  On its
+		 * first return it announces readiness; if a call arrived while
+		 * it was still booting, deliver that calling-area GPA now and
+		 * stay in the secure plane.  Otherwise switch back to plane 0.
+		 */
+		struct kvm_vcpu_common *common = vcpu->common;
+
+		if (vcpu->plane_level == 0) {
+			ret = -KVM_EPERM;
+			break;
+		}
+
+		common->vtl_plane_ready = true;
+
+		if (common->vtl_call_pending) {
+			common->vtl_call_pending = false;
+			ret = common->vtl_call_ca;
+			break;
+		}
+
+		kvm_vcpu_set_plane_runnable(common->vcpus[0]);
+		kvm_vcpu_set_plane_stopped(vcpu);
+		ret = 0;
+		break;
+	}
 	case KVM_HC_VM_PLANES_CONFIG:
 	case KVM_HC_VM_PLANES_ACTIVATE:
 		/*
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.