From patchwork Fri Nov 15 20:20:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rick Edgecombe X-Patchwork-Id: 13876775 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.9]) (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 D13FB15FD13; Fri, 15 Nov 2024 20:20:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.9 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731702042; cv=none; b=aM9z60ziUF7lL7bgcAe0Vw0kZPGSnc3LJAaw412A9TbFWlsmfm4PSYVeMPIZ01cl68aJxOdIe5xKI177i7/USrtpB5j6OXGYAPua441RSW3T2H2ycUvgSNhVzlHjWbKnD4i8LOQjtKn4h/TVjCXCN2+uyfIRj9ZXATT5WkWJw6I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731702042; c=relaxed/simple; bh=gBg3L2e5m3DkycRmAJj5P8rPfMkozkulXEtGKjJJvKE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PgbtDf2usXMCmUfjnjQ/huILtltC9Z8EqbEU83sSJM/+0pXozYkVZtcC0gpq6gVfEB47adfvfTn3mRQt8xopA2zAAd2vpwks/sBWz1K28iknpbpa8yaI98uShcUrArIJGa0LKuhWUkXy5UNtCbj60wmmG7PjgaA3xUvR0E4mvWo= 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=SSw1DsvS; arc=none smtp.client-ip=198.175.65.9 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="SSw1DsvS" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1731702041; x=1763238041; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=gBg3L2e5m3DkycRmAJj5P8rPfMkozkulXEtGKjJJvKE=; b=SSw1DsvSvtEetgjxt58v8MI0Hgordjf6xrr8s7IfWI6wnbKoCMoUb5K2 kYglAHntGk9zOext5lAuXsImVaO0GqryV97Jw4toUXqVy6PEK0Jtudknu GWv7WRvDA4tuiqybVnyxKtPI9g9YECWF1E4sEVdIEnDGSixofL9fDLKmZ Xw1QGVJvSRmm4HJ02w6QPYpgkABT97tflw7ChZZq0pEXdCnmjj39Qxg4b vxgrWv3Lmq5p9u+d/Jsk2A4RJLmaYc/cLYZs4HQq9/1nxHWU6yLtZ6Y5z mKQB0OoKor9ddyCTvZUOfeOyqguaaHDwgteNU88nbPZYs4FJDONifSnHJ A==; X-CSE-ConnectionGUID: KCPExCWmQbCQmyuxgFMpiA== X-CSE-MsgGUID: rZL1+UNKR7esh4R5SK3l5w== X-IronPort-AV: E=McAfee;i="6700,10204,11257"; a="54228327" X-IronPort-AV: E=Sophos;i="6.12,157,1728975600"; d="scan'208";a="54228327" Received: from orviesa005.jf.intel.com ([10.64.159.145]) by orvoesa101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Nov 2024 12:20:40 -0800 X-CSE-ConnectionGUID: qw4oD8xFRu+MZzD9gRAiHw== X-CSE-MsgGUID: 8601D9pbRNu0hJbNv7Q+sw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,157,1728975600"; d="scan'208";a="93599393" Received: from jairdeje-mobl1.amr.corp.intel.com (HELO rpedgeco-desk4..) ([10.124.221.173]) by orviesa005-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Nov 2024 12:20:39 -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 1/6] x86/virt/tdx: Add SEAMCALL wrappers for TDX KeyID management Date: Fri, 15 Nov 2024 12:20:22 -0800 Message-ID: <20241115202028.1585487-2-rick.p.edgecombe@intel.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241115202028.1585487-1-rick.p.edgecombe@intel.com> References: <20241115202028.1585487-1-rick.p.edgecombe@intel.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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: - 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 | 9 +++++++++ arch/x86/virt/vmx/tdx/tdx.c | 22 ++++++++++++++++++++++ arch/x86/virt/vmx/tdx/tdx.h | 16 +++++++++------- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index d33e46d53d59..ebee4260545f 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -34,6 +34,7 @@ #include #include "tdx_global_metadata.h" +#include /* * Used by the #VE exception handler to gather the #VE exception @@ -121,6 +122,14 @@ const struct tdx_sys_info *tdx_get_sysinfo(void); int tdx_guest_keyid_alloc(void); void tdx_guest_keyid_free(unsigned int keyid); + +struct tdx_td { + hpa_t tdr; + hpa_t *tdcs; +}; + +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..20eb756b41de 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1562,3 +1562,25 @@ void tdx_guest_keyid_free(unsigned int keyid) ida_free(&tdx_guest_keyid_pool, keyid); } EXPORT_SYMBOL_GPL(tdx_guest_keyid_free); + +u64 tdh_mng_key_config(struct tdx_td *td) +{ + struct tdx_module_args args = { + .rcx = td->tdr, + }; + + 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 = { + .rcx = td->tdr, + }; + + 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 /* TDX page types */ #define PT_NDA 0x0 From patchwork Fri Nov 15 20:20:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rick Edgecombe X-Patchwork-Id: 13876776 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.9]) (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 A14551E3769; Fri, 15 Nov 2024 20:20:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.9 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731702043; cv=none; b=p56dBKmALDZFc5mteO6xPfLb3RxfNzH1oE/LhFTF6uKTrCI0ZfCAAo/cKt81ilpRRk5/vw1+wIfgKUiSfNBIoM5KLzBcmQITRAJ7SlwLEyXT1U4CHV7e823fCu/9km+3eT5y4xJq5aBYKQ8h1o21XQW+MPIzoWwvxFTzt2s+nOY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731702043; c=relaxed/simple; bh=wMjPzp3QUVhWOaHltapTeuIa/kFRljLy6ptsM08qBv8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=su8pZ2VBr3THExQfN28+O/zUvfvPdHG4NtQD1HvN6vdJoJiUzq0BCfUQ51xTq0GlJq9ueckj0dgq4UTi31KQj1Ak+qHiUJUTedVMQBPkdr1rUZ4f2fphE/bmFPfOSMnRGKlF+RcGzPQt15PIDmrnX9CjwmqzG2q2F0IStRSKUDY= 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=VxiHmVJD; arc=none smtp.client-ip=198.175.65.9 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="VxiHmVJD" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1731702042; x=1763238042; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=wMjPzp3QUVhWOaHltapTeuIa/kFRljLy6ptsM08qBv8=; b=VxiHmVJDef/CqKc8dAZWXbswhk+Xjr32DBVfKJKE94bnjqrBUbPPhBeY LsVRDlpoYOgTr4teGFMjndwu1LgLQ6Aw3la5UzyOO9eWpI0TBa7HwLSfA 6q7Ug9ZYc1cONQGVmoRqP1tbdFK79knmw1w0L4VR0OJJVbAN2o1Tt6Oia Yha0RbhaU6S/z4sJDBwUnW8OqmTzDbwnZm6ME1aT7YoudyzxfWjca1l4C VV+2ZcDRrOsCm1sdEs2g/mAunfJBDP7EpkjllqRmlmYdaiZScqZ11sCvp 8jvHzcBnazoAaghkwBLhP8XKKKc1yUpSYN6fXWe9vt7ZMJdP6+vTt55e2 g==; X-CSE-ConnectionGUID: cgI+B2WkQ+uGBzP2TGzTmA== X-CSE-MsgGUID: JQ3ptZWiR2W7DA3OXaN8Gw== X-IronPort-AV: E=McAfee;i="6700,10204,11257"; a="54228333" X-IronPort-AV: E=Sophos;i="6.12,157,1728975600"; d="scan'208";a="54228333" Received: from orviesa005.jf.intel.com ([10.64.159.145]) by orvoesa101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Nov 2024 12:20:41 -0800 X-CSE-ConnectionGUID: 0/4o0IrKS+C2Bubl1YzIiA== X-CSE-MsgGUID: ZWJy2gddR5WyhKly8HJw8g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,157,1728975600"; d="scan'208";a="93599397" Received: from jairdeje-mobl1.amr.corp.intel.com (HELO rpedgeco-desk4..) ([10.124.221.173]) by orviesa005-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Nov 2024 12:20:40 -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 2/6] x86/virt/tdx: Add SEAMCALL wrappers for TDX TD creation Date: Fri, 15 Nov 2024 12:20:23 -0800 Message-ID: <20241115202028.1585487-3-rick.p.edgecombe@intel.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241115202028.1585487-1-rick.p.edgecombe@intel.com> References: <20241115202028.1585487-1-rick.p.edgecombe@intel.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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: - 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 ebee4260545f..4c4d092b7c8e 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -128,8 +128,11 @@ struct tdx_td { hpa_t *tdcs; }; +u64 tdh_mng_addcx(struct tdx_td *td, hpa_t tdcs); u64 tdh_mng_key_config(struct tdx_td *td); +u64 tdh_mng_create(struct tdx_td *td, hpa_t hkid); u64 tdh_mng_key_freeid(struct tdx_td *td); +u64 tdh_mng_init(struct tdx_td *td, u64 td_params, hpa_t *tdr); #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 20eb756b41de..311f8d85e18d 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1563,6 +1563,29 @@ void tdx_guest_keyid_free(unsigned int keyid) } EXPORT_SYMBOL_GPL(tdx_guest_keyid_free); +/* + * 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(hpa_t tdr) +{ + clflush_cache_range(__va(tdr), PAGE_SIZE); +} + +u64 tdh_mng_addcx(struct tdx_td *td, hpa_t tdcs) +{ + struct tdx_module_args args = { + .rcx = tdcs, + .rdx = td->tdr, + }; + + tdx_clflush_page(tdcs); + 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 = { @@ -1573,6 +1596,18 @@ u64 tdh_mng_key_config(struct tdx_td *td) } EXPORT_SYMBOL_GPL(tdh_mng_key_config); +u64 tdh_mng_create(struct tdx_td *td, hpa_t hkid) +{ + struct tdx_module_args args = { + .rcx = td->tdr, + .rdx = hkid, + }; + + tdx_clflush_page(td->tdr); + return seamcall(TDH_MNG_CREATE, &args); +} +EXPORT_SYMBOL_GPL(tdh_mng_create); + u64 tdh_mng_key_freeid(struct tdx_td *td) { @@ -1584,3 +1619,19 @@ u64 tdh_mng_key_freeid(struct tdx_td *td) } EXPORT_SYMBOL_GPL(tdh_mng_key_freeid); +u64 tdh_mng_init(struct tdx_td *td, u64 td_params, hpa_t *tdr) +{ + struct tdx_module_args args = { + .rcx = td->tdr, + .rdx = td_params, + }; + u64 ret; + + ret = seamcall_ret(TDH_MNG_INIT, &args); + + *tdr = 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 From patchwork Fri Nov 15 20:20:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rick Edgecombe X-Patchwork-Id: 13876778 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.9]) (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 16B251E47A5; Fri, 15 Nov 2024 20:20:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.9 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731702045; cv=none; b=GNoTprMUEJcr5JajMrYTqR/lXmZGGpTbenKOwgPHB5vFXGzwTrQA1Q2ftRl7yYCVMF8zgO1OW/zF2L6AIqEnxK0M95UyImVyOr+8CwWa5EMsZR56ddZXpd0rTGMuLZLkcrgP+Xwnv6mMtb/0JLPny1STC3tUKxI6YN88470vLHs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731702045; c=relaxed/simple; bh=OLXyWc6a+5iTsV6Lvu2X+9Publw3xDvwiHpcQKYgg4s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZOaRcdm15D4HP6P3+cPNrAq5sjC80igpkeGguG5BKihoXxhE6eV356NQvsvIfobpbPekNWxIZ88ZhqyZhEiqR/ekYTs7tcL9oosOSWEmdIRcDHUBwIXHwfECVXlcflYypPAXIKzT5KSDzXJMlUNsnWQCKx1eE5Ek03rUjyLXApc= 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=D8GDWG3K; arc=none smtp.client-ip=198.175.65.9 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="D8GDWG3K" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1731702044; x=1763238044; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=OLXyWc6a+5iTsV6Lvu2X+9Publw3xDvwiHpcQKYgg4s=; b=D8GDWG3KPdKPSM9ktPhXiPAJaCOJTluOTWnEB9/ahV4PNJY5HH73CAb3 Qkq3T/AADGtVMLe4/StI1wccYPpeOEVPGkE0LMdm9gsBG40pUxZ3rDmd9 VEtzZJ7oDhaKFZoDklAp8JBx6gAjLZIu/AeHCZxlHWJQV0N00wJeT+2Y3 Fg/EN1sOroUuQzPHQ+bqW3iJd0niaIQp3KI17d3sa69CzAvIkpyfYuhBH aESYBeGVVeejDJihybmmeoIYNiWvNzVNk+E6Nupd8aNkGykAWb/ZQGVPH Z1UJZvc/u77hmjyhdCuUBIrR03Yn6LlyIKCzufngkXK8lRFhvfXwjUaUs g==; X-CSE-ConnectionGUID: fZ4Uvk+QSrm/MJgOVDcphg== X-CSE-MsgGUID: EaJbIXZYSUiAH+M2Z10Qag== X-IronPort-AV: E=McAfee;i="6700,10204,11257"; a="54228339" X-IronPort-AV: E=Sophos;i="6.12,157,1728975600"; d="scan'208";a="54228339" Received: from orviesa005.jf.intel.com ([10.64.159.145]) by orvoesa101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Nov 2024 12:20:42 -0800 X-CSE-ConnectionGUID: 7tX84mT3TjCBjIKlEU0Tlg== X-CSE-MsgGUID: Qz6lTGaNRnSYwaomn9ISKg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,157,1728975600"; d="scan'208";a="93599400" Received: from jairdeje-mobl1.amr.corp.intel.com (HELO rpedgeco-desk4..) ([10.124.221.173]) by orviesa005-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Nov 2024 12:20:41 -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 3/6] x86/virt/tdx: Add SEAMCALL wrappers for TDX vCPU creation Date: Fri, 15 Nov 2024 12:20:24 -0800 Message-ID: <20241115202028.1585487-4-rick.p.edgecombe@intel.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241115202028.1585487-1-rick.p.edgecombe@intel.com> References: <20241115202028.1585487-1-rick.p.edgecombe@intel.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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: - 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 | 9 ++++++++ arch/x86/virt/vmx/tdx/tdx.c | 46 +++++++++++++++++++++++++++++++++++++ arch/x86/virt/vmx/tdx/tdx.h | 11 +++++++++ 3 files changed, 66 insertions(+) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 4c4d092b7c8e..83aa2a8a56d3 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -128,11 +128,20 @@ struct tdx_td { hpa_t *tdcs; }; +struct tdx_vp { + hpa_t tdvpr; + hpa_t *tdcx; +}; + u64 tdh_mng_addcx(struct tdx_td *td, hpa_t tdcs); +u64 tdh_vp_addcx(struct tdx_vp *vp, hpa_t tdcx); u64 tdh_mng_key_config(struct tdx_td *td); u64 tdh_mng_create(struct tdx_td *td, hpa_t 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, hpa_t *tdr); +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 311f8d85e18d..c125b1519072 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1586,6 +1586,18 @@ u64 tdh_mng_addcx(struct tdx_td *td, hpa_t tdcs) } EXPORT_SYMBOL_GPL(tdh_mng_addcx); +u64 tdh_vp_addcx(struct tdx_vp *vp, hpa_t tdcx) +{ + struct tdx_module_args args = { + .rcx = tdcx, + .rdx = vp->tdvpr, + }; + + tdx_clflush_page(tdcx); + 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 = { @@ -1608,6 +1620,17 @@ u64 tdh_mng_create(struct tdx_td *td, hpa_t hkid) } EXPORT_SYMBOL_GPL(tdh_mng_create); +u64 tdh_vp_create(struct tdx_td *td, struct tdx_vp *vp) +{ + struct tdx_module_args args = { + .rcx = vp->tdvpr, + .rdx = td->tdr, + }; + + tdx_clflush_page(vp->tdvpr); + return seamcall(TDH_VP_CREATE, &args); +} +EXPORT_SYMBOL_GPL(tdh_vp_create); u64 tdh_mng_key_freeid(struct tdx_td *td) { @@ -1635,3 +1658,26 @@ u64 tdh_mng_init(struct tdx_td *td, u64 td_params, hpa_t *tdr) } EXPORT_SYMBOL_GPL(tdh_mng_init); +u64 tdh_vp_init(struct tdx_vp *vp, u64 initial_rcx) +{ + struct tdx_module_args args = { + .rcx = vp->tdvpr, + .rdx = 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 = { + .rcx = vp->tdvpr, + .rdx = initial_rcx, + .r8 = x2apicid, + }; + + /* apicid requires version == 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 +/* + * 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 From patchwork Fri Nov 15 20:20:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rick Edgecombe X-Patchwork-Id: 13876777 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.9]) (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 E9ACA1E3DF5; Fri, 15 Nov 2024 20:20:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.9 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731702044; cv=none; b=e12ECwYQEL0EJZUUCBdy/4cIykS9QdkgPZOARITS2Yjl+MOO7EzUUkv24I4J/C0vN5SwcOmP4xJbwooTFDuMhyV6AzgBRbGYhBe0JKHNHQFJ6kKoiZQKLesjcmsKvPrnAVVJmt/a2poKiMDazCoEDqInBmTCptucRvHd/v0WQoA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731702044; c=relaxed/simple; bh=7VX5l20FR85WiBNAEV7f+KeOQw6r+KV1DrGMNPdEIBo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KsZr2dG9xTtOkXk66m4Gns/OESknV7wr9Ig+IpiJe1ByGBcr/g/Co1JwLhPGUX0XHIG9MbA1VpNDbU+t0Un3yf9k4hSo4s1Jo+3nuVmaPxyJcoG30e0DiWBjRwstbCCpXLIJgEuJX7rq+4VPcLRhYafjIq9ud/PINpDPpSJld54= 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=fxXVo29T; arc=none smtp.client-ip=198.175.65.9 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="fxXVo29T" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1731702044; x=1763238044; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=7VX5l20FR85WiBNAEV7f+KeOQw6r+KV1DrGMNPdEIBo=; b=fxXVo29Tx1GvN+AYs2tkGJ4dZ6/ZhqT0iGFKq4CT3kk48TOMmTEcZ7SP LK3vqiZyqIlFDn8uPfYxXUYAHt7EFnuIdEF4chQhW4OIjD7wZl/nJJrin lpJD5LNvxyiDZBMergXBUnIQHpTgA9r+NNFgWx/srKZxBecrY0ox9hncm oPff5E0/8hsuIQAWUK90RTLgquXSqpvZK4CKWPEVZlYr9TpaAcgy4Z7Cj c0+2rNT1JwwbnjFgfw1wn6uS+L/A2pJexpsXPWcrYwFngWV/P5UbDrBr6 4BB8rxG0z0ZfKnxkX8QQ+6kauBaw0PWFqP6M10XJlH1P1WhuNAOfI2reP A==; X-CSE-ConnectionGUID: k0IXA71XRxuzzpmOrNQFKA== X-CSE-MsgGUID: MndcyhmRQkC1MGf7ZDUs4A== X-IronPort-AV: E=McAfee;i="6700,10204,11257"; a="54228346" X-IronPort-AV: E=Sophos;i="6.12,157,1728975600"; d="scan'208";a="54228346" Received: from orviesa005.jf.intel.com ([10.64.159.145]) by orvoesa101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Nov 2024 12:20:43 -0800 X-CSE-ConnectionGUID: J9LOT0IeTjufJ6bA0ubSjg== X-CSE-MsgGUID: 1NGWfZNeRseznK4O6RKYzw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,157,1728975600"; d="scan'208";a="93599404" Received: from jairdeje-mobl1.amr.corp.intel.com (HELO rpedgeco-desk4..) ([10.124.221.173]) by orviesa005-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Nov 2024 12:20:42 -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 4/6] x86/virt/tdx: Add SEAMCALL wrappers for TDX page cache management Date: Fri, 15 Nov 2024 12:20:25 -0800 Message-ID: <20241115202028.1585487-5-rick.p.edgecombe@intel.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241115202028.1585487-1-rick.p.edgecombe@intel.com> References: <20241115202028.1585487-1-rick.p.edgecombe@intel.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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: - 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 | 38 +++++++++++++++++++++++++++++++++++++ arch/x86/virt/vmx/tdx/tdx.h | 3 +++ 3 files changed, 44 insertions(+) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 83aa2a8a56d3..72de04dc242e 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -142,6 +142,9 @@ u64 tdh_mng_key_freeid(struct tdx_td *td); u64 tdh_mng_init(struct tdx_td *td, u64 td_params, hpa_t *tdr); 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(hpa_t page, u64 *page_type, u64 *page_owner, u64 *page_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 c125b1519072..6f833d816899 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1681,3 +1681,41 @@ u64 tdh_vp_init_apicid(struct tdx_vp *vp, u64 initial_rcx, u32 x2apicid) return seamcall(TDH_VP_INIT | (1ULL << TDX_VERSION_SHIFT), &args); } EXPORT_SYMBOL_GPL(tdh_vp_init_apicid); + +u64 tdh_phymem_page_reclaim(hpa_t page, u64 *page_type, u64 *page_owner, u64 *page_size) +{ + struct tdx_module_args args = { + .rcx = page, + }; + u64 ret; + + ret = seamcall_ret(TDH_PHYMEM_PAGE_RECLAIM, &args); + + *page_type = args.rcx; + *page_owner = args.rdx; + *page_size = args.r8; + + return ret; +} +EXPORT_SYMBOL_GPL(tdh_phymem_page_reclaim); + +u64 tdh_phymem_cache_wb(bool resume) +{ + struct tdx_module_args args = { + .rcx = 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 = {}; + + args.rcx = td->tdr | ((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 /* From patchwork Fri Nov 15 20:20:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rick Edgecombe X-Patchwork-Id: 13876779 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.9]) (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 957321E570F; Fri, 15 Nov 2024 20:20:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.9 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731702045; cv=none; b=ZgfVSdoUons65+wi9kuW34/Yq3JWbqhoezLbsN8TDCXbOWZabeaTQcW2vIn0TNfngFfeFp/YL+U1KzL5gNy5DhhgDmsXWWc+OB09Nr7IXrsKcGxkbhfiNvIFo6drm2gK3lpopHeD2YVJRZlHtyN6FqaFsD4X1+OpUjSD+p/Wd58= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731702045; c=relaxed/simple; bh=9zjQlMAVAGFEnQFffV1hBC1dj1KdomkhQ77qmqMyMEY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZoXHkHPTHEfCvV0KTcq0EItbmUHXaSigIysuSZejIBlcttWiALohU43kGfpB6r7udHwfWhyAmEIGfZrFMARxdjXMPIJ6ZG+h4wo/Cx/yHzX1Ejr2e62fAoGJf5zW13V9uZIExpDc/RnxZi6wJzwC1BaC5afSOLFc3JvCUQyNM9A= 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=n2UKnDgC; arc=none smtp.client-ip=198.175.65.9 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="n2UKnDgC" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1731702044; x=1763238044; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=9zjQlMAVAGFEnQFffV1hBC1dj1KdomkhQ77qmqMyMEY=; b=n2UKnDgCX37OrNoMnSrHhHIz8RPKQtVQYiCHVTqXKJXpOsBoJkCWzGk9 wg+ckNikTaQSOwcgAMnIKLIcJzbgqTILCjpKM5/7BvtbeSl5ka16FEsFi HvIN9tfzBVPR0HvsYmoqjlfL7YvsxnRLWjqMzSKJ3DQZTApCVZ9t9ihDz l66v0GM0knzfm9KdR16cz2HCAHbBVrBitJt7/KeZPYtBubjw6KKYpAV5a v5VySbYvzhzQf9latdDeCz7rYthMxcis8jJPrCJ6jdj3+0ZJ31mAGTrlL 0x8g9ASl1wymO2N37e4o6T+lkyw5QdWPIQTPK1eXgwvHvQ3ud+zXZPGzg g==; X-CSE-ConnectionGUID: iG6TDUsVS/u5ch//40dGgw== X-CSE-MsgGUID: 4dSvbyjmTEiI47v1YgTqMw== X-IronPort-AV: E=McAfee;i="6700,10204,11257"; a="54228352" X-IronPort-AV: E=Sophos;i="6.12,157,1728975600"; d="scan'208";a="54228352" Received: from orviesa005.jf.intel.com ([10.64.159.145]) by orvoesa101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Nov 2024 12:20:43 -0800 X-CSE-ConnectionGUID: cSdbujAdTA+6FGeXZfrYIw== X-CSE-MsgGUID: YruSW7q6SrSnsKvY8PfRbw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,157,1728975600"; d="scan'208";a="93599408" Received: from jairdeje-mobl1.amr.corp.intel.com (HELO rpedgeco-desk4..) ([10.124.221.173]) by orviesa005-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Nov 2024 12:20:43 -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 5/6] x86/virt/tdx: Add SEAMCALL wrappers for TDX VM/vCPU field access Date: Fri, 15 Nov 2024 12:20:26 -0800 Message-ID: <20241115202028.1585487-6-rick.p.edgecombe@intel.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241115202028.1585487-1-rick.p.edgecombe@intel.com> References: <20241115202028.1585487-1-rick.p.edgecombe@intel.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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 72de04dc242e..6a892727fdc8 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -138,9 +138,12 @@ u64 tdh_vp_addcx(struct tdx_vp *vp, hpa_t tdcx); u64 tdh_mng_key_config(struct tdx_td *td); u64 tdh_mng_create(struct tdx_td *td, hpa_t 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, hpa_t *tdr); 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(hpa_t page, u64 *page_type, u64 *page_owner, u64 *page_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 6f833d816899..28b3caf5a445 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1632,6 +1632,23 @@ u64 tdh_vp_create(struct tdx_td *td, struct tdx_vp *vp) } EXPORT_SYMBOL_GPL(tdh_vp_create); +u64 tdh_mng_rd(struct tdx_td *td, u64 field, u64 *data) +{ + struct tdx_module_args args = { + .rcx = td->tdr, + .rdx = field, + }; + u64 ret; + + ret = seamcall_ret(TDH_MNG_RD, &args); + + /* R8: Content of the field, or 0 in case of error. */ + *data = args.r8; + + return ret; +} +EXPORT_SYMBOL_GPL(tdh_mng_rd); + u64 tdh_mng_key_freeid(struct tdx_td *td) { struct tdx_module_args args = { @@ -1669,6 +1686,36 @@ u64 tdh_vp_init(struct tdx_vp *vp, u64 initial_rcx) } EXPORT_SYMBOL_GPL(tdh_vp_init); +u64 tdh_vp_rd(struct tdx_vp *vp, u64 field, u64 *data) +{ + struct tdx_module_args args = { + .rcx = vp->tdvpr, + .rdx = field, + }; + u64 ret; + + ret = seamcall_ret(TDH_VP_RD, &args); + + /* R8: Content of the field, or 0 in case of error. */ + *data = 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 = { + .rcx = vp->tdvpr, + .rdx = field, + .r8 = data, + .r9 = 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 = { 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 /* From patchwork Fri Nov 15 20:20:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rick Edgecombe X-Patchwork-Id: 13876780 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.9]) (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 E27071FB3FC; Fri, 15 Nov 2024 20:20:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.9 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731702049; cv=none; b=RFyzkGm8CHQWTit2rQZoYM96cqaPGbHJN42bY76KUztze8CyHgvVa8fL8PmI6e5dvUDlZMDJ0A4cztHvVwp7L0m9hh6QoNSCQalQ1LiG5+Sq+H+W6J814hOMnUTNAwGZLRKRdNEqbAWCRK9szFHw8680txvIb7G/jkTq26J10lM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731702049; c=relaxed/simple; bh=LkOfsVoQdCHcuFKMR71CUvS0Y3CW9UvgY0qB1HoFsU4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JVPdmR/f3HyKj+tROnHMyAgEB8Ic+qTQTVEJraXsKqIEQU2nPxOXK+za5xHvqBx0xHQEBoecig9sIw9UH+RzOJPNswIBnGribMc2m+rsQmBG2blYSND/ftna1A9lp/q3DZoo6PCjGnQhfgTRXuStL0zON42dJ2c6rvMCnvqHXKI= 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=elL8ccAu; arc=none smtp.client-ip=198.175.65.9 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="elL8ccAu" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1731702046; x=1763238046; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=LkOfsVoQdCHcuFKMR71CUvS0Y3CW9UvgY0qB1HoFsU4=; b=elL8ccAuMpCqn3gnt5VDf5vob0BBIDu8J5UYSFElcEP80RN1J5yuUjY9 TmlKbiwAGHaWSmHvb7WWmZlCW5pNAHTiYDIKAw005b4GOPf2pBO7Xcvmm vb3hMOQ9/Az7RKuyjjtLL6PgS5QxvaA8izSyyRWacJUSgZxe8oYXcr3Al NcWXlzeEm5fKZmzNEQxDzbT9zz/OEf71kKbJengiDe+PACiMjx3IT/fFk QIpjJmc8c7tkUBhGh20IK2NOEr0nqvhVyeaq0lNmyM/HADXsH9E5QCKw0 d+wrDSAZqDqeKSAkxs46aKwqZBeY8VNM1/lQslWfRPJO92phsCqYecd9n w==; X-CSE-ConnectionGUID: nG2LAaG4TUqumzcj9daEow== X-CSE-MsgGUID: UERBc9JZSieNBi1b3qv7KA== X-IronPort-AV: E=McAfee;i="6700,10204,11257"; a="54228360" X-IronPort-AV: E=Sophos;i="6.12,157,1728975600"; d="scan'208";a="54228360" Received: from orviesa005.jf.intel.com ([10.64.159.145]) by orvoesa101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Nov 2024 12:20:44 -0800 X-CSE-ConnectionGUID: MuSy2kt4RLS9qv7RWaf8Tg== X-CSE-MsgGUID: rhfJSvtIQGWz91c+K0sORw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,157,1728975600"; d="scan'208";a="93599411" Received: from jairdeje-mobl1.amr.corp.intel.com (HELO rpedgeco-desk4..) ([10.124.221.173]) by orviesa005-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Nov 2024 12:20:43 -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 6/6] x86/virt/tdx: Add SEAMCALL wrappers for TDX flush operations Date: Fri, 15 Nov 2024 12:20:27 -0800 Message-ID: <20241115202028.1585487-7-rick.p.edgecombe@intel.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241115202028.1585487-1-rick.p.edgecombe@intel.com> References: <20241115202028.1585487-1-rick.p.edgecombe@intel.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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 6a892727fdc8..7843a88dc90e 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -139,6 +139,8 @@ u64 tdh_mng_key_config(struct tdx_td *td); u64 tdh_mng_create(struct tdx_td *td, hpa_t 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, hpa_t *tdr); 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 28b3caf5a445..59cfbd1c91c0 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1649,6 +1649,26 @@ u64 tdh_mng_rd(struct tdx_td *td, u64 field, u64 *data) } EXPORT_SYMBOL_GPL(tdh_mng_rd); +u64 tdh_vp_flush(struct tdx_vp *vp) +{ + struct tdx_module_args args = { + .rcx = vp->tdvpr, + }; + + 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 = { + .rcx = td->tdr, + }; + + 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 = { 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