From nobody Wed Dec 4 18:51:04 2024 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) (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 63A038C11; Tue, 3 Dec 2024 01:03:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733187817; cv=none; b=CJvLv3SUKht7SZSfISLuxkednm7xsmAjpn+9eE9nUwBPknKsHiYoQG78c3/vqe35HCTXst6mEckVk3KEZ+jsPr4Ci19pOFixhUFTolRSpAcGetw4f3GtiGFpOxrKe65Cc2zgCo8pg9viQEwseB6OsfFCUOGEilaacs2fHoO76tk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733187817; c=relaxed/simple; bh=RIvmX5zZ0l539ax8/LZmKUX086JpEhRWOfQUoKYm7us=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pDHsIKvjKS5gk8GCKCGi4x+eDa8FuRIs06kxbHMX/06M1n3cF6nMzX3bIRY+kCHb0Vho/VeU5kt6FTkspisF4/71A1XR5JsfkeyIry+eQG+4wB/bVOA4kQ0ukgoQRiCp8J3FHNu3cg1Qk61YVGHgOLWzTPoosZJimRtyz20VCyk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=VGqLU5Z5; arc=none smtp.client-ip=192.198.163.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="VGqLU5Z5" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1733187816; x=1764723816; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=RIvmX5zZ0l539ax8/LZmKUX086JpEhRWOfQUoKYm7us=; b=VGqLU5Z5pev6s3k/eKnK1E7b+oP6sP2/J/KnaWGsH3Bv3iPVRsJkzl+w DZQoe2i8dN/fhOpnUEQbK9vrSQ4Nc38+CDWFW7D7WsJneFMZYdp/TyC89 3qiw8XBKC8LeWCcgeLckPjsTIGSLA1qKV+Gp9oZh75NjycGx12XBee/4/ 4e9OUBoIoRd7/AlmcTdfQf4quq7TfYpgGyf0uXwZlKp/rCD7XghZV02y5 3+5XHCuUAu++HEIzUV2wkPXdlt+xXH76E+9uXngYPGt+/gr5f915METNO WjCQmpK+PVZw4dT7OkKTpkRRQ6ev0UrRO6fXMtHDJu2Uakd4Xd04bRdai g==; X-CSE-ConnectionGUID: xJlxD+2/QyyxkXflUHlHKQ== X-CSE-MsgGUID: Jf6c+SoXRxSYjMC+sJUN7w== X-IronPort-AV: E=McAfee;i="6700,10204,11274"; a="36237950" X-IronPort-AV: E=Sophos;i="6.12,203,1728975600"; d="scan'208";a="36237950" Received: from fmviesa002.fm.intel.com ([10.60.135.142]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Dec 2024 17:03:34 -0800 X-CSE-ConnectionGUID: PXXY/jDDQyKF99goQ5Bfyw== X-CSE-MsgGUID: z9c/wuqmQ6ScVa3aG4HxTA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,203,1728975600"; d="scan'208";a="116535790" Received: from jairdeje-mobl1.amr.corp.intel.com (HELO rpedgeco-desk4..) ([10.124.223.7]) by fmviesa002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Dec 2024 17:03:25 -0800 From: Rick Edgecombe To: kvm@vger.kernel.org, pbonzini@redhat.com, seanjc@google.com, dave.hansen@intel.com Cc: isaku.yamahata@gmail.com, kai.huang@intel.com, linux-kernel@vger.kernel.org, tony.lindgren@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, rick.p.edgecombe@intel.com, x86@kernel.org, adrian.hunter@intel.com, Isaku Yamahata , Binbin Wu , Yuan Yao Subject: [RFC PATCH v2 1/6] x86/virt/tdx: Add SEAMCALL wrappers for TDX KeyID management Date: Mon, 2 Dec 2024 17:03:11 -0800 Message-ID: <20241203010317.827803-2-rick.p.edgecombe@intel.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241203010317.827803-1-rick.p.edgecombe@intel.com> References: <20241203010317.827803-1-rick.p.edgecombe@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" Intel TDX protects guest VMs from malicious host and certain physical attacks. Pre-TDX Intel hardware has support for a memory encryption architecture called MK-TME, which repurposes several high bits of physical address as "KeyID". TDX ends up with reserving a sub-range of MK-TME KeyIDs as "TDX private KeyIDs". Like MK-TME, these KeyIDs can be associated with an ephemeral key. For TDX this association is done by the TDX module. It also has its own tracking for which KeyIDs are in use. To do this ephemeral key setup and manipulate the TDX module's internal tracking, KVM will use the following SEAMCALLs: TDH.MNG.KEY.CONFIG: Mark the KeyID as in use, and initialize its ephemeral key. TDH.MNG.KEY.FREEID: Mark the KeyID as not in use. These SEAMCALLs both operate on TDR structures, which are setup using the previously added TDH.MNG.CREATE SEAMCALL. KVM's use of these operations will go like: - tdx_guest_keyid_alloc() - Initialize TD and TDR page with TDH.MNG.CREATE (not yet-added), passing KeyID - TDH.MNG.KEY.CONFIG to initialize the key - TD runs, teardown is started - TDH.MNG.KEY.FREEID - tdx_guest_keyid_free() Don't try to combine the tdx_guest_keyid_alloc() and TDH.MNG.KEY.CONFIG operations because TDH.MNG.CREATE and some locking need to be done in the middle. Don't combine TDH.MNG.KEY.FREEID and tdx_guest_keyid_free() so they are symmetrical with the creation path. So implement tdh_mng_key_config() and tdh_mng_key_freeid() as separate functions than tdx_guest_keyid_alloc() and tdx_guest_keyid_free(). The TDX module provides SEAMCALLs to hand pages to the TDX module for storing TDX controlled state. SEAMCALLs that operate on this state are directed to the appropriate TD VM using references to the pages originally provided for managing the TD's state. So the host kernel needs to track these pages, both as an ID for specifying which TD to operate on, and to allow them to be eventually reclaimed. The TD VM associated pages are called TDR (Trust Domain Root) and TDCS (Trust Domain Control Structure). Introduce "struct tdx_td" for holding references to pages provided to the TDX module for this TD VM associated state. Don't plan for any TD associated state that is controlled by KVM to live in this struct. Only expect it to hold data for concepts specific to the TDX architecture, for which there can't already be preexisting storage for in KVM. Add both the TDR page and an array of TDCS pages, even though the SEAMCALL wrappers will only need to know about the TDR pages for directing the SEAMCALLs to the right TD. Adding the TDCS pages to this struct will let all of the TD VM associated pages handed to the TDX module be tracked in one location. For a type to specify physical pages, use KVM's hpa_t type. Do this for KVM's benefit This is the common type used to hold physical addresses in KVM, so will make interoperability easier. Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Signed-off-by: Isaku Yamahata Signed-off-by: Kai Huang Signed-off-by: Rick Edgecombe Reviewed-by: Binbin Wu Reviewed-by: Yuan Yao --- SEAMCALL RFC: - Use struct page (Dave) SEAMCALL RFC: - Introduce struct tdx_td to use instead of raw TDR u64 uAPI breakout v2: - Change to use 'u64' as function parameter to prepare to move SEAMCALL wrappers to arch/x86. (Kai) - Split to separate patch - Move SEAMCALL wrappers from KVM to x86 core; - Move TDH_xx macros from KVM to x86 core; - Re-write log uAPI breakout v1: - Make argument to C wrapper function struct kvm_tdx * or struct vcpu_tdx * .(Sean) - Drop unused helpers (Kai) - Fix bisectability issues in headers (Kai) - Updates from seamcall overhaul (Kai) v19: - Update the commit message to match the patch by Yuan - Use seamcall() and seamcall_ret() by paolo v18: - removed stub functions for __seamcall{,_ret}() - Added Reviewed-by Binbin - Make tdx_seamcall() use struct tdx_module_args instead of taking each inputs. --- arch/x86/include/asm/tdx.h | 12 ++++++++++++ arch/x86/virt/vmx/tdx/tdx.c | 26 ++++++++++++++++++++++++++ arch/x86/virt/vmx/tdx/tdx.h | 16 +++++++++------- 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index d33e46d53d59..139c003acd1b 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -121,6 +121,18 @@ const struct tdx_sys_info *tdx_get_sysinfo(void); =20 int tdx_guest_keyid_alloc(void); void tdx_guest_keyid_free(unsigned int keyid); + +struct tdx_td { + /* TD root structure: */ + struct page *tdr_page; + + int tdcs_nr_pages; + /* TD control structure: */ + struct page **tdcs_pages; +}; + +u64 tdh_mng_key_config(struct tdx_td *td); +u64 tdh_mng_key_freeid(struct tdx_td *td); #else static inline void tdx_init(void) { } static inline int tdx_cpu_enable(void) { return -ENODEV; } diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index b883c1a4b002..2d1cebce8c07 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1562,3 +1562,29 @@ void tdx_guest_keyid_free(unsigned int keyid) ida_free(&tdx_guest_keyid_pool, keyid); } EXPORT_SYMBOL_GPL(tdx_guest_keyid_free); + +static inline u64 tdx_tdr_pa(struct tdx_td *td) +{ + return page_to_pfn(td->tdr_page) << PAGE_SHIFT; +} + +u64 tdh_mng_key_config(struct tdx_td *td) +{ + struct tdx_module_args args =3D { + .rcx =3D tdx_tdr_pa(td), + }; + + return seamcall(TDH_MNG_KEY_CONFIG, &args); +} +EXPORT_SYMBOL_GPL(tdh_mng_key_config); + +u64 tdh_mng_key_freeid(struct tdx_td *td) +{ + struct tdx_module_args args =3D { + .rcx =3D tdx_tdr_pa(td), + }; + + return seamcall(TDH_MNG_KEY_FREEID, &args); +} +EXPORT_SYMBOL_GPL(tdh_mng_key_freeid); + diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h index 9b708a8fb568..95002e7ff4c5 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -17,13 +17,15 @@ /* * TDX module SEAMCALL leaf functions */ -#define TDH_PHYMEM_PAGE_RDMD 24 -#define TDH_SYS_KEY_CONFIG 31 -#define TDH_SYS_INIT 33 -#define TDH_SYS_RD 34 -#define TDH_SYS_LP_INIT 35 -#define TDH_SYS_TDMR_INIT 36 -#define TDH_SYS_CONFIG 45 +#define TDH_MNG_KEY_CONFIG 8 +#define TDH_MNG_KEY_FREEID 20 +#define TDH_PHYMEM_PAGE_RDMD 24 +#define TDH_SYS_KEY_CONFIG 31 +#define TDH_SYS_INIT 33 +#define TDH_SYS_RD 34 +#define TDH_SYS_LP_INIT 35 +#define TDH_SYS_TDMR_INIT 36 +#define TDH_SYS_CONFIG 45 =20 /* TDX page types */ #define PT_NDA 0x0 --=20 2.47.1 From nobody Wed Dec 4 18:51:04 2024 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) (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 662E91EA84; Tue, 3 Dec 2024 01:03:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733187819; cv=none; b=tlB9gvG+AUD1RjJGxwAfQBdIbw5y/oDX8CYM4cZ3Cn4JzOrhnRKKAwMUK2IP3W/B8KXxgwzBcv3l2KWzYlH3bQM4fhXc8mk2gLnY7klfODlZpC/8W1C2RSXgvJCvucZ1+ZIuRhHNACEO2sBg7xiplv0/cHQp4jKyug2L6B2VrUo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733187819; c=relaxed/simple; bh=ieyTdM5YEd8wdaYMMb/q/5qT1SRj0HgLviIrFJQ4ex8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lhe61QdPIQFvHUrPFZvUr1+3jVkGAijuh6aOfnr3fLDMEq+oe/VQq5wFBK1iUtdMfnZogzS9ZcQ+VnBi6TvK5had9tmcuUAjV7sEZUfSpwnCI+wiJiKKTDwISgAF6SCmS98TSqlQGhZdPddLhq36pc6PKKHqSXXWSPwjru5gas8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=AMOW5Pd/; arc=none smtp.client-ip=192.198.163.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="AMOW5Pd/" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1733187818; x=1764723818; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ieyTdM5YEd8wdaYMMb/q/5qT1SRj0HgLviIrFJQ4ex8=; b=AMOW5Pd/0Nu/NvIJPflfBVU9vuaVSXawo/4xMJZDZigZ7gw/MNch/L1q 01I+k5mct+0hu9+QP7WUB8tRyLBQLTSPMsirYVmtLo0KKVRs6tx1LF35t CruY6DGWK7wiNoqo6+NaNhBpvaZ3t2FhcvWQIWUgFkli8GFvBwycJ8irf Jbum8cMO7OUEnyyLXt9CxGyrBTWcaTxzFN//ErXQdYg91VeMEDZOQOK2i KxC2AxpBpBQwGWiWuUD2GA53l52l7xL8C1SMFSHOCA1/ZjnE6yltkvMVn oRyxy/S6vBja/z9CwT4Is699iDA+wRiDRDxzxMGFKPGiWC+8VMbnONyIm w==; X-CSE-ConnectionGUID: q9cHnIygTAqZuCFloeo6MA== X-CSE-MsgGUID: GnxOqJvDROOUSaan7qKhKg== X-IronPort-AV: E=McAfee;i="6700,10204,11274"; a="36237958" X-IronPort-AV: E=Sophos;i="6.12,203,1728975600"; d="scan'208";a="36237958" Received: from fmviesa002.fm.intel.com ([10.60.135.142]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Dec 2024 17:03:35 -0800 X-CSE-ConnectionGUID: pgtSBQFWRRevOIuy+a38rQ== X-CSE-MsgGUID: 0cIFuJloTbewUq2GTV+T5g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,203,1728975600"; d="scan'208";a="116535793" Received: from jairdeje-mobl1.amr.corp.intel.com (HELO rpedgeco-desk4..) ([10.124.223.7]) by fmviesa002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Dec 2024 17:03:25 -0800 From: Rick Edgecombe To: kvm@vger.kernel.org, pbonzini@redhat.com, seanjc@google.com, dave.hansen@intel.com Cc: isaku.yamahata@gmail.com, kai.huang@intel.com, linux-kernel@vger.kernel.org, tony.lindgren@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, rick.p.edgecombe@intel.com, x86@kernel.org, adrian.hunter@intel.com, Isaku Yamahata , Binbin Wu , Yuan Yao Subject: [RFC PATCH v2 2/6] x86/virt/tdx: Add SEAMCALL wrappers for TDX TD creation Date: Mon, 2 Dec 2024 17:03:12 -0800 Message-ID: <20241203010317.827803-3-rick.p.edgecombe@intel.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241203010317.827803-1-rick.p.edgecombe@intel.com> References: <20241203010317.827803-1-rick.p.edgecombe@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" Intel TDX protects guest VMs from malicious hosts and certain physical attacks. It defines various control structures that hold state for things like TDs or vCPUs. These control structures are stored in pages given to the TDX module and encrypted with either the global KeyID or the guest KeyIDs. To manipulate these control structures the TDX module defines a few SEAMCALLs. KVM will use these during the process of creating a TD as follows: 1) Allocate a unique TDX KeyID for a new guest. 1) Call TDH.MNG.CREATE to create a "TD Root" (TDR) page, together with the new allocated KeyID. Unlike the rest of the TDX guest, the TDR page is crypto-protected by the 'global KeyID'. 2) Call the previously added TDH.MNG.KEY.CONFIG on each package to configure the KeyID for the guest. After this step, the KeyID to protect the guest is ready and the rest of the guest will be protected by this KeyID. 3) Call TDH.MNG.ADDCX to add TD Control Structure (TDCS) pages. 4) Call TDH.MNG.INIT to initialize the TDCS. To reclaim these pages for use by the kernel other SEAMCALLs are needed, which will be added in future patches. Add tdh_mng_addcx(), tdh_mng_create() and tdh_mng_init() to export these SEAMCALLs so that KVM can use them to create TDs. For SEAMCALLs that give a page to the TDX module to be encrypted, CLFLUSH the page mapped with KeyID 0, such that any dirty cache lines don't write back later and clobber TD memory or control structures. Don't worry about the other MK-TME KeyIDs because the kernel doesn't use them. The TDX docs specify that this flush is not needed unless the TDX module exposes the CLFLUSH_BEFORE_ALLOC feature bit. Be conservative and always flush. Add a helper function to facilitate this. Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Signed-off-by: Isaku Yamahata Signed-off-by: Kai Huang Signed-off-by: Rick Edgecombe Reviewed-by: Binbin Wu Reviewed-by: Yuan Yao --- SEAMCALL RFC v2: - Use struct page (Dave) - Fix wrongly named arg in tdh_mng_init() - Fix type of hkid in tdh_mng_create() SEAMCALL RFC: - Use struct tdx_td - Introduce tdx_clflush_page() to hold CLFLUSH_BEFORE_ALLOC explanation uAPI breakout v2: - Change to use 'u64' as function parameter to prepare to move SEAMCALL wrappers to arch/x86. (Kai) - Split to separate patch - Move SEAMCALL wrappers from KVM to x86 core; - Move TDH_xx macros from KVM to x86 core; - Re-write log uAPI breakout v1: - Make argument to C wrapper function struct kvm_tdx * or struct vcpu_tdx * .(Sean) - Drop unused helpers (Kai) - Fix bisectability issues in headers (Kai) - Updates from seamcall overhaul (Kai) v19: - Update the commit message to match the patch by Yuan - Use seamcall() and seamcall_ret() by paolo v18: - removed stub functions for __seamcall{,_ret}() - Added Reviewed-by Binbin - Make tdx_seamcall() use struct tdx_module_args instead of taking each inputs. --- arch/x86/include/asm/tdx.h | 3 +++ arch/x86/virt/vmx/tdx/tdx.c | 51 +++++++++++++++++++++++++++++++++++++ arch/x86/virt/vmx/tdx/tdx.h | 3 +++ 3 files changed, 57 insertions(+) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 139c003acd1b..a4360a71dbdd 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -131,8 +131,11 @@ struct tdx_td { struct page **tdcs_pages; }; =20 +u64 tdh_mng_addcx(struct tdx_td *td, struct page *tdcs_page); u64 tdh_mng_key_config(struct tdx_td *td); +u64 tdh_mng_create(struct tdx_td *td, u64 hkid); u64 tdh_mng_key_freeid(struct tdx_td *td); +u64 tdh_mng_init(struct tdx_td *td, u64 td_params, u64 *extended_err); #else static inline void tdx_init(void) { } static inline int tdx_cpu_enable(void) { return -ENODEV; } diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 2d1cebce8c07..605eb9bd81d3 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1568,6 +1568,29 @@ static inline u64 tdx_tdr_pa(struct tdx_td *td) return page_to_pfn(td->tdr_page) << PAGE_SHIFT; } =20 +/* + * The TDX module exposes a CLFLUSH_BEFORE_ALLOC bit to specify whether + * a CLFLUSH of pages is required before handing them to the TDX module. + * Be conservative and make the code simpler by doing the CLFLUSH + * unconditionally. + */ +static void tdx_clflush_page(struct page *tdr) +{ + clflush_cache_range(page_to_virt(tdr), PAGE_SIZE); +} + +u64 tdh_mng_addcx(struct tdx_td *td, struct page *tdcs_page) +{ + struct tdx_module_args args =3D { + .rcx =3D page_to_pfn(tdcs_page) << PAGE_SHIFT, + .rdx =3D tdx_tdr_pa(td), + }; + + tdx_clflush_page(tdcs_page); + return seamcall(TDH_MNG_ADDCX, &args); +} +EXPORT_SYMBOL_GPL(tdh_mng_addcx); + u64 tdh_mng_key_config(struct tdx_td *td) { struct tdx_module_args args =3D { @@ -1578,6 +1601,18 @@ u64 tdh_mng_key_config(struct tdx_td *td) } EXPORT_SYMBOL_GPL(tdh_mng_key_config); =20 +u64 tdh_mng_create(struct tdx_td *td, u64 hkid) +{ + struct tdx_module_args args =3D { + .rcx =3D tdx_tdr_pa(td), + .rdx =3D hkid, + }; + + tdx_clflush_page(td->tdr_page); + return seamcall(TDH_MNG_CREATE, &args); +} +EXPORT_SYMBOL_GPL(tdh_mng_create); + u64 tdh_mng_key_freeid(struct tdx_td *td) { struct tdx_module_args args =3D { @@ -1588,3 +1623,19 @@ u64 tdh_mng_key_freeid(struct tdx_td *td) } EXPORT_SYMBOL_GPL(tdh_mng_key_freeid); =20 +u64 tdh_mng_init(struct tdx_td *td, u64 td_params, u64 *extended_err) +{ + struct tdx_module_args args =3D { + .rcx =3D tdx_tdr_pa(td), + .rdx =3D td_params, + }; + u64 ret; + + ret =3D seamcall_ret(TDH_MNG_INIT, &args); + + *extended_err =3D args.rcx; + + return ret; +} +EXPORT_SYMBOL_GPL(tdh_mng_init); + diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h index 95002e7ff4c5..b9287304f372 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -17,8 +17,11 @@ /* * TDX module SEAMCALL leaf functions */ +#define TDH_MNG_ADDCX 1 #define TDH_MNG_KEY_CONFIG 8 +#define TDH_MNG_CREATE 9 #define TDH_MNG_KEY_FREEID 20 +#define TDH_MNG_INIT 21 #define TDH_PHYMEM_PAGE_RDMD 24 #define TDH_SYS_KEY_CONFIG 31 #define TDH_SYS_INIT 33 --=20 2.47.1 From nobody Wed Dec 4 18:51:04 2024 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) (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 C2977558BB; Tue, 3 Dec 2024 01:03:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733187821; cv=none; b=Lf4ykVOWU3xwFlXRT/ZTl1t4yv8pGchtcTzeoMquShv2wlIqhoSlcKGamf534iwcPej9Ny0pgamRDAJUAtTXRyVrrzWa2rVE+BdbGWkWAYO1EpsBnANAphCzKqXq/XhnFEms9t1JLqCofKErcz+Zn3WwNJ58paHhlsmn/Aw8KUA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733187821; c=relaxed/simple; bh=cEPueJLgUoqsoeO50ks4Jav/oCG91h7phamTZBbX8qM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MPO6DrLh01IlTfTd3kBYKPmf+J8Qiykb/5n99zxfQPYMS1TC1WSbTun81zsWvMfU4ILp5z0i2cvG32cmMnM2hKTD4foNEmi9C11m1wWqo02L9jY4nle65sX0Ew6tCJmPGXECbPoouhj+BX8oWzTwRGN4VTDxgWQCsNatU02oejM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=nEumS/sl; arc=none smtp.client-ip=192.198.163.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="nEumS/sl" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1733187820; x=1764723820; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=cEPueJLgUoqsoeO50ks4Jav/oCG91h7phamTZBbX8qM=; b=nEumS/slNqAaS1tbWUklzlE2LWT4lzwASatjM4gWl/nkLkJQ73nqBDi7 OgEwKw0UFkImYVFJgBkWF/EO8+S2I6AGDXYEKCvzTbGHPFo44uqUvMAk7 21j5wtrYgnKhBabwWSYa1B84nVz+AKZi2leas0kwuUNf8Egn2ZUOOcYLh 2mXWqtvCig3LgK7/Ae4uotafN54Ejz7tMrQCq5lHOF5pmvYnvuWf9c3NS bu/Ru8tPb3VK5bojA16vFTRafD1yYrZbzE/Iu9tq063s0S0DHmqg2ELew SQZJ+Zpxe8J3oUxDg6Y6TKljDlu5E67toQC+z5B8ALD/ga2FIrZlcZtXA g==; X-CSE-ConnectionGUID: 8zyU04K+SQWPVn2xgWv+jA== X-CSE-MsgGUID: 1VdX1CP4Rma4sFKYUMEJNg== X-IronPort-AV: E=McAfee;i="6700,10204,11274"; a="36237974" X-IronPort-AV: E=Sophos;i="6.12,203,1728975600"; d="scan'208";a="36237974" Received: from fmviesa002.fm.intel.com ([10.60.135.142]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Dec 2024 17:03:35 -0800 X-CSE-ConnectionGUID: VlQ3gBBFTNin87Mx4nBJlQ== X-CSE-MsgGUID: dKW3INuAQq+GqNM0IJXmCQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,203,1728975600"; d="scan'208";a="116535796" Received: from jairdeje-mobl1.amr.corp.intel.com (HELO rpedgeco-desk4..) ([10.124.223.7]) by fmviesa002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Dec 2024 17:03:26 -0800 From: Rick Edgecombe To: kvm@vger.kernel.org, pbonzini@redhat.com, seanjc@google.com, dave.hansen@intel.com Cc: isaku.yamahata@gmail.com, kai.huang@intel.com, linux-kernel@vger.kernel.org, tony.lindgren@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, rick.p.edgecombe@intel.com, x86@kernel.org, adrian.hunter@intel.com, Isaku Yamahata , Binbin Wu , Yuan Yao Subject: [RFC PATCH v2 3/6] x86/virt/tdx: Add SEAMCALL wrappers for TDX vCPU creation Date: Mon, 2 Dec 2024 17:03:13 -0800 Message-ID: <20241203010317.827803-4-rick.p.edgecombe@intel.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241203010317.827803-1-rick.p.edgecombe@intel.com> References: <20241203010317.827803-1-rick.p.edgecombe@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" Intel TDX protects guest VMs from malicious host and certain physical attacks. It defines various control structures that hold state for virtualized components of the TD (i.e. VMs or vCPUs) These control structures are stored in pages given to the TDX module and encrypted with either the global KeyID or the guest KeyIDs. To manipulate these control structures the TDX module defines a few SEAMCALLs. KVM will use these during the process of creating a vCPU as follows: 1) Call TDH.VP.CREATE to create a TD vCPU Root (TDVPR) page for each vCPU. 2) Call TDH.VP.ADDCX to add per-vCPU control pages (TDCX) for each vCPU. 3) Call TDH.VP.INIT to initialize the TDCX for each vCPU. To reclaim these pages for use by the kernel other SEAMCALLs are needed, which will be added in future patches. Export functions to allow KVM to make these SEAMCALLs. Export two variants for TDH.VP.CREATE, in order to support the planned logic of KVM to support TDX modules with and without the ENUM_TOPOLOGY feature. If KVM can drop support for the !ENUM_TOPOLOGY case, this could go down a single version. Leave that for later discussion. The TDX module provides SEAMCALLs to hand pages to the TDX module for storing TDX controlled state. SEAMCALLs that operate on this state are directed to the appropriate TD vCPU using references to the pages originally provided for managing the vCPU's state. So the host kernel needs to track these pages, both as an ID for specifying which vCPU to operate on, and to allow them to be eventually reclaimed. The vCPU associated pages are called TDVPR (Trust Domain Virtual Processor Root) and TDCX (Trust Domain Control Extension). Introduce "struct tdx_vp" for holding references to pages provided to the TDX module for the TD vCPU associated state. Don't plan for any vCPU associated state that is controlled by KVM to live in this struct. Only expect it to hold data for concepts specific to the TDX architecture, for which there can't already be preexisting storage for in KVM. Add both the TDVPR page and an array of TDCX pages, even though the SEAMCALL wrappers will only need to know about the TDVPR pages for directing the SEAMCALLs to the right vCPU. Adding the TDCX pages to this struct will let all of the vCPU associated pages handed to the TDX module be tracked in one location. For a type to specify physical pages, use KVM's hpa_t type. Do this for KVM's benefit This is the common type used to hold physical addresses in KVM, so will make interoperability easier. Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Signed-off-by: Isaku Yamahata Signed-off-by: Kai Huang Signed-off-by: Rick Edgecombe Reviewed-by: Binbin Wu Reviewed-by: Yuan Yao --- SEAMCALL RFC v2: - Use struct page (Dave) SEAMCALL RFC: - Use struct tdx_td - Introduce tdx_vp uAPI breakout v2: - Change to use 'u64' as function parameter to prepare to move SEAMCALL wrappers to arch/x86. (Kai) - Split to separate patch - Move SEAMCALL wrappers from KVM to x86 core; - Move TDH_xx macros from KVM to x86 core; - Re-write log uAPI breakout v1: - Make argument to C wrapper function struct kvm_tdx * or struct vcpu_tdx * .(Sean) - Drop unused helpers (Kai) - Fix bisectability issues in headers (Kai) - Updates from seamcall overhaul (Kai) v19: - Update the commit message to match the patch by Yuan - Use seamcall() and seamcall_ret() by paolo v18: - removed stub functions for __seamcall{,_ret}() - Added Reviewed-by Binbin - Make tdx_seamcall() use struct tdx_module_args instead of taking each inputs. --- arch/x86/include/asm/tdx.h | 15 +++++++++++ arch/x86/virt/vmx/tdx/tdx.c | 53 +++++++++++++++++++++++++++++++++++++ arch/x86/virt/vmx/tdx/tdx.h | 11 ++++++++ 3 files changed, 79 insertions(+) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index a4360a71dbdd..018bbabf8639 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -129,13 +129,28 @@ struct tdx_td { int tdcs_nr_pages; /* TD control structure: */ struct page **tdcs_pages; + + /* Size of `tdcx_pages` in struct tdx_vp */ + int tdcx_nr_pages; +}; + +struct tdx_vp { + /* TDVP root page */ + struct page *tdvpr_page; + + /* TD vCPU control structure: */ + struct page **tdcx_pages; }; =20 u64 tdh_mng_addcx(struct tdx_td *td, struct page *tdcs_page); +u64 tdh_vp_addcx(struct tdx_vp *vp, struct page *tdcx_page); u64 tdh_mng_key_config(struct tdx_td *td); u64 tdh_mng_create(struct tdx_td *td, u64 hkid); +u64 tdh_vp_create(struct tdx_td *td, struct tdx_vp *vp); u64 tdh_mng_key_freeid(struct tdx_td *td); u64 tdh_mng_init(struct tdx_td *td, u64 td_params, u64 *extended_err); +u64 tdh_vp_init(struct tdx_vp *vp, u64 initial_rcx); +u64 tdh_vp_init_apicid(struct tdx_vp *vp, u64 initial_rcx, u32 x2apicid); #else static inline void tdx_init(void) { } static inline int tdx_cpu_enable(void) { return -ENODEV; } diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 605eb9bd81d3..d71656868fe4 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -5,6 +5,7 @@ * Intel Trusted Domain Extensions (TDX) support */ =20 +#include "asm/page_types.h" #define pr_fmt(fmt) "virt/tdx: " fmt =20 #include @@ -1568,6 +1569,11 @@ static inline u64 tdx_tdr_pa(struct tdx_td *td) return page_to_pfn(td->tdr_page) << PAGE_SHIFT; } =20 +static inline u64 tdx_tdvpr_pa(struct tdx_vp *td) +{ + return page_to_pfn(td->tdvpr_page) << PAGE_SHIFT; +} + /* * The TDX module exposes a CLFLUSH_BEFORE_ALLOC bit to specify whether * a CLFLUSH of pages is required before handing them to the TDX module. @@ -1591,6 +1597,18 @@ u64 tdh_mng_addcx(struct tdx_td *td, struct page *td= cs_page) } EXPORT_SYMBOL_GPL(tdh_mng_addcx); =20 +u64 tdh_vp_addcx(struct tdx_vp *vp, struct page *tdcx_page) +{ + struct tdx_module_args args =3D { + .rcx =3D page_to_pfn(tdcx_page) << PAGE_SHIFT, + .rdx =3D tdx_tdvpr_pa(vp), + }; + + tdx_clflush_page(tdcx_page); + return seamcall(TDH_VP_ADDCX, &args); +} +EXPORT_SYMBOL_GPL(tdh_vp_addcx); + u64 tdh_mng_key_config(struct tdx_td *td) { struct tdx_module_args args =3D { @@ -1613,6 +1631,18 @@ u64 tdh_mng_create(struct tdx_td *td, u64 hkid) } EXPORT_SYMBOL_GPL(tdh_mng_create); =20 +u64 tdh_vp_create(struct tdx_td *td, struct tdx_vp *vp) +{ + struct tdx_module_args args =3D { + .rcx =3D tdx_tdvpr_pa(vp), + .rdx =3D tdx_tdr_pa(td), + }; + + tdx_clflush_page(vp->tdvpr_page); + return seamcall(TDH_VP_CREATE, &args); +} +EXPORT_SYMBOL_GPL(tdh_vp_create); + u64 tdh_mng_key_freeid(struct tdx_td *td) { struct tdx_module_args args =3D { @@ -1639,3 +1669,26 @@ u64 tdh_mng_init(struct tdx_td *td, u64 td_params, u= 64 *extended_err) } EXPORT_SYMBOL_GPL(tdh_mng_init); =20 +u64 tdh_vp_init(struct tdx_vp *vp, u64 initial_rcx) +{ + struct tdx_module_args args =3D { + .rcx =3D tdx_tdvpr_pa(vp), + .rdx =3D initial_rcx, + }; + + return seamcall(TDH_VP_INIT, &args); +} +EXPORT_SYMBOL_GPL(tdh_vp_init); + +u64 tdh_vp_init_apicid(struct tdx_vp *vp, u64 initial_rcx, u32 x2apicid) +{ + struct tdx_module_args args =3D { + .rcx =3D tdx_tdvpr_pa(vp), + .rdx =3D initial_rcx, + .r8 =3D x2apicid, + }; + + /* apicid requires version =3D=3D 1. */ + return seamcall(TDH_VP_INIT | (1ULL << TDX_VERSION_SHIFT), &args); +} +EXPORT_SYMBOL_GPL(tdh_vp_init_apicid); diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h index b9287304f372..3663971a3669 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -18,10 +18,13 @@ * TDX module SEAMCALL leaf functions */ #define TDH_MNG_ADDCX 1 +#define TDH_VP_ADDCX 4 #define TDH_MNG_KEY_CONFIG 8 #define TDH_MNG_CREATE 9 +#define TDH_VP_CREATE 10 #define TDH_MNG_KEY_FREEID 20 #define TDH_MNG_INIT 21 +#define TDH_VP_INIT 22 #define TDH_PHYMEM_PAGE_RDMD 24 #define TDH_SYS_KEY_CONFIG 31 #define TDH_SYS_INIT 33 @@ -30,6 +33,14 @@ #define TDH_SYS_TDMR_INIT 36 #define TDH_SYS_CONFIG 45 =20 +/* + * SEAMCALL leaf: + * + * Bit 15:0 Leaf number + * Bit 23:16 Version number + */ +#define TDX_VERSION_SHIFT 16 + /* TDX page types */ #define PT_NDA 0x0 #define PT_RSVD 0x1 --=20 2.47.1 From nobody Wed Dec 4 18:51:04 2024 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) (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 E2F692AF05; Tue, 3 Dec 2024 01:03:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733187824; cv=none; b=rC02j9xlpJNGHLCLmU5OXk8IRJ00L85MPvIHNjzNZiNMnnKpML6osU/2CqVHA8361gYCa3tsmC8Pz7Syxh1p6UZRDTSvBhi/zFgOFcp/Hc6SGgQJQsBz1CmpganZISDoNGGotZ5MNtyQ5ZoahZ9Zc02jaNxWbidDJZsK043M+sc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733187824; c=relaxed/simple; bh=9g4xwN8+qz3jmgOq/OwIVU+iA/OjzRKatefCc4TD1E8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=U1F5pltK1lE+v7t2/qq2zV11fiJ6UchaP4S5ycR9svtl+Ib3ZdqvNoEbFuBa4OwAIEqPJzvKYoSsYk+PKBqdCx3MsGCx2kjmpZ0uHYreEtcdGYLni4dPXlxfEPALFYbbvLjfeTtlTyQjWqg8uMboWg8e8v3BBdqHglr4ZdArmBs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=IDfAEfh8; arc=none smtp.client-ip=192.198.163.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="IDfAEfh8" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1733187820; x=1764723820; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=9g4xwN8+qz3jmgOq/OwIVU+iA/OjzRKatefCc4TD1E8=; b=IDfAEfh8NuQnOfcaf/N8pPyD5Ws3036x0XAYKS1YGlZNabC9onyHADu3 V96RddQBIqB5WFfbz/rSnz9mxn3BlCqUZM/ZNsR3iarp7PBa5WQy0/8h8 5QM/Gks8Or9d1mgLVV0UZDtoYr8o0GpVteKl7aV3k3weZFvrEubE0Tbn5 mV1CUK3Qyyfmtjyk1YE5oUiJJ7SFt49BxPSiziNbcmR4R//XA4hgHUDlB T4RVL7vcDxSKTmrPcE4DU3vpICYPVtEB52/Krkk45gYO7BP/25EkTmi/1 7W6hdU9VT1cvLM0ktz/Qk+dRYPAyoAIKGtswW4/UzoSZppoGI97JVIuHA g==; X-CSE-ConnectionGUID: 4oih4AwCTPOrt8Zk5EZmjQ== X-CSE-MsgGUID: rVb/60btRvOOPY4RNpyMcQ== X-IronPort-AV: E=McAfee;i="6700,10204,11274"; a="36237981" X-IronPort-AV: E=Sophos;i="6.12,203,1728975600"; d="scan'208";a="36237981" Received: from fmviesa002.fm.intel.com ([10.60.135.142]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Dec 2024 17:03:35 -0800 X-CSE-ConnectionGUID: eAqRcyLNSkWByGAW/nJTWg== X-CSE-MsgGUID: iCD5sEtQQi6D7nCBjrQ8TA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,203,1728975600"; d="scan'208";a="116535799" Received: from jairdeje-mobl1.amr.corp.intel.com (HELO rpedgeco-desk4..) ([10.124.223.7]) by fmviesa002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Dec 2024 17:03:27 -0800 From: Rick Edgecombe To: kvm@vger.kernel.org, pbonzini@redhat.com, seanjc@google.com, dave.hansen@intel.com Cc: isaku.yamahata@gmail.com, kai.huang@intel.com, linux-kernel@vger.kernel.org, tony.lindgren@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, rick.p.edgecombe@intel.com, x86@kernel.org, adrian.hunter@intel.com, Isaku Yamahata , Binbin Wu , Yuan Yao Subject: [RFC PATCH v2 4/6] x86/virt/tdx: Add SEAMCALL wrappers for TDX page cache management Date: Mon, 2 Dec 2024 17:03:14 -0800 Message-ID: <20241203010317.827803-5-rick.p.edgecombe@intel.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241203010317.827803-1-rick.p.edgecombe@intel.com> References: <20241203010317.827803-1-rick.p.edgecombe@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" Intel TDX protects guest VMs from malicious host and certain physical attacks. The TDX module uses pages provided by the host for both control structures and for TD guest pages. These pages are encrypted using the MK-TME encryption engine, with its special requirements around cache invalidation. For its own security, the TDX module ensures pages are flushed properly and track which usage they are currently assigned. For creating and tearing down TD VMs and vCPUs KVM will need to use the TDH.PHYMEM.PAGE.RECLAIM, TDH.PHYMEM.CACHE.WB, and TDH.PHYMEM.PAGE.WBINVD SEAMCALLs. Add tdh_phymem_page_reclaim() to enable KVM to call TDH.PHYMEM.PAGE.RECLAIM to reclaim the page for use by the host kernel. This effectively resets its state in the TDX module's page tracking (PAMT), if the page is available to be reclaimed. This will be used by KVM to reclaim the various types of pages owned by the TDX module. It will have a small wrapper in KVM that retries in the case of a relevant error code. Don't implement this wrapper in arch/x86 because KVM's solution around retrying SEAMCALLs will be better located in a single place. Add tdh_phymem_cache_wb() to enable KVM to call TDH.PHYMEM.CACHE.WB to do a cache write back in a way that the TDX module can verify, before it allows a KeyID to be freed. The KVM code will use this to have a small wrapper that handles retries. Since the TDH.PHYMEM.CACHE.WB operation is interruptible, have tdh_phymem_cache_wb() take a resume argument to pass this info to the TDX module for restarts. It is worth noting that this SEAMCALL uses a SEAM specific MSR to do the write back in sections. In this way it does export some new functionality that affects CPU state. Add tdh_phymem_page_wbinvd_tdr() to enable KVM to call TDH.PHYMEM.PAGE.WBINVD to do a cache write back and invalidate of a TDR, using the global KeyID. The underlying TDH.PHYMEM.PAGE.WBINVD SEAMCALL requires the related KeyID to be encoded into the SEAMCALL args. Since the global KeyID is not exposed to KVM, a dedicated wrapper is needed for TDR focused TDH.PHYMEM.PAGE.WBINVD operations. Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Signed-off-by: Isaku Yamahata Signed-off-by: Kai Huang Signed-off-by: Rick Edgecombe Reviewed-by: Binbin Wu Reviewed-by: Yuan Yao --- SEAMCALL RFC v2: - Use struct page (Dave) - Rename out args for tdh_phymem_page_reclaim() to make it clear these are TDX specific values, and not to be interpreted normally. Also, add a comment about this. SEAMCALL RFC: - Use struct tdx_td - Use arg names with meaning for tdh_phymem_page_reclaim() for out args uAPI breakout v2: - Change to use 'u64' as function parameter to prepare to move SEAMCALL wrappers to arch/x86. (Kai) - Split to separate patch - Move SEAMCALL wrappers from KVM to x86 core; - Move TDH_xx macros from KVM to x86 core; - Re-write log uAPI breakout v1: - Make argument to C wrapper function struct kvm_tdx * or struct vcpu_tdx * .(Sean) - Drop unused helpers (Kai) - Fix bisectability issues in headers (Kai) - Updates from seamcall overhaul (Kai) v19: - Update the commit message to match the patch by Yuan - Use seamcall() and seamcall_ret() by paolo v18: - removed stub functions for __seamcall{,_ret}() - Added Reviewed-by Binbin - Make tdx_seamcall() use struct tdx_module_args instead of taking each inputs. --- arch/x86/include/asm/tdx.h | 3 +++ arch/x86/virt/vmx/tdx/tdx.c | 43 +++++++++++++++++++++++++++++++++++++ arch/x86/virt/vmx/tdx/tdx.h | 3 +++ 3 files changed, 49 insertions(+) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 018bbabf8639..f6ab8a9ea46b 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -151,6 +151,9 @@ u64 tdh_mng_key_freeid(struct tdx_td *td); u64 tdh_mng_init(struct tdx_td *td, u64 td_params, u64 *extended_err); u64 tdh_vp_init(struct tdx_vp *vp, u64 initial_rcx); u64 tdh_vp_init_apicid(struct tdx_vp *vp, u64 initial_rcx, u32 x2apicid); +u64 tdh_phymem_page_reclaim(struct page *page, u64 *tdx_pt, u64 *tdx_owner= , u64 *tdx_size); +u64 tdh_phymem_cache_wb(bool resume); +u64 tdh_phymem_page_wbinvd_tdr(struct tdx_td *td); #else static inline void tdx_init(void) { } static inline int tdx_cpu_enable(void) { return -ENODEV; } diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index d71656868fe4..b2a1ed13d0da 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1692,3 +1692,46 @@ u64 tdh_vp_init_apicid(struct tdx_vp *vp, u64 initia= l_rcx, u32 x2apicid) return seamcall(TDH_VP_INIT | (1ULL << TDX_VERSION_SHIFT), &args); } EXPORT_SYMBOL_GPL(tdh_vp_init_apicid); + +/* + * TDX ABI defines output operands as PT, OWNER and SIZE. These are TDX de= fined fomats. + * So despite the names, they must be interpted specially as described by = the spec. Return + * them only for error reporting purposes. + */ +u64 tdh_phymem_page_reclaim(struct page *page, u64 *tdx_pt, u64 *tdx_owner= , u64 *tdx_size) +{ + struct tdx_module_args args =3D { + .rcx =3D page_to_pfn(page) << PAGE_SHIFT, + }; + u64 ret; + + ret =3D seamcall_ret(TDH_PHYMEM_PAGE_RECLAIM, &args); + + *tdx_pt =3D args.rcx; + *tdx_owner =3D args.rdx; + *tdx_size =3D args.r8; + + return ret; +} +EXPORT_SYMBOL_GPL(tdh_phymem_page_reclaim); + +u64 tdh_phymem_cache_wb(bool resume) +{ + struct tdx_module_args args =3D { + .rcx =3D resume ? 1 : 0, + }; + + return seamcall(TDH_PHYMEM_CACHE_WB, &args); +} +EXPORT_SYMBOL_GPL(tdh_phymem_cache_wb); + +u64 tdh_phymem_page_wbinvd_tdr(struct tdx_td *td) +{ + struct tdx_module_args args =3D {}; + + args.rcx =3D tdx_tdr_pa(td) | ((u64)tdx_global_keyid << boot_cpu_data.x86= _phys_bits); + + return seamcall(TDH_PHYMEM_PAGE_WBINVD, &args); +} +EXPORT_SYMBOL_GPL(tdh_phymem_page_wbinvd_tdr); + diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h index 3663971a3669..191bdd1e571d 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -26,11 +26,14 @@ #define TDH_MNG_INIT 21 #define TDH_VP_INIT 22 #define TDH_PHYMEM_PAGE_RDMD 24 +#define TDH_PHYMEM_PAGE_RECLAIM 28 #define TDH_SYS_KEY_CONFIG 31 #define TDH_SYS_INIT 33 #define TDH_SYS_RD 34 #define TDH_SYS_LP_INIT 35 #define TDH_SYS_TDMR_INIT 36 +#define TDH_PHYMEM_CACHE_WB 40 +#define TDH_PHYMEM_PAGE_WBINVD 41 #define TDH_SYS_CONFIG 45 =20 /* --=20 2.47.1 From nobody Wed Dec 4 18:51:04 2024 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) (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 33CDE13BC26; Tue, 3 Dec 2024 01:03:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733187822; cv=none; b=j4WEMgl7XZ/2b6V+RctmGMpnatD8Ofyz19ZvZdw5Y+ph/rFjrfl96s0ahjcyU9bSiWR+BVO6UseQ9hc/Z2ILEj/uAyco5S39vhoanpAtzrIPpqlKdTROEyHzf0BhP2Awcvl1b8ScBnZNmYyaQqgRetrVL0Ry31a8D+05tgk3boA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733187822; c=relaxed/simple; bh=XgIw8C4zc2FbMwSPSQQEBwUlwsGZvZvMBluPPlEeKN4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=so+xJgPhSDLPLJbnH5yT/DXq4rrcMNn2rO5cD5aNbun7zZqAwmV80xn7Y6D/Bt80M/lVsUueovN48VUmcfKyWx/IHKrh36h6V7AKADtC4plH1Kw/0//yJ6gYudGvjJEfWza4ae/l6NKueimBp1Q6ZZoH83tC4rqw7/EwHgLxPDU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=aUlKwO1t; arc=none smtp.client-ip=192.198.163.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="aUlKwO1t" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1733187821; x=1764723821; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=XgIw8C4zc2FbMwSPSQQEBwUlwsGZvZvMBluPPlEeKN4=; b=aUlKwO1tzdF8D6v+8QvghUqRpRwm/V5MnO5brnvRSwILijkxB7KZ2S0h 9NLk1cSfKASqf8qE78CaUOD+Uijh6flH7CLl4XXIkGzavvrmGj423Uuhk Ok4R+wUKKjNVq8Qm4dGa7ggZNJ0gbUZ0NuBYxj8l7bSHuGh5HGCMz/8xF StfM0YNecFb6aIStOUGNaswAl9lBD4WCdkUyMfUIVbGCJfIpbeSsZsC42 OVmSEB2K9MIMNgdJhnOV4BsFxesWfj1Q3xE0ULZ0mHBSRGtzydNFJBhiH YkVMcBBYp52SUwhKYekOKqfarWgNhJyQlWkvx0Zsv1q7rEozYQn7y8tph Q==; X-CSE-ConnectionGUID: guNICuOiSBm4nndHwKj1vQ== X-CSE-MsgGUID: PheE++vQSNWZoxv9TrzhHw== X-IronPort-AV: E=McAfee;i="6700,10204,11274"; a="36237985" X-IronPort-AV: E=Sophos;i="6.12,203,1728975600"; d="scan'208";a="36237985" Received: from fmviesa002.fm.intel.com ([10.60.135.142]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Dec 2024 17:03:35 -0800 X-CSE-ConnectionGUID: at0paRHoTHyktfHPe+BhHA== X-CSE-MsgGUID: uraSvL7rSyWUEXgO90iWgg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,203,1728975600"; d="scan'208";a="116535803" Received: from jairdeje-mobl1.amr.corp.intel.com (HELO rpedgeco-desk4..) ([10.124.223.7]) by fmviesa002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Dec 2024 17:03:27 -0800 From: Rick Edgecombe To: kvm@vger.kernel.org, pbonzini@redhat.com, seanjc@google.com, dave.hansen@intel.com Cc: isaku.yamahata@gmail.com, kai.huang@intel.com, linux-kernel@vger.kernel.org, tony.lindgren@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, rick.p.edgecombe@intel.com, x86@kernel.org, adrian.hunter@intel.com, Isaku Yamahata , Binbin Wu , Yuan Yao Subject: [RFC PATCH v2 5/6] x86/virt/tdx: Add SEAMCALL wrappers for TDX VM/vCPU field access Date: Mon, 2 Dec 2024 17:03:15 -0800 Message-ID: <20241203010317.827803-6-rick.p.edgecombe@intel.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241203010317.827803-1-rick.p.edgecombe@intel.com> References: <20241203010317.827803-1-rick.p.edgecombe@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" Intel TDX protects guest VMs from malicious host and certain physical attacks. The TDX module has TD scoped and vCPU scoped "metadata fields". These fields are a bit like VMCS fields, and stored in data structures maintained by the TDX module. Export 3 SEAMCALLs for use in reading and writing these fields: Make tdh_mng_rd() use MNG.VP.RD to read the TD scoped metadata. Make tdh_vp_rd()/tdh_vp_wr() use TDH.VP.RD/WR to read/write the vCPU scoped metadata. KVM will use these by creating inline helpers that target various metadata sizes. Export the raw SEAMCALL leaf, to avoid exporting the large number of various sized helpers. Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Signed-off-by: Isaku Yamahata Signed-off-by: Kai Huang Signed-off-by: Rick Edgecombe Reviewed-by: Binbin Wu Reviewed-by: Yuan Yao --- SEAMCALL RFC: - Use struct tdx_td and struct tdx_vp uAPI breakout v2: - Change to use 'u64' as function parameter to prepare to move SEAMCALL wrappers to arch/x86. (Kai) - Split to separate patch - Move SEAMCALL wrappers from KVM to x86 core; - Move TDH_xx macros from KVM to x86 core; - Re-write log uAPI breakout v1: - Make argument to C wrapper function struct kvm_tdx * or struct vcpu_tdx * .(Sean) - Drop unused helpers (Kai) - Fix bisectability issues in headers (Kai) - Updates from seamcall overhaul (Kai) v19: - Update the commit message to match the patch by Yuan - Use seamcall() and seamcall_ret() by paolo v18: - removed stub functions for __seamcall{,_ret}() - Added Reviewed-by Binbin - Make tdx_seamcall() use struct tdx_module_args instead of taking each inputs. --- arch/x86/include/asm/tdx.h | 3 +++ arch/x86/virt/vmx/tdx/tdx.c | 47 +++++++++++++++++++++++++++++++++++++ arch/x86/virt/vmx/tdx/tdx.h | 3 +++ 3 files changed, 53 insertions(+) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index f6ab8a9ea46b..9bc3c1160d43 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -147,9 +147,12 @@ u64 tdh_vp_addcx(struct tdx_vp *vp, struct page *tdcx_= page); u64 tdh_mng_key_config(struct tdx_td *td); u64 tdh_mng_create(struct tdx_td *td, u64 hkid); u64 tdh_vp_create(struct tdx_td *td, struct tdx_vp *vp); +u64 tdh_mng_rd(struct tdx_td *td, u64 field, u64 *data); u64 tdh_mng_key_freeid(struct tdx_td *td); u64 tdh_mng_init(struct tdx_td *td, u64 td_params, u64 *extended_err); u64 tdh_vp_init(struct tdx_vp *vp, u64 initial_rcx); +u64 tdh_vp_rd(struct tdx_vp *vp, u64 field, u64 *data); +u64 tdh_vp_wr(struct tdx_vp *vp, u64 field, u64 data, u64 mask); u64 tdh_vp_init_apicid(struct tdx_vp *vp, u64 initial_rcx, u32 x2apicid); u64 tdh_phymem_page_reclaim(struct page *page, u64 *tdx_pt, u64 *tdx_owner= , u64 *tdx_size); u64 tdh_phymem_cache_wb(bool resume); diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index b2a1ed13d0da..6d35ea5b238f 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1643,6 +1643,23 @@ u64 tdh_vp_create(struct tdx_td *td, struct tdx_vp *= vp) } EXPORT_SYMBOL_GPL(tdh_vp_create); =20 +u64 tdh_mng_rd(struct tdx_td *td, u64 field, u64 *data) +{ + struct tdx_module_args args =3D { + .rcx =3D tdx_tdr_pa(td), + .rdx =3D field, + }; + u64 ret; + + ret =3D seamcall_ret(TDH_MNG_RD, &args); + + /* R8: Content of the field, or 0 in case of error. */ + *data =3D args.r8; + + return ret; +} +EXPORT_SYMBOL_GPL(tdh_mng_rd); + u64 tdh_mng_key_freeid(struct tdx_td *td) { struct tdx_module_args args =3D { @@ -1680,6 +1697,36 @@ u64 tdh_vp_init(struct tdx_vp *vp, u64 initial_rcx) } EXPORT_SYMBOL_GPL(tdh_vp_init); =20 +u64 tdh_vp_rd(struct tdx_vp *vp, u64 field, u64 *data) +{ + struct tdx_module_args args =3D { + .rcx =3D tdx_tdvpr_pa(vp), + .rdx =3D field, + }; + u64 ret; + + ret =3D seamcall_ret(TDH_VP_RD, &args); + + /* R8: Content of the field, or 0 in case of error. */ + *data =3D args.r8; + + return ret; +} +EXPORT_SYMBOL_GPL(tdh_vp_rd); + +u64 tdh_vp_wr(struct tdx_vp *vp, u64 field, u64 data, u64 mask) +{ + struct tdx_module_args args =3D { + .rcx =3D tdx_tdvpr_pa(vp), + .rdx =3D field, + .r8 =3D data, + .r9 =3D mask, + }; + + return seamcall(TDH_VP_WR, &args); +} +EXPORT_SYMBOL_GPL(tdh_vp_wr); + u64 tdh_vp_init_apicid(struct tdx_vp *vp, u64 initial_rcx, u32 x2apicid) { struct tdx_module_args args =3D { diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h index 191bdd1e571d..5179fc02d109 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -21,11 +21,13 @@ #define TDH_VP_ADDCX 4 #define TDH_MNG_KEY_CONFIG 8 #define TDH_MNG_CREATE 9 +#define TDH_MNG_RD 11 #define TDH_VP_CREATE 10 #define TDH_MNG_KEY_FREEID 20 #define TDH_MNG_INIT 21 #define TDH_VP_INIT 22 #define TDH_PHYMEM_PAGE_RDMD 24 +#define TDH_VP_RD 26 #define TDH_PHYMEM_PAGE_RECLAIM 28 #define TDH_SYS_KEY_CONFIG 31 #define TDH_SYS_INIT 33 @@ -34,6 +36,7 @@ #define TDH_SYS_TDMR_INIT 36 #define TDH_PHYMEM_CACHE_WB 40 #define TDH_PHYMEM_PAGE_WBINVD 41 +#define TDH_VP_WR 43 #define TDH_SYS_CONFIG 45 =20 /* --=20 2.47.1 From nobody Wed Dec 4 18:51:04 2024 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) (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 2C88238DDB; Tue, 3 Dec 2024 01:03:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733187819; cv=none; b=Qzl2pd+xEsuTXdLS8RqK4Bl38USOcE6LkSDCFDXrlAgU5RcgpRAGJlgsrrnWfRxQqyCWODM1B8y7ZRxu00jcDYidA+Mv7lX50hz49LGwtlYUaGXUfWjnUxj7zn7qGxgBmXvZy7m1/ynBoEN+lQhU+oadI3XjEHfiOOmGD/Ydus0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733187819; c=relaxed/simple; bh=54DU+ONjh4pkPzhTAsMKat9UD+OUecZLuC3YL4VA5Jg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mDXrSAwg1O3iuVC0sJvyg2+VEYJj7WRSqwlPUMBPZZV5YTA27KP/5B1ffekx0R6yGoRldrdSpSO+akC7+gGp+73sPCBQQPPnvLaYC/4ecsvZvnypwfe0JfytbpGxPf6/2ugAONvKm3kzYY2L2mBiTzjL19M+p0sjA6rKQEpYTsI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=SiPdOf6k; arc=none smtp.client-ip=192.198.163.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="SiPdOf6k" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1733187818; x=1764723818; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=54DU+ONjh4pkPzhTAsMKat9UD+OUecZLuC3YL4VA5Jg=; b=SiPdOf6keHa2RbHiqilztUYmNqiFr1pfnnUrpwuSZhB7vuzQiaKNeueO V5+nPtQkNlTVfXLn4QavPr8gDpxN3ApSNZw8pYoFv8xGrA0WNzRxCcq1e vsGDcYpsx0ZdW0wTZRtQ1FJyQMRpsSFe2u81uEUTBReCgu7Ea0nGXNKlX 1scTR1iIU0vNW/IdOSLYDE4JdbP8mE+JBHkZWz34eEc9XGcVe1hZ3F0TV BQXJ7e3OcdABUUn6aZyokfK0Q2+To29nLS3bIbqB2TkI86h3HQpb/l1Hz MyOi1E9202N9JODbw8ApAX5t4oNLZgVPnuSqLTUnxHn3GDjpVPZ7LS4u3 A==; X-CSE-ConnectionGUID: KZVbm9IzQPOQVfhV3jLPug== X-CSE-MsgGUID: V+tf/fnqQ1inTnITZfHazg== X-IronPort-AV: E=McAfee;i="6700,10204,11274"; a="36237964" X-IronPort-AV: E=Sophos;i="6.12,203,1728975600"; d="scan'208";a="36237964" Received: from fmviesa002.fm.intel.com ([10.60.135.142]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Dec 2024 17:03:35 -0800 X-CSE-ConnectionGUID: IpUsdDMERxeA+bnUhyRJtQ== X-CSE-MsgGUID: HilZh7QzTLCppxwX9+G2SA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,203,1728975600"; d="scan'208";a="116535806" Received: from jairdeje-mobl1.amr.corp.intel.com (HELO rpedgeco-desk4..) ([10.124.223.7]) by fmviesa002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Dec 2024 17:03:28 -0800 From: Rick Edgecombe To: kvm@vger.kernel.org, pbonzini@redhat.com, seanjc@google.com, dave.hansen@intel.com Cc: isaku.yamahata@gmail.com, kai.huang@intel.com, linux-kernel@vger.kernel.org, tony.lindgren@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, rick.p.edgecombe@intel.com, x86@kernel.org, adrian.hunter@intel.com, Isaku Yamahata , Binbin Wu , Yuan Yao Subject: [RFC PATCH v2 6/6] x86/virt/tdx: Add SEAMCALL wrappers for TDX flush operations Date: Mon, 2 Dec 2024 17:03:16 -0800 Message-ID: <20241203010317.827803-7-rick.p.edgecombe@intel.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20241203010317.827803-1-rick.p.edgecombe@intel.com> References: <20241203010317.827803-1-rick.p.edgecombe@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" Intel TDX protects guest VMs from malicious host and certain physical attacks. The TDX module has the concept of flushing vCPUs. These flushes include both a flush of the translation caches and also any other state internal to the TDX module. Before freeing a KeyID, this flush operation needs to be done. KVM will need to perform the flush on each pCPU associated with the TD, and also perform a TD scoped operation that checks if the flush has been done on all vCPU's associated with the TD. Add a tdh_vp_flush() function to be used to call TDH.VP.FLUSH on each pCPU associated with the TD during TD teardown. It will also be called when disabling TDX and during vCPU migration between pCPUs. Add tdh_mng_vpflushdone() to be used by KVM to call TDH.MNG.VPFLUSHDONE. KVM will use this during TD teardown to verify that TDH.VP.FLUSH has been called sufficiently, and advance the state machine that will allow for reclaiming the TD's KeyID. Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson Signed-off-by: Isaku Yamahata Signed-off-by: Kai Huang Signed-off-by: Rick Edgecombe Reviewed-by: Binbin Wu Reviewed-by: Yuan Yao --- SEAMCALL RFC: - Use struct tdx_td and struct tdx_vp uAPI breakout v2: - Change to use 'u64' as function parameter to prepare to move SEAMCALL wrappers to arch/x86. (Kai) - Split to separate patch - Move SEAMCALL wrappers from KVM to x86 core; - Move TDH_xx macros from KVM to x86 core; - Re-write log uAPI breakout v1: - Make argument to C wrapper function struct kvm_tdx * or struct vcpu_tdx * .(Sean) - Drop unused helpers (Kai) - Fix bisectability issues in headers (Kai) - Updates from seamcall overhaul (Kai) v19: - Update the commit message to match the patch by Yuan - Use seamcall() and seamcall_ret() by paolo v18: - removed stub functions for __seamcall{,_ret}() - Added Reviewed-by Binbin - Make tdx_seamcall() use struct tdx_module_args instead of taking each inputs. --- arch/x86/include/asm/tdx.h | 2 ++ arch/x86/virt/vmx/tdx/tdx.c | 20 ++++++++++++++++++++ arch/x86/virt/vmx/tdx/tdx.h | 2 ++ 3 files changed, 24 insertions(+) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 9bc3c1160d43..bbb8f0bae9ba 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -148,6 +148,8 @@ u64 tdh_mng_key_config(struct tdx_td *td); u64 tdh_mng_create(struct tdx_td *td, u64 hkid); u64 tdh_vp_create(struct tdx_td *td, struct tdx_vp *vp); u64 tdh_mng_rd(struct tdx_td *td, u64 field, u64 *data); +u64 tdh_vp_flush(struct tdx_vp *vp); +u64 tdh_mng_vpflushdone(struct tdx_td *td); u64 tdh_mng_key_freeid(struct tdx_td *td); u64 tdh_mng_init(struct tdx_td *td, u64 td_params, u64 *extended_err); u64 tdh_vp_init(struct tdx_vp *vp, u64 initial_rcx); diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 6d35ea5b238f..b30ee1cff22f 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1660,6 +1660,26 @@ u64 tdh_mng_rd(struct tdx_td *td, u64 field, u64 *da= ta) } EXPORT_SYMBOL_GPL(tdh_mng_rd); =20 +u64 tdh_vp_flush(struct tdx_vp *vp) +{ + struct tdx_module_args args =3D { + .rcx =3D tdx_tdvpr_pa(vp), + }; + + return seamcall(TDH_VP_FLUSH, &args); +} +EXPORT_SYMBOL_GPL(tdh_vp_flush); + +u64 tdh_mng_vpflushdone(struct tdx_td *td) +{ + struct tdx_module_args args =3D { + .rcx =3D tdx_tdr_pa(td), + }; + + return seamcall(TDH_MNG_VPFLUSHDONE, &args); +} +EXPORT_SYMBOL_GPL(tdh_mng_vpflushdone); + u64 tdh_mng_key_freeid(struct tdx_td *td) { struct tdx_module_args args =3D { diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h index 5179fc02d109..08b01b7fe7c2 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -22,6 +22,8 @@ #define TDH_MNG_KEY_CONFIG 8 #define TDH_MNG_CREATE 9 #define TDH_MNG_RD 11 +#define TDH_VP_FLUSH 18 +#define TDH_MNG_VPFLUSHDONE 19 #define TDH_VP_CREATE 10 #define TDH_MNG_KEY_FREEID 20 #define TDH_MNG_INIT 21 --=20 2.47.1