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: <20250610021422.1214715-4-binbin.wu@linux.intel.com>
Date: Tue, 10 Jun 2025 10:14:21 +0800
From: Binbin Wu <binbin.wu@...ux.intel.com>
To: pbonzini@...hat.com,
	seanjc@...gle.com,
	kvm@...r.kernel.org
Cc: rick.p.edgecombe@...el.com,
	kai.huang@...el.com,
	adrian.hunter@...el.com,
	reinette.chatre@...el.com,
	xiaoyao.li@...el.com,
	tony.lindgren@...el.com,
	isaku.yamahata@...el.com,
	yan.y.zhao@...el.com,
	mikko.ylinen@...ux.intel.com,
	linux-kernel@...r.kernel.org,
	kirill.shutemov@...el.com,
	jiewen.yao@...el.com,
	binbin.wu@...ux.intel.com
Subject: [RFC PATCH 3/4] KVM: TDX: Exit to userspace for GetTdVmCallInfo

Exit to userspace for TDG.VP.VMCALL<GetTdVmCallInfo> via a new KVM exit
reason to allow userspace to provide information about the support of
TDVMCALLs when r12 is 1 for the TDVMCALLs beyond the GHCI base API.

GHCI spec defines the GHCI base TDVMCALLs: <GetTdVmCallInfo>, <MapGPA>,
<ReportFatalError>, <Instruction.CPUID>, <#VE.RequestMMIO>,
<Instruction.HLT>, <Instruction.IO>, <Instruction.RDMSR> and
<Instruction.WRMSR>. They must be supported by VMM to support TDX guests.

For GetTdVmCallInfo
- When leaf (r12) to enumerate TDVMCALL functionality is set to 0,
  successful execution indicates all GHCI base TDVMCALLs listed above are
  supported.

  Update the KVM TDX document with the set of the GHCI base APIs.

- When leaf (r12) to enumerate TDVMCALL functionality is set to 1, it
  indicates the TDX guest is querying the supported TDVMCALLs beyond
  the GHCI base TDVMCALLs.
  Exit to userspace to let userspace set the TDVMCALL sub-function bit(s)
  accordingly to the leaf outputs.  KVM could set the TDVMCALL bit(s)
  supported by itself when the TDVMCALLs don't need support from userspace
  after returning from userspace and before entering guest. Currently, no
  such TDVMCALLs implemented, KVM just sets the values returned from
  userspace.

  A new KVM exit reason KVM_EXIT_TDX_GET_TDVMCALL_INFO and its structure
  are added. Userspace is required to handle the exit reason as the initial
  support for TDX.

Suggested-by: Paolo Bonzini <pbonzini@...hat.com>
Signed-off-by: Binbin Wu <binbin.wu@...ux.intel.com>
---
 Documentation/virt/kvm/api.rst           | 17 +++++++++++
 Documentation/virt/kvm/x86/intel-tdx.rst |  9 ++++++
 arch/x86/kvm/vmx/tdx.c                   | 36 +++++++++++++++++++++---
 include/uapi/linux/kvm.h                 |  7 +++++
 4 files changed, 65 insertions(+), 4 deletions(-)

diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 7c5bb6b5c2c2..4a729841e000 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -7201,6 +7201,23 @@ generated Quote is returned via the same buffer. Userspace is required to handle
 the KVM exit reason as the initial support for TDX, however, userspace is
 allowed to set 'ret' filed to TDVMCALL_STATUS_SUBFUNC_UNSUPPORTED.
 
+::
+
+		/* KVM_EXIT_TDX_GET_TDVMCALL_INFO */
+		struct tdx_get_tdvmcall_info {
+			__u64 ret;
+			__u64 leaf;
+			__u64 leaf_output[4];
+		};
+
+If the exit reason is KVM_EXIT_TDX_GET_TDVMCALL_INFO, then it indicates that a
+TDX guest has requested to get the supporting status of TDVMCALLs. Currently,
+KVM only exits to userspace when the leaf value is 1, i.e, the TDX guest is
+querying the supporting status of TDVMCALLs beyond the GHCI base TDVMCALLs.
+Userspace is expected to set leaf outputs according to the layout defined in
+the GHCI spec if they are supported by userspace. Userspace is required to
+handle the exit reason as the initial support for TDX.
+
 ::
 
 		/* Fix the size of the union. */
diff --git a/Documentation/virt/kvm/x86/intel-tdx.rst b/Documentation/virt/kvm/x86/intel-tdx.rst
index 76bdd95334d6..69c64453e9ca 100644
--- a/Documentation/virt/kvm/x86/intel-tdx.rst
+++ b/Documentation/virt/kvm/x86/intel-tdx.rst
@@ -249,6 +249,15 @@ control flow is as follows:
 
 #. Run VCPU
 
+The GHCI base TDVMCALLs
+=======================
+The GHCI base TDVMCALLs are: <GetTdVmCallInfo>, <MapGPA>, <ReportFatalError>,
+<Instruction.CPUID>, <#VE.RequestMMIO>, <Instruction.HLT>, <Instruction.IO>,
+<Instruction.RDMSR> and <Instruction.WRMSR>. These base TDVMCALLs are mandatory
+for VMMs to support TDX guests.
+For the TDVMCALLs beyond the GHCI base TDVMCALLs, TDX guests can query the
+support status via GetTdVmCallInfo with leaf set to 1.
+
 References
 ==========
 
diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
index 35428c6b5a67..a3cd68f44a9c 100644
--- a/arch/x86/kvm/vmx/tdx.c
+++ b/arch/x86/kvm/vmx/tdx.c
@@ -1449,18 +1449,46 @@ static int tdx_emulate_mmio(struct kvm_vcpu *vcpu)
 	return 1;
 }
 
+static int tdx_complete_get_tdcall_info(struct kvm_vcpu *vcpu)
+{
+	struct vcpu_tdx *tdx = to_tdx(vcpu);
+
+	tdvmcall_set_return_code(vcpu, vcpu->run->tdx_get_tdvmcall_info.ret);
+
+	/*
+	 * For now, there is no TDVMCALL beyond GHCI base API supported by KVM
+	 * directly without the support from userspace, just set the value
+	 * returned from userspace.
+	 */
+	tdx->vp_enter_args.r11 = vcpu->run->tdx_get_tdvmcall_info.leaf_output[0];
+	tdx->vp_enter_args.r12 = vcpu->run->tdx_get_tdvmcall_info.leaf_output[1];
+	tdx->vp_enter_args.r13 = vcpu->run->tdx_get_tdvmcall_info.leaf_output[2];
+	tdx->vp_enter_args.r14 = vcpu->run->tdx_get_tdvmcall_info.leaf_output[3];
+
+	return 1;
+}
+
 static int tdx_get_td_vm_call_info(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_tdx *tdx = to_tdx(vcpu);
 
-	if (tdx->vp_enter_args.r12)
-		tdvmcall_set_return_code(vcpu, TDVMCALL_STATUS_INVALID_OPERAND);
-	else {
+	switch (tdx->vp_enter_args.r12) {
+	case 0:
 		tdx->vp_enter_args.r11 = 0;
 		tdx->vp_enter_args.r13 = 0;
 		tdx->vp_enter_args.r14 = 0;
+		return 1;
+	case 1:
+		vcpu->run->tdx_get_tdvmcall_info.leaf = 1;
+		vcpu->run->exit_reason = KVM_EXIT_TDX_GET_TDVMCALL_INFO;
+		vcpu->arch.complete_userspace_io = tdx_complete_get_tdcall_info;
+		memset(vcpu->run->tdx_get_tdvmcall_info.leaf_output, 0,
+		       sizeof(vcpu->run->tdx_get_tdvmcall_info.leaf_output));
+		return 0;
+	default:
+		tdvmcall_set_return_code(vcpu, TDVMCALL_STATUS_INVALID_OPERAND);
+		return 1;
 	}
-	return 1;
 }
 
 static int tdx_complete_get_quote(struct kvm_vcpu *vcpu)
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index e63e4df468b5..0729b37ac911 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -179,6 +179,7 @@ struct kvm_xen_exit {
 #define KVM_EXIT_LOONGARCH_IOCSR  38
 #define KVM_EXIT_MEMORY_FAULT     39
 #define KVM_EXIT_TDX_GET_QUOTE    40
+#define KVM_EXIT_TDX_GET_TDVMCALL_INFO  41
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 /* Emulate instruction failed. */
@@ -454,6 +455,12 @@ struct kvm_run {
 			__u64 gpa;
 			__u64 size;
 		} tdx_get_quote;
+		/* KVM_EXIT_TDX_GET_TDVMCALL_INFO */
+		struct {
+			__u64 ret;
+			__u64 leaf;
+			__u64 leaf_output[4];
+		} tdx_get_tdvmcall_info;
 		/* Fix the size of the union. */
 		char padding[256];
 	};
-- 
2.46.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ