From nobody Sat Feb 7 15:38:38 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 376B5241CB6; Tue, 10 Jun 2025 02:13:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749521616; cv=none; b=jiXjr/wRv7vX+2BhXkhCbpHKTG33GD3KqGx5UpaX/rajHiw8KEcbgvg6FE4vCJtfRcIlGEqkV51p7+R2oujNfEYAMuq2n232asoeXsga9aJw/4V8wx4KV+svPdwY6YthwUW6+rgVACVp4SXzq676YKxwA0Pni7a9iaEVZYA1tyk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749521616; c=relaxed/simple; bh=JBhvf9pacAdWdDHVLo4yQfhQ98AEN7EsRSZJLl5dERU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EvLQq0lw92hAyP4v/mpBfbNON1eb+dI8Jbw+LQIT3GL265jd13jlRv2/HMU/wBMdnxr9d9dsIwDqOJKQofrF3rW6WkoJw9eHgRbSkWfshvZ/A1ozTI8nUYfrRPwEB7tikbSgmf5WeVEQjIggh3BV1PnPg/bPpBvhde81zAY8k94= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=iZKTQPGF; arc=none smtp.client-ip=192.198.163.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="iZKTQPGF" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1749521614; x=1781057614; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=JBhvf9pacAdWdDHVLo4yQfhQ98AEN7EsRSZJLl5dERU=; b=iZKTQPGFvu872WaD8kqh0ya/9YnXW8Mo/NPhgPvfCT09oiVPEHa5Rn5t ga/2QyLRJyzImp7WUJ8wXIX9+1iD94p+1ojZIfcmzs/n5Y/b0ZC6Gr95u PWxBM/00ZiIYfThv15uXLsE7yYW5/hPL4U1Jn9dbZ3ikE0X1/DGLHD48E jB/rgk0htvrZqge/RkyZt/CoHP5/FHQ6D24VlcwKSMJMxH6XVJhWfCf6Q i0MjIShcpCvmnAX4Zk458nHIA28VdUtOdP8Cfxwvz/jL8Et77KD6/oNLr gridxw6qxm4l6OeAwFrnn0xkZAXAcX8jqO1CJn8LSFqcPWTFLkea7Tq4k g==; X-CSE-ConnectionGUID: H5FmMI4uQGqptHYQ+nOcng== X-CSE-MsgGUID: 3asSDE3YRP67ckevvyQNkw== X-IronPort-AV: E=McAfee;i="6800,10657,11459"; a="50841179" X-IronPort-AV: E=Sophos;i="6.16,223,1744095600"; d="scan'208";a="50841179" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa112.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Jun 2025 19:13:34 -0700 X-CSE-ConnectionGUID: GI01MJORQ1ejLb+7OMo2bw== X-CSE-MsgGUID: B/DgHdgsT7yQFqdOuJf+1w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,223,1744095600"; d="scan'208";a="147253724" Received: from litbin-desktop.sh.intel.com ([10.239.156.93]) by orviesa007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Jun 2025 19:13:31 -0700 From: Binbin Wu To: pbonzini@redhat.com, seanjc@google.com, kvm@vger.kernel.org Cc: rick.p.edgecombe@intel.com, kai.huang@intel.com, adrian.hunter@intel.com, reinette.chatre@intel.com, xiaoyao.li@intel.com, tony.lindgren@intel.com, isaku.yamahata@intel.com, yan.y.zhao@intel.com, mikko.ylinen@linux.intel.com, linux-kernel@vger.kernel.org, kirill.shutemov@intel.com, jiewen.yao@intel.com, binbin.wu@linux.intel.com Subject: [RFC PATCH 1/4] KVM: TDX: Add new TDVMCALL status code for unsupported subfuncs Date: Tue, 10 Jun 2025 10:14:19 +0800 Message-ID: <20250610021422.1214715-2-binbin.wu@linux.intel.com> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20250610021422.1214715-1-binbin.wu@linux.intel.com> References: <20250610021422.1214715-1-binbin.wu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add the new TDVMCALL status code TDVMCALL_STATUS_SUBFUNC_UNSUPPORTED and return it for unimplemented TDVMCALL subfunctions. Returning TDVMCALL_STATUS_INVALID_OPERAND when a subfunction is not implemented is vague because TDX guests can't tell the error is due to the subfunction is not supported or an invalid input of the subfunction. New GHCI spec adds TDVMCALL_STATUS_SUBFUNC_UNSUPPORTED to avoid the ambiguity. Use it instead of TDVMCALL_STATUS_INVALID_OPERAND. Before the change, for common guest implementations, when a TDX guest receives TDVMCALL_STATUS_INVALID_OPERAND, it has two cases: 1. Some operand is invalid. It could change the operand to another value retry. 2. The subfunction is not supported. For case 1, an invalid operand usually means the guest implementation bug. Since the TDX guest can't tell which case is, the best practice for handling TDVMCALL_STATUS_INVALID_OPERAND is stopping calling such leaf. Treat it as fatal if the TDVMCALL is essential or ignore it if the TDVMCALL is optional. After the change, TDVMCALL_STATUS_SUBFUNC_UNSUPPORTED is unknown to the old TDX guest, the guest will make the same action as TDVMCALL_STATUS_INVALID_OPERAND, unless the guest check the TDVMCALL_STATUS_INVALID_OPERAND specifically. Currently, no known TDX guests do it, e.g., Linux TDX guests just check for success. Signed-off-by: Binbin Wu --- arch/x86/include/asm/shared/tdx.h | 1 + arch/x86/kvm/vmx/tdx.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/share= d/tdx.h index fd9209e996e7..b109b947fadf 100644 --- a/arch/x86/include/asm/shared/tdx.h +++ b/arch/x86/include/asm/shared/tdx.h @@ -79,6 +79,7 @@ #define TDVMCALL_STATUS_RETRY 0x0000000000000001ULL #define TDVMCALL_STATUS_INVALID_OPERAND 0x8000000000000000ULL #define TDVMCALL_STATUS_ALIGN_ERROR 0x8000000000000002ULL +#define TDVMCALL_STATUS_SUBFUNC_UNSUPPORTED 0x8000000000000003ULL =20 /* * Bitmasks of exposed registers (with VMM). diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c index b952bc673271..8134d5805b03 100644 --- a/arch/x86/kvm/vmx/tdx.c +++ b/arch/x86/kvm/vmx/tdx.c @@ -1476,7 +1476,7 @@ static int handle_tdvmcall(struct kvm_vcpu *vcpu) break; } =20 - tdvmcall_set_return_code(vcpu, TDVMCALL_STATUS_INVALID_OPERAND); + tdvmcall_set_return_code(vcpu, TDVMCALL_STATUS_SUBFUNC_UNSUPPORTED); return 1; } =20 --=20 2.46.0 From nobody Sat Feb 7 15:38:38 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A3ED72417C3; Tue, 10 Jun 2025 02:13:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749521625; cv=none; b=qX0H5Im4qT/aUt+Jl+nXHX40ccsndV47ZRDl93KkidYOhcZ1ddeVTMeoPWn/bXlJkVcmh73YjWrtofgK/a5jTwprY021t22j8awS7G4/7BGcpy/kZ823UVF8JgNtzq4NKMmy8QC84X+II0dF3inzyAHDDYyLFPfbSQZzDh8GgPw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749521625; c=relaxed/simple; bh=zN74o/ir6eSl0BT6r5GIO5+qKaPJoK1kJ2MoO/zI7vo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bD7EaNu4ZLGnUSB2lisSzHyrGcE9DHiGeOWoPHmo+vj+sc79NcrPf+AdD1SAukHAtgFZTNJpgzqMf6qAUpugKKTRDJzOWOmT1vBOeC//Upm6aPZeX+wg76Xt6fpkA/FeeaQmxMQAGDDescyZiBUyp3m16btiEbNxTwKfebSpedE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=S706fC8d; arc=none smtp.client-ip=192.198.163.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="S706fC8d" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1749521624; x=1781057624; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=zN74o/ir6eSl0BT6r5GIO5+qKaPJoK1kJ2MoO/zI7vo=; b=S706fC8dYnNS+hUHoesNkEc6zMNAh9g0bC2O7dDrecdk5R3V5YIYM4sI 6ky50H7yk7G9LIbNiSeIWvo600Gmn5vS03hccwiMuxcljkuHNwDx/UhTb hLHbi/9R0oQO/bvHqIbxwLu4X7rlWnExMumBPIfnw/GvfqXkoxg4q49V2 r1yEVSeolIZPcB24/Keandu2YFQCjQ73TQD8R/QQOl+jTE8Jdnff9bNzG Cpk1Gf/cXz3ZJ20iTIQK1WAPUO6SZgAY2GrMcOmRlwIsBo7VNDjQOzn5Y 11Y648gjdZCMSI1QCmv1XLZGya8ypYUXTdY5oSPNNpQMGfcanYOw1EY7L A==; X-CSE-ConnectionGUID: nSHNXmrHTNOPUEhpPHddLg== X-CSE-MsgGUID: 3fwOP9+pTq6gFldJKVOXMg== X-IronPort-AV: E=McAfee;i="6800,10657,11459"; a="50841185" X-IronPort-AV: E=Sophos;i="6.16,223,1744095600"; d="scan'208";a="50841185" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa112.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Jun 2025 19:13:38 -0700 X-CSE-ConnectionGUID: Pai/b6P6Sry4oY7aBUh9pQ== X-CSE-MsgGUID: vS94t4dRQQ+/wN8bW4fE4A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,223,1744095600"; d="scan'208";a="147253753" Received: from litbin-desktop.sh.intel.com ([10.239.156.93]) by orviesa007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Jun 2025 19:13:34 -0700 From: Binbin Wu To: pbonzini@redhat.com, seanjc@google.com, kvm@vger.kernel.org Cc: rick.p.edgecombe@intel.com, kai.huang@intel.com, adrian.hunter@intel.com, reinette.chatre@intel.com, xiaoyao.li@intel.com, tony.lindgren@intel.com, isaku.yamahata@intel.com, yan.y.zhao@intel.com, mikko.ylinen@linux.intel.com, linux-kernel@vger.kernel.org, kirill.shutemov@intel.com, jiewen.yao@intel.com, binbin.wu@linux.intel.com Subject: [RFC PATCH 2/4] KVM: TDX: Handle TDG.VP.VMCALL Date: Tue, 10 Jun 2025 10:14:20 +0800 Message-ID: <20250610021422.1214715-3-binbin.wu@linux.intel.com> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20250610021422.1214715-1-binbin.wu@linux.intel.com> References: <20250610021422.1214715-1-binbin.wu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Handle TDVMCALL for GetQuote to generate a TD-Quote. GetQuote is a doorbell-like interface used by TDX guests to request VMM to generate a TD-Quote signed by a service hosting TD-Quoting Enclave operating on the host. A TDX guest passes a TD Report (TDREPORT_STRUCT) in a shared-memory area as parameter. Host VMM can access it and queue the operation for a service hosting TD-Quoting enclave. When completed, the Quote is returned via the same shared-memory area. KVM only checks the GPA from the TDX guest has the shared-bit set and drops the shared-bit before exiting to userspace to avoid bleeding the shared-bit into KVM's exit ABI. KVM forwards the request to userspace VMM (e.g. QEMU) and userspace VMM queues the operation asynchronously. KVM sets the return code according to the 'ret' field set by userspace to notify the TDX guest whether the request has been queued successfully or not. When the request has been queued successfully, the TDX guest can poll the status field in the shared-memory area to check whether the Quote generation is completed or not. When completed, the generated Quote is returned via the same buffer. Add KVM_EXIT_TDX_GET_QUOTE as a new exit reason to userspace. 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. Signed-off-by: Binbin Wu Tested-by: Mikko Ylinen Acked-by: Kai Huang --- v2: - Skip sanity checks except for the check of the shared-bit. (Rick, Sean) - Drop the shared-bit of the GPA before exiting to userspace. (Sean) - Improve the description of 'ret' field in the document. (Kai) - Use number 40 for KVM_EXIT_TDX_GET_QUOTE. (Xiaoyao, Rick) - Update the changelog and the description of KVM_EXIT_TDX_GET_QUOTE in the document according to the code changes. RFC v1: - Add "Acked-by" from Kai. - State that KVM_EXIT_TDX_GET_QUOTE should be handled by userspace as the initial support for TDX. - Remove a blank line. --- Documentation/virt/kvm/api.rst | 27 +++++++++++++++++++++++++++ arch/x86/kvm/vmx/tdx.c | 29 +++++++++++++++++++++++++++++ include/uapi/linux/kvm.h | 7 +++++++ 3 files changed, 63 insertions(+) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index 1bd2d42e6424..7c5bb6b5c2c2 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -7174,6 +7174,33 @@ The valid value for 'flags' is: - KVM_NOTIFY_CONTEXT_INVALID -- the VM context is corrupted and not valid in VMCS. It would run into unknown result if resume the target VM. =20 +:: + + /* KVM_EXIT_TDX_GET_QUOTE */ + struct tdx_get_quote { + __u64 ret; + __u64 gpa; + __u64 size; + }; + +If the exit reason is KVM_EXIT_TDX_GET_QUOTE, then it indicates that a TDX +guest has requested to generate a TD-Quote signed by a service hosting +TD-Quoting Enclave operating on the host. The 'gpa' field and 'size' speci= fy +the guest physical address and size of a shared-memory buffer, in which the +TDX guest passes a TD Report. KVM checks the GPA from the TDX guest has the +shared-bit set and drops the shared-bit in 'gpa' field before exiting to +userspace. KVM doesn't do other sanity checks. The 'ret' field represents = the +return value of the GetQuote request. KVM only bridges the request to the +userspace VMM, and the userspace VMM is responsible for setting up the ret= urn +value since only userspace knows whether the request has been queued +successfully or not. KVM sets the return code according to the 'ret' field +before returning back to the TDX guest. When the request has been queued +successfully, the TDX guest can poll the status field in the shared-memory= area +to check whether the Quote generation is completed or not. When completed,= the +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. + :: =20 /* Fix the size of the union. */ diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c index 8134d5805b03..35428c6b5a67 100644 --- a/arch/x86/kvm/vmx/tdx.c +++ b/arch/x86/kvm/vmx/tdx.c @@ -1463,6 +1463,33 @@ static int tdx_get_td_vm_call_info(struct kvm_vcpu *= vcpu) return 1; } =20 +static int tdx_complete_get_quote(struct kvm_vcpu *vcpu) +{ + tdvmcall_set_return_code(vcpu, vcpu->run->tdx_get_quote.ret); + return 1; +} + +static int tdx_get_quote(struct kvm_vcpu *vcpu) +{ + struct vcpu_tdx *tdx =3D to_tdx(vcpu); + u64 gpa =3D tdx->vp_enter_args.r12; + u64 size =3D tdx->vp_enter_args.r13; + + /* The gpa of buffer must have shared bit set. */ + if (vt_is_tdx_private_gpa(vcpu->kvm, gpa)) { + tdvmcall_set_return_code(vcpu, TDVMCALL_STATUS_INVALID_OPERAND); + return 1; + } + + vcpu->run->exit_reason =3D KVM_EXIT_TDX_GET_QUOTE; + vcpu->run->tdx_get_quote.gpa =3D gpa & ~gfn_to_gpa(kvm_gfn_direct_bits(td= x->vcpu.kvm)); + vcpu->run->tdx_get_quote.size =3D size; + + vcpu->arch.complete_userspace_io =3D tdx_complete_get_quote; + + return 0; +} + static int handle_tdvmcall(struct kvm_vcpu *vcpu) { switch (tdvmcall_leaf(vcpu)) { @@ -1472,6 +1499,8 @@ static int handle_tdvmcall(struct kvm_vcpu *vcpu) return tdx_report_fatal_error(vcpu); case TDVMCALL_GET_TD_VM_CALL_INFO: return tdx_get_td_vm_call_info(vcpu); + case TDVMCALL_GET_QUOTE: + return tdx_get_quote(vcpu); default: break; } diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index d00b85cb168c..e63e4df468b5 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -178,6 +178,7 @@ struct kvm_xen_exit { #define KVM_EXIT_NOTIFY 37 #define KVM_EXIT_LOONGARCH_IOCSR 38 #define KVM_EXIT_MEMORY_FAULT 39 +#define KVM_EXIT_TDX_GET_QUOTE 40 =20 /* For KVM_EXIT_INTERNAL_ERROR */ /* Emulate instruction failed. */ @@ -447,6 +448,12 @@ struct kvm_run { __u64 gpa; __u64 size; } memory_fault; + /* KVM_EXIT_TDX_GET_QUOTE */ + struct { + __u64 ret; + __u64 gpa; + __u64 size; + } tdx_get_quote; /* Fix the size of the union. */ char padding[256]; }; --=20 2.46.0 From nobody Sat Feb 7 15:38:38 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 91F86242909; Tue, 10 Jun 2025 02:13:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749521627; cv=none; b=Cub3sn6tds54pBsM7qusL6pLFQ5/Urm86JKk4nHb9o+Oq3go+9jQqzkB0GLBY3m3XMErHkwZwvtIqFEhxHcjYARzL7T7kHI72K73bDSwupAwlwG99BHYyRfBebTMLg8oglPOynTg4EUMTtFV3TFS9bbqKD/XHsSSktkqj9I3KdA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749521627; c=relaxed/simple; bh=qyS3Hw2HNbn8etjY4K2OSgsAtv5O5q2J4SVd6WFY+mE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=t9U21MYqF77ZFl0B8mB/Ltbfz2mgQyawiT8J2ySa2KVLBXOb9Hgk0uSXcxu1imn8UKIF6XF3rGOAobhNgtjMdNOnzw8fCojvM87QFCbJ5kV5ZxuFxcpH3FM+OJRPYO5nZFMsYnL6Yrj9JpkoJAprRtoGFdCoDoxnYinHkNFEHjs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=bh9gMIWC; arc=none smtp.client-ip=192.198.163.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="bh9gMIWC" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1749521625; x=1781057625; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=qyS3Hw2HNbn8etjY4K2OSgsAtv5O5q2J4SVd6WFY+mE=; b=bh9gMIWCHeVjUwJ4ObFuw5qVCgE7JnYld3fqyRhhfW+Inzfp3cNLx+Fh blUTB24TQkp2or6mOPVs5rXz+TQV1M/wppDHTIsKa24TaFt3XkxqtrYHe XkpDvbKankYDkErmC3pZfOathwE6xSrunwi/iAo3qSVC7o6xn8NJHzKj4 OuHPmxCAnrqqriaKxbPt26VQ6WczVjPLxWBqxhLhLeB41sL1LXaG8jBHN ZuEr5Rvpil8+QNYzimQQBzBkZN5XoivRl9exgAXxlNy9aeCxikKusdZvy y3AXOdLzJnjeOPhfRlIlvowzQCbVMLExkPlSInJOr3rLhDzZxkRh3HU2I w==; X-CSE-ConnectionGUID: txyOR1i6TPyAi6UZozeIiw== X-CSE-MsgGUID: zVv6fdP9TLitAO13mBQAEA== X-IronPort-AV: E=McAfee;i="6800,10657,11459"; a="50841194" X-IronPort-AV: E=Sophos;i="6.16,223,1744095600"; d="scan'208";a="50841194" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa112.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Jun 2025 19:13:42 -0700 X-CSE-ConnectionGUID: PEaS6U6hQp203jiLLgnoQw== X-CSE-MsgGUID: IbSenGuBQbSLNYL7saY6ZA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,223,1744095600"; d="scan'208";a="147253784" Received: from litbin-desktop.sh.intel.com ([10.239.156.93]) by orviesa007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Jun 2025 19:13:38 -0700 From: Binbin Wu To: pbonzini@redhat.com, seanjc@google.com, kvm@vger.kernel.org Cc: rick.p.edgecombe@intel.com, kai.huang@intel.com, adrian.hunter@intel.com, reinette.chatre@intel.com, xiaoyao.li@intel.com, tony.lindgren@intel.com, isaku.yamahata@intel.com, yan.y.zhao@intel.com, mikko.ylinen@linux.intel.com, linux-kernel@vger.kernel.org, kirill.shutemov@intel.com, jiewen.yao@intel.com, binbin.wu@linux.intel.com Subject: [RFC PATCH 3/4] KVM: TDX: Exit to userspace for GetTdVmCallInfo Date: Tue, 10 Jun 2025 10:14:21 +0800 Message-ID: <20250610021422.1214715-4-binbin.wu@linux.intel.com> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20250610021422.1214715-1-binbin.wu@linux.intel.com> References: <20250610021422.1214715-1-binbin.wu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Exit to userspace for TDG.VP.VMCALL 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: , , , , <#VE.RequestMMIO>, , , and . 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 Signed-off-by: Binbin Wu --- 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. Use= rspace 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. =20 +:: + + /* 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 th= at a +TDX guest has requested to get the supporting status of TDVMCALLs. Current= ly, +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. + :: =20 /* 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: =20 #. Run VCPU =20 +The GHCI base TDVMCALLs +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +The GHCI base TDVMCALLs are: , , , +, <#VE.RequestMMIO>, , , + and . These base TDVMCALLs are mand= atory +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 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 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; } =20 +static int tdx_complete_get_tdcall_info(struct kvm_vcpu *vcpu) +{ + struct vcpu_tdx *tdx =3D 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 =3D vcpu->run->tdx_get_tdvmcall_info.leaf_output[0= ]; + tdx->vp_enter_args.r12 =3D vcpu->run->tdx_get_tdvmcall_info.leaf_output[1= ]; + tdx->vp_enter_args.r13 =3D vcpu->run->tdx_get_tdvmcall_info.leaf_output[2= ]; + tdx->vp_enter_args.r14 =3D 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 =3D to_tdx(vcpu); =20 - 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 =3D 0; tdx->vp_enter_args.r13 =3D 0; tdx->vp_enter_args.r14 =3D 0; + return 1; + case 1: + vcpu->run->tdx_get_tdvmcall_info.leaf =3D 1; + vcpu->run->exit_reason =3D KVM_EXIT_TDX_GET_TDVMCALL_INFO; + vcpu->arch.complete_userspace_io =3D 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; } =20 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 =20 /* 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]; }; --=20 2.46.0 From nobody Sat Feb 7 15:38:38 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 77D8F24336D; Tue, 10 Jun 2025 02:13:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749521629; cv=none; b=XeT8+WV+IkrnLdtg+yRwxA/sUR8JYfafJL5/msF/Aune4fr/pLQE+HHu7Y5WbqZN8hxTYVuWjmeRurBpCTof+rsXQzrOB+3Zr3D9Az1wdYJ952Wjqu0xfJ0MTPxLNTP+nqwrCgQEYfRUB17L3+POHHtoP9Sy51F8fzsxCA+GC2A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1749521629; c=relaxed/simple; bh=FchX01MFxp5Y1PBJ6clFSa6v4H4hbzOl1iwsa5RQRm4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PSlnie7rwwCIE8jzoxdVtAbppfDB9J2u78q6tPGZMZe5yUn/2f477g60EWlN4OfIhGrv2LWk7tQVOPrIeNaH1rYNgXsBECn9ebs5A+tLHtjpgwsvxF5jWFrMn5gC2NmN1yEcwVVDKUe9qPOmQDA4pEMGni5Dxo2GkAWlkgAx558= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=gqrGUIBc; arc=none smtp.client-ip=192.198.163.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="gqrGUIBc" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1749521627; x=1781057627; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=FchX01MFxp5Y1PBJ6clFSa6v4H4hbzOl1iwsa5RQRm4=; b=gqrGUIBcTH07CTOdt8SUM5iWtrphWa3ism96jUsv6ZF3+O/J+p6zp4nX RUSbzmvqe7DMx/AQ6CZa8VSUdKKuFOiK05NvTjSc5CN9IF/6Uwh73xfwC nFH25RNr1V2OKee4SDzQoZWY40uGsY8EOnWX76LOSlks45eEWtlTjToVq fo4baENtDrZAADv4lDHbVACh/K4HupOi2PCZm206gQob/RSR9A1bqLCLc PcemrnkdtCo4iwEsQ8WAqmRHHweiRugb9BGqCrBU9gIowFMvV3XlebdGd zfIrOVeyEqNQRST6fGO4pN+owsYpDloLUocsTQPMeadEYewnDRCyTUNTt w==; X-CSE-ConnectionGUID: y99Ej/XDRsGWVyDCRv8GtQ== X-CSE-MsgGUID: dJ4JecCXThO3AJuOWHRkig== X-IronPort-AV: E=McAfee;i="6800,10657,11459"; a="50841203" X-IronPort-AV: E=Sophos;i="6.16,223,1744095600"; d="scan'208";a="50841203" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa112.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Jun 2025 19:13:45 -0700 X-CSE-ConnectionGUID: zdOaYM4UTKu3aD2g8wXQLQ== X-CSE-MsgGUID: 0dsI/uksSh6+OV4Z3gmCDg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,223,1744095600"; d="scan'208";a="147253818" Received: from litbin-desktop.sh.intel.com ([10.239.156.93]) by orviesa007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Jun 2025 19:13:42 -0700 From: Binbin Wu To: pbonzini@redhat.com, seanjc@google.com, kvm@vger.kernel.org Cc: rick.p.edgecombe@intel.com, kai.huang@intel.com, adrian.hunter@intel.com, reinette.chatre@intel.com, xiaoyao.li@intel.com, tony.lindgren@intel.com, isaku.yamahata@intel.com, yan.y.zhao@intel.com, mikko.ylinen@linux.intel.com, linux-kernel@vger.kernel.org, kirill.shutemov@intel.com, jiewen.yao@intel.com, binbin.wu@linux.intel.com Subject: [RFC PATCH 4/4] KVM: TDX: Check KVM exit on KVM_HC_MAP_GPA_RANGE when TD finalize Date: Tue, 10 Jun 2025 10:14:22 +0800 Message-ID: <20250610021422.1214715-5-binbin.wu@linux.intel.com> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20250610021422.1214715-1-binbin.wu@linux.intel.com> References: <20250610021422.1214715-1-binbin.wu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Check userspace has enabled KVM exit on KVM_HC_MAP_GPA_RANGE during KVM_TDX_FINALIZE_VM. TDVMCALL_MAP_GPA is one of the GHCI base TDVMCALLs, so it must be implemented by VMM to support TDX guests. KVM converts TDVMCALL_MAP_GPA to KVM_HC_MAP_GPA_RANGE, which requires userspace to enable KVM_CAP_EXIT_HYPERCALL with KVM_HC_MAP_GPA_RANGE bit set. Check it when userspace requests KVM_TDX_FINALIZE_VM, so that there is no need to check it during TDX guests running. Signed-off-by: Binbin Wu --- Documentation/virt/kvm/x86/intel-tdx.rst | 3 +++ arch/x86/kvm/vmx/tdx.c | 20 +++++++++----------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Documentation/virt/kvm/x86/intel-tdx.rst b/Documentation/virt/= kvm/x86/intel-tdx.rst index 69c64453e9ca..41e38c38b034 100644 --- a/Documentation/virt/kvm/x86/intel-tdx.rst +++ b/Documentation/virt/kvm/x86/intel-tdx.rst @@ -246,6 +246,9 @@ control flow is as follows: * Prepare content of initial guest memory. * KVM_TDX_INIT_MEM_REGION: Add initial guest memory. * KVM_TDX_FINALIZE_VM: Finalize the measurement of the TDX guest. + Note: To support TDVMCALL_MAP_GPA, userspace must opt-in + KVM_CAP_EXIT_HYPERCALL with KVM_HC_MAP_GPA_RANGE before calling + KVM_TDX_FINALIZE_VM. =20 #. Run VCPU =20 diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c index a3cd68f44a9c..7fc6e6b9c131 100644 --- a/arch/x86/kvm/vmx/tdx.c +++ b/arch/x86/kvm/vmx/tdx.c @@ -1209,17 +1209,6 @@ static int tdx_map_gpa(struct kvm_vcpu *vcpu) u64 size =3D tdx->vp_enter_args.r13; u64 ret; =20 - /* - * Converting TDVMCALL_MAP_GPA to KVM_HC_MAP_GPA_RANGE requires - * userspace to enable KVM_CAP_EXIT_HYPERCALL with KVM_HC_MAP_GPA_RANGE - * bit set. If not, the error code is not defined in GHCI for TDX, use - * TDVMCALL_STATUS_INVALID_OPERAND for this case. - */ - if (!user_exit_on_hypercall(vcpu->kvm, KVM_HC_MAP_GPA_RANGE)) { - ret =3D TDVMCALL_STATUS_INVALID_OPERAND; - goto error; - } - if (gpa + size <=3D gpa || !kvm_vcpu_is_legal_gpa(vcpu, gpa) || !kvm_vcpu_is_legal_gpa(vcpu, gpa + size - 1) || (vt_is_tdx_private_gpa(vcpu->kvm, gpa) !=3D @@ -2821,6 +2810,15 @@ static int tdx_td_finalize(struct kvm *kvm, struct k= vm_tdx_cmd *cmd) { struct kvm_tdx *kvm_tdx =3D to_kvm_tdx(kvm); =20 + /* + * TDVMCALL_MAP_GPA is one of the GHCI base TDVMCALLs, so it must be + * implemented by VMM to support TDX guests. KVM converts + * TDVMCALL_MAP_GPA to KVM_HC_MAP_GPA_RANGE, which requires userspace to + * enable KVM_CAP_EXIT_HYPERCALL with KVM_HC_MAP_GPA_RANGE bit set. + */ + if (!user_exit_on_hypercall(kvm, KVM_HC_MAP_GPA_RANGE)) + return -EINVAL; + guard(mutex)(&kvm->slots_lock); =20 if (!is_hkid_assigned(kvm_tdx) || kvm_tdx->state =3D=3D TD_STATE_RUNNABLE) --=20 2.46.0