From nobody Thu Apr 2 15:41:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 CA71B34DB4B; Fri, 27 Mar 2026 16:22:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628559; cv=none; b=HyvFry/w8zl82BQksroaWDErIZdduBWr0CZQHg/ac6yAlHPbWxarCkvbzc6a+s9fayEJcD8yXA61CPv9ELX+BnsDYwrXaCtVTqo9LsyqQIJNk9nQQmcLnAL8+NUamuVCC3n/Eo0PMHrvjyq1EtLSbSYoUEBpx6+v+aLI6CDLbd8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628559; c=relaxed/simple; bh=tn87qbpi3uJdSP6hJiwGmQFrzB7vH6TbAKN6CQKakWs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=gLdHaZi3OIfHA9qe8OJh9CjmPj59wpOv1WkgbFAR0e74APLeiYaFilcbff1tW16lMrC3TZ7PfeeshZnMMAnt1Q0WEqU4gYXl0udB514niSjTqYk3uOT1NcQmA/a7zaCEFFu9gOOsjECZkYJy9tEucEyIdbdCESXFl2rjwUATyno= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=BtqQAND4; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="BtqQAND4" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628557; x=1806164557; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=tn87qbpi3uJdSP6hJiwGmQFrzB7vH6TbAKN6CQKakWs=; b=BtqQAND4QBLjA0dv4hbJFPy4KoGdSMxqI6IoKj31yISSbz+I4WcGxL7J AqrD1zUZhgo/XgEns0wJaYuet/2EbpF8iSF4bW3QnNKhe2cs6DFLNoXF2 dj9akjrg7mEanCtptbpehEcywENMVeT/bF7J/KItsLEJQcRgz4fMIFDyn CULf7VCBjr1QvgI83ERsEO0ZL3ae/ft0fVBZjF318eUpvfoq07A0JHQxk DsX7z4t706mlGwLh540whvXGfH/BXkKLhtECz/GKqgwSFChJ9KQfkqpbh vDa+KIxwYI/VHOr/KSnabQAkBrSClmIb+sSlSaNqgIIwe6wcSJG/scHru Q==; X-CSE-ConnectionGUID: ZH/2QFkRT0m3HSejyTjR0A== X-CSE-MsgGUID: j5IQSO10Ro+w0+hvkXJkGw== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565486" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565486" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:22:37 -0700 X-CSE-ConnectionGUID: n5MuiketTTKylM0c7VmCRw== X-CSE-MsgGUID: FsBQH4yORziItrEV7TBWJQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516112" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:22:34 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 01/31] x86/tdx: Move all TDX error defines into Date: Sat, 28 Mar 2026 00:01:02 +0800 Message-Id: <20260327160132.2946114-2-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Kirill A. Shutemov" Today there are two separate locations where TDX error codes are defined: arch/x86/include/asm/tdx.h arch/x86/kvm/vmx/tdx_errno.h They have some overlap that is already defined similarly. Reduce the duplication and prepare to introduce some helpers for these error codes in the central place by unifying them. Join them at: asm/shared/tdx_errno.h ...and update the headers that contained the duplicated definitions to include the new unified header. "asm/shared" is used for sharing TDX code between the early compressed code and the normal kernel code. While the compressed code for the guest doesn't use these error code header definitions today, it does make the types of calls that return the values they define. So place the defines in "shared" location so that it can, but leave such cleanups for future changes. Also, adjust BITUL() -> _BITULL() to address 32 bit build errors after the move. Signed-off-by: Kirill A. Shutemov [enhance log] Signed-off-by: Rick Edgecombe Signed-off-by: Vishal Verma Reviewed-by: Chao Gao --- arch/x86/include/asm/shared/tdx.h | 1 + .../vmx =3D> include/asm/shared}/tdx_errno.h | 28 +++++++++++++++---- arch/x86/include/asm/tdx.h | 21 -------------- arch/x86/kvm/vmx/tdx.h | 1 - 4 files changed, 23 insertions(+), 28 deletions(-) rename arch/x86/{kvm/vmx =3D> include/asm/shared}/tdx_errno.h (64%) diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/share= d/tdx.h index 8bc074c8d7c6..6a1646fc2b2f 100644 --- a/arch/x86/include/asm/shared/tdx.h +++ b/arch/x86/include/asm/shared/tdx.h @@ -4,6 +4,7 @@ =20 #include #include +#include =20 #define TDX_HYPERCALL_STANDARD 0 =20 diff --git a/arch/x86/kvm/vmx/tdx_errno.h b/arch/x86/include/asm/shared/tdx= _errno.h similarity index 64% rename from arch/x86/kvm/vmx/tdx_errno.h rename to arch/x86/include/asm/shared/tdx_errno.h index 6ff4672c4181..8bf6765cf082 100644 --- a/arch/x86/kvm/vmx/tdx_errno.h +++ b/arch/x86/include/asm/shared/tdx_errno.h @@ -1,14 +1,15 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* architectural status code for SEAMCALL */ - -#ifndef __KVM_X86_TDX_ERRNO_H -#define __KVM_X86_TDX_ERRNO_H +#ifndef _ASM_X86_SHARED_TDX_ERRNO_H +#define _ASM_X86_SHARED_TDX_ERRNO_H +#include =20 +/* Upper 32 bit of the TDX error code encodes the status */ #define TDX_SEAMCALL_STATUS_MASK 0xFFFFFFFF00000000ULL =20 /* - * TDX SEAMCALL Status Codes (returned in RAX) + * TDX Status Codes (returned in RAX) */ +#define TDX_SUCCESS 0ULL #define TDX_NON_RECOVERABLE_VCPU 0x4000000100000000ULL #define TDX_NON_RECOVERABLE_TD 0x4000000200000000ULL #define TDX_NON_RECOVERABLE_TD_NON_ACCESSIBLE 0x6000000500000000ULL @@ -17,6 +18,7 @@ #define TDX_OPERAND_INVALID 0xC000010000000000ULL #define TDX_OPERAND_BUSY 0x8000020000000000ULL #define TDX_PREVIOUS_TLB_EPOCH_BUSY 0x8000020100000000ULL +#define TDX_RND_NO_ENTROPY 0x8000020300000000ULL #define TDX_PAGE_METADATA_INCORRECT 0xC000030000000000ULL #define TDX_VCPU_NOT_ASSOCIATED 0x8000070200000000ULL #define TDX_KEY_GENERATION_FAILED 0x8000080000000000ULL @@ -28,6 +30,20 @@ #define TDX_EPT_ENTRY_STATE_INCORRECT 0xC0000B0D00000000ULL #define TDX_METADATA_FIELD_NOT_READABLE 0xC0000C0200000000ULL =20 +/* + * SW-defined error codes. + * + * Bits 47:40 =3D=3D 0xFF indicate Reserved status code class that never u= sed by + * TDX module. + */ +#define TDX_ERROR _BITULL(63) +#define TDX_NON_RECOVERABLE _BITULL(62) +#define TDX_SW_ERROR (TDX_ERROR | GENMASK_ULL(47, 40)) +#define TDX_SEAMCALL_VMFAILINVALID (TDX_SW_ERROR | _ULL(0xFFFF0000)) + +#define TDX_SEAMCALL_GP (TDX_SW_ERROR | X86_TRAP_GP) +#define TDX_SEAMCALL_UD (TDX_SW_ERROR | X86_TRAP_UD) + /* * TDX module operand ID, appears in 31:0 part of error code as * detail information @@ -37,4 +53,4 @@ #define TDX_OPERAND_ID_SEPT 0x92 #define TDX_OPERAND_ID_TD_EPOCH 0xa9 =20 -#endif /* __KVM_X86_TDX_ERRNO_H */ +#endif /* _ASM_X86_SHARED_TDX_ERRNO_H */ diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 6b338d7f01b7..e040e0467ae4 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -9,29 +9,8 @@ =20 #include #include -#include #include =20 -/* - * SW-defined error codes. - * - * Bits 47:40 =3D=3D 0xFF indicate Reserved status code class that never u= sed by - * TDX module. - */ -#define TDX_ERROR _BITUL(63) -#define TDX_NON_RECOVERABLE _BITUL(62) -#define TDX_SW_ERROR (TDX_ERROR | GENMASK_ULL(47, 40)) -#define TDX_SEAMCALL_VMFAILINVALID (TDX_SW_ERROR | _UL(0xFFFF0000)) - -#define TDX_SEAMCALL_GP (TDX_SW_ERROR | X86_TRAP_GP) -#define TDX_SEAMCALL_UD (TDX_SW_ERROR | X86_TRAP_UD) - -/* - * TDX module SEAMCALL leaf function error codes - */ -#define TDX_SUCCESS 0ULL -#define TDX_RND_NO_ENTROPY 0x8000020300000000ULL - #ifndef __ASSEMBLER__ =20 #include diff --git a/arch/x86/kvm/vmx/tdx.h b/arch/x86/kvm/vmx/tdx.h index 45b5183ccb36..ce2720a028ad 100644 --- a/arch/x86/kvm/vmx/tdx.h +++ b/arch/x86/kvm/vmx/tdx.h @@ -3,7 +3,6 @@ #define __KVM_X86_VMX_TDX_H =20 #include "tdx_arch.h" -#include "tdx_errno.h" =20 #ifdef CONFIG_KVM_INTEL_TDX #include "common.h" --=20 2.25.1 From nobody Thu Apr 2 15:41:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 6972334A789; Fri, 27 Mar 2026 16:22:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628562; cv=none; b=sgUwKS4HCqrnQEbw5EQxrAKD4z1cu0hKxRkpIzDy9RneoFms4V8SJ6iP61m2Wd5IZY6Jgkf7qWGvLnZmsN+hoDm/eD47kgd9mGszGM/Hn+R8L4eW6rCSBG0pBqAOgrTH5OWSSgRmoDjxHm5DDibjFqr/UlSAVy1YT94Mvvf70og= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628562; c=relaxed/simple; bh=kpGbvHoaXkXL7UPtDLh0r6IDkgZKESQJe+SKEMtuWqs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=gLYfMULFXX6uwlMGzmZaYMEcl4w3ZdiBlM5xK7tS5nB2emhCcJ7ZBEeLafFIjDpmLXS6OTUJKrfR4PYWOTV6XxRKfhp5fl7TAN1Cbyb6sj5ryMMni5QrQAGhB9IWtlnsZn3dLtABjNWR7rWGplWtEZjoof6nVqD08tOLooDyXeo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=gD3cKNzD; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="gD3cKNzD" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628561; x=1806164561; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=kpGbvHoaXkXL7UPtDLh0r6IDkgZKESQJe+SKEMtuWqs=; b=gD3cKNzDF+RbYhh5t44mdyIJnpKnXKwd37xqy1EGMEAlMSctd24C7/lJ X9NHY8OXilEnYCBdFuQ28OfiAxIcXgp39ty1AeVw70fY64fh+epo/yTId GQ+yR9WnBNm0p7x9bC+r6LAm2RlLfqN5hXEPRgeghY88p7aVxfwmxt3DF 7fmRXPtQ/w94TzIB+NOa6z/zwqPRpoKqhgwExPUMD4KFVs7PCtvZoT73N YuAo5F1lyRO3ub2axTJnL6Z9ByT2oLXkEWWY3J8qXMisfUs3jYcVpcHpp Jv4h+8sxMblaVclqQmpW7uchfrRAZWEBLKB1ysgXmwIZkUHKrcKTEvP0n Q==; X-CSE-ConnectionGUID: maLePqYFSEetb3+6qQ+p4Q== X-CSE-MsgGUID: zdBW4plWRyOaIz/+J0zXxw== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565497" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565497" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:22:40 -0700 X-CSE-ConnectionGUID: 8cAe9lgUQYOSEy9qJyUBwQ== X-CSE-MsgGUID: eh2NIIVNT4uURSnlVSCYtQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516125" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:22:37 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 02/31] x86/virt/tdx: Move bit definitions of TDX_FEATURES0 to public header Date: Sat, 28 Mar 2026 00:01:03 +0800 Message-Id: <20260327160132.2946114-3-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Move bit definitions of TDX_FEATURES0 to TDX core public header. Kernel users get TDX_FEATURES0 bitmap via tdx_get_sysinfo(). It is reasonable to also public the definitions of each bit. TDX Connect (a new TDX feature to enable Trusted I/O virtualization) will add new bits and check them in separate kernel modules. Take the opportunity to change its type to BIT_ULL since TDX_FEATURES0 is explicitly defined as 64-bit in both TDX Module Specification and TDX core code. Signed-off-by: Xu Yilun --- arch/x86/include/asm/tdx.h | 4 ++++ arch/x86/virt/vmx/tdx/tdx.h | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index e040e0467ae4..65c4da396450 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -127,6 +127,10 @@ static __always_inline u64 sc_retry(sc_func_t func, u6= 4 fn, int tdx_cpu_enable(void); int tdx_enable(void); const char *tdx_dump_mce_info(struct mce *m); + +/* Bit definitions of TDX_FEATURES0 metadata field */ +#define TDX_FEATURES0_NO_RBP_MOD BIT_ULL(18) + const struct tdx_sys_info *tdx_get_sysinfo(void); =20 int tdx_guest_keyid_alloc(void); diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h index 82bb82be8567..c641b4632826 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -84,9 +84,6 @@ struct tdmr_info { DECLARE_FLEX_ARRAY(struct tdmr_reserved_area, reserved_areas); } __packed __aligned(TDMR_INFO_ALIGNMENT); =20 -/* Bit definitions of TDX_FEATURES0 metadata field */ -#define TDX_FEATURES0_NO_RBP_MOD BIT(18) - /* * Do not put any hardware-defined TDX structure representations below * this comment! --=20 2.25.1 From nobody Thu Apr 2 15:41:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 10A0335B65F; Fri, 27 Mar 2026 16:22:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628568; cv=none; b=YZQH9XN8uROumQ0n6ihw99WZC7Tkl3/m84JoWCPEUqjG37Z691XUZKFf5r4MPYF1TqhJTCB6VOUmvDsB2IM5/x/8XC+Qh3U5OHn1K2Kupion0HhzefKAKuWfjNh1bZQDIHCfzP78rqMv+j62vldDWhN5BUfisZZQdGSUwdLgJvs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628568; c=relaxed/simple; bh=AG4iml9WAszT+rigBrGpH8H5M7c1d9jK3pet9HvraTI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=AgFMO0gBWFuhdPbYeFN9v2Pt6PzIHDmElA28nes7Jm7bbml5a+QbXROEOK47kCixBpo9NUMc6g+9jzCZLj8MJubG8A6B9CmAGd1GAzyZVwEzs/KbYvlU42Kll+HSDIScyNO1NiJD9qy2FkqcWBMLJahAglwQ0SXajQHdseV4Tbg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=l08lMvyJ; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="l08lMvyJ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628564; x=1806164564; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=AG4iml9WAszT+rigBrGpH8H5M7c1d9jK3pet9HvraTI=; b=l08lMvyJAgqCdtAAbmwyB2qIqHQw5+4hetBEN5m1oK/R9h24gv2OK/HI pOXBRce/PaiubjEbPgKbLg5JWKl9DnuBuKNEbfoDyEqblIadPkGJEma8j MMPOJgE2AvrmoNefdHAAIvPqW9cwfDlGuBzockWacmD2AIvwCeaiVpOE3 GBTx9zmOgZRCiB8qSwYud/TB7zY4YnPtk3ukq5fOMCNjLSyFI7Q2Q61Nu OKfRaUMsdiTFJ6eARTMoJte/sDYsSzRDj85EA2fW8ITfKp1stmKb3AWUV +esc4UgnDY+amTARYx3o5WWn9kyhvMrvP6CDQSU7+PsiNtD/YBr67ZDrp w==; X-CSE-ConnectionGUID: yz5aT9laR5GrvwOa4Bj9Dg== X-CSE-MsgGUID: DLmGIb0BRPm/oJOtmlPDkQ== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565504" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565504" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:22:44 -0700 X-CSE-ConnectionGUID: u9OExjqsRtGhT2BbGg6cfg== X-CSE-MsgGUID: DJi5nfsTRC+prmNX404Lmw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516132" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:22:41 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 03/31] x86/virt/tdx: Add tdx_page_array helpers for new TDX Module objects Date: Sat, 28 Mar 2026 00:01:04 +0800 Message-Id: <20260327160132.2946114-4-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add struct tdx_page_array definition for new TDX Module object types - HPA_ARRAY_T and HPA_LIST_INFO. They are used as input/output parameters in newly defined SEAMCALLs. Also define some helpers to allocate, setup and free tdx_page_array. HPA_ARRAY_T and HPA_LIST_INFO are similar in most aspects. They both represent a list of pages for TDX Module accessing. There are several use cases for these 2 structures: - As SEAMCALL inputs. They are claimed by TDX Module as control pages. Control pages are private pages for TDX Module to hold its internal control structures or private data. TDR, TDCS, TDVPR... are existing control pages, just not added via tdx_page_array. - As SEAMCALL outputs. They were TDX Module control pages and now are released. - As SEAMCALL inputs. They are just temporary buffers for exchanging data blobs in one SEAMCALL. TDX Module will not hold them for long time. The 2 structures both need a 'root page' which contains a list of HPAs. They collapse the HPA of the root page and the number of valid HPAs into a 64 bit raw value for SEAMCALL parameters. The root page is always a medium for passing data pages, TDX Module never keeps the root page. A main difference is HPA_ARRAY_T requires singleton mode when containing just 1 functional page (page0). In this mode the root page is not needed and the HPA field of the raw value directly points to the page0. But in this patch, root page is always allocated for user friendly kAPIs. Another small difference is HPA_LIST_INFO contains a 'first entry' field which could be filled by TDX Module. This simplifies host by providing the same structure when re-invoke the interrupted SEAMCALL. No need for host to touch this field. Typical usages of the tdx_page_array: 1. Add control pages: - struct tdx_page_array *array =3D tdx_page_array_create(nr_pages); - seamcall(TDH_XXX_CREATE, array, ...); 2. Release control pages: - seamcall(TDX_XXX_DELETE, array, &nr_released, &released_hpa); - tdx_page_array_ctrl_release(array, nr_released, released_hpa); 3. Exchange data blobs: - struct tdx_page_array *array =3D tdx_page_array_create(nr_pages); - seamcall(TDX_XXX, array, ...); - Read data from array. - tdx_page_array_free(array); 4. Note the root page contains 512 HPAs at most, if more pages are required, re-populate the tdx_page_array is needed. - struct tdx_page_array *array =3D tdx_page_array_alloc(nr_pages); - for each 512-page bulk - tdx_page_array_populate(array, offset); - seamcall(TDH_XXX_ADD, array, ...); In case 2, SEAMCALLs output the released page array in the form of HPA_ARRAY_T or PAGE_LIST_INFO. Use tdx_page_array_ctrl_release() to check if the output pages match the original input pages. If failed, TDX Module is buggy. In this case the safer way is to leak the control pages, call tdx_page_array_ctrl_leak(). The usage of tdx_page_array will be in following patches. Co-developed-by: Zhenzhong Duan Signed-off-by: Zhenzhong Duan Signed-off-by: Xu Yilun --- arch/x86/include/asm/tdx.h | 37 +++++ arch/x86/virt/vmx/tdx/tdx.c | 299 ++++++++++++++++++++++++++++++++++++ 2 files changed, 336 insertions(+) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 65c4da396450..9173a432b312 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -139,6 +139,43 @@ void tdx_guest_keyid_free(unsigned int keyid); =20 void tdx_quirk_reset_page(struct page *page); =20 +/** + * struct tdx_page_array - Represents a list of pages for TDX Module access + * @nr_pages: Total number of data pages in the collection + * @pages: Array of data page pointers containing all the data + * + * @offset: Internal: The starting index in @pages, positions the currently + * populated page window in @root. + * @nents: Internal: Number of valid HPAs for the page window in @root + * @root: Internal: A single 4KB page holding the 8-byte HPAs of the page + * window. The page window max size is constrained by the root page, + * which is 512 HPAs. + * + * This structure abstracts several TDX Module defined object types, e.g., + * HPA_ARRAY_T and HPA_LIST_INFO. Typically they all use a "root page" as = the + * medium to exchange a list of data pages between host and TDX Module. Th= is + * structure serves as a unified parameter type for SEAMCALL wrappers, whe= re + * these hardware object types are needed. + */ +struct tdx_page_array { + /* public: */ + unsigned int nr_pages; + struct page **pages; + + /* private: */ + unsigned int offset; + unsigned int nents; + u64 *root; +}; + +void tdx_page_array_free(struct tdx_page_array *array); +DEFINE_FREE(tdx_page_array_free, struct tdx_page_array *, if (_T) tdx_page= _array_free(_T)) +struct tdx_page_array *tdx_page_array_create(unsigned int nr_pages); +void tdx_page_array_ctrl_leak(struct tdx_page_array *array); +int tdx_page_array_ctrl_release(struct tdx_page_array *array, + unsigned int nr_released, + u64 released_hpa); + struct tdx_td { /* TD root structure: */ struct page *tdr_page; diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 8b8e165a2001..a3021e7e2490 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -258,6 +259,304 @@ static int build_tdx_memlist(struct list_head *tmb_li= st) return ret; } =20 +#define TDX_PAGE_ARRAY_MAX_NENTS (PAGE_SIZE / sizeof(u64)) + +static int tdx_page_array_populate(struct tdx_page_array *array, + unsigned int offset) +{ + u64 *entries; + int i; + + if (offset >=3D array->nr_pages) + return 0; + + array->offset =3D offset; + array->nents =3D umin(array->nr_pages - offset, + TDX_PAGE_ARRAY_MAX_NENTS); + + entries =3D array->root; + for (i =3D 0; i < array->nents; i++) + entries[i] =3D page_to_phys(array->pages[offset + i]); + + return array->nents; +} + +static void tdx_free_pages_bulk(unsigned int nr_pages, struct page **pages) +{ + int i; + + for (i =3D 0; i < nr_pages; i++) + __free_page(pages[i]); +} + +static int tdx_alloc_pages_bulk(unsigned int nr_pages, struct page **pages) +{ + unsigned int filled, done =3D 0; + + do { + filled =3D alloc_pages_bulk(GFP_KERNEL, nr_pages - done, + pages + done); + if (!filled) { + tdx_free_pages_bulk(done, pages); + return -ENOMEM; + } + + done +=3D filled; + } while (done !=3D nr_pages); + + return 0; +} + +/** + * tdx_page_array_free() - Free all memory for a tdx_page_array + * @array: The tdx_page_array to be freed. + * + * Free all associated pages and the container itself. + */ +void tdx_page_array_free(struct tdx_page_array *array) +{ + if (!array) + return; + + tdx_free_pages_bulk(array->nr_pages, array->pages); + kfree(array->pages); + kfree(array->root); + kfree(array); +} +EXPORT_SYMBOL_GPL(tdx_page_array_free); + +static struct tdx_page_array * +tdx_page_array_alloc(unsigned int nr_pages) +{ + struct tdx_page_array *array =3D NULL; + struct page **pages =3D NULL; + u64 *root =3D NULL; + int ret; + + if (!nr_pages) + return NULL; + + array =3D kzalloc_obj(*array); + if (!array) + goto out_free; + + root =3D kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!root) + goto out_free; + + pages =3D kcalloc(nr_pages, sizeof(*pages), GFP_KERNEL); + if (!pages) + goto out_free; + + ret =3D tdx_alloc_pages_bulk(nr_pages, pages); + if (ret) + goto out_free; + + array->nr_pages =3D nr_pages; + array->pages =3D pages; + array->root =3D root; + + return array; + +out_free: + kfree(pages); + kfree(root); + kfree(array); + + return NULL; +} + +/** + * tdx_page_array_create() - Create a small tdx_page_array (up to 512 page= s) + * @nr_pages: Number of pages to allocate (must be <=3D 512). + * + * Allocate and populate a tdx_page_array in a single step. This is intend= ed + * for small collections that fit within a single root page. The allocated + * pages are all order-0 pages. This is the most common use case for a lis= t of + * TDX control pages. + * + * If more pages are required, use tdx_page_array_alloc() and + * tdx_page_array_populate() to build tdx_page_array chunk by chunk. + * + * Return: Fully populated tdx_page_array or NULL on failure. + */ +struct tdx_page_array *tdx_page_array_create(unsigned int nr_pages) +{ + struct tdx_page_array *array; + int populated; + + if (nr_pages > TDX_PAGE_ARRAY_MAX_NENTS) + return NULL; + + array =3D tdx_page_array_alloc(nr_pages); + if (!array) + return NULL; + + populated =3D tdx_page_array_populate(array, 0); + if (populated !=3D nr_pages) + goto out_free; + + return array; + +out_free: + tdx_page_array_free(array); + return NULL; +} +EXPORT_SYMBOL_GPL(tdx_page_array_create); + +/** + * tdx_page_array_ctrl_leak() - Leak data pages and free the container + * @array: The tdx_page_array to be leaked. + * + * Call this function when failed to reclaim the control pages. Free the r= oot + * page and the holding structures, but orphan the data pages, to prevent = the + * host from re-allocating and accessing memory that the hardware may still + * consider private. + */ +void tdx_page_array_ctrl_leak(struct tdx_page_array *array) +{ + if (!array) + return; + + kfree(array->pages); + kfree(array->root); + kfree(array); +} +EXPORT_SYMBOL_GPL(tdx_page_array_ctrl_leak); + +static bool tdx_page_array_validate_release(struct tdx_page_array *array, + unsigned int offset, + unsigned int nr_released, + u64 released_hpa) +{ + unsigned int nents; + + if (offset >=3D array->nr_pages) + return false; + + nents =3D umin(array->nr_pages - offset, TDX_PAGE_ARRAY_MAX_NENTS); + + if (nents !=3D nr_released) { + pr_err("%s nr_released [%d] doesn't match page array nents [%d]\n", + __func__, nr_released, nents); + return false; + } + + /* + * Unfortunately TDX has multiple page allocation protocols, check the + * "singleton" case required for HPA_ARRAY_T. + */ + if (page_to_phys(array->pages[0]) =3D=3D released_hpa && + array->nr_pages =3D=3D 1) + return true; + + /* Then check the "non-singleton" case */ + if (virt_to_phys(array->root) =3D=3D released_hpa) { + u64 *entries =3D array->root; + int i; + + for (i =3D 0; i < nents; i++) { + struct page *page =3D array->pages[offset + i]; + u64 val =3D page_to_phys(page); + + if (val !=3D entries[i]) { + pr_err("%s entry[%d] [0x%llx] doesn't match page hpa [0x%llx]\n", + __func__, i, entries[i], val); + return false; + } + } + + return true; + } + + pr_err("%s failed to validate, released_hpa [0x%llx], root page hpa [0x%l= lx], page0 hpa [%#llx], number pages %u\n", + __func__, released_hpa, virt_to_phys(array->root), + page_to_phys(array->pages[0]), array->nr_pages); + + return false; +} + +/** + * tdx_page_array_ctrl_release() - Verify and release TDX control pages + * @array: The tdx_page_array used to originally create control pages. + * @nr_released: Number of HPAs the TDX Module reported as released. + * @released_hpa: The HPA list the TDX Module reported as released. + * + * TDX Module can at most release 512 control pages, so this function only + * accepts small tdx_page_array (up to 512 pages), usually created by + * tdx_page_array_create(). + * + * Return: 0 on success, -errno on page release protocol error. + */ +int tdx_page_array_ctrl_release(struct tdx_page_array *array, + unsigned int nr_released, + u64 released_hpa) +{ + int i; + + /* + * The only case where ->nr_pages is allowed to be > + * TDX_PAGE_ARRAY_MAX_NENTS is a case where those pages are never + * expected to be released by this function. + */ + if (WARN_ON(array->nr_pages > TDX_PAGE_ARRAY_MAX_NENTS)) + return -EINVAL; + + if (WARN_ONCE(!tdx_page_array_validate_release(array, 0, nr_released, + released_hpa), + "page release protocol error, consider reboot and replace TDX Modu= le.\n")) + return -EFAULT; + + for (i =3D 0; i < array->nr_pages; i++) { + u64 r; + + r =3D tdh_phymem_page_wbinvd_hkid(tdx_global_keyid, + array->pages[i]); + if (WARN_ON(r)) + return -EFAULT; + } + + tdx_page_array_free(array); + return 0; +} +EXPORT_SYMBOL_GPL(tdx_page_array_ctrl_release); + +#define HPA_LIST_INFO_FIRST_ENTRY GENMASK_U64(11, 3) +#define HPA_LIST_INFO_PFN GENMASK_U64(51, 12) +#define HPA_LIST_INFO_LAST_ENTRY GENMASK_U64(63, 55) + +static u64 __maybe_unused hpa_list_info_assign_raw(struct tdx_page_array *= array) +{ + return FIELD_PREP(HPA_LIST_INFO_FIRST_ENTRY, 0) | + FIELD_PREP(HPA_LIST_INFO_PFN, + PFN_DOWN(virt_to_phys(array->root))) | + FIELD_PREP(HPA_LIST_INFO_LAST_ENTRY, array->nents - 1); +} + +#define HPA_ARRAY_T_PFN GENMASK_U64(51, 12) +#define HPA_ARRAY_T_SIZE GENMASK_U64(63, 55) + +static u64 __maybe_unused hpa_array_t_assign_raw(struct tdx_page_array *ar= ray) +{ + unsigned long pfn; + + if (array->nents =3D=3D 1) + pfn =3D page_to_pfn(array->pages[array->offset]); + else + pfn =3D PFN_DOWN(virt_to_phys(array->root)); + + return FIELD_PREP(HPA_ARRAY_T_PFN, pfn) | + FIELD_PREP(HPA_ARRAY_T_SIZE, array->nents - 1); +} + +static u64 __maybe_unused hpa_array_t_release_raw(struct tdx_page_array *a= rray) +{ + if (array->nents =3D=3D 1) + return 0; + + return virt_to_phys(array->root); +} + static int read_sys_metadata_field(u64 field_id, u64 *data) { struct tdx_module_args args =3D {}; --=20 2.25.1 From nobody Thu Apr 2 15:41:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 A0BFE35B646; Fri, 27 Mar 2026 16:22:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628569; cv=none; b=O8lJIW4Xn4rXKAYeuTqzkx2wG6tXNZVUynrK6KsQzB8npGsvR6WklcOmqKlJRl6MUZPxC2Rr7tLxnQG2T+pZrewIou2I++Z3S1/D9tNY9aGfc1R8ONUuKGeOxhqcX19TWOaIEMVbB4mhR+GqWO5a+B4XTEJEhNh4xBIkMyLbK44= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628569; c=relaxed/simple; bh=tqGp7zAocPvqaSnOyu6xaRIKdzXyFBuBaIxg8X/6vco=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=uerQCRteG8meKf7JBlJf1VznszA438uwJLwsi880nD0Dizlk5m45+xxPgXytvTqwAbw+k2OGHWdRyWA63lbbdTbFOW4XJhyRj1J/Bd20VHPvdwfkiBySBrPFlZ4rfprp+AvwL9VHD0ud+hKiSv1MPHjpmw4Hi2VmfTTZh1mrUDM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=bL3xD+n+; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="bL3xD+n+" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628568; x=1806164568; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=tqGp7zAocPvqaSnOyu6xaRIKdzXyFBuBaIxg8X/6vco=; b=bL3xD+n+lS5XqCGF3ivpAzmFGU6HYvIljXhZkNCDZxYB7FqVPbo6q6ZC ACwIkbUoqEJZzDB6cu+UIKM7zpLvZh7xBc4zxHxH9Pk70jF0JE7TNUdAV i8VrLLzoEdqqcDNyBc+uSkWIjp78aEXbks8A9blSGuMcAx532N+ZBur16 BEMts5bGMETpfZ45AHkKM+3FH6gtn7EDCyjOzqj7MYxQUBl92Sz6IYatR VsYQvfW2jIQqEoMPWCws3ilWknay7N//GksU+I/yKeyTkCeaIOovRPzIW C5m7ucmA4iJRaTamFOrx9MrTQbt/EgnYlGgqux6S8kFcokP1ydDZKpHfc g==; X-CSE-ConnectionGUID: UYbuIjShQSiADJk1BOLAKA== X-CSE-MsgGUID: G9ojT8vIRt2v6zoiu08SVw== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565508" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565508" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:22:48 -0700 X-CSE-ConnectionGUID: gKXXZ7+RQuKLIE0qtKVoWw== X-CSE-MsgGUID: XeYds5OAQ9+YkPiEWPamWQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516143" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:22:45 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 04/31] x86/virt/tdx: Support allocating contiguous pages for tdx_page_array Date: Sat, 28 Mar 2026 00:01:05 +0800 Message-Id: <20260327160132.2946114-5-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The current tdx_page_array implementation allocates scattered order-0 pages. However, some TDX Module operations benefit from contiguous physical memory. E.g. Enabling TDX Module Extensions (an optional TDX feature) requires ~50MB memory and never returns. Such allocation would at worst cause ~25GB permanently fragmented memory if each allocated page is from a different 2M region. Support allocating contiguous pages for tdx_page_array by making the allocation method configurable. Change the tdx_page_array_alloc() to accept a custom allocation function pointer and a context parameter. Wrap the specific allocation into a tdx_page_array_alloc_contig() helper. The foreseeable caller will allocate ~50MB memory with this helper, exceeding the maximum HPAs (512) a root page can hold, the typical usage will be: - struct tdx_page_array *array =3D tdx_page_array_alloc_contig(nr_pages); - for each 512-page bulk - tdx_page_array_populate(array, offset); - seamcall(TDH_XXX_ADD, array, ...); The configurable allocation method would also benefit more tdx_page_array usages. TDX Module may require more specific memory layouts encoded in the root page. Will introduce them in following patches. Signed-off-by: Xu Yilun --- arch/x86/virt/vmx/tdx/tdx.c | 42 +++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index a3021e7e2490..6c4ed80e8e5a 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -289,7 +289,8 @@ static void tdx_free_pages_bulk(unsigned int nr_pages, = struct page **pages) __free_page(pages[i]); } =20 -static int tdx_alloc_pages_bulk(unsigned int nr_pages, struct page **pages) +static int tdx_alloc_pages_bulk(unsigned int nr_pages, struct page **pages, + void *data) { unsigned int filled, done =3D 0; =20 @@ -326,7 +327,10 @@ void tdx_page_array_free(struct tdx_page_array *array) EXPORT_SYMBOL_GPL(tdx_page_array_free); =20 static struct tdx_page_array * -tdx_page_array_alloc(unsigned int nr_pages) +tdx_page_array_alloc(unsigned int nr_pages, + int (*alloc_fn)(unsigned int nr_pages, + struct page **pages, void *data), + void *data) { struct tdx_page_array *array =3D NULL; struct page **pages =3D NULL; @@ -348,7 +352,7 @@ tdx_page_array_alloc(unsigned int nr_pages) if (!pages) goto out_free; =20 - ret =3D tdx_alloc_pages_bulk(nr_pages, pages); + ret =3D alloc_fn(nr_pages, pages, data); if (ret) goto out_free; =20 @@ -388,7 +392,7 @@ struct tdx_page_array *tdx_page_array_create(unsigned i= nt nr_pages) if (nr_pages > TDX_PAGE_ARRAY_MAX_NENTS) return NULL; =20 - array =3D tdx_page_array_alloc(nr_pages); + array =3D tdx_page_array_alloc(nr_pages, tdx_alloc_pages_bulk, NULL); if (!array) return NULL; =20 @@ -521,6 +525,36 @@ int tdx_page_array_ctrl_release(struct tdx_page_array = *array, } EXPORT_SYMBOL_GPL(tdx_page_array_ctrl_release); =20 +static int tdx_alloc_pages_contig(unsigned int nr_pages, struct page **pag= es, + void *data) +{ + struct page *page; + int i; + + page =3D alloc_contig_pages(nr_pages, GFP_KERNEL, numa_mem_id(), + &node_online_map); + if (!page) + return -ENOMEM; + + for (i =3D 0; i < nr_pages; i++) + pages[i] =3D page + i; + + return 0; +} + +/* + * For holding large number of contiguous pages, usually larger than + * TDX_PAGE_ARRAY_MAX_NENTS (512). + * + * Similar to tdx_page_array_alloc(), after allocating with this + * function, call tdx_page_array_populate() to populate the tdx_page_array. + */ +static __maybe_unused struct tdx_page_array * +tdx_page_array_alloc_contig(unsigned int nr_pages) +{ + return tdx_page_array_alloc(nr_pages, tdx_alloc_pages_contig, NULL); +} + #define HPA_LIST_INFO_FIRST_ENTRY GENMASK_U64(11, 3) #define HPA_LIST_INFO_PFN GENMASK_U64(51, 12) #define HPA_LIST_INFO_LAST_ENTRY GENMASK_U64(63, 55) --=20 2.25.1 From nobody Thu Apr 2 15:41:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 49C1435E940; Fri, 27 Mar 2026 16:22:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628573; cv=none; b=LyhKRFyxnrJcA5vqFSVBSva+VchwhN6XWeZBbhRwPYahM8DRSbTV/b2UG1WtLbbLbNwCmfiMob/q7TzSG93Or1BWCf0i7WjEw9JIlB1LlTtiYoS4QpSzvpIMOF9Wa0LD3fwvR0ZN0CXskiGnzMtpf3A2WBa9reqlDTQS/TuBixE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628573; c=relaxed/simple; bh=USq+0qILH9pbLBmpZHYQbhDjl5P3jkvMI4zsV0/QepU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=UL4IuvdxLszOhEMxqRmsR3msFtuJgd0ajkpj4XEtTtay6wUKfj5hmoXdYbWhTfyz2sJjzuKDt+CyCeW5rbvZnPXgrJCMPSpdgZyvPGz9EUuFp5QBwiL2xOUNu07ew3/SJOK+438lTh/S5wb2PRxcgjsApYP9RnglwobOUs7Q0JA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=R61jeR5W; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="R61jeR5W" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628571; x=1806164571; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=USq+0qILH9pbLBmpZHYQbhDjl5P3jkvMI4zsV0/QepU=; b=R61jeR5WWbKH9l9NspS+exTDn/bIfmTPxj2mTTUgeqTxXc2hj0L0e7wn iYSkZAUq++4EBUi/1oIULveNiC60HTkJUVezyvztZhEIIb3180pXdJTsK J7Awr2INkVf6HPV/mMnofP4nWnbpdkC2cypFZCBpQBS1nGgvYhcqVDMCC /NVrHTbM9OPkvHziD5bU1Xalt0eIANHbHEXZq1avCQOINFAWVJj7NC1b5 EWER8i3/niO9Be5djk8ioV9wYvH6Pkm4EbGHo7AVrNs10/9qsgODXhkoU U2xwZgUCC59wzfqvLxugWUZFGhEIYgr+ml8ybuHQixKlCTcqMCdan+ft5 Q==; X-CSE-ConnectionGUID: 348s2YDGRQaxVjm1ObHKRA== X-CSE-MsgGUID: vD+ERaUaTAugRGpiWpqeLA== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565514" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565514" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:22:51 -0700 X-CSE-ConnectionGUID: COEQRPy/QgSyM6AlpsKiag== X-CSE-MsgGUID: lKGOSQ2KQ26sBhpgS9rn9g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516146" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:22:48 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 05/31] x86/virt/tdx: Extend tdx_page_array to support IOMMU_MT Date: Sat, 28 Mar 2026 00:01:06 +0800 Message-Id: <20260327160132.2946114-6-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" IOMMU_MT is another TDX Module defined structure similar to HPA_ARRAY_T and HPA_LIST_INFO. The difference is it requires multi-order contiguous pages for some entries. It adds an additional NUM_PAGES field for every multi-order page entry. Add a dedicated allocation helper for IOMMU_MT. Fortunately put_page() works well for both single pages and multi-order folios, simplifying the cleanup logic for all allocation methods. Signed-off-by: Xu Yilun --- arch/x86/include/asm/tdx.h | 2 + arch/x86/virt/vmx/tdx/tdx.c | 90 +++++++++++++++++++++++++++++++++++-- 2 files changed, 89 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 9173a432b312..d5f1d7b7d1e7 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -175,6 +175,8 @@ void tdx_page_array_ctrl_leak(struct tdx_page_array *ar= ray); int tdx_page_array_ctrl_release(struct tdx_page_array *array, unsigned int nr_released, u64 released_hpa); +struct tdx_page_array * +tdx_page_array_create_iommu_mt(unsigned int iq_order, unsigned int nr_mt_p= ages); =20 struct tdx_td { /* TD root structure: */ diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 6c4ed80e8e5a..2b17e0f73dac 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -275,8 +275,15 @@ static int tdx_page_array_populate(struct tdx_page_arr= ay *array, TDX_PAGE_ARRAY_MAX_NENTS); =20 entries =3D array->root; - for (i =3D 0; i < array->nents; i++) - entries[i] =3D page_to_phys(array->pages[offset + i]); + for (i =3D 0; i < array->nents; i++) { + struct page *page =3D array->pages[offset + i]; + + entries[i] =3D page_to_phys(page); + + /* Now only for iommu_mt */ + if (compound_nr(page) > 1) + entries[i] |=3D compound_nr(page); + } =20 return array->nents; } @@ -286,7 +293,7 @@ static void tdx_free_pages_bulk(unsigned int nr_pages, = struct page **pages) int i; =20 for (i =3D 0; i < nr_pages; i++) - __free_page(pages[i]); + put_page(pages[i]); } =20 static int tdx_alloc_pages_bulk(unsigned int nr_pages, struct page **pages, @@ -463,6 +470,10 @@ static bool tdx_page_array_validate_release(struct tdx= _page_array *array, struct page *page =3D array->pages[offset + i]; u64 val =3D page_to_phys(page); =20 + /* Now only for iommu_mt */ + if (compound_nr(page) > 1) + val |=3D compound_nr(page); + if (val !=3D entries[i]) { pr_err("%s entry[%d] [0x%llx] doesn't match page hpa [0x%llx]\n", __func__, i, entries[i], val); @@ -555,6 +566,79 @@ tdx_page_array_alloc_contig(unsigned int nr_pages) return tdx_page_array_alloc(nr_pages, tdx_alloc_pages_contig, NULL); } =20 +static int tdx_alloc_pages_iommu_mt(unsigned int nr_pages, struct page **p= ages, + void *data) +{ + unsigned int iq_order =3D (unsigned int)(long)data; + struct folio *t_iq, *t_ctxiq; + int ret; + + /* TODO: folio_alloc_node() is preferred, but need numa info */ + t_iq =3D folio_alloc(GFP_KERNEL | __GFP_ZERO, iq_order); + if (!t_iq) + return -ENOMEM; + + t_ctxiq =3D folio_alloc(GFP_KERNEL | __GFP_ZERO, iq_order); + if (!t_ctxiq) { + ret =3D -ENOMEM; + goto out_t_iq; + } + + ret =3D tdx_alloc_pages_bulk(nr_pages - 2, pages + 2, NULL); + if (ret) + goto out_t_ctxiq; + + pages[0] =3D folio_page(t_iq, 0); + pages[1] =3D folio_page(t_ctxiq, 0); + + return 0; + +out_t_ctxiq: + folio_put(t_ctxiq); +out_t_iq: + folio_put(t_iq); + + return ret; +} + +/** + * tdx_page_array_create_iommu_mt() - Create a page array for IOMMU Memory= Tables + * @iq_order: The allocation order for the IOMMU Invalidation Queue. + * @nr_mt_pages: Number of additional order-0 pages for the MT. + * + * Allocate and populate a specialized tdx_page_array for IOMMU_MT structu= res. + * The resulting array consists of two multi-order folios (at index 0 and = 1) + * followed by the requested number of order-0 pages. + * + * Return: Fully populated tdx_page_array or NULL on failure. + */ +struct tdx_page_array * +tdx_page_array_create_iommu_mt(unsigned int iq_order, unsigned int nr_mt_p= ages) +{ + unsigned int nr_pages =3D nr_mt_pages + 2; + struct tdx_page_array *array; + int populated; + + if (nr_pages > TDX_PAGE_ARRAY_MAX_NENTS) + return NULL; + + array =3D tdx_page_array_alloc(nr_pages, tdx_alloc_pages_iommu_mt, + (void *)(long)iq_order); + if (!array) + return NULL; + + populated =3D tdx_page_array_populate(array, 0); + if (populated !=3D nr_pages) + goto out_free; + + return array; + +out_free: + tdx_page_array_free(array); + return NULL; +} +EXPORT_SYMBOL_GPL(tdx_page_array_create_iommu_mt); + #define HPA_LIST_INFO_FIRST_ENTRY GENMASK_U64(11, 3) #define HPA_LIST_INFO_PFN GENMASK_U64(51, 12) #define HPA_LIST_INFO_LAST_ENTRY GENMASK_U64(63, 55) --=20 2.25.1 From nobody Thu Apr 2 15:41:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 E706B3624A9; Fri, 27 Mar 2026 16:22:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628577; cv=none; b=ToPv/fnqYjYRXB7UzDIP8RqX8px82/qgD2SsD6JbcLTIod2l7u3JMs526eO0Nr7PPMrKDVNg4Kf2D0wKTWlomC6egtg4c8LmsOC7UQm7NrBr/T8aB68IoHu6ln84bheIYUXpGcXZpnnsqoUP0BtSDZn9KMEz4I3O7oK9+wUVB1s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628577; c=relaxed/simple; bh=xPHgxfDyMSOxBqXoGww2xpS50SPwXH+y3hJLxy7+2vg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=IacB7Gvd9MiZrgzpKZmBr3Y7mzzwkK/RDAS90Z9v2uERRA7V6jwzUAoDkjekomX8jywXIWDAfSY2pESMlaA/k1gr2W4wPwMZ/DJZkHQF21zigu6XMuRLWHB85w9fCfDF+dftJkYoznIImsgQIGISnTXLM/2veCpqxYU6OwCqoJc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=XZcSikWu; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="XZcSikWu" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628575; x=1806164575; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=xPHgxfDyMSOxBqXoGww2xpS50SPwXH+y3hJLxy7+2vg=; b=XZcSikWu/2mHxzT0/NPoma0AfG2+A6c7QTboa5tdvJZUxIyS4Fte0l9g c84V7Q6vat4hebxR8yxJQfAxff4huXn8ZW6AqS4CRVWlxyMGcuHBu5Qg4 h/RhZ74x2sPiOrtTyTbZj2kci6rm712EplJkCUDdRQOwUfRVKZdnfmHSc eGgTckMnYYcXIY1c49sGJr8zZcwBHU4wxrBGMpiOC2r+1xCzw9LMeDxX+ el+6bs5DYIPUph1MZQM10bG6dMd7z1LB50YHUSI/YJKBJl2mLJ5kX2RNA jen8cYtbHL5MuSckyABYdxhX7sPtd4GCMMYYqxGNj0+Cx5n4cu5UkGR3A A==; X-CSE-ConnectionGUID: UZEFPanBTOyQ4EbvIT4Q6g== X-CSE-MsgGUID: T13VESzaRj2fJAsqrkb2vg== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565524" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565524" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:22:55 -0700 X-CSE-ConnectionGUID: dzGbcFO8RruOGMCFpo70sQ== X-CSE-MsgGUID: 6TkXo9ENSwqs1Qx4+FpUgg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516153" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:22:52 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 06/31] x86/virt/tdx: Read global metadata for TDX Module Extensions/Connect Date: Sat, 28 Mar 2026 00:01:07 +0800 Message-Id: <20260327160132.2946114-7-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add reading of the global metadata for TDX Module Extensions & TDX Connect. Add them in a batch as TDX Connect is currently the only user of TDX Module Extensions and no way to initialize TDX Module Extensions without firstly enabling TDX Connect. TDX Module Extensions & TDX Connect are optional features enumerated by TDX_FEATURES0. Check the TDX_FEATURES0 before reading these metadata to avoid failing the whole TDX initialization. Signed-off-by: Xu Yilun --- arch/x86/include/asm/tdx.h | 2 ++ arch/x86/include/asm/tdx_global_metadata.h | 14 ++++++++ arch/x86/virt/vmx/tdx/tdx_global_metadata.c | 36 +++++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index d5f1d7b7d1e7..d7605235aa9b 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -129,7 +129,9 @@ int tdx_enable(void); const char *tdx_dump_mce_info(struct mce *m); =20 /* Bit definitions of TDX_FEATURES0 metadata field */ +#define TDX_FEATURES0_TDXCONNECT BIT_ULL(6) #define TDX_FEATURES0_NO_RBP_MOD BIT_ULL(18) +#define TDX_FEATURES0_EXT BIT_ULL(39) =20 const struct tdx_sys_info *tdx_get_sysinfo(void); =20 diff --git a/arch/x86/include/asm/tdx_global_metadata.h b/arch/x86/include/= asm/tdx_global_metadata.h index 060a2ad744bf..e7948bca671a 100644 --- a/arch/x86/include/asm/tdx_global_metadata.h +++ b/arch/x86/include/asm/tdx_global_metadata.h @@ -34,11 +34,25 @@ struct tdx_sys_info_td_conf { u64 cpuid_config_values[128][2]; }; =20 +struct tdx_sys_info_ext { + u16 memory_pool_required_pages; + u8 ext_required; +}; + +struct tdx_sys_info_connect { + u16 ide_mt_page_count; + u16 spdm_mt_page_count; + u16 iommu_mt_page_count; + u16 spdm_max_dev_info_pages; +}; + struct tdx_sys_info { struct tdx_sys_info_features features; struct tdx_sys_info_tdmr tdmr; struct tdx_sys_info_td_ctrl td_ctrl; struct tdx_sys_info_td_conf td_conf; + struct tdx_sys_info_ext ext; + struct tdx_sys_info_connect connect; }; =20 #endif diff --git a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c b/arch/x86/virt/vm= x/tdx/tdx_global_metadata.c index 13ad2663488b..a07f1e7b18e8 100644 --- a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c +++ b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c @@ -85,6 +85,36 @@ static int get_tdx_sys_info_td_conf(struct tdx_sys_info_= td_conf *sysinfo_td_conf return ret; } =20 +static int get_tdx_sys_info_ext(struct tdx_sys_info_ext *sysinfo_ext) +{ + int ret =3D 0; + u64 val; + + if (!ret && !(ret =3D read_sys_metadata_field(0x3100000100000000, &val))) + sysinfo_ext->memory_pool_required_pages =3D val; + if (!ret && !(ret =3D read_sys_metadata_field(0x3100000100000001, &val))) + sysinfo_ext->ext_required =3D val; + + return ret; +} + +static int get_tdx_sys_info_connect(struct tdx_sys_info_connect *sysinfo_c= onnect) +{ + int ret =3D 0; + u64 val; + + if (!ret && !(ret =3D read_sys_metadata_field(0x3000000100000001, &val))) + sysinfo_connect->ide_mt_page_count =3D val; + if (!ret && !(ret =3D read_sys_metadata_field(0x3000000100000002, &val))) + sysinfo_connect->spdm_mt_page_count =3D val; + if (!ret && !(ret =3D read_sys_metadata_field(0x3000000100000003, &val))) + sysinfo_connect->iommu_mt_page_count =3D val; + if (!ret && !(ret =3D read_sys_metadata_field(0x3000000100000007, &val))) + sysinfo_connect->spdm_max_dev_info_pages =3D val; + + return ret; +} + static int get_tdx_sys_info(struct tdx_sys_info *sysinfo) { int ret =3D 0; @@ -94,5 +124,11 @@ static int get_tdx_sys_info(struct tdx_sys_info *sysinf= o) ret =3D ret ?: get_tdx_sys_info_td_ctrl(&sysinfo->td_ctrl); ret =3D ret ?: get_tdx_sys_info_td_conf(&sysinfo->td_conf); =20 + if (sysinfo->features.tdx_features0 & TDX_FEATURES0_EXT) + ret =3D ret ?: get_tdx_sys_info_ext(&sysinfo->ext); + + if (sysinfo->features.tdx_features0 & TDX_FEATURES0_TDXCONNECT) + ret =3D ret ?: get_tdx_sys_info_connect(&sysinfo->connect); + return ret; } --=20 2.25.1 From nobody Thu Apr 2 15:41:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 949A63644D7; Fri, 27 Mar 2026 16:22:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628580; cv=none; b=bRVD9Euj+TsI2XIrNwfLIYnBK81zfiziz0jzaokHPdG5wvAFfjpHtPfp5El1i9DNyVyWHZhazs+0YaBindhrjLoIbQmn829hxGI0tHubAPlr5L5c8lN+zO/Gy2zjg8Y6g45vZPGNH+juI2B8yBNO2z9ht1SNwCChiGOqJY2SOWI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628580; c=relaxed/simple; bh=Bt+AXgtn75w+rtXbNgQtMbF5XGKAtT1/wyjaqcGdGfU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=mtgqIp2ccU9yrHW75bvhEf9tQZ6gVYfFj+ps9c/FFtbATrDOFAhOjQOOHSbMtD6WXlXmvYVZUD3caxe4wo5LOzZF6RYDuFUgCwxol3Xs7tcFdnieJ5dt9rQwiVaVaUFrJ4i9rd99zCfOSEIjGDkB2hkSMc1XJx8EOUemutfb6OE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=kdvQIbGI; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="kdvQIbGI" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628579; x=1806164579; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Bt+AXgtn75w+rtXbNgQtMbF5XGKAtT1/wyjaqcGdGfU=; b=kdvQIbGIn7Mdt8FrOPmoHAq+5P/fLBy0z2dv2Ojtl6Kv5Rrw5MAg4WjP bAX29Bmra7o0GKUrSljXF7PJ5dMV7Zhzcg3cebGpMZUFgrQvuGqlUp7LJ tdMc9s8XDcPcO50o3mXKFGtXkyKv8kLfffW+SNUZq4QsuBtk9uEWyjAVv xODzEmkDXeBHsa6iY59ajyvB71bPo3Ie1ZjdPTvu8Q1MG2aOBbEkAkP75 XrCsh5FEosKer9XMGXJ6vth6s9ZuUK64H3SlpiYljZ8nJM479Ps/dNFli GCZhjS6n7mF/yPgsHPSaHzTEZemkvPvV28jQ/zKY2cpra5cAvrJuoJaVw A==; X-CSE-ConnectionGUID: QuowUohcQL2C1sE1KCgWng== X-CSE-MsgGUID: sTQu5qcbROamvUvU+EBVxA== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565530" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565530" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:22:59 -0700 X-CSE-ConnectionGUID: YdQUWutwQw+iZMy1w4tZGQ== X-CSE-MsgGUID: GtvkTFD1RIGQEdOsfwxIdA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516160" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:22:55 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 07/31] x86/virt/tdx: Embed version info in SEAMCALL leaf function definitions Date: Sat, 28 Mar 2026 00:01:08 +0800 Message-Id: <20260327160132.2946114-8-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Embed version information in SEAMCALL leaf function definitions rather than let the caller open code them. For now, only TDH.VP.INIT is involved. Don't bother the caller to choose the SEAMCALL version if unnecessary. New version SEAMCALLs are guaranteed to be backward compatible, so ideally kernel doesn't need to keep version history and only uses the latest version SEAMCALLs. The concern is some old TDX Modules don't recognize new version SEAMCALLs. Multiple SEAMCALL versions co-exist when kernel should support these old Modules. As time goes by, the old Modules deprecate and old version SEAMCALL definitions should disappear. The old TDX Modules that only support TDH.VP.INIT v0 are all deprecated, so only provide the latest (v1) definition. Signed-off-by: Xu Yilun --- arch/x86/virt/vmx/tdx/tdx.h | 23 ++++++++++++++--------- arch/x86/virt/vmx/tdx/tdx.c | 4 ++-- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h index c641b4632826..e5a9331df451 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -2,6 +2,7 @@ #ifndef _X86_VIRT_TDX_H #define _X86_VIRT_TDX_H =20 +#include #include =20 /* @@ -11,6 +12,18 @@ * architectural definitions come first. */ =20 +/* + * SEAMCALL leaf: + * + * Bit 15:0 Leaf number + * Bit 23:16 Version number + */ +#define SEAMCALL_LEAF GENMASK(15, 0) +#define SEAMCALL_VER GENMASK(23, 16) + +#define SEAMCALL_LEAF_VER(l, v) (FIELD_PREP(SEAMCALL_LEAF, l) | \ + FIELD_PREP(SEAMCALL_VER, v)) + /* * TDX module SEAMCALL leaf functions */ @@ -31,7 +44,7 @@ #define TDH_VP_CREATE 10 #define TDH_MNG_KEY_FREEID 20 #define TDH_MNG_INIT 21 -#define TDH_VP_INIT 22 +#define TDH_VP_INIT SEAMCALL_LEAF_VER(22, 1) #define TDH_PHYMEM_PAGE_RDMD 24 #define TDH_VP_RD 26 #define TDH_PHYMEM_PAGE_RECLAIM 28 @@ -47,14 +60,6 @@ #define TDH_VP_WR 43 #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 diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 2b17e0f73dac..130214933c2f 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -2202,8 +2202,8 @@ u64 tdh_vp_init(struct tdx_vp *vp, u64 initial_rcx, u= 32 x2apicid) .r8 =3D x2apicid, }; =20 - /* apicid requires version =3D=3D 1. */ - return seamcall(TDH_VP_INIT | (1ULL << TDX_VERSION_SHIFT), &args); + /* apicid requires version =3D=3D 1. See TDH_VP_INIT definition.*/ + return seamcall(TDH_VP_INIT, &args); } EXPORT_SYMBOL_FOR_KVM(tdh_vp_init); =20 --=20 2.25.1 From nobody Thu Apr 2 15:41:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 2FF38365A1E; Fri, 27 Mar 2026 16:23:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628584; cv=none; b=bBpoRAoryFvQFaiqqUr1QFltHHL9Dl44PRxQSO54BPfB3i1HVQ3h+5sp+An/YqIEYnsITmVdcXvXHQVDHi7mHWgmq97Efr+4LWhk6pzsoTlBwIPCNIUbTfsCCAF66pJT0qNyASVL2SPwD6+nrK99v86CPk2HCB9wrZH79HDT23g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628584; c=relaxed/simple; bh=+upVX1QhrFrQr7GIQbke+fYKEB7JHU6Rc+v4ck+/2sY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=e7awGkxi2Bkhn+CZeH+e66EWyKuOsV6V8eQTh08X/F5UFbnF1YnrfmcnPf8YWdbJsL2Szgv9fCsx7XTqTw77jFyMN4vHbFEzDtdmHgfLryRkUuYytyDxNk5lDfLAMlwmWMpKqP7r2A6mg0TAX4fJ7YXZxxSSDbbwHeugGrDYXe8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=CSqrof3q; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="CSqrof3q" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628582; x=1806164582; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+upVX1QhrFrQr7GIQbke+fYKEB7JHU6Rc+v4ck+/2sY=; b=CSqrof3qt4U36Q4bMYlQieKvGiWw+WSG1K3GWfzKck0PLWLEy83bxjZi 4mXLEZ0NGLxDzIHqEKnqp4BHVZwc0JnL2Zc8SkOzSX1FYurIl3axX4jcx pw1SmpeFTMZzOh1YC61Ut9AMza/K/h7QmcpyveyF4u8RIAHmIpBKhRImi vy4SqDoID3DX3h3KOVJ7V/CFCys0lCsXlfSf2sAhFh5IcQcIPlspvQ3nQ QiirgGZdl7PdjNEvNJZ8HgSgc8B3+xBZYD+uCvaDgSejIv/JZlT66mWdJ qeF26rJxllJGbChLyf6je5jSzFGJfOXooMUhuB1SGmHiyyepPHOEQWno3 g==; X-CSE-ConnectionGUID: VUYPf1NURwCI8XuqBA1RyA== X-CSE-MsgGUID: FvcqTJ9wRt++0LXqIWcnSw== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565535" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565535" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:23:02 -0700 X-CSE-ConnectionGUID: cpJeYFmcQWeJ6DZdIYULlQ== X-CSE-MsgGUID: na2u/tGSRk2g87aLLo8LJQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516164" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:22:59 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 08/31] x86/virt/tdx: Configure TDX Module with optional TDX Connect feature Date: Sat, 28 Mar 2026 00:01:09 +0800 Message-Id: <20260327160132.2946114-9-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" TDX Module supports optional TDX features (e.g. TDX Connect & TDX Module Extensions) that won't be enabled by default. It extends TDH.SYS.CONFIG for host to choose to enable them on bootup. Call TDH.SYS.CONFIG with a new bitmap input parameter to specify which features to enable. The bitmap uses the same definitions as TDX_FEATURES0. But note not all bits in TDX_FEATURES0 are valid for configuration, e.g. TDX Module Extensions is a service that supports TDX Connect, it is implicitly enabled when TDX Connect is enabled. Setting TDX_FEATURES0_EXT in the bitmap has no effect. TDX Module advances the version of TDH.SYS.CONFIG for the change, so use the latest version (v1) for optional feature enabling. But supporting existing Modules which only support v0 is still necessary until they are deprecated, enumerate via TDX_FEATURES0 to decide which version to use. TDX Module updates global metadata when optional features are enabled. Host should update the cached tdx_sysinfo to reflect these changes. Co-developed-by: Zhenzhong Duan Signed-off-by: Zhenzhong Duan Signed-off-by: Xu Yilun --- arch/x86/virt/vmx/tdx/tdx.h | 3 ++- arch/x86/virt/vmx/tdx/tdx.c | 16 +++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h index e5a9331df451..870bb75da3ba 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -58,7 +58,8 @@ #define TDH_PHYMEM_CACHE_WB 40 #define TDH_PHYMEM_PAGE_WBINVD 41 #define TDH_VP_WR 43 -#define TDH_SYS_CONFIG 45 +#define TDH_SYS_CONFIG_V0 45 +#define TDH_SYS_CONFIG SEAMCALL_LEAF_VER(TDH_SYS_CONFIG_V0, 1) =20 /* TDX page types */ #define PT_NDA 0x0 diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 130214933c2f..0c5d6bdd810f 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1353,6 +1353,7 @@ static int construct_tdmrs(struct list_head *tmb_list, static int config_tdx_module(struct tdmr_info_list *tdmr_list, u64 global_= keyid) { struct tdx_module_args args =3D {}; + u64 seamcall_fn =3D TDH_SYS_CONFIG_V0; u64 *tdmr_pa_array; size_t array_sz; int i, ret; @@ -1377,7 +1378,15 @@ static int config_tdx_module(struct tdmr_info_list *= tdmr_list, u64 global_keyid) args.rcx =3D __pa(tdmr_pa_array); args.rdx =3D tdmr_list->nr_consumed_tdmrs; args.r8 =3D global_keyid; - ret =3D seamcall_prerr(TDH_SYS_CONFIG, &args); + + if (tdx_sysinfo.features.tdx_features0 & TDX_FEATURES0_TDXCONNECT) { + args.r9 |=3D TDX_FEATURES0_TDXCONNECT; + args.r11 =3D ktime_get_real_seconds(); + /* These parameters requires version >=3D 1 */ + seamcall_fn =3D TDH_SYS_CONFIG; + } + + ret =3D seamcall_prerr(seamcall_fn, &args); =20 /* Free the array as it is not required anymore. */ kfree(tdmr_pa_array); @@ -1537,6 +1546,11 @@ static int init_tdx_module(void) if (ret) goto err_free_pamts; =20 + /* configuration to tdx module may change tdx_sysinfo, update it */ + ret =3D get_tdx_sys_info(&tdx_sysinfo); + if (ret) + goto err_reset_pamts; + /* Config the key of global KeyID on all packages */ ret =3D config_global_keyid(); if (ret) --=20 2.25.1 From nobody Thu Apr 2 15:41:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 BD852367F28; Fri, 27 Mar 2026 16:23:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628587; cv=none; b=l8tZVybTtom/6cti/zdq5265VsSlJKM5/XYyjam4iwRVo05/gICMZBmtqU7iM6gSym4OlV+qvCFidTq2A15fUGF6mkRc2vVaPX9vNi8xJoG0hhkbsXT1AJi506cRqIi4Fy50W72hrg/13/IVpwcRe/5s34XeJFL9u57hH/4R+zo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628587; c=relaxed/simple; bh=NRFQsWbcpqDGf5zixGV9qrACvFa8LqbAu2Kx6hhchmk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=aW/dtmitmdSMq4xX3i6+g9aoUbTFG0WYnKaxD7jEs87ofkeNo1EoTHV4t65oIvrlMqPGTIrFZ6+qG/AY2Leit8UTOCPI7z1BT0OwKJBNAgWAlAOipAYILZEcU6kQ2NacJNnGySY+nDn+OiVqpj1/aKELStpgcD/H82hyrdDglMA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=jdLqOKfr; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="jdLqOKfr" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628586; x=1806164586; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=NRFQsWbcpqDGf5zixGV9qrACvFa8LqbAu2Kx6hhchmk=; b=jdLqOKfrLH5BvsTdi1FafVLOp5Ul829yFXXtTDZKwYaaF3fiQuAl9Wm3 qolDGX1flfRBCt8gPdCPJcFi8zmjIffZAIYOSXSbW+6mjH9+4dLTDiLPB IaTG6jPkRJQ0YxaWnViCPIaG5nyKMWLCBFYYNjgnnFaBEPO7bqemVjcS9 z2t1gK9HCEqQV/oHEK0vZbKMpJJgjroK9rwq9vYPsoF0ef4/XxL2oCT2a wh66gKWZLSpVpbKjd0OazfyOlvBnX57f2LRa7Q49Z17N813D5CeYj1PLh 6Ymwh4+NTQzzfp0cJENk/3omMp0sG2yd7TP+eDVTjfnDmF9/+mXh15Yof Q==; X-CSE-ConnectionGUID: N5CHLIiwTU+kTESlG3PceQ== X-CSE-MsgGUID: 14u/s5FzSG6KBFyrqLHZbw== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565540" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565540" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:23:06 -0700 X-CSE-ConnectionGUID: Je9XVUSpSNCJAKe+QF6ErQ== X-CSE-MsgGUID: 5Sf7lSvYT3SPjffYmyVSJw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516170" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:23:03 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 09/31] x86/virt/tdx: Move tdx_clflush_page() up in the file Date: Sat, 28 Mar 2026 00:01:10 +0800 Message-Id: <20260327160132.2946114-10-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Prepare to add more callers earlier in this file, so move this function up in advance. Signed-off-by: Xu Yilun --- arch/x86/virt/vmx/tdx/tdx.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 0c5d6bdd810f..4fb56bb442f0 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1502,6 +1502,17 @@ static int init_tdmrs(struct tdmr_info_list *tdmr_li= st) return 0; } =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 *page) +{ + clflush_cache_range(page_to_virt(page), PAGE_SIZE); +} + static int init_tdx_module(void) { int ret; @@ -1936,17 +1947,6 @@ static inline u64 tdx_tdr_pa(struct tdx_td *td) return page_to_phys(td->tdr_page); } =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 *page) -{ - clflush_cache_range(page_to_virt(page), PAGE_SIZE); -} - noinstr u64 tdh_vp_enter(struct tdx_vp *td, struct tdx_module_args *args) { args->rcx =3D td->tdvpr_pa; --=20 2.25.1 From nobody Thu Apr 2 15:41:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 92D2C369974; Fri, 27 Mar 2026 16:23:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628592; cv=none; b=OC4FWVrqMJVBTXPk6uTHfnIE7cpySkvlGg7JowH89OHtR9sokq5SPw3aGPeDwl5yT4zsztPyrKMgbS07HdJsaIgp3kyN2IezeBv2GYJAsLRqNStuwZelK0IE4kNHt6ITvyCvTSS3c5Hn4ZMY30xzXi3CRYNQP9TQtuSVrONowMo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628592; c=relaxed/simple; bh=DFu7IpMW3OWHV01lKFnhvTeC+NplEcS0CgOhg0CuuzQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=DrnVCMEylG0TIxCvc5Hhz20Gx21yuydnEQQW5UHO60heDLImA1RG/SNnMOMLb/3tLGcNC92CjWhUMGYcnNFIim0zcmGiIDvIqjjN56vhRDik10HLPefK3kxLzEmrhHljQcCIqHyHRqDrizyDaPFY3nyRwK7Z4zgFVlyqcZbkrh4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=H3gNA4jx; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="H3gNA4jx" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628590; x=1806164590; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=DFu7IpMW3OWHV01lKFnhvTeC+NplEcS0CgOhg0CuuzQ=; b=H3gNA4jx5DJsKg9jftEccdV1IrDwqB8UuKXSG+NGBqEEvsII7AFTLXJB qqTCWUu8OfXdKyinmcBPgLnB/ZgbUh2QCbkVvLpSE0/PJqY8+dYVtqISf bq940jT9ftnUynUl30mfjFs8+17IJmgirCj+q0K7jJZmxrdXbKT8rn9g6 NSxh9MU2mhXLAQ894Db314m1Z9Ny0E/5fLn+jHXf45+JV8sCIiZTA6h4H sHSJZqZ84Kg6pJCRP5o9qDsGLjww175vhuLDfo1yE24j0+TH74sDTvY+O gaAtSmNU8bWT3f1u6dwCxfUZwjRMUz5jqvOHNOVdLU6DrPyl9kzKlX8dR g==; X-CSE-ConnectionGUID: OxwI/7/QQbOem4CVfEvbPg== X-CSE-MsgGUID: MDZPgzB8QVaMunKyawzXrA== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565545" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565545" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:23:10 -0700 X-CSE-ConnectionGUID: 78QD7ClFQlOkfsj+yeSW4g== X-CSE-MsgGUID: 8/iKa9MpQxOohP7dpzqWIg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516181" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:23:06 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 10/31] x86/virt/tdx: Add extra memory to TDX Module for Extensions Date: Sat, 28 Mar 2026 00:01:11 +0800 Message-Id: <20260327160132.2946114-11-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Adding more memory to TDX Module is the first step to enable Extensions. Currently, TDX Module memory use is relatively static. But, some new features (called "TDX Module Extensions") need to use memory more dynamically. While 'static' here means the kernel provides necessary amount of memory to TDX Module for its basic functionalities, 'dynamic' means extra memory is needed only if new optional features are to be enabled. So add a new memory feeding process backed by a new SEAMCALL TDH.EXT.MEM.ADD. The process is mostly the same as adding PAMT. The kernel queries TDX Module how much memory needed, allocates it, hands it over, and never gets it back. TDH.EXT.MEM.ADD uses tdx_page_array to provide control (private) pages to TDX Module. Introduce a tdx_clflush_page_array() helper to flush shared cache before SEAMCALL, to avoid shared cache write back damages these private pages. For now, TDX Module Extensions consume relatively large amount of memory (~50MB). Use contiguous page allocation to avoid permanently fragment too much memory. Print this readout value on TDX Module Extensions initialization for visibility. Co-developed-by: Zhenzhong Duan Signed-off-by: Zhenzhong Duan Signed-off-by: Xu Yilun --- arch/x86/virt/vmx/tdx/tdx.h | 1 + arch/x86/virt/vmx/tdx/tdx.c | 92 ++++++++++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h index 870bb75da3ba..31ccdfcf518c 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -60,6 +60,7 @@ #define TDH_VP_WR 43 #define TDH_SYS_CONFIG_V0 45 #define TDH_SYS_CONFIG SEAMCALL_LEAF_VER(TDH_SYS_CONFIG_V0, 1) +#define TDH_EXT_MEM_ADD 61 =20 /* TDX page types */ #define PT_NDA 0x0 diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 4fb56bb442f0..5fae17c13191 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -560,7 +560,7 @@ static int tdx_alloc_pages_contig(unsigned int nr_pages= , struct page **pages, * Similar to tdx_page_array_alloc(), after allocating with this * function, call tdx_page_array_populate() to populate the tdx_page_array. */ -static __maybe_unused struct tdx_page_array * +static struct tdx_page_array * tdx_page_array_alloc_contig(unsigned int nr_pages) { return tdx_page_array_alloc(nr_pages, tdx_alloc_pages_contig, NULL); @@ -643,7 +643,7 @@ EXPORT_SYMBOL_GPL(tdx_page_array_create_iommu_mt); #define HPA_LIST_INFO_PFN GENMASK_U64(51, 12) #define HPA_LIST_INFO_LAST_ENTRY GENMASK_U64(63, 55) =20 -static u64 __maybe_unused hpa_list_info_assign_raw(struct tdx_page_array *= array) +static u64 hpa_list_info_assign_raw(struct tdx_page_array *array) { return FIELD_PREP(HPA_LIST_INFO_FIRST_ENTRY, 0) | FIELD_PREP(HPA_LIST_INFO_PFN, @@ -1513,6 +1513,94 @@ static void tdx_clflush_page(struct page *page) clflush_cache_range(page_to_virt(page), PAGE_SIZE); } =20 +static void tdx_clflush_page_array(struct tdx_page_array *array) +{ + for (int i =3D 0; i < array->nents; i++) + tdx_clflush_page(array->pages[array->offset + i]); +} + +static int tdx_ext_mem_add(struct tdx_page_array *ext_mem) +{ + struct tdx_module_args args =3D { + .rcx =3D hpa_list_info_assign_raw(ext_mem), + }; + u64 r; + + tdx_clflush_page_array(ext_mem); + + do { + r =3D seamcall_ret(TDH_EXT_MEM_ADD, &args); + cond_resched(); + } while (r =3D=3D TDX_INTERRUPTED_RESUMABLE); + + if (r !=3D TDX_SUCCESS) + return -EFAULT; + + return 0; +} + +static int tdx_ext_mem_setup(struct tdx_page_array *ext_mem) +{ + unsigned int populated, offset =3D 0; + int ret; + + /* + * tdx_page_array's root page can hold 512 HPAs at most. We have ~50MB + * memory to add, re-populate the array and add pages bulk by bulk. + */ + while (1) { + populated =3D tdx_page_array_populate(ext_mem, offset); + if (!populated) + break; + + ret =3D tdx_ext_mem_add(ext_mem); + if (ret) + return ret; + + offset +=3D populated; + } + + return 0; +} + +static int __maybe_unused init_tdx_ext(void) +{ + struct tdx_page_array *ext_mem =3D NULL; + unsigned int nr_pages; + int ret; + + if (!(tdx_sysinfo.features.tdx_features0 & TDX_FEATURES0_EXT)) + return 0; + + nr_pages =3D tdx_sysinfo.ext.memory_pool_required_pages; + /* + * memory_pool_required_pages =3D=3D 0 means no need to add more pages, + * skip the memory setup. + */ + if (nr_pages) { + ext_mem =3D tdx_page_array_alloc_contig(nr_pages); + if (!ext_mem) + return -ENOMEM; + + ret =3D tdx_ext_mem_setup(ext_mem); + if (ret) + goto out_ext_mem; + } + + /* Extension memory is never reclaimed once assigned */ + tdx_page_array_ctrl_leak(ext_mem); + + pr_info("%lu KB allocated for TDX Module Extensions\n", + nr_pages * PAGE_SIZE / 1024); + + return 0; + +out_ext_mem: + tdx_page_array_free(ext_mem); + + return ret; +} + static int init_tdx_module(void) { int ret; --=20 2.25.1 From nobody Thu Apr 2 15:41:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 2D25A36BCFD; Fri, 27 Mar 2026 16:23:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628595; cv=none; b=uim0lkKR+bUUZ9mZPNd0ZIIo0TGCCXCFwciCenH5uxH1c6GzspHeCbWfiokFgs0VqSVCThdDx5OEZSfCmo8BZY0hvP2HQWYeAMHiKhcclJomtCNObkh5CAtJ1xCUC+mBgDq4XOKZ6Bg3JpziGAnKNifseQc0vsGD8IGApk3yy/M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628595; c=relaxed/simple; bh=z5CL/0DGGrz7pQMCfp9DD/99lRybVld0TfABDp+3gMk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=W71jCwErjXUa+ItNWyY3cSR+YyLGy1HDzf92lqR8w2R02ofR+PKGDTGtsBeQE95XyjydODoxRmEG4O4OtARSZESko5kTeG5Eps7GcWtyZZr3tWw9zILqWHv1fR1ZlvdlsBm3kxNy6IQ45AAoYdQCqka+PBf+g92hLGTYizsOQJw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=GfViFb8a; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="GfViFb8a" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628593; x=1806164593; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=z5CL/0DGGrz7pQMCfp9DD/99lRybVld0TfABDp+3gMk=; b=GfViFb8aUHoyYwhxZNtaocQ3sjQdWtAbnRUJc1snC8VsmaY/nd1B5IiL ZOvMMY5FidSdBECKU6geySpyHzNBGsRkNZEzBM6wI9HaQkckvxT7/XGTa vgMWsBGs7Sq3iAh/ST8AlcBMBzHO2XjaqD4lqkREaQEYrtTLLAlI1cvnQ /NSM7tKurWbKHWv+mHiD/lFhVSkjO0OuKQnfgtrcETyOhcddDWRBXBa99 OG9uu767Klc/4nbCl+SJHejpDgRfZS/1UISKQzmMkkB2ToLVATPmX3WUz USIWAGo/EkFktijL+hI7x+wE3GT3rDlg0+/I2InkZMG59Iw3ps00CmpIe Q==; X-CSE-ConnectionGUID: OoKRgvbcQBW1pOLX8eLdLA== X-CSE-MsgGUID: 7hxR6OkMSaiOszx05MH3lQ== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565554" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565554" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:23:13 -0700 X-CSE-ConnectionGUID: BK74wRU+T86K0QGGrRTlww== X-CSE-MsgGUID: V54k45S2Ro+2cOJ3jO7Q6g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516201" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:23:10 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 11/31] x86/virt/tdx: Make TDX Module initialize Extensions Date: Sat, 28 Mar 2026 00:01:12 +0800 Message-Id: <20260327160132.2946114-12-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" After providing all required memory to TDX Module, initialize the Extensions via TDH.EXT.INIT, and then Extension-SEAMCALLs can be used. The initialization of Extensions touches the required memory (previously provided by TDH.EXT.MEM.ADD) in private manner. If failed, flush cache before freeing these memory, to avoid private cache write back damages the shared pages. TDX should use movdir64b to clear private pages when reclaiming them on older platforms with the X86_BUG_TDX_PW_MCE erratum. For simplicity, don't expect this errata on any TDX Extensions supported platform. So TDX Extensions & all features that require TDX Extensions (e.g. TDX Connect) will not call the clearing helpers. Note the "ext_required" global metadata specifies if TDH.EXT.INIT call is needed. If 0, the Extensions are already working, so skip the SEAMCALL. Co-developed-by: Zhenzhong Duan Signed-off-by: Zhenzhong Duan Signed-off-by: Xu Yilun --- arch/x86/virt/vmx/tdx/tdx.h | 1 + arch/x86/virt/vmx/tdx/tdx.c | 45 +++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h index 31ccdfcf518c..a26fe94c07ff 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -60,6 +60,7 @@ #define TDH_VP_WR 43 #define TDH_SYS_CONFIG_V0 45 #define TDH_SYS_CONFIG SEAMCALL_LEAF_VER(TDH_SYS_CONFIG_V0, 1) +#define TDH_EXT_INIT 60 #define TDH_EXT_MEM_ADD 61 =20 /* TDX page types */ diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 5fae17c13191..4134f92425da 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1519,6 +1519,23 @@ static void tdx_clflush_page_array(struct tdx_page_a= rray *array) tdx_clflush_page(array->pages[array->offset + i]); } =20 +/* Initialize the TDX Module Extensions then Extension-SEAMCALLs can be us= ed */ +static int tdx_ext_init(void) +{ + struct tdx_module_args args =3D {}; + u64 r; + + do { + r =3D seamcall(TDH_EXT_INIT, &args); + cond_resched(); + } while (r =3D=3D TDX_INTERRUPTED_RESUMABLE); + + if (r !=3D TDX_SUCCESS) + return -EFAULT; + + return 0; +} + static int tdx_ext_mem_add(struct tdx_page_array *ext_mem) { struct tdx_module_args args =3D { @@ -1572,6 +1589,17 @@ static int __maybe_unused init_tdx_ext(void) if (!(tdx_sysinfo.features.tdx_features0 & TDX_FEATURES0_EXT)) return 0; =20 + /* + * With this errata, TDX should use movdir64b to clear private pages + * when reclaiming them. See tdx_quirk_reset_paddr(). + * + * Don't expect this errata on any TDX Extensions supported platform. + * All features require TDX Extensions (including TDX Extensions + * itself) will never call tdx_quirk_reset_paddr(). + */ + if (boot_cpu_has_bug(X86_BUG_TDX_PW_MCE)) + return -ENXIO; + nr_pages =3D tdx_sysinfo.ext.memory_pool_required_pages; /* * memory_pool_required_pages =3D=3D 0 means no need to add more pages, @@ -1587,6 +1615,20 @@ static int __maybe_unused init_tdx_ext(void) goto out_ext_mem; } =20 + /* + * ext_required =3D=3D 0 means no need to call TDH.EXT.INIT, the Extensio= ns + * are already working. + */ + if (tdx_sysinfo.ext.ext_required) { + ret =3D tdx_ext_init(); + /* + * Some pages may have been touched by the TDX module. + * Flush cache before returning these pages to kernel. + */ + if (ret) + goto out_flush; + } + /* Extension memory is never reclaimed once assigned */ tdx_page_array_ctrl_leak(ext_mem); =20 @@ -1595,6 +1637,9 @@ static int __maybe_unused init_tdx_ext(void) =20 return 0; =20 +out_flush: + if (ext_mem) + wbinvd_on_all_cpus(); out_ext_mem: tdx_page_array_free(ext_mem); =20 --=20 2.25.1 From nobody Thu Apr 2 15:41:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 E0228371CFD; Fri, 27 Mar 2026 16:23:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628600; cv=none; b=fEcpbB60p1xY+MwF3DwwrzqoVfqG4kA0oved2i+HAp9ZtSoN3ox/IB8et9Pb9UCThbW5YAQC3Mtt3JalsaFzsDtjJiIL+Fmo02/N7cNKDBRNWqgQGJowStVFRXul4DW1Gmmjx/8YuKjtMJA+FRxWLaQUbCnAa7l4RcA4/PkL5Ng= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628600; c=relaxed/simple; bh=RtbDb463am0ETHo/8RtK51kAaPZf1IlC30Of1RwsQQ0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ABQQoQZMZsw+XAyIsY2owoRbpiUe5Cq+RX86WXeYJ39lszpdYnTsa/up7IBnrmt0iVg7Pc5fU4En9qhHU8NcCVIhoA/E2ZWWdla16dPj31ul48FQObpo7ZgTuJwbtw4tUxbjVUioLTvuuT0G8TpTGVq6nna379TDc03zazIQ7FA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=nHpz8zr0; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="nHpz8zr0" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628597; x=1806164597; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=RtbDb463am0ETHo/8RtK51kAaPZf1IlC30Of1RwsQQ0=; b=nHpz8zr0bWUolDn8goqbTE4CBVTfwNp3K3hwFp7OB1HJat/t6cIs3C38 EIAUUCC8J4k9gjNxD00z/g7Jb32ltjJ/kCd66J/ZKSKIv68gCYwwQX/rm uU4bIxIODQBJ3kF46U1UKfF9Owe7ExGS1uQrT2+F8gyGC46ZsGF9hTMwX x+77W9OmhrvAHTZ+9OlueBBDf6gXEaqbVHOg61CViNrgQEZ149OZEdpYN jqdbNMkW6lUpTCgExF/XQISu++jiNpKd0bpKbvyxrLZOPreR00VOaZwwu y3QvqwYNkXgpYHeB+171/rZhu1jYVsGmAgzh8PqVHNwKhcylzrhf1BsHp A==; X-CSE-ConnectionGUID: RoKFU9JATo6mbahaFY405w== X-CSE-MsgGUID: 57qmkzDrR7i8I9tuyxjgRQ== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565557" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565557" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:23:17 -0700 X-CSE-ConnectionGUID: Bb7IBTbCSyyXuI5HkgFb0g== X-CSE-MsgGUID: z3taUSlXSEmCvY8q9njN9w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516211" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:23:14 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 12/31] x86/virt/tdx: Enable the Extensions after basic TDX Module init Date: Sat, 28 Mar 2026 00:01:13 +0800 Message-Id: <20260327160132.2946114-13-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The detailed initialization flow for TDX Module Extensions has been fully implemented. Enable the flow after basic TDX Module initialization. Theoretically, the Extensions can be initialized later when the first usage of the Extension-SEAMCALL comes. That would save or postpone the usage of ~50M memory. But it isn't worth the complexity, the needs for Extensions are vast but the savings are little for a typical TDX capable system (about 0.001% of memory). So just enable it along with the basic TDX. Signed-off-by: Xu Yilun --- arch/x86/virt/vmx/tdx/tdx.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 4134f92425da..0e1ad793e648 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1580,7 +1580,7 @@ static int tdx_ext_mem_setup(struct tdx_page_array *e= xt_mem) return 0; } =20 -static int __maybe_unused init_tdx_ext(void) +static int init_tdx_ext(void) { struct tdx_page_array *ext_mem =3D NULL; unsigned int nr_pages; @@ -1705,6 +1705,10 @@ static int init_tdx_module(void) if (ret) goto err_reset_pamts; =20 + ret =3D init_tdx_ext(); + if (ret) + goto err_reset_pamts; + pr_info("%lu KB allocated for PAMT\n", tdmrs_count_pamt_kb(&tdx_tdmr_list= )); =20 out_put_tdxmem: --=20 2.25.1 From nobody Thu Apr 2 15:41:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 B66F1373C02; Fri, 27 Mar 2026 16:23:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628602; cv=none; b=kMyAyMtmRfIS1z+Suv06Ypx5dAIm7+gAZjFUxX4Kfe/3fYhbTX3ZGNRXpiwmgJuVlyHuwHD7xFBLxzSunk+N9OoUsGBDzzHGh/8dbyIybx6EgHn+tlsgjr6yMNIZlOm/O7AXZPIPy34R9wgWaxE88ok5OE0fKvnQuM8JwOYSpTY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628602; c=relaxed/simple; bh=WGFPbx7sgPfDQCJrPwMdxh2FwqrprHEWOswcgWAGZe0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=C6Z/Eh37+S84AnYuJBDmPUN9nAui1YhKulQx74ZYMxKeHrNM+n0Bv+gXFYnXVydMW1tjHITM/R/aGf6lew3OPXaoenjbplWQqkNfVxW/f5i+n0JdsCtgCTn2Xpd/4Bg3R0KGFGhMdobQ3hLq8IeSr7Fn64hU0EBK13eeBEzTs98= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=GV8be0Ij; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="GV8be0Ij" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628601; x=1806164601; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=WGFPbx7sgPfDQCJrPwMdxh2FwqrprHEWOswcgWAGZe0=; b=GV8be0IjvNWMi5nCPKo9F9Ke9VfCO2nN//gkipA/uHQlCUgNGjH6M4wd vhlNRGnLcGRG7aKxXgS25ltEwEjinntWpu9mE2QfQLs66w2rPmdOBOUOJ FyQxiF8CTTbqWPF8eSLJIdo/Y0MriFpq1aOtyncTGSZALVbM37Bargbwn WlrV3ipwPxCPgTpfO4d9Uex+JUGTrlwDq53UdJsWidrYpWHl/Yxvu97X3 3m7iirmSsFm1S7Lr7NHB4EVh+zX/U+lWsnmI8agdd/6FaDZ1VzuGvWon4 LIjRMUXpnzG5GDd/60kFNHT/4mnLRpQGjG8RCx3adovKTmFMY/j1N/IqG g==; X-CSE-ConnectionGUID: EMa/TsdSQpmLCxcYfqtmqg== X-CSE-MsgGUID: t3PD/HiWT2KLe0pMUT2ktQ== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565575" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565575" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:23:21 -0700 X-CSE-ConnectionGUID: J1a8EKhESLywQV8Ib29x2g== X-CSE-MsgGUID: pVo962/CTmOwIowi7PFdnw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516225" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:23:18 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 13/31] x86/virt/tdx: Extend tdx_clflush_page() to handle compound pages Date: Sat, 28 Mar 2026 00:01:14 +0800 Message-Id: <20260327160132.2946114-14-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Use page_size() to correctly flush the range that a compound page covers. Recall that TDX Module requires VMM to provide IOMMU metadata known as IOMMU_MT, which contains some multi-order pages. Like all other metadata, TDX Module will convert these multi-order pages to private so VMM should flush the shared cache beforehand. Extend tdx_clflush_page() to handle this case. The usage of tdx_clflush_page() for IOMMU_MT will be introduced later, but the change stands as a valid improvement on its own. Signed-off-by: Xu Yilun --- arch/x86/virt/vmx/tdx/tdx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 0e1ad793e648..e7d47fbe7057 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1510,7 +1510,7 @@ static int init_tdmrs(struct tdmr_info_list *tdmr_lis= t) */ static void tdx_clflush_page(struct page *page) { - clflush_cache_range(page_to_virt(page), PAGE_SIZE); + clflush_cache_range(page_to_virt(page), page_size(page)); } =20 static void tdx_clflush_page_array(struct tdx_page_array *array) --=20 2.25.1 From nobody Thu Apr 2 15:41:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 8068035B645; Fri, 27 Mar 2026 16:23:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628606; cv=none; b=s/qK5pUoJNJ9WE3jnNM2yuwiybl2u6dvj6dMGhFuYF8N2p6qaDqzqLVJnl1EvmMn9qiDOFCNCvypw+sigmYzuL2weefi2ql6PxfXYYnLCy2vF1/IXTKi9VV3klzNUUZXNq4VfvRLSrlF9EOpHQpgdJX2bIXDzJqWx0nXp1B3HRU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628606; c=relaxed/simple; bh=NUtWTN+YsNz/G7G+LqClLzUTJJRtWG7YocdGIa0hACU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=k78cSMuS/K1kAC/0Mq+4XVl0ROGLzbvUKyUYbQWOPAWiwYJuwqlYcKrhj27wuzaPKizsr2EcveUviMbiUOH3KQkNwS+U/En4cLdltOXbn3Dg2u6so95qQo9JEfmURFZn8syDqEIeso924zq7/E12j+v5TUKOqYTPultzLq86hKw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Y9u41UTu; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Y9u41UTu" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628605; x=1806164605; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=NUtWTN+YsNz/G7G+LqClLzUTJJRtWG7YocdGIa0hACU=; b=Y9u41UTuVNNg2UhB1hFh8Cnlc8v4lYYYfEESXOeLCq6sian18rCLKk5j MqwAaYvbvjpS9wbhK9gp+KssM7EyatntSL9o0u4mzofVv1zqcvX+tBxCi 1ntTijbyTXt28fooIFPNb8xn6e/DcStXvC6iSVNKHn/RQw8Z7TQsTWQxs 3xmx1Em34Q9mlA0BibVS0Atl20Oi2pZRGwHlK5kncXc3tK4Ossuh/FnIs 9D0ntMnbHH5NHoS/OP7oTaVsv0oHPkX/bhvluujMIUh+eIqg9RvCbBQWd 8xhRk/Hlp6tSgvG5YtXJXXpZQ1PSfq/itnT1bLwLI6HTYFynktn3fgFHV g==; X-CSE-ConnectionGUID: kZD+/wvEQRKWC9dML8Ke9w== X-CSE-MsgGUID: dYSDFBk2SAS0n9bKzYu+yw== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565584" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565584" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:23:24 -0700 X-CSE-ConnectionGUID: bd88HM/eRFevey5pYm38Xw== X-CSE-MsgGUID: Mgpwnhy6Qc+U3vXdgdZwpg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516236" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:23:21 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 14/31] PCI/TSM: Report active IDE streams per host bridge Date: Sat, 28 Mar 2026 00:01:15 +0800 Message-Id: <20260327160132.2946114-15-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Dan Williams The first attempt at an ABI for this failed to account for naming collisions across host bridges: Commit a4438f06b1db ("PCI/TSM: Report active IDE streams") Revive this ABI with a per host bridge link that appears at first stream creation for a given host bridge and disappears after the last stream is removed. For systems with many host bridge objects it allows: ls /sys/class/tsm/tsmN/pci*/stream* ...to find all the host bridges with active streams without first iterating over all host bridges. Yilun notes that is handy to have this short cut [1] and from an administrator perspective it helps with inventory for constrained stream resources. Link: http://lore.kernel.org/aXLtILY85oMU5qlb@yilunxu-OptiPlex-7050 [1] Signed-off-by: Dan Williams --- Documentation/ABI/testing/sysfs-class-tsm | 13 +++ include/linux/pci-ide.h | 2 + include/linux/tsm.h | 3 + drivers/pci/ide.c | 4 + drivers/virt/coco/tsm-core.c | 97 +++++++++++++++++++++++ 5 files changed, 119 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-class-tsm b/Documentation/ABI/= testing/sysfs-class-tsm index 2949468deaf7..1ddb8f357961 100644 --- a/Documentation/ABI/testing/sysfs-class-tsm +++ b/Documentation/ABI/testing/sysfs-class-tsm @@ -7,3 +7,16 @@ Description: signals when the PCI layer is able to support establishment of link encryption and other device-security features coordinated through a platform tsm. + +What: /sys/class/tsm/tsmN/pciDDDD:BB +Contact: linux-pci@vger.kernel.org +Description: + (RO) When a PCIe host bridge has established a secure connection + via a TSM to an endpoint, this symlink appears. It facilitates a + TSM instance scoped view of PCIe Link Encryption and Secure + Session resource consumption across host bridges. The symlink + appears when a host bridge has 1 or more IDE streams established + with this TSM, and disappears when that number returns to 0. See + Documentation/ABI/testing/sysfs-devices-pci-host-bridge for the + description of the pciDDDD:BB/streamH.R.E symlink and the + pciDDDD:BB/available_secure_streams attribute. diff --git a/include/linux/pci-ide.h b/include/linux/pci-ide.h index ae07d9f699c0..381a1bf22a95 100644 --- a/include/linux/pci-ide.h +++ b/include/linux/pci-ide.h @@ -82,6 +82,7 @@ struct pci_ide_regs { * @host_bridge_stream: allocated from host bridge @ide_stream_ida pool * @stream_id: unique Stream ID (within Partner Port pairing) * @name: name of the established Selective IDE Stream in sysfs + * @tsm_dev: For TSM established IDE, the TSM device context * * Negative @stream_id values indicate "uninitialized" on the * expectation that with TSM established IDE the TSM owns the stream_id @@ -93,6 +94,7 @@ struct pci_ide { u8 host_bridge_stream; int stream_id; const char *name; + struct tsm_dev *tsm_dev; }; =20 /* diff --git a/include/linux/tsm.h b/include/linux/tsm.h index 381c53244c83..7f72a154b6b2 100644 --- a/include/linux/tsm.h +++ b/include/linux/tsm.h @@ -123,4 +123,7 @@ int tsm_report_unregister(const struct tsm_report_ops *= ops); struct tsm_dev *tsm_register(struct device *parent, struct pci_tsm_ops *op= s); void tsm_unregister(struct tsm_dev *tsm_dev); struct tsm_dev *find_tsm_dev(int id); +struct pci_ide; +int tsm_ide_stream_register(struct pci_ide *ide); +void tsm_ide_stream_unregister(struct pci_ide *ide); #endif /* __TSM_H */ diff --git a/drivers/pci/ide.c b/drivers/pci/ide.c index be74e8f0ae21..b35e8aba7ecb 100644 --- a/drivers/pci/ide.c +++ b/drivers/pci/ide.c @@ -11,6 +11,7 @@ #include #include #include +#include =20 #include "pci.h" =20 @@ -372,6 +373,9 @@ void pci_ide_stream_release(struct pci_ide *ide) if (ide->partner[PCI_IDE_EP].enable) pci_ide_stream_disable(pdev, ide); =20 + if (ide->tsm_dev) + tsm_ide_stream_unregister(ide); + if (ide->partner[PCI_IDE_RP].setup) pci_ide_stream_teardown(rp, ide); =20 diff --git a/drivers/virt/coco/tsm-core.c b/drivers/virt/coco/tsm-core.c index 98dcf7d836df..ece7cd7ea9d8 100644 --- a/drivers/virt/coco/tsm-core.c +++ b/drivers/virt/coco/tsm-core.c @@ -4,10 +4,12 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt =20 #include +#include #include #include #include #include +#include =20 static struct class *tsm_class; static DEFINE_IDA(tsm_ida); @@ -104,6 +106,100 @@ void tsm_unregister(struct tsm_dev *tsm_dev) } EXPORT_SYMBOL_GPL(tsm_unregister); =20 +static DEFINE_XARRAY(tsm_ide_streams); +static DEFINE_MUTEX(tsm_ide_streams_lock); + +/* tracker for the bridge symlink when the bridge has any streams */ +struct tsm_ide_stream { + struct tsm_dev *tsm_dev; + struct pci_host_bridge *bridge; + struct kref kref; +}; + +static struct tsm_ide_stream *create_streams(struct tsm_dev *tsm_dev, + struct pci_host_bridge *bridge) +{ + int rc; + + struct tsm_ide_stream *streams __free(kfree) =3D + kzalloc(sizeof(*streams), GFP_KERNEL); + if (!streams) + return NULL; + + streams->tsm_dev =3D tsm_dev; + streams->bridge =3D bridge; + kref_init(&streams->kref); + rc =3D xa_insert(&tsm_ide_streams, (unsigned long)bridge, streams, + GFP_KERNEL); + if (rc) + return NULL; + + rc =3D sysfs_create_link(&tsm_dev->dev.kobj, &bridge->dev.kobj, + dev_name(&bridge->dev)); + if (rc) { + xa_erase(&tsm_ide_streams, (unsigned long)bridge); + return NULL; + } + + return no_free_ptr(streams); +} + +int tsm_ide_stream_register(struct pci_ide *ide) +{ + struct tsm_ide_stream *streams; + struct pci_dev *pdev =3D ide->pdev; + struct pci_tsm *tsm =3D pdev->tsm; + struct tsm_dev *tsm_dev =3D tsm->tsm_dev; + struct pci_host_bridge *bridge =3D pci_find_host_bridge(pdev->bus); + + guard(mutex)(&tsm_ide_streams_lock); + streams =3D xa_load(&tsm_ide_streams, (unsigned long)bridge); + if (streams) + kref_get(&streams->kref); + else + streams =3D create_streams(tsm_dev, bridge); + + if (!streams) + return -ENOMEM; + ide->tsm_dev =3D tsm_dev; + + return 0; +} +EXPORT_SYMBOL_GPL(tsm_ide_stream_register); + +static void destroy_streams(struct kref *kref) +{ + struct tsm_ide_stream *streams =3D + container_of(kref, struct tsm_ide_stream, kref); + struct tsm_dev *tsm_dev =3D streams->tsm_dev; + struct pci_host_bridge *bridge =3D streams->bridge; + + lockdep_assert_held(&tsm_ide_streams_lock); + sysfs_remove_link(&tsm_dev->dev.kobj, dev_name(&bridge->dev)); + xa_erase(&tsm_ide_streams, (unsigned long)bridge); + kfree(streams); +} + +void tsm_ide_stream_unregister(struct pci_ide *ide) +{ + struct tsm_ide_stream *streams; + struct tsm_dev *tsm_dev =3D ide->tsm_dev; + struct pci_dev *pdev =3D ide->pdev; + struct pci_host_bridge *bridge =3D pci_find_host_bridge(pdev->bus); + + guard(mutex)(&tsm_ide_streams_lock); + streams =3D xa_load(&tsm_ide_streams, (unsigned long)bridge); + /* catch API abuse */ + if (dev_WARN_ONCE(&tsm_dev->dev, + !streams || streams->tsm_dev !=3D tsm_dev, + "no IDE streams associated with %s\n", + dev_name(&bridge->dev))) + return; + kref_put(&streams->kref, destroy_streams); + ide->tsm_dev =3D NULL; +} +EXPORT_SYMBOL_GPL(tsm_ide_stream_unregister); + static void tsm_release(struct device *dev) { struct tsm_dev *tsm_dev =3D container_of(dev, typeof(*tsm_dev), dev); @@ -126,6 +222,7 @@ module_init(tsm_init) static void __exit tsm_exit(void) { class_destroy(tsm_class); + xa_destroy(&tsm_ide_streams); } module_exit(tsm_exit) =20 --=20 2.25.1 From nobody Thu Apr 2 15:41:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 108803C4566; Fri, 27 Mar 2026 16:23:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628611; cv=none; b=MB/JkG5hsy4b+GqWmkxWDNYnG+oy17m5XhNObkGUtJFh6t7Uoxzu3yPCngvD8Dg/LG2qKSzN9BZuq6eL9dfxArE2XzuNYKWMtAA7VBCd2GZh9CM4Eq9RHYQ3eITKpqKqT9Ellij0nKJ8y0EVJT65h5lCuPXQyGgrlcMLgtYq4Z8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628611; c=relaxed/simple; bh=NiScli6lde2atwZcei95350RL54jHBrh2mruHTpKuTw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=q9z+qBTs4BqsCfVUvgf7O+3V+fN/BPleHEzRTm7MPcVGAZQ0nomV5RVjYpUm5ZmsdD6kOmHQy+26va25wXFDy8Ow/lXRRkhA/r0X9huHbRVnjYWDc4rRy8s8v23sTNRwDuryzSnbd0G/ISZ5AjS7SlHrWxa1lrbxVzUtxeD6teQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=au9iuZTM; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="au9iuZTM" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628608; x=1806164608; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=NiScli6lde2atwZcei95350RL54jHBrh2mruHTpKuTw=; b=au9iuZTMWb1yeYoP3YdC0NmppGUjR9p4+3OE3jngRjKQBk4D9snPs8iV 01Jb0QZwTP5ILrpBfaWEz+roBmCYuQi4NOr8whFBVhRLWJkQZmlsG0DtY Mw5UwEajQMhjKn2vct9ArKT8nkY5a8b7gBefWZP+3+RS/p2L3p2cndBV9 a1Ifwi+Tf2v8LyPKfHFI63fyio+a4MNfdgsyuGRbd9egNxRzrKItZmEmJ PrzZ/+IcDKaeo+6CFraeSgk2M3m+FKYPXhEwewCJjYUcebRF/7tWBZ+9T nB6MUDCi4RI/Z+0KkW18OiBKuzvoHT2sX7WLMUOVguehXAeoZxDrg4AYI w==; X-CSE-ConnectionGUID: O0idgr8YQOqx1uPGiTlRyg== X-CSE-MsgGUID: /t1P57YhS7OM5qjIT049HQ== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565591" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565591" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:23:28 -0700 X-CSE-ConnectionGUID: AK1zgE10TFqPPfFrpL7DHw== X-CSE-MsgGUID: xu8ZxhJWR82dJe2kkh/nCg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516243" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:23:25 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 15/31] coco/tdx-host: Introduce a "tdx_host" device Date: Sat, 28 Mar 2026 00:01:16 +0800 Message-Id: <20260327160132.2946114-16-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Chao Gao TDX depends on a platform firmware module that is invoked via instructions similar to vmenter (i.e. enter into a new privileged "root-mode" context to manage private memory and private device mechanisms). It is a software construct that depends on the CPU vmxon state to enable invocation of TDX module ABIs. Unlike other Trusted Execution Environment (TEE) platform implementations that employ a firmware module running on a PCI device with an MMIO mailbox for communication, TDX has no hardware device to point to as the TEE Secure Manager (TSM). Create a virtual device not only to align with other implementations but also to make it easier to - expose metadata (e.g., TDX module version, seamldr version etc) to the userspace as device attributes - implement firmware uploader APIs which are tied to a device. This is needed to support TDX module runtime updates - enable TDX Connect which will share a common infrastructure with other platform implementations. In the TDX Connect context, every architecture has a TSM, represented by a PCIe or virtual device. The new "tdx_host" device will serve the TSM role. A faux device is used for TDX because the TDX module is singular within the system and lacks associated platform resources. Using a faux device eliminates the need to create a stub bus. The call to tdx_get_sysinfo() ensures that the TDX module is ready to provide services. Note that AMD has a PCI device for the PSP for SEV and ARM CCA will likely have a faux device [1]. Co-developed-by: Xu Yilun Signed-off-by: Dan Williams Signed-off-by: Chao Gao Reviewed-by: Jonathan Cameron Reviewed-by: Tony Lindgren Reviewed-by: Xu Yilun Reviewed-by: Kai Huang Reviewed-by: Kiryl Shutsemau (Meta) Link: https://lore.kernel.org/all/2025073035-bulginess-rematch-b92e@gregkh/= # [1] Signed-off-by: Xu Yilun --- drivers/virt/coco/Kconfig | 2 ++ drivers/virt/coco/tdx-host/Kconfig | 10 +++++++ drivers/virt/coco/Makefile | 1 + drivers/virt/coco/tdx-host/Makefile | 1 + arch/x86/virt/vmx/tdx/tdx.c | 2 +- drivers/virt/coco/tdx-host/tdx-host.c | 43 +++++++++++++++++++++++++++ 6 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 drivers/virt/coco/tdx-host/Kconfig create mode 100644 drivers/virt/coco/tdx-host/Makefile create mode 100644 drivers/virt/coco/tdx-host/tdx-host.c diff --git a/drivers/virt/coco/Kconfig b/drivers/virt/coco/Kconfig index df1cfaf26c65..f7691f64fbe3 100644 --- a/drivers/virt/coco/Kconfig +++ b/drivers/virt/coco/Kconfig @@ -17,5 +17,7 @@ source "drivers/virt/coco/arm-cca-guest/Kconfig" source "drivers/virt/coco/guest/Kconfig" endif =20 +source "drivers/virt/coco/tdx-host/Kconfig" + config TSM bool diff --git a/drivers/virt/coco/tdx-host/Kconfig b/drivers/virt/coco/tdx-hos= t/Kconfig new file mode 100644 index 000000000000..d35d85ef91c0 --- /dev/null +++ b/drivers/virt/coco/tdx-host/Kconfig @@ -0,0 +1,10 @@ +config TDX_HOST_SERVICES + tristate "TDX Host Services Driver" + depends on INTEL_TDX_HOST + default m + help + Enable access to TDX host services like module update and + extensions (e.g. TDX Connect). + + Say y or m if enabling support for confidential virtual machine + support (CONFIG_INTEL_TDX_HOST). The module is called tdx_host.ko. diff --git a/drivers/virt/coco/Makefile b/drivers/virt/coco/Makefile index cb52021912b3..b323b0ae4f82 100644 --- a/drivers/virt/coco/Makefile +++ b/drivers/virt/coco/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_EFI_SECRET) +=3D efi_secret/ obj-$(CONFIG_ARM_PKVM_GUEST) +=3D pkvm-guest/ obj-$(CONFIG_SEV_GUEST) +=3D sev-guest/ obj-$(CONFIG_INTEL_TDX_GUEST) +=3D tdx-guest/ +obj-$(CONFIG_INTEL_TDX_HOST) +=3D tdx-host/ obj-$(CONFIG_ARM_CCA_GUEST) +=3D arm-cca-guest/ obj-$(CONFIG_TSM) +=3D tsm-core.o obj-$(CONFIG_TSM_GUEST) +=3D guest/ diff --git a/drivers/virt/coco/tdx-host/Makefile b/drivers/virt/coco/tdx-ho= st/Makefile new file mode 100644 index 000000000000..e61e749a8dff --- /dev/null +++ b/drivers/virt/coco/tdx-host/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_TDX_HOST_SERVICES) +=3D tdx-host.o diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index e7d47fbe7057..cd0948794b6c 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -2057,7 +2057,7 @@ const struct tdx_sys_info *tdx_get_sysinfo(void) =20 return p; } -EXPORT_SYMBOL_FOR_KVM(tdx_get_sysinfo); +EXPORT_SYMBOL_FOR_MODULES(tdx_get_sysinfo, "kvm-intel,tdx-host"); =20 u32 tdx_get_nr_guest_keyids(void) { diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-= host/tdx-host.c new file mode 100644 index 000000000000..c77885392b09 --- /dev/null +++ b/drivers/virt/coco/tdx-host/tdx-host.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * TDX host user interface driver + * + * Copyright (C) 2025 Intel Corporation + */ + +#include +#include +#include + +#include +#include + +static const struct x86_cpu_id tdx_host_ids[] =3D { + X86_MATCH_FEATURE(X86_FEATURE_TDX_HOST_PLATFORM, NULL), + {} +}; +MODULE_DEVICE_TABLE(x86cpu, tdx_host_ids); + +static struct faux_device *fdev; + +static int __init tdx_host_init(void) +{ + if (!x86_match_cpu(tdx_host_ids) || !tdx_get_sysinfo()) + return -ENODEV; + + fdev =3D faux_device_create(KBUILD_MODNAME, NULL, NULL); + if (!fdev) + return -ENODEV; + + return 0; +} +module_init(tdx_host_init); + +static void __exit tdx_host_exit(void) +{ + faux_device_destroy(fdev); +} +module_exit(tdx_host_exit); + +MODULE_DESCRIPTION("TDX Host Services"); +MODULE_LICENSE("GPL"); --=20 2.25.1 From nobody Thu Apr 2 15:41:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 9F2803E3C47; Fri, 27 Mar 2026 16:23:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628614; cv=none; b=UIgD1/i4C7UbK3I9BCZB/+t263MTwi6ILeCNuzxD0gxyP6edpQvfrxVGVCKxZOy7BOoB7LFV8+m5kfVijX8Tj+XQf8b5BZ7VDXj4xFCTRoJrLaukscJR6KyF6l8AnSPVGmHsx50t4J+KsDlHXuRdsvFl87LKr3pkuKwlMtZ2CXg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628614; c=relaxed/simple; bh=dzQVPWIaSxETgDXevSN0G82bnXnd5YoCZ3n3bdcc8Zw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=EZ2sUBBRUPtaL/ntkjGqlLpR4DMQ825UdX/OA8FKuGeEujZWwCEBOx43wmDDjIG5ZhOM2ODzzuWgR3JC2e+QjNnnQQcmP6KaITwLGwYfAUL7hSBoCSLiSfgkcRA+eMgvNOdHlEbPCJWyJ6CyZJJXG6tea93hb9nDdGAq/bdbExs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=WsXxciyg; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="WsXxciyg" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628612; x=1806164612; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=dzQVPWIaSxETgDXevSN0G82bnXnd5YoCZ3n3bdcc8Zw=; b=WsXxciygjX9xR/+mY+NXBXcRPhCU0tsVvRvLG0IOcT3GkN9mCf+9ETds QTbbpjDHVKSg78Cghpd/smS8qN87g10vOwfJDFxQ2HMN7R1Voa2XE606R eo7w+hoQ/3AouX2M5HlUc87sw98drd2JlXoKvergXxxrq888cpxux32BS UJoTyq+Lmuoy5vOyPAUPgFGSN9+EKrxcBJHLdwkKeKY17oz6cjBS2UZfB pOYd2mt7qD+uaTZaRXCReLpAdDfcdrDPQ3hbyhXI/1OVP7xLiMxFC7jep wnLACv3a3OKPzQOK7pcrhBe/cggbbatuFCVPK3m9230BPm4KzL7WcQCMW w==; X-CSE-ConnectionGUID: BRXUEIN9SW26+Ec5n5CIKQ== X-CSE-MsgGUID: kszwnvuMQA+Hz5IMcItovw== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565600" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565600" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:23:32 -0700 X-CSE-ConnectionGUID: hr8btrkQS3K/8jDTuCM4eQ== X-CSE-MsgGUID: VKoD1c00RHeRl0xVyucjlA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516261" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:23:29 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 16/31] coco/tdx-host: Support Link TSM for TDX host Date: Sat, 28 Mar 2026 00:01:17 +0800 Message-Id: <20260327160132.2946114-17-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Register a Link TSM instance to support host side TSM operations for TDISP, when the TDX Connect support bit is set by TDX Module in tdx_feature0. This is the main purpose of an independent tdx-host module out of TDX core. Recall that a TEE Security Manager (TSM) is a platform agent that speaks the TEE Device Interface Security Protocol (TDISP) to PCIe devices and manages private memory resources for the platform. An independent tdx-host module allows for device-security enumeration and initialization flows to be deferred from other TDX Module initialization requirements. Crucially, when / if TDX Module init moves earlier in x86 initialization flow this driver is still guaranteed to run after IOMMU and PCI init (i.e. subsys_initcall() vs device_initcall()). The ability to unload the module, or unbind the driver is also useful for debug and coarse grained transitioning between PCI TSM operation and PCI CMA operation (native kernel PCI device authentication). For now only verify TDX Connect support in TDX Module and enable TDX Module Extentions. The TSM support are basic boilerplate with operation flows to be added later. Co-developed-by: Dan Williams Signed-off-by: Dan Williams Reviewed-by: Jonathan Cameron Signed-off-by: Xu Yilun --- drivers/virt/coco/tdx-host/Kconfig | 5 + drivers/virt/coco/tdx-host/tdx-host.c | 138 +++++++++++++++++++++++++- 2 files changed, 141 insertions(+), 2 deletions(-) diff --git a/drivers/virt/coco/tdx-host/Kconfig b/drivers/virt/coco/tdx-hos= t/Kconfig index d35d85ef91c0..32add81b7d56 100644 --- a/drivers/virt/coco/tdx-host/Kconfig +++ b/drivers/virt/coco/tdx-host/Kconfig @@ -8,3 +8,8 @@ config TDX_HOST_SERVICES =20 Say y or m if enabling support for confidential virtual machine support (CONFIG_INTEL_TDX_HOST). The module is called tdx_host.ko. + +config TDX_CONNECT + def_bool y + depends on TDX_HOST_SERVICES + depends on PCI_TSM diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-= host/tdx-host.c index c77885392b09..5ea35a514865 100644 --- a/drivers/virt/coco/tdx-host/tdx-host.c +++ b/drivers/virt/coco/tdx-host/tdx-host.c @@ -8,9 +8,13 @@ #include #include #include +#include +#include +#include =20 #include #include +#include =20 static const struct x86_cpu_id tdx_host_ids[] =3D { X86_MATCH_FEATURE(X86_FEATURE_TDX_HOST_PLATFORM, NULL), @@ -18,14 +22,144 @@ static const struct x86_cpu_id tdx_host_ids[] =3D { }; MODULE_DEVICE_TABLE(x86cpu, tdx_host_ids); =20 +/* + * The global pointer is for features which won't be affected by tdx_sysin= fo + * change after TDX Module update, e.g. TDX Connect, so could cache it. A + * counterexample is the TDX Module version. + */ +static const struct tdx_sys_info *tdx_sysinfo; + +struct tdx_tsm_link { + struct pci_tsm_pf0 pci; +}; + +static struct tdx_tsm_link *to_tdx_tsm_link(struct pci_tsm *tsm) +{ + return container_of(tsm, struct tdx_tsm_link, pci.base_tsm); +} + +static int tdx_tsm_link_connect(struct pci_dev *pdev) +{ + return -ENXIO; +} + +static void tdx_tsm_link_disconnect(struct pci_dev *pdev) +{ +} + +static struct pci_tsm *tdx_tsm_link_pf0_probe(struct tsm_dev *tsm_dev, + struct pci_dev *pdev) +{ + int rc; + + struct tdx_tsm_link *tlink __free(kfree) =3D kzalloc_obj(*tlink); + if (!tlink) + return NULL; + + rc =3D pci_tsm_pf0_constructor(pdev, &tlink->pci, tsm_dev); + if (rc) + return NULL; + + return &no_free_ptr(tlink)->pci.base_tsm; +} + +static void tdx_tsm_link_pf0_remove(struct pci_tsm *tsm) +{ + struct tdx_tsm_link *tlink =3D to_tdx_tsm_link(tsm); + + pci_tsm_pf0_destructor(&tlink->pci); + kfree(tlink); +} + +static struct pci_tsm *tdx_tsm_link_fn_probe(struct tsm_dev *tsm_dev, + struct pci_dev *pdev) +{ + int rc; + + struct pci_tsm *pci_tsm __free(kfree) =3D kzalloc_obj(*pci_tsm); + if (!pci_tsm) + return NULL; + + rc =3D pci_tsm_link_constructor(pdev, pci_tsm, tsm_dev); + if (rc) + return NULL; + + return no_free_ptr(pci_tsm); +} + +static struct pci_tsm *tdx_tsm_link_probe(struct tsm_dev *tsm_dev, + struct pci_dev *pdev) +{ + if (is_pci_tsm_pf0(pdev)) + return tdx_tsm_link_pf0_probe(tsm_dev, pdev); + + return tdx_tsm_link_fn_probe(tsm_dev, pdev); +} + +static void tdx_tsm_link_remove(struct pci_tsm *tsm) +{ + if (is_pci_tsm_pf0(tsm->pdev)) { + tdx_tsm_link_pf0_remove(tsm); + return; + } + + /* for sub-functions */ + kfree(tsm); +} + +static struct pci_tsm_ops tdx_tsm_link_ops =3D { + .probe =3D tdx_tsm_link_probe, + .remove =3D tdx_tsm_link_remove, + .connect =3D tdx_tsm_link_connect, + .disconnect =3D tdx_tsm_link_disconnect, +}; + +static void unregister_link_tsm(void *link) +{ + tsm_unregister(link); +} + +static int __maybe_unused tdx_connect_init(struct device *dev) +{ + struct tsm_dev *link; + int ret; + + if (!IS_ENABLED(CONFIG_TDX_CONNECT)) + return 0; + + if (!(tdx_sysinfo->features.tdx_features0 & TDX_FEATURES0_TDXCONNECT)) + return 0; + + link =3D tsm_register(dev, &tdx_tsm_link_ops); + if (IS_ERR(link)) + return dev_err_probe(dev, PTR_ERR(link), + "failed to register TSM\n"); + + return devm_add_action_or_reset(dev, unregister_link_tsm, link); +} + +static int tdx_host_probe(struct faux_device *fdev) +{ + /* TODO: do tdx_connect_init() when it is fully implemented. */ + return 0; +} + +static struct faux_device_ops tdx_host_ops =3D { + .probe =3D tdx_host_probe, +}; + static struct faux_device *fdev; =20 static int __init tdx_host_init(void) { - if (!x86_match_cpu(tdx_host_ids) || !tdx_get_sysinfo()) + if (!x86_match_cpu(tdx_host_ids)) + return -ENODEV; + + tdx_sysinfo =3D tdx_get_sysinfo(); + if (!tdx_sysinfo) return -ENODEV; =20 - fdev =3D faux_device_create(KBUILD_MODNAME, NULL, NULL); + fdev =3D faux_device_create(KBUILD_MODNAME, NULL, &tdx_host_ops); if (!fdev) return -ENODEV; =20 --=20 2.25.1 From nobody Thu Apr 2 15:41:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 3AE2B3F54D0; Fri, 27 Mar 2026 16:23:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628618; cv=none; b=aEdcy2UUohYJ7vIr/NGfpJombAbkuUh0jLsqklRH+sJ4obhPsjMf+vvE0KlfS+bCp9ewhM2HoA6XkB8LREsDRKBkmatSORjthp0kOwYQgWoyT25FIrzof4ffrws32zXAYhbgZREu91QV7N/UVxrYNNJEzhp9n2XX3OJCZqZ4Di4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628618; c=relaxed/simple; bh=Yw2arDmH4MgdmE+FoKrycqUBPwKxZLL2Da+EzWHNEjE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=AsyQbobnExCA3v1zUlUzCPYOwqouMDWkrma7P+vcavRLhUaSW2Ddq/8iJtae0JhF0y6GqVF2TT72W5N0KYBfm8yifEUCdSPBCy77KLYJIC3HbJb42dMe5c+Q7AL9UqRBiq34TOZ3VdffSw6HtKd6SVwo352PcZtk7rasf5N0OVs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=lTRGge+t; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="lTRGge+t" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628616; x=1806164616; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Yw2arDmH4MgdmE+FoKrycqUBPwKxZLL2Da+EzWHNEjE=; b=lTRGge+tzqKYuhJEbM9GHlTcPH31e+jeAjxtd70B5oOH6v1isTJhj3B1 Ub8mrfgSD9150GNm4Rb/J0XT2S+KNnMsEr7C7fWnOo8TrbY+8HNOahfI1 lnJeOUg+59tYuNoUqqPIMkf09yb5xwz5aETlvrgnZGBxEKJnvkwgt1H+w tOY7VVpsywCYRNIzYHCo7hpKrzOStK0wV2wCo5zhZp3ZPaSL5awaqwKCp rIP65x1muGAulY1ie7ozPHCu3Z17/AN8urzqdsJj7oLVfhvMT6Q3awFFW /bs2uSuwKsBUIuz/P/8zRhLPoNHXALEQrIKrSAB9dzcaqEVqtjTVm392d g==; X-CSE-ConnectionGUID: 6wM+xWjLQr67XmYzX61TPQ== X-CSE-MsgGUID: hVbxGcS7QHekOE2/X4HKpw== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565611" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565611" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:23:36 -0700 X-CSE-ConnectionGUID: OzketJJZS/OmPIQa/DKplQ== X-CSE-MsgGUID: dFqNlNTTQrixRH4N3fGZcQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516280" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:23:32 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 17/31] acpi: Add KEYP support to fw_table parsing Date: Sat, 28 Mar 2026 00:01:18 +0800 Message-Id: <20260327160132.2946114-18-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Dave Jiang KEYP ACPI table can be parsed using the common fw_table handlers. Add additional support to detect and parse the table. Co-developed-by: Xu Yilun Signed-off-by: Xu Yilun Signed-off-by: Dave Jiang Reviewed-by: Jonathan Cameron --- include/linux/acpi.h | 3 +++ include/linux/fw_table.h | 1 + drivers/acpi/tables.c | 12 +++++++++++- lib/fw_table.c | 9 +++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 4d2f0bed7a06..e5b51bd46600 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -247,6 +247,9 @@ int acpi_table_parse_madt(enum acpi_madt_type id, int __init_or_acpilib acpi_table_parse_cedt(enum acpi_cedt_type id, acpi_tbl_entry_handler_arg handler_arg, void *arg); +int __init_or_acpilib +acpi_table_parse_keyp(enum acpi_keyp_type id, + acpi_tbl_entry_handler_arg handler_arg, void *arg); =20 int acpi_parse_mcfg (struct acpi_table_header *header); void acpi_table_print_madt_entry (struct acpi_subtable_header *madt); diff --git a/include/linux/fw_table.h b/include/linux/fw_table.h index 9bd605b87c4c..293252cb0b7e 100644 --- a/include/linux/fw_table.h +++ b/include/linux/fw_table.h @@ -36,6 +36,7 @@ union acpi_subtable_headers { struct acpi_prmt_module_header prmt; struct acpi_cedt_header cedt; struct acpi_cdat_header cdat; + struct acpi_keyp_common_header keyp; }; =20 int acpi_parse_entries_array(char *id, unsigned long table_size, diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 4286e4af1092..8dc60632faf3 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -299,6 +299,16 @@ acpi_table_parse_cedt(enum acpi_cedt_type id, } EXPORT_SYMBOL_ACPI_LIB(acpi_table_parse_cedt); =20 +int __init_or_acpilib +acpi_table_parse_keyp(enum acpi_keyp_type id, + acpi_tbl_entry_handler_arg handler_arg, void *arg) +{ + return __acpi_table_parse_entries(ACPI_SIG_KEYP, + sizeof(struct acpi_table_keyp), id, + NULL, handler_arg, arg, 0); +} +EXPORT_SYMBOL_ACPI_LIB(acpi_table_parse_keyp); + int __init acpi_table_parse_entries(char *id, unsigned long table_size, int entry_id, acpi_tbl_entry_handler handler, @@ -408,7 +418,7 @@ static const char table_sigs[][ACPI_NAMESEG_SIZE] __non= string_array __initconst ACPI_SIG_PSDT, ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, ACPI_SIG_IORT, ACPI_SIG_NFIT, ACPI_SIG_HMAT, ACPI_SIG_PPTT, ACPI_SIG_NHLT, ACPI_SIG_AEST, ACPI_SIG_CEDT, ACPI_SIG_AGDI, - ACPI_SIG_NBFT, ACPI_SIG_SWFT, ACPI_SIG_MPAM}; + ACPI_SIG_NBFT, ACPI_SIG_SWFT, ACPI_SIG_MPAM, ACPI_SIG_KEYP}; =20 #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header) =20 diff --git a/lib/fw_table.c b/lib/fw_table.c index 16291814450e..147e3895e94c 100644 --- a/lib/fw_table.c +++ b/lib/fw_table.c @@ -20,6 +20,7 @@ enum acpi_subtable_type { ACPI_SUBTABLE_PRMT, ACPI_SUBTABLE_CEDT, CDAT_SUBTABLE, + ACPI_SUBTABLE_KEYP, }; =20 struct acpi_subtable_entry { @@ -41,6 +42,8 @@ acpi_get_entry_type(struct acpi_subtable_entry *entry) return entry->hdr->cedt.type; case CDAT_SUBTABLE: return entry->hdr->cdat.type; + case ACPI_SUBTABLE_KEYP: + return entry->hdr->keyp.type; } return 0; } @@ -61,6 +64,8 @@ acpi_get_entry_length(struct acpi_subtable_entry *entry) __le16 length =3D (__force __le16)entry->hdr->cdat.length; =20 return le16_to_cpu(length); + case ACPI_SUBTABLE_KEYP: + return entry->hdr->keyp.length; } } return 0; @@ -80,6 +85,8 @@ acpi_get_subtable_header_length(struct acpi_subtable_entr= y *entry) return sizeof(entry->hdr->cedt); case CDAT_SUBTABLE: return sizeof(entry->hdr->cdat); + case ACPI_SUBTABLE_KEYP: + return sizeof(entry->hdr->keyp); } return 0; } @@ -95,6 +102,8 @@ acpi_get_subtable_type(char *id) return ACPI_SUBTABLE_CEDT; if (strncmp(id, ACPI_SIG_CDAT, 4) =3D=3D 0) return CDAT_SUBTABLE; + if (strncmp(id, ACPI_SIG_KEYP, 4) =3D=3D 0) + return ACPI_SUBTABLE_KEYP; return ACPI_SUBTABLE_COMMON; } =20 --=20 2.25.1 From nobody Thu Apr 2 15:41:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 D5C353F8E03; Fri, 27 Mar 2026 16:23:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628622; cv=none; b=RDeozXimClwPuI1FPeRZyABACXtdWDnBZ/TXndIHtLLvTK9gj4THQIHBVpvcCBx0OylJimAZCDX2CUk3Eu9Qh1N+8JfNaZoeLpizF121VtTgRM6LrAaiPvJGfehDL5wOTZZTXa6LjNQzD4oCHfK+3wQC+zm9NKa/GYn5yS6g9hQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628622; c=relaxed/simple; bh=MjaiQQUsi0uHldZUeFA1C5Pe04DjmHcDoKFmUK/lKgU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=aAow05O0AuTimNA+g8s57REgOOSQcsmCuvi2UDuwhQpBZv6SOBbRkEHluUt7JZc+deY9ZrNYJ07qYOPcsgPWZmR20uAiwv3Xl0xZvyyxiVXZzlsvThumQ+IRUNeT09bL2jG5t9h904wyDxd4v6OP6Z5hip8ICRYEPp3cDIf/azE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Wb5iqVUj; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Wb5iqVUj" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628620; x=1806164620; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=MjaiQQUsi0uHldZUeFA1C5Pe04DjmHcDoKFmUK/lKgU=; b=Wb5iqVUjKP/cvh6yTbA3I1qlZv/Ek3FFwY79eCRaeCAVkcxBoFTfpOdf 4PZtAwlN36WdWs4i0x1lLUyNfT1fmyPesW8+A9XmaNiIVgIeDKEcgxSD3 njuWnIIpIxZjKNWWzDsxFofqn0cfpKHb3wMR+igPJAgKDECDyO3Pej1lP PSH4feo6ZqJlPEuM51rn6F61lD9pt3ikCeRYoJ5AqFRbEbN5R5CpZjmTr ciO8hAvBURS8OizE3UEso6Xr8WsU4bP3DWPLx11FjscyYN89fJnwolvPM FHcnHhFvd8ifuKTU5faQhNc0R1TReU6fUv0W5B2Cra8ZqiV8FnVxYapuz g==; X-CSE-ConnectionGUID: KJ1yOLFfRVSeAqLeqmLifg== X-CSE-MsgGUID: iJJY8QokSS6SJLO74035hQ== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565627" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565627" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:23:40 -0700 X-CSE-ConnectionGUID: xAnUCVlMRKC4eFHIu1Fh1A== X-CSE-MsgGUID: cUCaAbRwT5ywKqcI65ywdA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516302" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:23:37 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 18/31] iommu/vt-d: Cache max domain ID to avoid redundant calculation Date: Sat, 28 Mar 2026 00:01:19 +0800 Message-Id: <20260327160132.2946114-19-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Lu Baolu The cap_ndoms() helper calculates the maximum available domain ID from the value of capability register, which can be inefficient if called repeatedly. Cache the maximum supported domain ID in max_domain_id field during initialization to avoid redundant calls to cap_ndoms() throughout the IOMMU driver. No functionality change. Signed-off-by: Lu Baolu Signed-off-by: Xu Yilun --- drivers/iommu/intel/iommu.h | 1 + drivers/iommu/intel/dmar.c | 1 + drivers/iommu/intel/iommu.c | 10 +++++----- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h index 599913fb65d5..4a21ab6a311d 100644 --- a/drivers/iommu/intel/iommu.h +++ b/drivers/iommu/intel/iommu.h @@ -705,6 +705,7 @@ struct intel_iommu { /* mutex to protect domain_ida */ struct mutex did_lock; struct ida domain_ida; /* domain id allocator */ + unsigned long max_domain_id; unsigned long *copied_tables; /* bitmap of copied tables */ spinlock_t lock; /* protect context, domain ids */ struct root_entry *root_entry; /* virtual address */ diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c index d68c06025cac..93efd1a5dc5b 100644 --- a/drivers/iommu/intel/dmar.c +++ b/drivers/iommu/intel/dmar.c @@ -1099,6 +1099,7 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) spin_lock_init(&iommu->lock); ida_init(&iommu->domain_ida); mutex_init(&iommu->did_lock); + iommu->max_domain_id =3D cap_ndoms(iommu->cap); =20 ver =3D readl(iommu->reg + DMAR_VER_REG); pr_info("%s: reg_base_addr %llx ver %d:%d cap %llx ecap %llx\n", diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index ef7613b177b9..9a57f78647ed 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -1043,7 +1043,7 @@ int domain_attach_iommu(struct dmar_domain *domain, s= truct intel_iommu *iommu) } =20 num =3D ida_alloc_range(&iommu->domain_ida, IDA_START_DID, - cap_ndoms(iommu->cap) - 1, GFP_KERNEL); + iommu->max_domain_id - 1, GFP_KERNEL); if (num < 0) { pr_err("%s: No free domain ids\n", iommu->name); goto err_unlock; @@ -1107,7 +1107,7 @@ static void copied_context_tear_down(struct intel_iom= mu *iommu, did_old =3D context_domain_id(context); context_clear_entry(context); =20 - if (did_old < cap_ndoms(iommu->cap)) { + if (did_old < iommu->max_domain_id) { iommu->flush.flush_context(iommu, did_old, PCI_DEVID(bus, devfn), DMA_CCMD_MASK_NOBIT, @@ -1505,7 +1505,7 @@ static int copy_context_table(struct intel_iommu *iom= mu, continue; =20 did =3D context_domain_id(&ce); - if (did >=3D 0 && did < cap_ndoms(iommu->cap)) + if (did >=3D 0 && did < iommu->max_domain_id) ida_alloc_range(&iommu->domain_ida, did, did, GFP_KERNEL); =20 set_context_copied(iommu, bus, devfn); @@ -2425,7 +2425,7 @@ static ssize_t domains_supported_show(struct device *= dev, struct device_attribute *attr, char *buf) { struct intel_iommu *iommu =3D dev_to_intel_iommu(dev); - return sysfs_emit(buf, "%ld\n", cap_ndoms(iommu->cap)); + return sysfs_emit(buf, "%ld\n", iommu->max_domain_id); } static DEVICE_ATTR_RO(domains_supported); =20 @@ -2436,7 +2436,7 @@ static ssize_t domains_used_show(struct device *dev, unsigned int count =3D 0; int id; =20 - for (id =3D 0; id < cap_ndoms(iommu->cap); id++) + for (id =3D 0; id < iommu->max_domain_id; id++) if (ida_exists(&iommu->domain_ida, id)) count++; =20 --=20 2.25.1 From nobody Thu Apr 2 15:41:48 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 74ED834FF4D; Fri, 27 Mar 2026 16:23:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628625; cv=none; b=O1JFvtCW7UJXqvhqOzinYsXI1jfjDYE6iFZ06DwSIfe5egO9ymJahPdp+1XYuAG3OU/z3aXLRNLcaC4QCvMixTYAOT0vd8r542v7NPu8Df/MF6aJCNxPlMVHod41Y61OSIRoxLMRjR7z3MHz5TajtQ/Cga10S+jj9oC66SehaUI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628625; c=relaxed/simple; bh=dJBSY5nZlLW3s/69xR3iEOmBKQ+myKH7t2obUbqnFKg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=AKLmHCgPgJghzlhZ/MQmdX6jwcmn+pYy0g9VJsOpRmj9Wjqrvk8IufaB6Y12nZ9J6dBFwp6HBT/XW79zmQg4acK+YusejzOyG4P4p5dJ7UYBSZmI35mZ64B7fN8dKUi7su338alg29+Nh9aJrNB709NEivmBT/UA9XBVb4mX2js= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=m/UpO+UC; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="m/UpO+UC" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628624; x=1806164624; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=dJBSY5nZlLW3s/69xR3iEOmBKQ+myKH7t2obUbqnFKg=; b=m/UpO+UChNkfF1uUqdmIKV8Ct3qrbmFO3h4zDtEPcFvmx8nsjpg0lbDg JaO0dnrZYODoNgcXfDjmNaIIFj/83G7HlbNTpK1Ut08oE91OwX0Swh54w w9AIfD/xGqE0tmcGtj/rXSfI94Xs6zG+cP/058awL+8gwDZfmRnhDOlRe k+uVsXfTs56tplRFXxGVhZeciO+8B8swT9sLEij/0dMZ6BzmLnbZ0J+5B wbVfXqkFkAZIuu4kjeyhDDGPBBPbzwc29TKhpTLMH4ckLxeYckJ5iPOja kdTZiDoxldKdWM91XTknlmvlpw7IBiMXWIx2YOJN1vcoXQhi2o5z3EYR8 Q==; X-CSE-ConnectionGUID: VJVUh5ytS8OEqrFzIKWmNw== X-CSE-MsgGUID: sllwQ513T6WModCw+dj9aA== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565634" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565634" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:23:43 -0700 X-CSE-ConnectionGUID: IEKcN4BnRUCescArNhzMNQ== X-CSE-MsgGUID: B9AlSQTAS4eNwRJhspnjug== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516311" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:23:40 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 19/31] iommu/vt-d: Reserve the MSB domain ID bit for the TDX module Date: Sat, 28 Mar 2026 00:01:20 +0800 Message-Id: <20260327160132.2946114-20-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Lu Baolu The Intel TDX Connect Architecture Specification defines some enhancements for the VT-d architecture to introduce IOMMU support for TEE-IO requests. Section 2.2, 'Trusted DMA' states that: "I/O TLB and DID Isolation =E2=80=93 When IOMMU is enabled to support TDX Connect, the IOMMU restricts the VMM=E2=80=99s DID setting, reserving the M= SB bit for the TDX module. The TDX module always sets this reserved bit on the trusted DMA table. IOMMU tags IOTLB, PASID cache, and context entries to indicate whether they were created from TEE-IO transactions, ensuring isolation between TEE and non-TEE requests in translation caches." Reserve the MSB in the domain ID for the TDX module's use if the enhancement is required, which is detected if the ECAP.TDXCS bit in the VT-d extended capability register is set and the TVM Usable field of the ACPI KEYP table is set. Co-developed-by: Xu Yilun Signed-off-by: Xu Yilun Signed-off-by: Lu Baolu --- drivers/iommu/intel/iommu.h | 1 + drivers/iommu/intel/dmar.c | 52 ++++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h index 4a21ab6a311d..0c2b4e38dee7 100644 --- a/drivers/iommu/intel/iommu.h +++ b/drivers/iommu/intel/iommu.h @@ -192,6 +192,7 @@ */ =20 #define ecap_pms(e) (((e) >> 51) & 0x1) +#define ecap_tdxc(e) (((e) >> 50) & 0x1) #define ecap_rps(e) (((e) >> 49) & 0x1) #define ecap_smpwc(e) (((e) >> 48) & 0x1) #define ecap_flts(e) (((e) >> 47) & 0x1) diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c index 93efd1a5dc5b..4f9571eee1d4 100644 --- a/drivers/iommu/intel/dmar.c +++ b/drivers/iommu/intel/dmar.c @@ -1033,6 +1033,56 @@ static int map_iommu(struct intel_iommu *iommu, stru= ct dmar_drhd_unit *drhd) return err; } =20 +static int keyp_config_unit_tvm_usable(union acpi_subtable_headers *header, + void *arg, const unsigned long end) +{ + struct acpi_keyp_config_unit *acpi_cu =3D + (struct acpi_keyp_config_unit *)&header->keyp; + int *tvm_usable =3D arg; + + if (acpi_cu->flags & ACPI_KEYP_F_TVM_USABLE) + *tvm_usable =3D 1; + + return 0; +} + +static bool platform_is_tdxc_enhanced(void) +{ + static int tvm_usable =3D -1; + int ret; + + /* only need to parse once */ + if (tvm_usable !=3D -1) + return !!tvm_usable; + + tvm_usable =3D 0; + ret =3D acpi_table_parse_keyp(ACPI_KEYP_TYPE_CONFIG_UNIT, + keyp_config_unit_tvm_usable, &tvm_usable); + if (ret < 0) + tvm_usable =3D 0; + + return !!tvm_usable; +} + +static unsigned long iommu_max_domain_id(struct intel_iommu *iommu) +{ + unsigned long ndoms =3D cap_ndoms(iommu->cap); + + /* + * Intel TDX Connect Architecture Specification, Section 2.2 Trusted DMA + * + * When IOMMU is enabled to support TDX Connect, the IOMMU restricts + * the VMM=E2=80=99s DID setting, reserving the MSB bit for the TDX modul= e. The + * TDX module always sets this reserved bit on the trusted DMA table. + */ + if (ecap_tdxc(iommu->ecap) && platform_is_tdxc_enhanced()) { + pr_info_once("Most Significant Bit of domain ID reserved.\n"); + return ndoms >> 1; + } + + return ndoms; +} + static int alloc_iommu(struct dmar_drhd_unit *drhd) { struct intel_iommu *iommu; @@ -1099,7 +1149,7 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) spin_lock_init(&iommu->lock); ida_init(&iommu->domain_ida); mutex_init(&iommu->did_lock); - iommu->max_domain_id =3D cap_ndoms(iommu->cap); + iommu->max_domain_id =3D iommu_max_domain_id(iommu); =20 ver =3D readl(iommu->reg + DMAR_VER_REG); pr_info("%s: reg_base_addr %llx ver %d:%d cap %llx ecap %llx\n", --=20 2.25.1 From nobody Thu Apr 2 15:41:48 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 107B13FBEA3; Fri, 27 Mar 2026 16:23:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628630; cv=none; b=IN+l4+deKLcfm2zZagLeW5GA1ZSgAEU3r6BK2RUvjusX3gAA3AQ2hc03ItwlOnfr02BC1ZOpJxrOT++7DQStkEiEx70Ne6R4yCn3Qh9cbaQl/jKZ/57NIA0vLzHOZ2m2IdZptGOWTYCFprqZQAegBaf8SrcMX7ffTGi/jCTPGok= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628630; c=relaxed/simple; bh=JpFljdI5U/a/gNIVQmuIsHGSGIbydMYmkZ3Ia68L6tY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=H9cnWGF6nKOV27DV8mP5BVllG/coB1myXcZdcUV5ll9fFDb0o9X6Zgm7zELaa0g+i+D/E9ciczlM7IzTaQVpzPld6SFhafpAi9RYapRwzOecsn2OalCUArfuHWoultG1PRI3nqoACe/U8BE0rCRFxYg4+HOeV0SnKUT1RRq6ghE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=lCsZM/kr; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="lCsZM/kr" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628627; x=1806164627; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=JpFljdI5U/a/gNIVQmuIsHGSGIbydMYmkZ3Ia68L6tY=; b=lCsZM/kr62MegnwBbFhk9vZ+WBHCtPdFk/iI/kfVGYTAcTNCMSdMxhOv pz29OLPo5m86fesM9CwT7Syxqacmg04/GIeFE/Qy/gAAIl7hiQz2DTbgY eGDBhPwrnr0z4mHkjdc/Hqxj8KPZmZmBv81FzID8eSaqGWrQokw1nEEYc HAMI8I1JK0w6DWijsRZq/JooaS8IgZARvNETX7Z+vhOq3Q+zI2YoY7B98 RnLhr/BJQSeoy8N8ai6xsaMAzAcE2vRL0qy8fehZY2U5pIqgM3WoLyinF aNBme6E/3+7AlbMKFy/FdaBNd4B+pSlqgeiKQE9m2eUxzniERFa3ZJGZn g==; X-CSE-ConnectionGUID: p9lcJTVjRpe9Ha0HhAo4FQ== X-CSE-MsgGUID: tmy7QabXT5iNCTRkvm3L6A== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565638" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565638" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:23:47 -0700 X-CSE-ConnectionGUID: kDe/7qQWQEuII0+9rgCC4w== X-CSE-MsgGUID: d6DN10EoR3GvEZ5n+2TJQg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516321" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:23:44 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 20/31] x86/virt/tdx: Add a helper to loop on TDX_INTERRUPTED_RESUMABLE Date: Sat, 28 Mar 2026 00:01:21 +0800 Message-Id: <20260327160132.2946114-21-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a helper to handle SEAMCALL return code TDX_INTERRUPTED_RESUMABLE. SEAMCALL returns TDX_INTERRUPTED_RESUMABLE to avoid stalling host for long time. After host has handled the interrupt, it calls the interrupted SEAMCALL again and TDX Module continues to execute. TDX Module made progress in this case and would eventually finish. An infinite loop in host should be safe. The helper is for SEAMCALL wrappers which output information by using seamcall_ret() or seamcall_saved_ret(). The 2 functions overwrite input arguments by outputs but much SEAMCALLs expect the same inputs to resume. The helper is not for special cases where the SEAMCALL expects modified inputs to resume. The helper is also not for SEAMCALLs with no output, do {...} while (r =3D=3D TDX_INTERRUPTED_RESUMABLE) just works. Signed-off-by: Xu Yilun --- arch/x86/virt/vmx/tdx/tdx.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index cd0948794b6c..294f36048c03 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -2084,6 +2084,29 @@ static inline u64 tdx_tdr_pa(struct tdx_td *td) return page_to_phys(td->tdr_page); } =20 +static u64 __maybe_unused __seamcall_ir_resched(sc_func_t sc_func, u64 fn, + struct tdx_module_args *args) +{ + struct tdx_module_args _args; + u64 r; + + while (1) { + _args =3D *(args); + r =3D sc_retry(sc_func, fn, &_args); + if (r !=3D TDX_INTERRUPTED_RESUMABLE) + break; + + cond_resched(); + } + + *args =3D _args; + + return r; +} + +#define seamcall_ret_ir_resched(fn, args) \ + __seamcall_ir_resched(__seamcall_ret, fn, args) + noinstr u64 tdh_vp_enter(struct tdx_vp *td, struct tdx_module_args *args) { args->rcx =3D td->tdvpr_pa; --=20 2.25.1 From nobody Thu Apr 2 15:41:48 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 B9D683FBED6; Fri, 27 Mar 2026 16:23:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628633; cv=none; b=lK1XidmT3RAcdfHgFhArK4r47V9CnVROOb34VsLYHGyphbVkB7bGWtx0mc1wwTR9Ann/skQFHHYVLkmQQ5TRw/iAAWzgVgUKwUUUbAIIIkV5yO+J/w9H5ZnGpJ0YwJpkwJcHHDIQrnV3+PCvpffz6mzsFQ0tOny4hChzKt4CSJE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628633; c=relaxed/simple; bh=p74J85piSN9BkcvDMTXCNhHlHi+VhcHjF9ro/OcIERY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=mjXa+cT00xRaO7IIPhFbg1Gge70u6fOb+herwxLPfg0dGlUO/uVfRURinLOJgcEmVxOCSIbU45OrvtiN+YbOLIO5lcf0Mr6WuVYEC5yznCjNYukLGfPT7AYq+RJKi/BPRi4PBoobfKe68l3DGaXqMAdA1aA4N/zZ3OhV1vnVQ54= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=XL050/D/; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="XL050/D/" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628631; x=1806164631; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=p74J85piSN9BkcvDMTXCNhHlHi+VhcHjF9ro/OcIERY=; b=XL050/D/8no3SrgVi1/4WpaKCNKtBrv1qwj3RFLAIQecsur3rE7lQBeQ AE6uy96/JJ9Aav62haqkXG9XiWdSAQvEs9c75/qDjdeQZevxvKVuelqKJ cQKpy/UNRfxytfdqcT2Z/q9ZcA85Hc0RB0YeAJpohGyaUetsvdXESXzz2 RgQTDbfYzRKpVXKMTR9EPcIBOlj7/GW+nJ3Dl/JnJeyXvk/+MhRevRYxz AUa4QiYWaEz0I4RZCHC6+kVecol8s8fI7s13wnoH/MqhNfXH1EKJ1PvkB Hv/N7+z3D82nOJ+p6Z/Nc4KxE7ola2XTLgwJn+6VB0YcdUPSbZ3Fq+d+0 A==; X-CSE-ConnectionGUID: zuY+GoOvSralKgyN+xj5IA== X-CSE-MsgGUID: TddK54gLTBK9KhtRO5fMjg== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565644" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565644" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:23:51 -0700 X-CSE-ConnectionGUID: NmYVE2SyT9GJw+idXiU8bw== X-CSE-MsgGUID: PuuD2cDqQZWXAnHvUIYGfg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516334" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:23:48 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 21/31] x86/virt/tdx: Add SEAMCALL wrappers for trusted IOMMU setup and clear Date: Sat, 28 Mar 2026 00:01:22 +0800 Message-Id: <20260327160132.2946114-22-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Zhenzhong Duan Add SEAMCALLs to setup/clear trusted IOMMU for TDX Connect. Enable TEE I/O support for a target device requires to setup trusted IOMMU for the related IOMMU device first, even only for enabling physical secure links like SPDM/IDE. TDH.IOMMU.SETUP takes the register base address (VTBAR) to position an IOMMU device, and outputs an IOMMU_ID as the trusted IOMMU identifier. TDH.IOMMU.CLEAR takes the IOMMU_ID to reverse the setup. More information see Intel TDX Connect ABI Specification [1] Section 3.2 TDX Connect Host-Side (SEAMCALL) Interface Functions. [1]: https://cdrdv2.intel.com/v1/dl/getContent/858625 Co-developed-by: Xu Yilun Signed-off-by: Xu Yilun Signed-off-by: Zhenzhong Duan --- arch/x86/include/asm/tdx.h | 2 ++ arch/x86/virt/vmx/tdx/tdx.h | 2 ++ arch/x86/virt/vmx/tdx/tdx.c | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index d7605235aa9b..a59e0e43e465 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -245,6 +245,8 @@ u64 tdh_mem_page_remove(struct tdx_td *td, u64 gpa, u64= level, u64 *ext_err1, u6 u64 tdh_phymem_cache_wb(bool resume); u64 tdh_phymem_page_wbinvd_tdr(struct tdx_td *td); u64 tdh_phymem_page_wbinvd_hkid(u64 hkid, struct page *page); +u64 tdh_iommu_setup(u64 vtbar, struct tdx_page_array *iommu_mt, u64 *iommu= _id); +u64 tdh_iommu_clear(u64 iommu_id, struct tdx_page_array *iommu_mt); #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.h b/arch/x86/virt/vmx/tdx/tdx.h index a26fe94c07ff..b25c418f6e61 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -62,6 +62,8 @@ #define TDH_SYS_CONFIG SEAMCALL_LEAF_VER(TDH_SYS_CONFIG_V0, 1) #define TDH_EXT_INIT 60 #define TDH_EXT_MEM_ADD 61 +#define TDH_IOMMU_SETUP 128 +#define TDH_IOMMU_CLEAR 129 =20 /* TDX page types */ #define PT_NDA 0x0 diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 294f36048c03..790713881f1f 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -2084,8 +2084,8 @@ static inline u64 tdx_tdr_pa(struct tdx_td *td) return page_to_phys(td->tdr_page); } =20 -static u64 __maybe_unused __seamcall_ir_resched(sc_func_t sc_func, u64 fn, - struct tdx_module_args *args) +static u64 __seamcall_ir_resched(sc_func_t sc_func, u64 fn, + struct tdx_module_args *args) { struct tdx_module_args _args; u64 r; @@ -2478,3 +2478,31 @@ void tdx_cpu_flush_cache_for_kexec(void) } EXPORT_SYMBOL_FOR_KVM(tdx_cpu_flush_cache_for_kexec); #endif + +u64 tdh_iommu_setup(u64 vtbar, struct tdx_page_array *iommu_mt, u64 *iommu= _id) +{ + struct tdx_module_args args =3D { + .rcx =3D vtbar, + .rdx =3D virt_to_phys(iommu_mt->root), + }; + u64 r; + + tdx_clflush_page_array(iommu_mt); + + r =3D seamcall_ret_ir_resched(TDH_IOMMU_SETUP, &args); + + *iommu_id =3D args.rcx; + return r; +} +EXPORT_SYMBOL_FOR_MODULES(tdh_iommu_setup, "tdx-host"); + +u64 tdh_iommu_clear(u64 iommu_id, struct tdx_page_array *iommu_mt) +{ + struct tdx_module_args args =3D { + .rcx =3D iommu_id, + .rdx =3D virt_to_phys(iommu_mt->root), + }; + + return seamcall_ret_ir_resched(TDH_IOMMU_CLEAR, &args); +} +EXPORT_SYMBOL_FOR_MODULES(tdh_iommu_clear, "tdx-host"); --=20 2.25.1 From nobody Thu Apr 2 15:41:48 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 6312A3FEB1C; Fri, 27 Mar 2026 16:23:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628636; cv=none; b=bftN4OLwWUj5r4FUb0vVcVsFTFxJyRDIRoiY6sRqvCFZUkcKnWi3hg10Pmyn9oI6s4g2qVOz1M01nWeIPjIOz1McyJizjv4H1Z+0g24zJzf3KjLK+u3KwNI26+ZjQIWRZPCGQLc2J/Yuz7mrE/JzhBAeD81J/4ip5Kz2NsyjfdA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628636; c=relaxed/simple; bh=4N4OssQklL/B7HyKRZJOSblHOdQoFgXqUseYPZid0EE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=tjNUI8TptrAcBUAjYcl1ZPP1p1FjoWZ6AbflRkl9kpj9c3AYoHZIyRa8h+jAXmUHsW+q+dF6RqWQmsWa4ulfZseJxF9aJE4s0YLOZqfTfhyqiKIvFnZGtTTwfpSGshOUW4CUl/6jvL+q+eiqxRphE3SdR0OStHL989jkPVcaHMM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=EhEqOiPA; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="EhEqOiPA" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628635; x=1806164635; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=4N4OssQklL/B7HyKRZJOSblHOdQoFgXqUseYPZid0EE=; b=EhEqOiPAz2WV/AGZJDDK/TXNOA1DuJbqh0LJPfF9yrhwzezTHj090dac 9xSppzvLuYob4zC3hIvPZPG+BatmATngAwhmoyGydmrOaEu4HzXhRU9Ec w/tdEfbu0/KwAZyJjMh5+ahQ5O2dRig6H2iZabr+xi7355xZHgug2VvN9 xUE0LC91G5Z7Cq8C2PwKwDM0sjBdO9l2k010ADLl5rIe5xjAJN8GcQw8P sBE73nPXxKfsQ1e27SGKnOis6+WbIDERa5Li122vgl7oA9omXDVXGTxfc vYcFzfa4VZHeMHoiZClvRRfDyPwEyBFz+2Vg2SV5te+Tdi6eL0AgQTBxk g==; X-CSE-ConnectionGUID: ZQQ3XzckRuWCbBKvA8d5yg== X-CSE-MsgGUID: MgCKW7QzSBe3oUMUu3uvRg== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565651" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565651" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:23:54 -0700 X-CSE-ConnectionGUID: dt1l+oQwR5iY4ZOfYTtnEg== X-CSE-MsgGUID: QZ4FgOGYQSOqVGVIpnJ43g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516341" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:23:51 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 22/31] iommu/vt-d: Export a helper to do function for each dmar_drhd_unit Date: Sat, 28 Mar 2026 00:01:23 +0800 Message-Id: <20260327160132.2946114-23-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Enable the tdx-host module to get VTBAR address for every IOMMU device. The VTBAR address is for TDX Module to identify the IOMMU device and setup its trusted configuraion. Suggested-by: Lu Baolu Signed-off-by: Xu Yilun --- include/linux/dmar.h | 2 ++ drivers/iommu/intel/dmar.c | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/include/linux/dmar.h b/include/linux/dmar.h index 692b2b445761..cd8d9f440975 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -86,6 +86,8 @@ extern struct list_head dmar_drhd_units; dmar_rcu_check()) \ if (i=3Ddrhd->iommu, 0) {} else=20 =20 +int do_for_each_drhd_unit(int (*fn)(struct dmar_drhd_unit *)); + static inline bool dmar_rcu_check(void) { return rwsem_is_locked(&dmar_global_lock) || diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c index 4f9571eee1d4..eea9ba691f99 100644 --- a/drivers/iommu/intel/dmar.c +++ b/drivers/iommu/intel/dmar.c @@ -2452,3 +2452,19 @@ bool dmar_platform_optin(void) return ret; } EXPORT_SYMBOL_GPL(dmar_platform_optin); + +int do_for_each_drhd_unit(int (*fn)(struct dmar_drhd_unit *)) +{ + struct dmar_drhd_unit *drhd; + int ret; + + guard(rwsem_read)(&dmar_global_lock); + + for_each_drhd_unit(drhd) { + ret =3D fn(drhd); + if (ret) + return ret; + } + return 0; +} +EXPORT_SYMBOL_GPL(do_for_each_drhd_unit); --=20 2.25.1 From nobody Thu Apr 2 15:41:48 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 E87B23FFABA; Fri, 27 Mar 2026 16:23:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628640; cv=none; b=hjkS+gaulU156LWZWyeDaN11dITwFlk+ZXUjmENhhHRk4XCbcIz3fiN01zvkPvzCAjd17PkrZVot+lY8+BSjl4n9K61BHuoLT3u2pc3BqHknYqayndfwpWk/Oy1wpCVvcqbt7B/Cy5ZYL8D8wHFNC5RX7s/9lKkODX6jF61TBug= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628640; c=relaxed/simple; bh=YzOkHMivVD/+gHSn2pojaLxbNd1uQTgUv+wqAcBP+bs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=rjF+wMD4yNnfS4UUNzOPKjFkBqcCjqh+WuGPYICqswH98SO80W7QNpgp0bXIWfFRix+EsSvaJSVHXEX2hkVKJ/0GzxzbMKnoP9ibwNLjgZlmhTHEzteSyoZ82zi/Y+LAnxb3pbk29k2TusfXxEE170aQ+aHsTwRrg+EFzIhWOZU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=ZrdqVmU4; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="ZrdqVmU4" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628638; x=1806164638; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=YzOkHMivVD/+gHSn2pojaLxbNd1uQTgUv+wqAcBP+bs=; b=ZrdqVmU4XhDKzKT6Pd+S34YHPinjMNO4DICd9Dt7w4PHaDS2IuIP9X8Z o+lrMWL1Hw5LPo+qRUiZzqmn/1aNs737uHzhtY7qBGrKiHaGeRQa97CXU o9CQVO4BhCM/7a2S9KDW7K71kV7ltJyANOWOVaG+NbRCWL26N8lND0Z5Z leKf9ppsojJS5kK05Z/FGSR9t3tdBe36cGWFHxmznjnihtt4+Mk92+pxO VWd7wp0kLmkCVetUSwPr2Gt+rVB9+JAdWlvrZgdtLjDZNyeDv3/B/BKOQ 55f7ecy8rgMLZHH24UFxh4bADUJ7hCWIqQNHKHSyryyDdqaSR5DRaqQLn Q==; X-CSE-ConnectionGUID: bjySKThtSoSOQ4KGPIAckg== X-CSE-MsgGUID: 3U6Bg8BEROqwIi07aK775w== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565654" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565654" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:23:58 -0700 X-CSE-ConnectionGUID: YWnWYM/cS2icefPw8WDqWQ== X-CSE-MsgGUID: 41WgSvkdQ7uo8CXRqhfzxA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516345" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:23:55 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 23/31] coco/tdx-host: Setup all trusted IOMMUs on TDX Connect init Date: Sat, 28 Mar 2026 00:01:24 +0800 Message-Id: <20260327160132.2946114-24-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Setup all trusted IOMMUs on TDX Connect initialization and clear all on TDX Connect removal. Trusted IOMMU setup is the pre-condition for all following TDX Connect operations such as SPDM/IDE setup. It is more of a platform configuration than a standalone IOMMU configuration, so put the implementation in tdx-host driver. There is no dedicated way to enumerate which IOMMU devices support trusted operations. The host has to call TDH.IOMMU.SETUP on all IOMMU devices and tell their trusted capability by the return value. Suggested-by: Lu Baolu Signed-off-by: Xu Yilun --- drivers/virt/coco/tdx-host/Kconfig | 1 + drivers/virt/coco/tdx-host/tdx-host.c | 85 +++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/drivers/virt/coco/tdx-host/Kconfig b/drivers/virt/coco/tdx-hos= t/Kconfig index 32add81b7d56..24e872f8953e 100644 --- a/drivers/virt/coco/tdx-host/Kconfig +++ b/drivers/virt/coco/tdx-host/Kconfig @@ -13,3 +13,4 @@ config TDX_CONNECT def_bool y depends on TDX_HOST_SERVICES depends on PCI_TSM + depends on INTEL_IOMMU diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-= host/tdx-host.c index 5ea35a514865..98ed93ac0153 100644 --- a/drivers/virt/coco/tdx-host/tdx-host.c +++ b/drivers/virt/coco/tdx-host/tdx-host.c @@ -6,6 +6,7 @@ */ =20 #include +#include #include #include #include @@ -119,6 +120,82 @@ static void unregister_link_tsm(void *link) tsm_unregister(link); } =20 +static DEFINE_XARRAY(tlink_iommu_xa); + +static void tdx_iommu_clear(u64 iommu_id, struct tdx_page_array *iommu_mt) +{ + u64 r; + + r =3D tdh_iommu_clear(iommu_id, iommu_mt); + if (r) { + pr_err("fail to clear tdx iommu 0x%llx\n", r); + goto leak; + } + + if (tdx_page_array_ctrl_release(iommu_mt, iommu_mt->nr_pages, + virt_to_phys(iommu_mt->root))) { + pr_err("fail to release iommu_mt pages\n"); + goto leak; + } + + return; + +leak: + tdx_page_array_ctrl_leak(iommu_mt); +} + +static int tdx_iommu_enable_one(struct dmar_drhd_unit *drhd) +{ + unsigned int nr_pages =3D tdx_sysinfo->connect.iommu_mt_page_count; + u64 r, iommu_id; + int ret; + + struct tdx_page_array *iommu_mt __free(tdx_page_array_free) =3D + tdx_page_array_create_iommu_mt(1, nr_pages); + if (!iommu_mt) + return -ENOMEM; + + r =3D tdh_iommu_setup(drhd->reg_base_addr, iommu_mt, &iommu_id); + /* This drhd doesn't support tdx mode, skip. */ + if ((r & TDX_SEAMCALL_STATUS_MASK) =3D=3D TDX_OPERAND_INVALID) + return 0; + + if (r) { + pr_err("fail to enable tdx mode for DRHD[0x%llx]\n", + drhd->reg_base_addr); + return -EFAULT; + } + + ret =3D xa_insert(&tlink_iommu_xa, (unsigned long)iommu_id, + no_free_ptr(iommu_mt), GFP_KERNEL); + if (ret) { + tdx_iommu_clear(iommu_id, iommu_mt); + return ret; + } + + return 0; +} + +static void tdx_iommu_disable_all(void *data) +{ + struct tdx_page_array *iommu_mt; + unsigned long iommu_id; + + xa_for_each(&tlink_iommu_xa, iommu_id, iommu_mt) + tdx_iommu_clear(iommu_id, iommu_mt); +} + +static int tdx_iommu_enable_all(void) +{ + int ret; + + ret =3D do_for_each_drhd_unit(tdx_iommu_enable_one); + if (ret) + tdx_iommu_disable_all(NULL); + + return ret; +} + static int __maybe_unused tdx_connect_init(struct device *dev) { struct tsm_dev *link; @@ -130,6 +207,14 @@ static int __maybe_unused tdx_connect_init(struct devi= ce *dev) if (!(tdx_sysinfo->features.tdx_features0 & TDX_FEATURES0_TDXCONNECT)) return 0; =20 + ret =3D tdx_iommu_enable_all(); + if (ret) + return dev_err_probe(dev, ret, "Enable tdx iommu failed\n"); + + ret =3D devm_add_action_or_reset(dev, tdx_iommu_disable_all, NULL); + if (ret) + return ret; + link =3D tsm_register(dev, &tdx_tsm_link_ops); if (IS_ERR(link)) return dev_err_probe(dev, PTR_ERR(link), --=20 2.25.1 From nobody Thu Apr 2 15:41:48 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 950714014B5; Fri, 27 Mar 2026 16:24:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628643; cv=none; b=n7Nf6/UILff+j1zF6Ccpaiz3RoGPIzcIsogog7f9oJDYFdTpOcHzP+31wD4JFgnAqfNQs6baBkVwT3sWfrk5BlSJZEWKUw1AOWZ59aGDqGJ+a96DWJExFuu1G1BHjnG+4bN2P49lgIwTowMRpNNeUqwxtrOMkFDMdUaDOKL5hvA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628643; c=relaxed/simple; bh=BWgvuTh4wsiASYHYze+pv0K77l3r+BTKGEH1em4ro3s=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=AwHJIm2gC0bqyHijkHVPNVleGLGY8zI8OqadgPwzdztxWxlkI8vxePcRYtSpLdjLoxLugeRMt2yspT+SnV4k9R49Ys/8BNZMVp1Pu0ZoK1ZVQ2ki1XFeje31b9oiim9E56B8F2+/aHe2qfC7DssQH5N0X3+7VrZ90m8IHAUdD4o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=OOuK9H9K; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="OOuK9H9K" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628642; x=1806164642; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=BWgvuTh4wsiASYHYze+pv0K77l3r+BTKGEH1em4ro3s=; b=OOuK9H9K6FQlEaahdcz38NMaZj5GtWcfEOtubz6utyeHa8O0AinedHVi QckDdQxVFHvDt4/FevUjx5eQU7sa7NAy+Zdye84CCNRBONJH8Jad7vixr vivFOF6a9oqVbWWYo9hgS7eI+/zjhxoEm8R07rvrWUCJpa//iVkiv82wx B7UIsnnd3C454OM3hyG+IDBEtU5ql/+tzD7Rxoye5ztS+3vex1Xeu+x+d UpwBaqPRndfQDFIvgZw72tib3xMrRZn7in20j67/8333OySQ5StSZXlhm ERWKk+TuSiy7r8FyYnf1rboI/3vQM/ghoqcjAeTTnm8Ow5X9cL2OoQ10h g==; X-CSE-ConnectionGUID: 4895LyNvSQubsUrMcJkjHw== X-CSE-MsgGUID: 0anwO/gySa6aHPrDmMEbYA== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565662" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565662" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:24:02 -0700 X-CSE-ConnectionGUID: X0Uz/QmCSSujRQRpRKYfyg== X-CSE-MsgGUID: DY8Zas4iTC+bZkPFfJug2w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516349" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:23:58 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 24/31] coco/tdx-host: Add a helper to exchange SPDM messages through DOE Date: Sat, 28 Mar 2026 00:01:25 +0800 Message-Id: <20260327160132.2946114-25-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Zhenzhong Duan TDX host uses this function to exchange TDX Module encrypted data with devices via SPDM. It is unfortunate that TDX passes raw DOE frames with headers included and the PCI DOE core wants payloads separated from headers. This conversion code is about the same amount of work as teaching the PCI DOE driver to support raw frames. Unless and until another raw frame use case shows up, just do this conversion in the TDX TSM driver. Co-developed-by: Xu Yilun Signed-off-by: Xu Yilun Signed-off-by: Zhenzhong Duan Reviewed-by: Jonathan Cameron --- drivers/virt/coco/tdx-host/tdx-host.c | 61 +++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-= host/tdx-host.c index 98ed93ac0153..06f3d194e0a8 100644 --- a/drivers/virt/coco/tdx-host/tdx-host.c +++ b/drivers/virt/coco/tdx-host/tdx-host.c @@ -5,11 +5,13 @@ * Copyright (C) 2025 Intel Corporation */ =20 +#include #include #include #include #include #include +#include #include #include =20 @@ -39,6 +41,65 @@ static struct tdx_tsm_link *to_tdx_tsm_link(struct pci_t= sm *tsm) return container_of(tsm, struct tdx_tsm_link, pci.base_tsm); } =20 +#define PCI_DOE_DATA_OBJECT_HEADER_1_OFFSET 0 +#define PCI_DOE_DATA_OBJECT_HEADER_2_OFFSET 4 +#define PCI_DOE_DATA_OBJECT_HEADER_SIZE 8 +#define PCI_DOE_DATA_OBJECT_PAYLOAD_OFFSET PCI_DOE_DATA_OBJECT_HEADER_SIZE + +#define PCI_DOE_PROTOCOL_SECURE_SPDM 2 + +static int __maybe_unused tdx_spdm_msg_exchange(struct tdx_tsm_link *tlink, + void *request, size_t request_sz, + void *response, size_t response_sz) +{ + struct pci_dev *pdev =3D tlink->pci.base_tsm.pdev; + void *req_pl_addr, *resp_pl_addr; + size_t req_pl_sz, resp_pl_sz; + u32 data, len; + u16 vendor; + u8 type; + int ret; + + /* + * pci_doe() accept DOE PAYLOAD only but request carries DOE HEADER so + * shift the buffers, skip DOE HEADER in request buffer, and fill DOE + * HEADER in response buffer manually. + */ + + data =3D le32_to_cpu(*(__le32 *)(request + PCI_DOE_DATA_OBJECT_HEADER_1_O= FFSET)); + vendor =3D FIELD_GET(PCI_DOE_DATA_OBJECT_HEADER_1_VID, data); + type =3D FIELD_GET(PCI_DOE_DATA_OBJECT_HEADER_1_TYPE, data); + + data =3D le32_to_cpu(*(__le32 *)(request + PCI_DOE_DATA_OBJECT_HEADER_2_O= FFSET)); + len =3D FIELD_GET(PCI_DOE_DATA_OBJECT_HEADER_2_LENGTH, data); + + req_pl_sz =3D len * sizeof(__le32) - PCI_DOE_DATA_OBJECT_HEADER_SIZE; + resp_pl_sz =3D response_sz - PCI_DOE_DATA_OBJECT_HEADER_SIZE; + req_pl_addr =3D request + PCI_DOE_DATA_OBJECT_HEADER_SIZE; + resp_pl_addr =3D response + PCI_DOE_DATA_OBJECT_HEADER_SIZE; + + ret =3D pci_tsm_doe_transfer(pdev, type, req_pl_addr, req_pl_sz, + resp_pl_addr, resp_pl_sz); + if (ret < 0) { + pci_err(pdev, "spdm msg exchange fail %d\n", ret); + return ret; + } + + data =3D FIELD_PREP(PCI_DOE_DATA_OBJECT_HEADER_1_VID, vendor) | + FIELD_PREP(PCI_DOE_DATA_OBJECT_HEADER_1_TYPE, type); + *(__le32 *)(response + PCI_DOE_DATA_OBJECT_HEADER_1_OFFSET) =3D cpu_to_le= 32(data); + + len =3D (ret + PCI_DOE_DATA_OBJECT_HEADER_SIZE) / sizeof(__le32); + data =3D FIELD_PREP(PCI_DOE_DATA_OBJECT_HEADER_2_LENGTH, len); + *(__le32 *)(response + PCI_DOE_DATA_OBJECT_HEADER_2_OFFSET) =3D cpu_to_le= 32(data); + + ret +=3D PCI_DOE_DATA_OBJECT_HEADER_SIZE; + + pci_dbg(pdev, "%s complete: vendor 0x%x type 0x%x rsp_sz %d\n", + __func__, vendor, type, ret); + return ret; +} + static int tdx_tsm_link_connect(struct pci_dev *pdev) { return -ENXIO; --=20 2.25.1 From nobody Thu Apr 2 15:41:48 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 44001401A30; Fri, 27 Mar 2026 16:24:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628647; cv=none; b=ssk2EtSQA3Hd7MfRqJlPFDLMhtKocDcIgX4IGfbIpNSU2L95TlW0diuZ+g9OWW57bhUik8lkG/m+AQP+gdTVOS6Jr8C7zWAR6vG6GkXUVD4hjIBYMLU7AVQFdQulm6EUGdpyA3RNnNBijQQuqlrXo3yhSqj7tgNYynvz4JuxAnk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628647; c=relaxed/simple; bh=d5v7kombDkpimMLhqFIFaDnGOds7NdDu5NS7qDGKkQQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=GJb9flL6xva3WJtF1vHe5xRr/NtQ3oCNM0rutGYHS9EIufu6zKgQlkpzOmlRfbAjmnIWolcay4u73xzUCKSSXQGu2fv2nvMs5F2T/2ntcBWVtWMotg6eCAVgh/wg674svs5H/FwcVlrjIFlZJ5/qjhE0izDSzHBfJmkbkT2dprI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=cItCTTno; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="cItCTTno" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628646; x=1806164646; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=d5v7kombDkpimMLhqFIFaDnGOds7NdDu5NS7qDGKkQQ=; b=cItCTTno3cWJQBKSSyco1N9pQ12QOIO6n7k4ZTTZNp8QEvzzXFBv8vbN J4kbhUTBld5M9MWkQr8hD8xWs6k21bxE61YTJGG0k7jKwWntjubXjCcJN If1PT6y18djYE6cb2nFXkxKvc33DM/lLPuVkwO5b7+nfWbLBI9ar0HcEF /cQmSGXeRRjBzv5fybldDQHafntyIfKEmU/n8DeGGWkFsMiQ/rzTzW+W8 9MYxaqeA7F6+BL9MRJKY9FWjAt0eqLYw4yhE/L61YPypKrwk9DndjGV13 lI6yyQD5uULGi0X1bcoay6OV0t7pnCD+QY7aKB9VH1nT5yqLrWyb/kMUG g==; X-CSE-ConnectionGUID: E5CfgM7CQH23y/CaAlNTSA== X-CSE-MsgGUID: loGfHvF6TUyUKha8c4Fk5A== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565666" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565666" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:24:05 -0700 X-CSE-ConnectionGUID: uPp5MI4jQcKo/WTcMstNsw== X-CSE-MsgGUID: fmhf5p5NSIGthkwPzkRFIw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516357" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:24:02 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 25/31] x86/virt/tdx: Add SEAMCALL wrappers for SPDM management Date: Sat, 28 Mar 2026 00:01:26 +0800 Message-Id: <20260327160132.2946114-26-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Zhenzhong Duan Add several SEAMCALL wrappers for SPDM management. TDX Module requires HPA_ARRAY_T structure as input/output parameters for these SEAMCALLs. So use tdx_page_array for these wrappers. - TDH.SPDM.CREATE creates SPDM session metadata buffers for TDX Module. - TDH.SPDM.DELETE destroys SPDM session metadata and returns these buffers to host, after checking no reference attached to the metadata. - TDH.SPDM.CONNECT establishes a new SPDM session with the device. - TDH.SPDM.DISCONNECT tears down the SPDM session with the device. - TDH.SPDM.MNG supports three SPDM runtime operations: HEARTBEAT, KEY_UPDATE and DEV_INFO_RECOLLECTION. Co-developed-by: Xu Yilun Signed-off-by: Xu Yilun Signed-off-by: Zhenzhong Duan --- arch/x86/include/asm/tdx.h | 13 ++++ arch/x86/virt/vmx/tdx/tdx.h | 5 ++ arch/x86/virt/vmx/tdx/tdx.c | 114 +++++++++++++++++++++++++++++++++++- 3 files changed, 130 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index a59e0e43e465..8abdad084972 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -247,6 +247,19 @@ u64 tdh_phymem_page_wbinvd_tdr(struct tdx_td *td); u64 tdh_phymem_page_wbinvd_hkid(u64 hkid, struct page *page); u64 tdh_iommu_setup(u64 vtbar, struct tdx_page_array *iommu_mt, u64 *iommu= _id); u64 tdh_iommu_clear(u64 iommu_id, struct tdx_page_array *iommu_mt); +u64 tdh_spdm_create(u64 func_id, struct tdx_page_array *spdm_mt, u64 *spdm= _id); +u64 tdh_spdm_delete(u64 spdm_id, struct tdx_page_array *spdm_mt, + unsigned int *nr_released, u64 *released_hpa); +u64 tdh_exec_spdm_connect(u64 spdm_id, struct page *spdm_conf, + struct page *spdm_rsp, struct page *spdm_req, + struct tdx_page_array *spdm_out, + u64 *spdm_req_or_out_len); +u64 tdh_exec_spdm_disconnect(u64 spdm_id, struct page *spdm_rsp, + struct page *spdm_req, u64 *spdm_req_len); +u64 tdh_exec_spdm_mng(u64 spdm_id, u64 spdm_op, struct page *spdm_param, + struct page *spdm_rsp, struct page *spdm_req, + struct tdx_page_array *spdm_out, + u64 *spdm_req_or_out_len); #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.h b/arch/x86/virt/vmx/tdx/tdx.h index b25c418f6e61..4784db2d1d92 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -64,6 +64,11 @@ #define TDH_EXT_MEM_ADD 61 #define TDH_IOMMU_SETUP 128 #define TDH_IOMMU_CLEAR 129 +#define TDH_SPDM_CREATE 130 +#define TDH_SPDM_DELETE 131 +#define TDH_SPDM_CONNECT 142 +#define TDH_SPDM_DISCONNECT 143 +#define TDH_SPDM_MNG 144 =20 /* TDX page types */ #define PT_NDA 0x0 diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 790713881f1f..02882c2ad177 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -654,7 +654,7 @@ static u64 hpa_list_info_assign_raw(struct tdx_page_arr= ay *array) #define HPA_ARRAY_T_PFN GENMASK_U64(51, 12) #define HPA_ARRAY_T_SIZE GENMASK_U64(63, 55) =20 -static u64 __maybe_unused hpa_array_t_assign_raw(struct tdx_page_array *ar= ray) +static u64 hpa_array_t_assign_raw(struct tdx_page_array *array) { unsigned long pfn; =20 @@ -667,7 +667,7 @@ static u64 __maybe_unused hpa_array_t_assign_raw(struct= tdx_page_array *array) FIELD_PREP(HPA_ARRAY_T_SIZE, array->nents - 1); } =20 -static u64 __maybe_unused hpa_array_t_release_raw(struct tdx_page_array *a= rray) +static u64 hpa_array_t_release_raw(struct tdx_page_array *array) { if (array->nents =3D=3D 1) return 0; @@ -2107,6 +2107,15 @@ static u64 __seamcall_ir_resched(sc_func_t sc_func, = u64 fn, #define seamcall_ret_ir_resched(fn, args) \ __seamcall_ir_resched(__seamcall_ret, fn, args) =20 +/* + * seamcall_ret_ir_exec() aliases seamcall_ret_ir_resched() for + * documentation purposes. It documents the TDX Module extension + * seamcalls that are long running / hard-irq preemptible flows that + * generate events. The calls using seamcall_ret_ir_resched() are long + * running flows, that periodically yield. + */ +#define seamcall_ret_ir_exec seamcall_ret_ir_resched + noinstr u64 tdh_vp_enter(struct tdx_vp *td, struct tdx_module_args *args) { args->rcx =3D td->tdvpr_pa; @@ -2506,3 +2515,104 @@ u64 tdh_iommu_clear(u64 iommu_id, struct tdx_page_a= rray *iommu_mt) return seamcall_ret_ir_resched(TDH_IOMMU_CLEAR, &args); } EXPORT_SYMBOL_FOR_MODULES(tdh_iommu_clear, "tdx-host"); + +u64 tdh_spdm_create(u64 func_id, struct tdx_page_array *spdm_mt, u64 *spdm= _id) +{ + struct tdx_module_args args =3D { + .rcx =3D func_id, + .rdx =3D hpa_array_t_assign_raw(spdm_mt) + }; + u64 r; + + tdx_clflush_page_array(spdm_mt); + + r =3D seamcall_ret(TDH_SPDM_CREATE, &args); + + *spdm_id =3D args.rcx; + + return r; +} +EXPORT_SYMBOL_FOR_MODULES(tdh_spdm_create, "tdx-host"); + +u64 tdh_spdm_delete(u64 spdm_id, struct tdx_page_array *spdm_mt, + unsigned int *nr_released, u64 *released_hpa) +{ + struct tdx_module_args args =3D { + .rcx =3D spdm_id, + .rdx =3D hpa_array_t_release_raw(spdm_mt), + }; + u64 r; + + r =3D seamcall_ret(TDH_SPDM_DELETE, &args); + if (r !=3D TDX_SUCCESS) + return r; + + *nr_released =3D FIELD_GET(HPA_ARRAY_T_SIZE, args.rcx) + 1; + *released_hpa =3D FIELD_GET(HPA_ARRAY_T_PFN, args.rcx) << PAGE_SHIFT; + + return r; +} +EXPORT_SYMBOL_FOR_MODULES(tdh_spdm_delete, "tdx-host"); + +u64 tdh_exec_spdm_connect(u64 spdm_id, struct page *spdm_conf, + struct page *spdm_rsp, struct page *spdm_req, + struct tdx_page_array *spdm_out, + u64 *spdm_req_or_out_len) +{ + struct tdx_module_args args =3D { + .rcx =3D spdm_id, + .rdx =3D page_to_phys(spdm_conf), + .r8 =3D page_to_phys(spdm_rsp), + .r9 =3D page_to_phys(spdm_req), + .r10 =3D hpa_array_t_assign_raw(spdm_out), + }; + u64 r; + + r =3D seamcall_ret_ir_exec(TDH_SPDM_CONNECT, &args); + + *spdm_req_or_out_len =3D args.rcx; + + return r; +} +EXPORT_SYMBOL_FOR_MODULES(tdh_exec_spdm_connect, "tdx-host"); + +u64 tdh_exec_spdm_disconnect(u64 spdm_id, struct page *spdm_rsp, + struct page *spdm_req, u64 *spdm_req_len) +{ + struct tdx_module_args args =3D { + .rcx =3D spdm_id, + .rdx =3D page_to_phys(spdm_rsp), + .r8 =3D page_to_phys(spdm_req), + }; + u64 r; + + r =3D seamcall_ret_ir_exec(TDH_SPDM_DISCONNECT, &args); + + *spdm_req_len =3D args.rcx; + + return r; +} +EXPORT_SYMBOL_FOR_MODULES(tdh_exec_spdm_disconnect, "tdx-host"); + +u64 tdh_exec_spdm_mng(u64 spdm_id, u64 spdm_op, struct page *spdm_param, + struct page *spdm_rsp, struct page *spdm_req, + struct tdx_page_array *spdm_out, + u64 *spdm_req_or_out_len) +{ + struct tdx_module_args args =3D { + .rcx =3D spdm_id, + .rdx =3D spdm_op, + .r8 =3D spdm_param ? page_to_phys(spdm_param) : -1, + .r9 =3D page_to_phys(spdm_rsp), + .r10 =3D page_to_phys(spdm_req), + .r11 =3D spdm_out ? hpa_array_t_assign_raw(spdm_out) : -1, + }; + u64 r; + + r =3D seamcall_ret_ir_exec(TDH_SPDM_MNG, &args); + + *spdm_req_or_out_len =3D args.rcx; + + return r; +} +EXPORT_SYMBOL_FOR_MODULES(tdh_exec_spdm_mng, "tdx-host"); --=20 2.25.1 From nobody Thu Apr 2 15:41:48 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 C6746402B8E; Fri, 27 Mar 2026 16:24:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628650; cv=none; b=XxuMztE977utoXO8SMVYGETfkzDkEsIb48HXUjV1xjbpcSkrmGDtyk3bV7cdR9X22IxqKKkBOCnIRmRcDsJr+aJ4vsOnOAPOx9goGD0hL7x7mqpiVQzo4542L+o8d+nzPvuwxoR7mYpRAhLfW2L9l768HpR1b9nNJ+83K7HhWIo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628650; c=relaxed/simple; bh=8E2PLd8Xi1KBtL2Kxec5V5ZmUSQnGJ77ky0/+RmRlqo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=l3R4vTjeayZdS5bDsmBRQho45Ngok61Qk4/V/5TgD9NDd/ST8WijRb3JFPYqofCEVUfyrK0EsqxHtzioStMp5r3dzqdPrZqS1Yf1l5xy40zQZZWSBqIdHAcMRU+xHOD8WgrfnJY/FFtwTbfNFzH/gaG+UyN8vQPnbq+xLAV2jbo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=PmDk0dLx; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="PmDk0dLx" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628649; x=1806164649; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=8E2PLd8Xi1KBtL2Kxec5V5ZmUSQnGJ77ky0/+RmRlqo=; b=PmDk0dLxtx3OtJzIU9LzR+iZlfFFogJAJ3rZcV6OU4HToL8AVxJDS9Ye F4ONWE+oYKE0r2UMvIzBUo4Owkoj+fN0BLI8WHhI3F4vk9+yJSss6Nbuz WJ4vYs1/5MaZpQm/rQaWnzmSVUZ3cyf/jRQTrkYKpFCOs4LXoizIXjaGT 4Ii9d/mKhO/NO8DlUfyBIwtQAyepIh/he+qBu7oF0izGzKP+DfzDM6SQJ asgCb3vv9uLnKg8f3qCBYKbo3WPvEBZvOL0DKE1KwvfE16yMZnUVOhxfU jHJ4Fqtw+plxtL7EDarJUQxNLgN6IWUlYA0niuDwXEMKEqZpkCtb6tQTA Q==; X-CSE-ConnectionGUID: cGuIfJfzSsKoq0zlWdSO1Q== X-CSE-MsgGUID: y2EJi8zETKaJUyYhyXlK/w== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565672" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565672" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:24:09 -0700 X-CSE-ConnectionGUID: INInqSmmT5GX8l6IsBXsZw== X-CSE-MsgGUID: MDEUJzpURl2LxhyA9Xh66w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516363" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:24:06 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 26/31] mm: Add __free() support for __free_page() Date: Sat, 28 Mar 2026 00:01:27 +0800 Message-Id: <20260327160132.2946114-27-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Allow for the declaration of struct page * variables that trigger __free_page() when they go out of scope. A example usage would be in the following patch: static struct pci_tsm *tdx_tsm_link_pf0_probe(...) { ... struct page *in_msg_page __free(__free_page) =3D alloc_page(GFP_KERNEL | __GFP_ZERO); if (!in_msg_page) return NULL; struct page *out_msg_page __free(__free_page) =3D alloc_page(GFP_KERNEL | __GFP_ZERO); if (!out_msg_page) return NULL; ... tlink->in_msg =3D no_free_ptr(in_msg_page); tlink->out_msg =3D no_free_ptr(out_msg_page); ... } Signed-off-by: Xu Yilun Reviewed-by: Jonathan Cameron --- include/linux/gfp.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 51ef13ed756e..d37e5564234e 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -391,6 +391,7 @@ extern void free_pages_nolock(struct page *page, unsign= ed int order); extern void free_pages(unsigned long addr, unsigned int order); =20 #define __free_page(page) __free_pages((page), 0) +DEFINE_FREE(__free_page, struct page *, if (_T) __free_page(_T)) #define free_page(addr) free_pages((addr), 0) =20 void page_alloc_init_cpuhp(void); --=20 2.25.1 From nobody Thu Apr 2 15:41:48 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 838E2405ABE; Fri, 27 Mar 2026 16:24:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628655; cv=none; b=ukJZE3i8JTuDt0oKSsS4RgS2QgWxP7+ukpHBtXfvgPWDXXUjYZxoDD9hbAjjs/k/F2zmP4T3z+3kVgNl81pnPq4hQ6+G/VF7ktdg1Bl5X8uJ8a4wh/Kl8cGga2RSRQKj3r+whEw1h3YS6w8HHxDkse4aaElgbEhoY7wmDARVnjc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628655; c=relaxed/simple; bh=n7uly1FuTt8IxbLUfNOG+D/wp07voqj2pWsdTiSpJ38=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=vGvW6Opv2tSMN35PZRAi+up6U0640X0PcakMh53L4ZtG/Sl0lgnHpo8ESwaHg0M9YYTb/7LTLizxLIraKbFANVTuUYWu+afjvnN48T0T3WLXziTkHV5FAeGb+Ds6n4dzRPkJSr1ReuXkkrxqt9deDoI4MjF4AWxt/AFwof8yOps= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Cqt+bNOT; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Cqt+bNOT" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628653; x=1806164653; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=n7uly1FuTt8IxbLUfNOG+D/wp07voqj2pWsdTiSpJ38=; b=Cqt+bNOTRnnd9Tmk6I4IHxc35+37bRkkCWR+qHzOYRan/KR1w7l01Y2m QYJ28Vn0xQ3iBZq57MOGAZn1EwYrIYPcvbYVRc/fkKLhKEUAyleECqN1F HOQhwa43wrPtugV0OE+SMWySgL2sgGH+edz7I80bi5gmB0I7O7CxXDF8U 0oSHBhxTbKTowLxS1Ahems2rce0fIID5R9TAivjNnbwIgKJKv1yS5Ik+W +NtFC6bZr80jjjlm6ZlBdmH9HK+XXlGe6HD38WG0zlgCzwsB3MMJSB3su HOA4BPG8qXctniHEQAwO1s1AqjejiYDawNjeePUPnyk+4889bgHwAXkK8 A==; X-CSE-ConnectionGUID: rBlps5x2RVSQHXnMs+FDhw== X-CSE-MsgGUID: m653rxfnQrClpkfIVIHPzg== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565678" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565678" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:24:12 -0700 X-CSE-ConnectionGUID: JhFbTS2tRxmk9oNzW6AjMw== X-CSE-MsgGUID: NooGNMkyRXiFbdm7LziO3w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516373" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:24:09 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 27/31] coco/tdx-host: Implement SPDM session setup Date: Sat, 28 Mar 2026 00:01:28 +0800 Message-Id: <20260327160132.2946114-28-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Zhenzhong Duan Implementation for a most straightforward SPDM session setup, using all default session options. Retrieve device info data from TDX Module which contains the SPDM negotiation results. TDH.SPDM.CONNECT/DISCONNECT are TDX Module Extension introduced SEAMCALLs which can run for longer periods and interruptible. But there is resource constraints that limit how many SEAMCALLs of this kind can run simultaneously. The current situation is One SEAMCALL at a time. Otherwise TDX_OPERAND_BUSY is returned. To avoid "broken indefinite" retry, a tdx_ext_lock is used to guard these SEAMCALLs. Co-developed-by: Xu Yilun Signed-off-by: Xu Yilun Signed-off-by: Zhenzhong Duan --- arch/x86/include/asm/shared/tdx_errno.h | 2 + drivers/virt/coco/tdx-host/tdx-host.c | 301 +++++++++++++++++++++++- 2 files changed, 299 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/shared/tdx_errno.h b/arch/x86/include/asm= /shared/tdx_errno.h index 8bf6765cf082..7db04fe30378 100644 --- a/arch/x86/include/asm/shared/tdx_errno.h +++ b/arch/x86/include/asm/shared/tdx_errno.h @@ -29,6 +29,8 @@ #define TDX_EPT_WALK_FAILED 0xC0000B0000000000ULL #define TDX_EPT_ENTRY_STATE_INCORRECT 0xC0000B0D00000000ULL #define TDX_METADATA_FIELD_NOT_READABLE 0xC0000C0200000000ULL +#define TDX_SPDM_SESSION_KEY_REQUIRE_REFRESH 0xC0000F4500000000ULL +#define TDX_SPDM_REQUEST 0xC0000F5700000000ULL =20 /* * SW-defined error codes. diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-= host/tdx-host.c index 06f3d194e0a8..4d127b7c2591 100644 --- a/drivers/virt/coco/tdx-host/tdx-host.c +++ b/drivers/virt/coco/tdx-host/tdx-host.c @@ -14,6 +14,7 @@ #include #include #include +#include =20 #include #include @@ -32,8 +33,43 @@ MODULE_DEVICE_TABLE(x86cpu, tdx_host_ids); */ static const struct tdx_sys_info *tdx_sysinfo; =20 +#define TDISP_FUNC_ID GENMASK(15, 0) +#define TDISP_FUNC_ID_SEGMENT GENMASK(23, 16) +#define TDISP_FUNC_ID_SEG_VALID BIT(24) + +static inline u32 tdisp_func_id(struct pci_dev *pdev) +{ + u32 func_id; + + func_id =3D FIELD_PREP(TDISP_FUNC_ID_SEGMENT, pci_domain_nr(pdev->bus)); + if (func_id) + func_id |=3D TDISP_FUNC_ID_SEG_VALID; + func_id |=3D FIELD_PREP(TDISP_FUNC_ID, + PCI_DEVID(pdev->bus->number, pdev->devfn)); + + return func_id; +} + +struct spdm_config_info_t { + u32 vmm_spdm_cap; +#define SPDM_CAP_HBEAT BIT(13) +#define SPDM_CAP_KEY_UPD BIT(14) + u8 spdm_session_policy; + u8 certificate_slot_mask; + u8 raw_bitstream_requested; +} __packed; + struct tdx_tsm_link { struct pci_tsm_pf0 pci; + u32 func_id; + struct page *in_msg; + struct page *out_msg; + + u64 spdm_id; + struct page *spdm_conf; + struct tdx_page_array *spdm_mt; + unsigned int dev_info_size; + void *dev_info_data; }; =20 static struct tdx_tsm_link *to_tdx_tsm_link(struct pci_tsm *tsm) @@ -48,9 +84,9 @@ static struct tdx_tsm_link *to_tdx_tsm_link(struct pci_ts= m *tsm) =20 #define PCI_DOE_PROTOCOL_SECURE_SPDM 2 =20 -static int __maybe_unused tdx_spdm_msg_exchange(struct tdx_tsm_link *tlink, - void *request, size_t request_sz, - void *response, size_t response_sz) +static int tdx_spdm_msg_exchange(struct tdx_tsm_link *tlink, + void *request, size_t request_sz, + void *response, size_t response_sz) { struct pci_dev *pdev =3D tlink->pci.base_tsm.pdev; void *req_pl_addr, *resp_pl_addr; @@ -100,18 +136,246 @@ static int __maybe_unused tdx_spdm_msg_exchange(stru= ct tdx_tsm_link *tlink, return ret; } =20 +static int tdx_spdm_session_keyupdate(struct tdx_tsm_link *tlink); + +static int tdx_tsm_link_event_handler(struct tdx_tsm_link *tlink, + u64 tdx_ret, u64 out_msg_sz) +{ + int ret; + + if (tdx_ret =3D=3D TDX_SUCCESS) + return 0; + + if (tdx_ret =3D=3D TDX_SPDM_REQUEST) { + ret =3D tdx_spdm_msg_exchange(tlink, + page_address(tlink->out_msg), + out_msg_sz, + page_address(tlink->in_msg), + PAGE_SIZE); + if (ret < 0) + return ret; + + return -EAGAIN; + } + + if (tdx_ret =3D=3D TDX_SPDM_SESSION_KEY_REQUIRE_REFRESH) { + /* keyupdate won't trigger this error again, no recursion risk */ + ret =3D tdx_spdm_session_keyupdate(tlink); + if (ret) + return ret; + + return -EAGAIN; + } + + return -EFAULT; +} + +/* + * TDX Module extension introduced SEAMCALLs work like a request queue. + * The caller is responsible for grabbing a queue slot before SEAMCALL, + * otherwise will fail with TDX_OPERAND_BUSY. Currently the queue depth is= 1. + * So a mutex could work for simplicity. + */ +static DEFINE_MUTEX(tdx_ext_lock); + +enum tdx_spdm_mng_op { + TDX_SPDM_MNG_HEARTBEAT =3D 0, + TDX_SPDM_MNG_KEY_UPDATE =3D 1, + TDX_SPDM_MNG_RECOLLECT =3D 2, +}; + +static int tdx_spdm_session_mng(struct tdx_tsm_link *tlink, + enum tdx_spdm_mng_op op) +{ + u64 r, out_msg_sz; + int ret; + + guard(mutex)(&tdx_ext_lock); + do { + r =3D tdh_exec_spdm_mng(tlink->spdm_id, op, NULL, tlink->in_msg, + tlink->out_msg, NULL, &out_msg_sz); + ret =3D tdx_tsm_link_event_handler(tlink, r, out_msg_sz); + } while (ret =3D=3D -EAGAIN); + + return ret; +} + +static int tdx_spdm_session_keyupdate(struct tdx_tsm_link *tlink) +{ + return tdx_spdm_session_mng(tlink, TDX_SPDM_MNG_KEY_UPDATE); +} + +static void *tdx_dup_array_data(struct tdx_page_array *array, + unsigned int data_size) +{ + unsigned int npages =3D (data_size + PAGE_SIZE - 1) / PAGE_SIZE; + void *data, *dup_data; + + if (npages > array->nr_pages) + return NULL; + + data =3D vm_map_ram(array->pages, npages, -1); + if (!data) + return NULL; + + dup_data =3D kmemdup(data, data_size, GFP_KERNEL); + vm_unmap_ram(data, npages); + + return dup_data; +} + +static struct tdx_tsm_link * +tdx_spdm_session_connect(struct tdx_tsm_link *tlink, + struct tdx_page_array *dev_info) +{ + u64 r, out_msg_sz; + int ret; + + guard(mutex)(&tdx_ext_lock); + do { + r =3D tdh_exec_spdm_connect(tlink->spdm_id, tlink->spdm_conf, + tlink->in_msg, tlink->out_msg, + dev_info, &out_msg_sz); + ret =3D tdx_tsm_link_event_handler(tlink, r, out_msg_sz); + } while (ret =3D=3D -EAGAIN); + + if (ret) + return ERR_PTR(ret); + + tlink->dev_info_size =3D out_msg_sz; + return tlink; +} + +static void tdx_spdm_session_disconnect(struct tdx_tsm_link *tlink) +{ + u64 r, out_msg_sz; + int ret; + + guard(mutex)(&tdx_ext_lock); + do { + r =3D tdh_exec_spdm_disconnect(tlink->spdm_id, tlink->in_msg, + tlink->out_msg, &out_msg_sz); + ret =3D tdx_tsm_link_event_handler(tlink, r, out_msg_sz); + } while (ret =3D=3D -EAGAIN); + + WARN_ON(ret); +} + +DEFINE_FREE(tdx_spdm_session_disconnect, struct tdx_tsm_link *, + if (!IS_ERR_OR_NULL(_T)) tdx_spdm_session_disconnect(_T)) + +static struct tdx_tsm_link *tdx_spdm_create(struct tdx_tsm_link *tlink) +{ + unsigned int nr_pages =3D tdx_sysinfo->connect.spdm_mt_page_count; + u64 spdm_id, r; + + struct tdx_page_array *spdm_mt __free(tdx_page_array_free) =3D + tdx_page_array_create(nr_pages); + if (!spdm_mt) + return ERR_PTR(-ENOMEM); + + r =3D tdh_spdm_create(tlink->func_id, spdm_mt, &spdm_id); + if (r) + return ERR_PTR(-EFAULT); + + tlink->spdm_id =3D spdm_id; + tlink->spdm_mt =3D no_free_ptr(spdm_mt); + return tlink; +} + +static void tdx_spdm_delete(struct tdx_tsm_link *tlink) +{ + struct pci_dev *pdev =3D tlink->pci.base_tsm.pdev; + unsigned int nr_released; + u64 released_hpa, r; + + r =3D tdh_spdm_delete(tlink->spdm_id, tlink->spdm_mt, &nr_released, &rele= ased_hpa); + if (r) { + pci_err(pdev, "fail to delete spdm 0x%llx\n", r); + goto leak; + } + + if (tdx_page_array_ctrl_release(tlink->spdm_mt, nr_released, released_hpa= )) { + pci_err(pdev, "fail to release spdm_mt pages\n"); + goto leak; + } + + return; + +leak: + tdx_page_array_ctrl_leak(tlink->spdm_mt); +} + +DEFINE_FREE(tdx_spdm_delete, struct tdx_tsm_link *, if (!IS_ERR_OR_NULL(_T= )) tdx_spdm_delete(_T)) + +static struct tdx_tsm_link *tdx_spdm_session_setup(struct tdx_tsm_link *tl= ink) +{ + unsigned int nr_pages =3D tdx_sysinfo->connect.spdm_max_dev_info_pages; + + struct tdx_tsm_link *tlink_create __free(tdx_spdm_delete) =3D + tdx_spdm_create(tlink); + if (IS_ERR(tlink_create)) + return tlink_create; + + struct tdx_page_array *dev_info __free(tdx_page_array_free) =3D + tdx_page_array_create(nr_pages); + if (!dev_info) + return ERR_PTR(-ENOMEM); + + struct tdx_tsm_link *tlink_connect __free(tdx_spdm_session_disconnect) = =3D + tdx_spdm_session_connect(tlink, dev_info); + if (IS_ERR(tlink_connect)) + return tlink_connect; + + tlink->dev_info_data =3D tdx_dup_array_data(dev_info, + tlink->dev_info_size); + if (!tlink->dev_info_data) + return ERR_PTR(-ENOMEM); + + retain_and_null_ptr(tlink_create); + retain_and_null_ptr(tlink_connect); + + return tlink; +} + +static void tdx_spdm_session_teardown(struct tdx_tsm_link *tlink) +{ + kfree(tlink->dev_info_data); + + tdx_spdm_session_disconnect(tlink); + tdx_spdm_delete(tlink); +} + +DEFINE_FREE(tdx_spdm_session_teardown, struct tdx_tsm_link *, + if (!IS_ERR_OR_NULL(_T)) tdx_spdm_session_teardown(_T)) + static int tdx_tsm_link_connect(struct pci_dev *pdev) { - return -ENXIO; + struct tdx_tsm_link *tlink =3D to_tdx_tsm_link(pdev->tsm); + + struct tdx_tsm_link *tlink_spdm __free(tdx_spdm_session_teardown) =3D + tdx_spdm_session_setup(tlink); + if (IS_ERR(tlink_spdm)) { + pci_err(pdev, "fail to setup spdm session\n"); + return PTR_ERR(tlink_spdm); + } + + retain_and_null_ptr(tlink_spdm); + + return 0; } =20 static void tdx_tsm_link_disconnect(struct pci_dev *pdev) { + struct tdx_tsm_link *tlink =3D to_tdx_tsm_link(pdev->tsm); + + tdx_spdm_session_teardown(tlink); } =20 static struct pci_tsm *tdx_tsm_link_pf0_probe(struct tsm_dev *tsm_dev, struct pci_dev *pdev) { + struct spdm_config_info_t *spdm_conf; int rc; =20 struct tdx_tsm_link *tlink __free(kfree) =3D kzalloc_obj(*tlink); @@ -122,6 +386,32 @@ static struct pci_tsm *tdx_tsm_link_pf0_probe(struct t= sm_dev *tsm_dev, if (rc) return NULL; =20 + tlink->func_id =3D tdisp_func_id(pdev); + + struct page *in_msg_page __free(__free_page) =3D + alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!in_msg_page) + return NULL; + + struct page *out_msg_page __free(__free_page) =3D + alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!out_msg_page) + return NULL; + + struct page *spdm_conf_page __free(kfree) =3D + alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!spdm_conf_page) + return NULL; + + /* use a default configuration, may require user input later */ + spdm_conf =3D page_address(spdm_conf_page); + spdm_conf->vmm_spdm_cap =3D SPDM_CAP_KEY_UPD; + spdm_conf->certificate_slot_mask =3D 0xff; + + tlink->in_msg =3D no_free_ptr(in_msg_page); + tlink->out_msg =3D no_free_ptr(out_msg_page); + tlink->spdm_conf =3D no_free_ptr(spdm_conf_page); + return &no_free_ptr(tlink)->pci.base_tsm; } =20 @@ -129,6 +419,9 @@ static void tdx_tsm_link_pf0_remove(struct pci_tsm *tsm) { struct tdx_tsm_link *tlink =3D to_tdx_tsm_link(tsm); =20 + __free_page(tlink->spdm_conf); + __free_page(tlink->out_msg); + __free_page(tlink->in_msg); pci_tsm_pf0_destructor(&tlink->pci); kfree(tlink); } --=20 2.25.1 From nobody Thu Apr 2 15:41:48 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 06D9C405ACD; Fri, 27 Mar 2026 16:24:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628658; cv=none; b=aUs1fv+VvAHi1gq/y1Y1ITfyppRMdJShGE1xfDctYFHlcaHGfvIzLPZ5M9qBOPh7t0IGtN5HnejQtJlk40MCb4bj0TBTN0jppa/pU55DhiIpZfkc+vgW4je2Yb/JwqR2YtK2ogSXE0fTH2SIHjcnbtlToV72I2QOKLIoefIh1J0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628658; c=relaxed/simple; bh=qUyRwAaoP/Pd1LzP3/qJcfABY/rt+g58V38MuLi8Pu0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=YCo+ezs9wPNERTNvYRZb2CRBPrYtcZ87oUXcI3NokQopUmTcjfDjdnwh1MzcTDDmueDYKRMdHQanCy0UyYge6hAV5DYtrhq+EI/SDgXacpZ3z93F8i2XhnXIJ/6XO6FUX+DuMmCPtjsY4MkzJvFzIpK4+BNQiWfqeR5jQ5efWVM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=QmjYwiPm; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="QmjYwiPm" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628656; x=1806164656; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=qUyRwAaoP/Pd1LzP3/qJcfABY/rt+g58V38MuLi8Pu0=; b=QmjYwiPmNqOpsK9SuY9qoz0h+iUfbrRy8OdY+os4QYIO8G1vUSKTTfvy dBjc1ctxJITgZGM1Pnb894c0qFtF9MWbDU3/J9j6tRbjC4cqQ/V1B9R3Z KO9dFAtUGKZ/uJs6YbfWpkO6xWxtucOfTCQFXyF4AFxc/S9fIn7GUS5aW ZxpxbyTcNJeGrNOr1PPItRrSJ/5jpTYawMMpfrpDc5tRZytHDSGUbZPU5 3jY4RVsZCNf+GrjYS7h5tmhDRElgpRGJavMMHwVpU4nWlwq76za9RdosL iKwMsaH0o6CmbhkNBsbdNl837+CEz87OkXar7Cgf1VdQxwfS58/MiClOe w==; X-CSE-ConnectionGUID: nnoW+v+qTiGShy/FICJgiQ== X-CSE-MsgGUID: FqEbF/gzTEuefFJnQXHq9w== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565686" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565686" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:24:16 -0700 X-CSE-ConnectionGUID: z4SQgsAsS+SrUSoIgdBDMg== X-CSE-MsgGUID: MoAPMc/wRW+/IysahX6pRQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516380" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:24:13 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 28/31] coco/tdx-host: Parse ACPI KEYP table to init IDE for PCI host bridges Date: Sat, 28 Mar 2026 00:01:29 +0800 Message-Id: <20260327160132.2946114-29-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Parse the KEYP Key Configuration Units (KCU), to decide the max IDE streams supported for each host bridge. The KEYP table points to a number of KCU structures that each associates with a list of root ports (RP) via segment, bus, and devfn. Sanity check the KEYP table, ensure all RPs listed for each KCU are included in one host bridge. Then extact the max IDE streams supported to pci_host_bridge via pci_ide_set_nr_streams(). Co-developed-by: Dave Jiang Signed-off-by: Dave Jiang Reviewed-by: Jonathan Cameron Signed-off-by: Xu Yilun --- drivers/virt/coco/tdx-host/tdx-host.c | 111 ++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-= host/tdx-host.c index 4d127b7c2591..d5072a68b81a 100644 --- a/drivers/virt/coco/tdx-host/tdx-host.c +++ b/drivers/virt/coco/tdx-host/tdx-host.c @@ -5,6 +5,7 @@ * Copyright (C) 2025 Intel Corporation */ =20 +#include #include #include #include @@ -12,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -474,6 +476,111 @@ static void unregister_link_tsm(void *link) tsm_unregister(link); } =20 +#define KCU_STR_CAP_NUM_STREAMS GENMASK(8, 0) + +/* The bus_end is inclusive */ +struct keyp_hb_info { + /* input */ + u16 segment; + u8 bus_start; + u8 bus_end; + /* output */ + u8 nr_ide_streams; +}; + +static bool keyp_info_match(struct acpi_keyp_rp_info *rp, + struct keyp_hb_info *hb) +{ + return rp->segment =3D=3D hb->segment && rp->bus >=3D hb->bus_start && + rp->bus <=3D hb->bus_end; +} + +static int keyp_config_unit_handler(union acpi_subtable_headers *header, + void *arg, const unsigned long end) +{ + struct acpi_keyp_config_unit *acpi_cu =3D + (struct acpi_keyp_config_unit *)&header->keyp; + struct keyp_hb_info *hb_info =3D arg; + int rp_size, rp_count, i; + void __iomem *addr; + bool match =3D false; + u32 cap; + + rp_size =3D acpi_cu->header.length - sizeof(*acpi_cu); + if (rp_size % sizeof(struct acpi_keyp_rp_info)) + return -EINVAL; + + rp_count =3D rp_size / sizeof(struct acpi_keyp_rp_info); + if (!rp_count || rp_count !=3D acpi_cu->root_port_count) + return -EINVAL; + + for (i =3D 0; i < rp_count; i++) { + struct acpi_keyp_rp_info *rp_info =3D &acpi_cu->rp_info[i]; + + if (i =3D=3D 0) { + match =3D keyp_info_match(rp_info, hb_info); + /* The host bridge already matches another KCU */ + if (match && hb_info->nr_ide_streams) + return -EINVAL; + + continue; + } + + if (match ^ keyp_info_match(rp_info, hb_info)) + return -EINVAL; + } + + if (!match) + return 0; + + addr =3D ioremap(acpi_cu->register_base_address, sizeof(cap)); + if (!addr) + return -ENOMEM; + cap =3D ioread32(addr); + iounmap(addr); + + hb_info->nr_ide_streams =3D FIELD_GET(KCU_STR_CAP_NUM_STREAMS, cap) + 1; + + return 0; +} + +static u8 keyp_find_nr_ide_stream(u16 segment, u8 bus_start, u8 bus_end) +{ + struct keyp_hb_info hb_info =3D { + .segment =3D segment, + .bus_start =3D bus_start, + .bus_end =3D bus_end, + }; + int rc; + + rc =3D acpi_table_parse_keyp(ACPI_KEYP_TYPE_CONFIG_UNIT, + keyp_config_unit_handler, &hb_info); + if (rc < 0) + return 0; + + return hb_info.nr_ide_streams; +} + +static void keyp_setup_nr_ide_stream(struct pci_bus *bus) +{ + struct pci_host_bridge *hb =3D pci_find_host_bridge(bus); + u8 nr_ide_streams; + + nr_ide_streams =3D keyp_find_nr_ide_stream(pci_domain_nr(bus), + bus->busn_res.start, + bus->busn_res.end); + + pci_ide_set_nr_streams(hb, nr_ide_streams); +} + +static void tdx_setup_nr_ide_stream(void) +{ + struct pci_bus *bus =3D NULL; + + while ((bus =3D pci_find_next_bus(bus))) + keyp_setup_nr_ide_stream(bus); +} + static DEFINE_XARRAY(tlink_iommu_xa); =20 static void tdx_iommu_clear(u64 iommu_id, struct tdx_page_array *iommu_mt) @@ -569,6 +676,8 @@ static int __maybe_unused tdx_connect_init(struct devic= e *dev) if (ret) return ret; =20 + tdx_setup_nr_ide_stream(); + link =3D tsm_register(dev, &tdx_tsm_link_ops); if (IS_ERR(link)) return dev_err_probe(dev, PTR_ERR(link), @@ -612,5 +721,7 @@ static void __exit tdx_host_exit(void) } module_exit(tdx_host_exit); =20 +MODULE_IMPORT_NS("ACPI"); +MODULE_IMPORT_NS("PCI_IDE"); MODULE_DESCRIPTION("TDX Host Services"); MODULE_LICENSE("GPL"); --=20 2.25.1 From nobody Thu Apr 2 15:41:48 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 9FD38407119; Fri, 27 Mar 2026 16:24:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628661; cv=none; b=WUP85A4T86XMcOpcqPQXGY1WKsdpj/tF+s97+0DUbk8z5tQ+XjVCtc+PfgrFOJfgCiJM9bEk5Ze3Vzbt/h/dWZobyuEbMexWw0a72cfrWn4JyJ68YkHjnD5OtqqlpBbLIQg6z27t9HF29fD9UJmpBG/mMX1ERfKgpuZ8rLpRBG8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628661; c=relaxed/simple; bh=nSxKB/mCLDrbbeTMk6Of7USqSp6UAUKOXUxNYtSimUQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=pFiIsFFy9XujFqePIS6S3KRIGzxj9MQtOTfzc0YXmgYkaDKOpooWHOF42H7aeAC1RBObfGhvYV95oHiO4Uq5hwto+HxXpJM9LhVVEv3sFXlnqcYpJd/UFLC06SxqEHyB2mhaxFQW8uN2qKqjUthwFLaG7Vk9BTJBOtbe1ZaC5Wc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=hX20DsvX; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="hX20DsvX" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628660; x=1806164660; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=nSxKB/mCLDrbbeTMk6Of7USqSp6UAUKOXUxNYtSimUQ=; b=hX20DsvXtg2K6hBpLW1DXk70+tsRyVtYqQ9iiXY3YiJpGuAfyoWDSbiW I1FLXp0S3kBX/p1BnxwQBXufMb0ZKw3aTNQqhKEAFPXO6Vm977+jDeiak KLAgC2cwxaxVPJqweC7rgyHXiCNBhetUc9Sqwf9PGwjMRa6eDLhGaF8cp yVGaV88wgsatkUhxMrUK8g+e3SnqwV8otVy1aZCNpivfHxGlEU+bnjmcD 0mVarUilpLycDWWn+Z++9Zi8toMah9jlinQwwVgM5tNmh9NfxUkqOPdPt YZINLC2S9sIhu1mWrNRioPr8LmQhfOiT+vNIPAyJWhyBL+YB8GZZViyYI w==; X-CSE-ConnectionGUID: v9rN96s/QpSSZ28j8HXjqA== X-CSE-MsgGUID: 7ZwL2awETuWGPJVtDOge0A== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565694" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565694" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:24:20 -0700 X-CSE-ConnectionGUID: OhsKLpSLSxWe+zwCDUuyEw== X-CSE-MsgGUID: NioMDJNJR9Gj9xcXUa9o/A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516389" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:24:17 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 29/31] x86/virt/tdx: Add SEAMCALL wrappers for IDE stream management Date: Sat, 28 Mar 2026 00:01:30 +0800 Message-Id: <20260327160132.2946114-30-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add several SEAMCALL wrappers for IDE stream management. - TDH.IDE.STREAM.CREATE creates IDE stream metadata buffers for TDX Module, and does root port side IDE configuration. - TDH.IDE.STREAM.BLOCK clears the root port side IDE configuration. - TDH.IDE.STREAM.DELETE releases the IDE stream metadata buffers. - TDH.IDE.STREAM.KM deals with the IDE Key Management protocol (IDE-KM) More information see Intel TDX Connect ABI Specification [1] Section 3.2 TDX Connect Host-Side (SEAMCALL) Interface Functions. [1]: https://cdrdv2.intel.com/v1/dl/getContent/858625 Signed-off-by: Xu Yilun --- arch/x86/include/asm/tdx.h | 14 ++++++ arch/x86/virt/vmx/tdx/tdx.h | 4 ++ arch/x86/virt/vmx/tdx/tdx.c | 86 +++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 8abdad084972..7bdd66acda5b 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -260,6 +260,20 @@ u64 tdh_exec_spdm_mng(u64 spdm_id, u64 spdm_op, struct= page *spdm_param, struct page *spdm_rsp, struct page *spdm_req, struct tdx_page_array *spdm_out, u64 *spdm_req_or_out_len); +u64 tdh_ide_stream_create(u64 stream_info, u64 spdm_id, + struct tdx_page_array *stream_mt, u64 stream_ctrl, + u64 rid_assoc1, u64 rid_assoc2, + u64 addr_assoc1, u64 addr_assoc2, + u64 addr_assoc3, + u64 *stream_id, + u64 *rp_ide_id); +u64 tdh_ide_stream_block(u64 spdm_id, u64 stream_id); +u64 tdh_ide_stream_delete(u64 spdm_id, u64 stream_id, + struct tdx_page_array *stream_mt, + unsigned int *nr_released, u64 *released_hpa); +u64 tdh_ide_stream_km(u64 spdm_id, u64 stream_id, u64 operation, + struct page *spdm_rsp, struct page *spdm_req, + u64 *spdm_req_len); #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.h b/arch/x86/virt/vmx/tdx/tdx.h index 4784db2d1d92..d0a9694432de 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -66,6 +66,10 @@ #define TDH_IOMMU_CLEAR 129 #define TDH_SPDM_CREATE 130 #define TDH_SPDM_DELETE 131 +#define TDH_IDE_STREAM_CREATE 132 +#define TDH_IDE_STREAM_BLOCK 133 +#define TDH_IDE_STREAM_DELETE 134 +#define TDH_IDE_STREAM_KM 135 #define TDH_SPDM_CONNECT 142 #define TDH_SPDM_DISCONNECT 143 #define TDH_SPDM_MNG 144 diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 02882c2ad177..72d836b25bd6 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -2616,3 +2616,89 @@ u64 tdh_exec_spdm_mng(u64 spdm_id, u64 spdm_op, stru= ct page *spdm_param, return r; } EXPORT_SYMBOL_FOR_MODULES(tdh_exec_spdm_mng, "tdx-host"); + +u64 tdh_ide_stream_create(u64 stream_info, u64 spdm_id, + struct tdx_page_array *stream_mt, u64 stream_ctrl, + u64 rid_assoc1, u64 rid_assoc2, + u64 addr_assoc1, u64 addr_assoc2, + u64 addr_assoc3, + u64 *stream_id, + u64 *rp_ide_id) +{ + struct tdx_module_args args =3D { + .rcx =3D stream_info, + .rdx =3D spdm_id, + .r8 =3D hpa_array_t_assign_raw(stream_mt), + .r9 =3D stream_ctrl, + .r10 =3D rid_assoc1, + .r11 =3D rid_assoc2, + .r12 =3D addr_assoc1, + .r13 =3D addr_assoc2, + .r14 =3D addr_assoc3, + }; + u64 r; + + tdx_clflush_page_array(stream_mt); + + r =3D seamcall_saved_ret(TDH_IDE_STREAM_CREATE, &args); + + *stream_id =3D args.rcx; + *rp_ide_id =3D args.rdx; + + return r; +} +EXPORT_SYMBOL_FOR_MODULES(tdh_ide_stream_create, "tdx-host"); + +u64 tdh_ide_stream_block(u64 spdm_id, u64 stream_id) +{ + struct tdx_module_args args =3D { + .rcx =3D spdm_id, + .rdx =3D stream_id, + }; + + return seamcall(TDH_IDE_STREAM_BLOCK, &args); +} +EXPORT_SYMBOL_FOR_MODULES(tdh_ide_stream_block, "tdx-host"); + +u64 tdh_ide_stream_delete(u64 spdm_id, u64 stream_id, + struct tdx_page_array *stream_mt, + unsigned int *nr_released, u64 *released_hpa) +{ + struct tdx_module_args args =3D { + .rcx =3D spdm_id, + .rdx =3D stream_id, + .r8 =3D hpa_array_t_release_raw(stream_mt), + }; + u64 r; + + r =3D seamcall_ret(TDH_IDE_STREAM_DELETE, &args); + if (r !=3D TDX_SUCCESS) + return r; + + *nr_released =3D FIELD_GET(HPA_ARRAY_T_SIZE, args.rcx) + 1; + *released_hpa =3D FIELD_GET(HPA_ARRAY_T_PFN, args.rcx) << PAGE_SHIFT; + + return r; +} +EXPORT_SYMBOL_FOR_MODULES(tdh_ide_stream_delete, "tdx-host"); + +u64 tdh_ide_stream_km(u64 spdm_id, u64 stream_id, u64 operation, + struct page *spdm_rsp, struct page *spdm_req, + u64 *spdm_req_len) +{ + struct tdx_module_args args =3D { + .rcx =3D spdm_id, + .rdx =3D stream_id, + .r8 =3D operation, + .r9 =3D page_to_phys(spdm_rsp), + .r10 =3D page_to_phys(spdm_req), + }; + u64 r; + + r =3D seamcall_ret_ir_resched(TDH_IDE_STREAM_KM, &args); + + *spdm_req_len =3D args.rcx; + + return r; +} +EXPORT_SYMBOL_FOR_MODULES(tdh_ide_stream_km, "tdx-host"); --=20 2.25.1 From nobody Thu Apr 2 15:41:48 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 62985408251; Fri, 27 Mar 2026 16:24:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628665; cv=none; b=jnqOxb1SJ3+qh+wY51yqHCtNAtpfOh5IVwahxPq0zE2Atb9Xbje2T93QH76ZFGGt4BLH2mXh4vSbTeudxHQCSAFMZIi8COi8LUlfDx0p23YUZbkyDLAp9esSi1bNb3OLFszYViQg/+fk9ZsZChswAktCWGjMFuJkVPjz/uM+Lqw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628665; c=relaxed/simple; bh=xIsA7BZZ8qFNyEF3mVWscDtKnNs9xK0BAxYPPzQTAOk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=tWmNJWiQstL7yYO+/SRfGt/KqKPurn/n3+UY5D7qECzGtjp5cy8yG16JBKQIVkpBX1Pqvz3grdknPuDj6VnIRtM785EkkzoQmgLutwffd7U3gJ9UGw59qBJ0IcOTppejP9p2sNlFboGuAUtvlZTsX5PmdgcyXiRJbR1/3oEXb7g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=e4qgqw3f; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="e4qgqw3f" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628664; x=1806164664; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=xIsA7BZZ8qFNyEF3mVWscDtKnNs9xK0BAxYPPzQTAOk=; b=e4qgqw3fgNk9Nby2XC28kcadNGS46KqHuCWWVPN5xL0j3QQNI59fO9Dk d2cKKs9WP4IGGDuxZc/De/Pd1rEP1VgousD3OT7o7Vk9esS6Ev6M/gK2r SensE02Gj2cQdliFl8G0BFQLMQwdnzaEo5g9Sl2zJO3KhsWFpojnKM0VI b6zuVWBU4sXVC9IktH7faaTjvP8F0wuz2i3KAXjUK62rnLrMbv/ukLEG/ tZ9e34LbVpPzn6Wt42U5qxhAeK1hEiUaI1ogwLvSmgeq09sOl7KVL1p+w ctMFC32U5qz1cIQb6IgDD4074lB9njjmaX/rfHA3PU05Jv6+02+lY7sqn A==; X-CSE-ConnectionGUID: BRANar8lR0eWJhuCacxqZA== X-CSE-MsgGUID: WOFf8RlCTf+QK1ccYTbFBg== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565707" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565707" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:24:23 -0700 X-CSE-ConnectionGUID: GkiPIhJKReKCyJCqLIzbsg== X-CSE-MsgGUID: D819/3SzQf23uFLusEu/Fw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516395" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:24:20 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 30/31] coco/tdx-host: Implement IDE stream setup/teardown Date: Sat, 28 Mar 2026 00:01:31 +0800 Message-Id: <20260327160132.2946114-31-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implementation for a most straightforward Selective IDE stream setup. Hard code all parameters for Stream Control Register. And no IDE Key Refresh support. Signed-off-by: Xu Yilun --- include/linux/pci-ide.h | 2 + drivers/pci/ide.c | 5 +- drivers/virt/coco/tdx-host/tdx-host.c | 226 ++++++++++++++++++++++++++ 3 files changed, 231 insertions(+), 2 deletions(-) diff --git a/include/linux/pci-ide.h b/include/linux/pci-ide.h index 381a1bf22a95..f0c6975fd429 100644 --- a/include/linux/pci-ide.h +++ b/include/linux/pci-ide.h @@ -106,6 +106,8 @@ struct pci_ide { void pci_ide_set_nr_streams(struct pci_host_bridge *hb, u16 nr); struct pci_ide_partner *pci_ide_to_settings(struct pci_dev *pdev, struct pci_ide *ide); +void pci_ide_stream_to_regs(struct pci_dev *pdev, struct pci_ide *ide, + struct pci_ide_regs *regs); struct pci_ide *pci_ide_stream_alloc(struct pci_dev *pdev); void pci_ide_stream_free(struct pci_ide *ide); int pci_ide_stream_register(struct pci_ide *ide); diff --git a/drivers/pci/ide.c b/drivers/pci/ide.c index b35e8aba7ecb..1337608448c2 100644 --- a/drivers/pci/ide.c +++ b/drivers/pci/ide.c @@ -556,8 +556,8 @@ static void mem_assoc_to_regs(struct pci_bus_region *re= gion, * @ide: registered IDE settings descriptor * @regs: output register values */ -static void pci_ide_stream_to_regs(struct pci_dev *pdev, struct pci_ide *i= de, - struct pci_ide_regs *regs) +void pci_ide_stream_to_regs(struct pci_dev *pdev, struct pci_ide *ide, + struct pci_ide_regs *regs) { struct pci_ide_partner *settings =3D pci_ide_to_settings(pdev, ide); int assoc_idx =3D 0; @@ -586,6 +586,7 @@ static void pci_ide_stream_to_regs(struct pci_dev *pdev= , struct pci_ide *ide, =20 regs->nr_addr =3D assoc_idx; } +EXPORT_SYMBOL_GPL(pci_ide_stream_to_regs); =20 /** * pci_ide_stream_setup() - program settings to Selective IDE Stream regis= ters diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-= host/tdx-host.c index d5072a68b81a..0f6056945788 100644 --- a/drivers/virt/coco/tdx-host/tdx-host.c +++ b/drivers/virt/coco/tdx-host/tdx-host.c @@ -72,6 +72,10 @@ struct tdx_tsm_link { struct tdx_page_array *spdm_mt; unsigned int dev_info_size; void *dev_info_data; + + struct pci_ide *ide; + struct tdx_page_array *stream_mt; + unsigned int stream_id; }; =20 static struct tdx_tsm_link *to_tdx_tsm_link(struct pci_tsm *tsm) @@ -351,6 +355,219 @@ static void tdx_spdm_session_teardown(struct tdx_tsm_= link *tlink) DEFINE_FREE(tdx_spdm_session_teardown, struct tdx_tsm_link *, if (!IS_ERR_OR_NULL(_T)) tdx_spdm_session_teardown(_T)) =20 +enum tdx_ide_stream_km_op { + TDX_IDE_STREAM_KM_SETUP =3D 0, + TDX_IDE_STREAM_KM_REFRESH =3D 1, + TDX_IDE_STREAM_KM_STOP =3D 2, +}; + +static int tdx_ide_stream_km(struct tdx_tsm_link *tlink, + enum tdx_ide_stream_km_op op) +{ + u64 r, out_msg_sz; + int ret; + + do { + r =3D tdh_ide_stream_km(tlink->spdm_id, tlink->stream_id, op, + tlink->in_msg, tlink->out_msg, + &out_msg_sz); + ret =3D tdx_tsm_link_event_handler(tlink, r, out_msg_sz); + } while (ret =3D=3D -EAGAIN); + + return ret; +} + +static struct tdx_tsm_link * +tdx_ide_stream_key_program(struct tdx_tsm_link *tlink) +{ + int ret; + + ret =3D tdx_ide_stream_km(tlink, TDX_IDE_STREAM_KM_SETUP); + if (ret) + return ERR_PTR(ret); + + return tlink; +} + +static void tdx_ide_stream_key_stop(struct tdx_tsm_link *tlink) +{ + tdx_ide_stream_km(tlink, TDX_IDE_STREAM_KM_STOP); +} + +DEFINE_FREE(tdx_ide_stream_key_stop, struct tdx_tsm_link *, + if (!IS_ERR_OR_NULL(_T)) tdx_ide_stream_key_stop(_T)) + +static void sel_stream_block_regs(struct pci_dev *pdev, struct pci_ide *id= e, + struct pci_ide_regs *regs) +{ + struct pci_dev *rp =3D pcie_find_root_port(pdev); + struct pci_ide_partner *setting =3D pci_ide_to_settings(rp, ide); + + /* only support address association for prefetchable memory */ + setting->mem_assoc =3D (struct pci_bus_region) { 0, -1 }; + pci_ide_stream_to_regs(rp, ide, regs); +} + +#define STREAM_INFO_RP_DEVFN GENMASK_ULL(7, 0) +#define STREAM_INFO_TYPE BIT_ULL(8) +#define STREAM_INFO_TYPE_LINK 0 +#define STREAM_INFO_TYPE_SEL 1 + +static struct tdx_tsm_link *tdx_ide_stream_create(struct tdx_tsm_link *tli= nk, + struct pci_ide *ide) +{ + u64 stream_info, stream_ctrl; + u64 stream_id, rp_ide_id; + unsigned int nr_pages =3D tdx_sysinfo->connect.ide_mt_page_count; + struct pci_dev *pdev =3D tlink->pci.base_tsm.pdev; + struct pci_dev *rp =3D pcie_find_root_port(pdev); + struct pci_ide_regs regs; + u64 r; + + struct tdx_page_array *stream_mt __free(tdx_page_array_free) =3D + tdx_page_array_create(nr_pages); + if (!stream_mt) + return ERR_PTR(-ENOMEM); + + stream_info =3D FIELD_PREP(STREAM_INFO_RP_DEVFN, rp->devfn); + stream_info |=3D FIELD_PREP(STREAM_INFO_TYPE, STREAM_INFO_TYPE_SEL); + + /* + * For Selective IDE stream, below values must be 0: + * NPR_AGG/PR_AGG/CPL_AGG/CONF_REQ/ALGO/DEFAULT/STREAM_ID + * + * below values are configurable but now hardcode to 0: + * PCRC/TC + */ + stream_ctrl =3D FIELD_PREP(PCI_IDE_SEL_CTL_EN, 0) | + FIELD_PREP(PCI_IDE_SEL_CTL_TX_AGGR_NPR, 0) | + FIELD_PREP(PCI_IDE_SEL_CTL_TX_AGGR_PR, 0) | + FIELD_PREP(PCI_IDE_SEL_CTL_TX_AGGR_CPL, 0) | + FIELD_PREP(PCI_IDE_SEL_CTL_PCRC_EN, 0) | + FIELD_PREP(PCI_IDE_SEL_CTL_CFG_EN, 0) | + FIELD_PREP(PCI_IDE_SEL_CTL_ALG, 0) | + FIELD_PREP(PCI_IDE_SEL_CTL_TC, 0) | + FIELD_PREP(PCI_IDE_SEL_CTL_ID, 0); + + sel_stream_block_regs(pdev, ide, ®s); + if (regs.nr_addr !=3D 1) + return ERR_PTR(-EFAULT); + + r =3D tdh_ide_stream_create(stream_info, tlink->spdm_id, + stream_mt, stream_ctrl, + regs.rid1, regs.rid2, regs.addr[0].assoc1, + regs.addr[0].assoc2, regs.addr[0].assoc3, + &stream_id, &rp_ide_id); + if (r) + return ERR_PTR(-EFAULT); + + tlink->stream_id =3D stream_id; + tlink->stream_mt =3D no_free_ptr(stream_mt); + + pci_dbg(pdev, "%s stream id 0x%x rp ide_id 0x%llx\n", __func__, + tlink->stream_id, rp_ide_id); + return tlink; +} + +static void tdx_ide_stream_delete(struct tdx_tsm_link *tlink) +{ + struct pci_dev *pdev =3D tlink->pci.base_tsm.pdev; + unsigned int nr_released; + u64 released_hpa, r; + + r =3D tdh_ide_stream_block(tlink->spdm_id, tlink->stream_id); + if (r) { + pci_err(pdev, "ide stream block fail 0x%llx\n", r); + goto leak; + } + + r =3D tdh_ide_stream_delete(tlink->spdm_id, tlink->stream_id, + tlink->stream_mt, &nr_released, + &released_hpa); + if (r) { + pci_err(pdev, "ide stream delete fail 0x%llx\n", r); + goto leak; + } + + if (tdx_page_array_ctrl_release(tlink->stream_mt, nr_released, + released_hpa)) { + pci_err(pdev, "fail to release IDE stream_mt pages\n"); + goto leak; + } + + return; + +leak: + tdx_page_array_ctrl_leak(tlink->stream_mt); +} + +DEFINE_FREE(tdx_ide_stream_delete, struct tdx_tsm_link *, + if (!IS_ERR_OR_NULL(_T)) tdx_ide_stream_delete(_T)) + +static struct tdx_tsm_link *tdx_ide_stream_setup(struct tdx_tsm_link *tlin= k) +{ + struct pci_dev *pdev =3D tlink->pci.base_tsm.pdev; + int ret; + + struct pci_ide *ide __free(pci_ide_stream_release) =3D + pci_ide_stream_alloc(pdev); + if (!ide) + return ERR_PTR(-ENOMEM); + + /* Configure IDE capability for RP & get stream_id */ + struct tdx_tsm_link *tlink_create __free(tdx_ide_stream_delete) =3D + tdx_ide_stream_create(tlink, ide); + if (IS_ERR(tlink_create)) + return tlink_create; + + ide->stream_id =3D tlink->stream_id; + ret =3D pci_ide_stream_register(ide); + if (ret) + return ERR_PTR(ret); + + /* + * Configure IDE capability for target device + * + * Some test devices work only with DEFAULT_STREAM enabled. For + * simplicity, enable DEFAULT_STREAM for all devices. A future decent + * solution may be to have a quirk table to specify which devices need + * DEFAULT_STREAM. + */ + ide->partner[PCI_IDE_EP].default_stream =3D 1; + pci_ide_stream_setup(pdev, ide); + + /* Key Programming for RP & target device, enable IDE stream for RP */ + struct tdx_tsm_link *tlink_program __free(tdx_ide_stream_key_stop) =3D + tdx_ide_stream_key_program(tlink); + if (IS_ERR(tlink_program)) + return tlink_program; + + ret =3D tsm_ide_stream_register(ide); + if (ret) + return ERR_PTR(ret); + + /* Enable IDE stream for target device */ + ret =3D pci_ide_stream_enable(pdev, ide); + if (ret) + return ERR_PTR(ret); + + retain_and_null_ptr(tlink_create); + retain_and_null_ptr(tlink_program); + tlink->ide =3D no_free_ptr(ide); + + return tlink; +} + +static void tdx_ide_stream_teardown(struct tdx_tsm_link *tlink) +{ + tdx_ide_stream_key_stop(tlink); + tdx_ide_stream_delete(tlink); + pci_ide_stream_release(tlink->ide); +} + +DEFINE_FREE(tdx_ide_stream_teardown, struct tdx_tsm_link *, + if (!IS_ERR_OR_NULL(_T)) tdx_ide_stream_teardown(_T)) + static int tdx_tsm_link_connect(struct pci_dev *pdev) { struct tdx_tsm_link *tlink =3D to_tdx_tsm_link(pdev->tsm); @@ -362,7 +579,15 @@ static int tdx_tsm_link_connect(struct pci_dev *pdev) return PTR_ERR(tlink_spdm); } =20 + struct tdx_tsm_link *tlink_ide __free(tdx_ide_stream_teardown) =3D + tdx_ide_stream_setup(tlink); + if (IS_ERR(tlink_ide)) { + pci_err(pdev, "fail to setup ide stream\n"); + return PTR_ERR(tlink_ide); + } + retain_and_null_ptr(tlink_spdm); + retain_and_null_ptr(tlink_ide); =20 return 0; } @@ -371,6 +596,7 @@ static void tdx_tsm_link_disconnect(struct pci_dev *pde= v) { struct tdx_tsm_link *tlink =3D to_tdx_tsm_link(pdev->tsm); =20 + tdx_ide_stream_teardown(tlink); tdx_spdm_session_teardown(tlink); } =20 --=20 2.25.1 From nobody Thu Apr 2 15:41:48 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) (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 E460740F8C1; Fri, 27 Mar 2026 16:24:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.14 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628669; cv=none; b=R14YfbR3KWHXxGpqQQhBy2gDzN841fUVjPvBPCByl5I0/paod0XnJBLXpdbBCwGEqu4CXgtDFnTSVUQRm2hFy3nBcxPY8seeJSF/ivct95lEKhqucRA5KtHS40ZHKEEW1uDvUPZSCKOu0MY/vl/h2wzvCFgVfvs8OuYRLNnITCw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774628669; c=relaxed/simple; bh=e3F8B2xO+pmyAcCvVmFZ6e91fRtjUozwO9dyL7DqLVo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=CNj4hqYR2aO6L1O4wm9gBHQI0DigiFYnawLYNryn0da8iig3QQOHJn1pglQK2YpbbIGFqd3tVHpbfy6DXKskD3u0UWq47M4McsBGsxnzkRCqNkAmR3qgX+ehcK3g49psBSA5O/G1oFEYsLBRtTRr2nEocMUFz4BRmlgCHXGJ0aE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=pass smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Lv+Qd+VV; arc=none smtp.client-ip=198.175.65.14 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Lv+Qd+VV" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1774628667; x=1806164667; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=e3F8B2xO+pmyAcCvVmFZ6e91fRtjUozwO9dyL7DqLVo=; b=Lv+Qd+VVAu3CACoOokdFASpm7L3B+FcNOQT6JCXyNoWVOxIzr3DOqmsP vf5A6dIRi5dJJoeUeiunQukfGcR5U5lDz/1vubvaJ8t6+kEMBpi1+PVAA 6ERXbVzIA89VEcuAsr4EVIeK+V0XpAl9oV9o0Zi0/x6n6DGnCAnVZntuJ 0g7CyMbVjQfM77/1nLMLCR6SXzFK6cgOqffWA8Fp4DxYZmwXFObfI5CNW PJ3CfJujuRCdPz8yeQYPTc4MiD1NRXO71aDHRdww6NEPKYA623A60mLS5 PzgrqZbITiYy97F8JP1xwbEVOWQknFMaRU+6lgSBxZhpCYtGToeIruGNq A==; X-CSE-ConnectionGUID: 9cFhp+/pQNKnNRsWp19vJQ== X-CSE-MsgGUID: plzuFNNHT9+Q6MN90Ju/GA== X-IronPort-AV: E=McAfee;i="6800,10657,11741"; a="79565712" X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="79565712" Received: from fmviesa006.fm.intel.com ([10.60.135.146]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Mar 2026 09:24:27 -0700 X-CSE-ConnectionGUID: D42qXb8nS2GqNB9VSReytw== X-CSE-MsgGUID: frmzYPmVQ62s1CJ9Wz5V5w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,144,1770624000"; d="scan'208";a="220516409" Received: from yilunxu-optiplex-7050.sh.intel.com ([10.239.159.165]) by fmviesa006.fm.intel.com with ESMTP; 27 Mar 2026 09:24:24 -0700 From: Xu Yilun To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org, dan.j.williams@intel.com, x86@kernel.org Cc: chao.gao@intel.com, dave.jiang@intel.com, baolu.lu@linux.intel.com, yilun.xu@linux.intel.com, yilun.xu@intel.com, zhenzhong.duan@intel.com, kvm@vger.kernel.org, rick.p.edgecombe@intel.com, dave.hansen@linux.intel.com, kas@kernel.org, xiaoyao.li@intel.com, vishal.l.verma@intel.com, linux-kernel@vger.kernel.org Subject: [PATCH v2 31/31] coco/tdx-host: Finally enable SPDM session and IDE Establishment Date: Sat, 28 Mar 2026 00:01:32 +0800 Message-Id: <20260327160132.2946114-32-yilun.xu@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com> References: <20260327160132.2946114-1-yilun.xu@linux.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The basic SPDM session and IDE functionalities are all implemented, enable them. Reviewed-by: Jonathan Cameron Signed-off-by: Xu Yilun --- drivers/virt/coco/tdx-host/tdx-host.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-= host/tdx-host.c index 0f6056945788..7800afb0893d 100644 --- a/drivers/virt/coco/tdx-host/tdx-host.c +++ b/drivers/virt/coco/tdx-host/tdx-host.c @@ -883,7 +883,7 @@ static int tdx_iommu_enable_all(void) return ret; } =20 -static int __maybe_unused tdx_connect_init(struct device *dev) +static int tdx_connect_init(struct device *dev) { struct tsm_dev *link; int ret; @@ -914,8 +914,7 @@ static int __maybe_unused tdx_connect_init(struct devic= e *dev) =20 static int tdx_host_probe(struct faux_device *fdev) { - /* TODO: do tdx_connect_init() when it is fully implemented. */ - return 0; + return tdx_connect_init(&fdev->dev); } =20 static struct faux_device_ops tdx_host_ops =3D { --=20 2.25.1