Message ID | 014302e0bd2f0797aa7d27ed8b730603d2859c2d.1727173372.git.kai.huang@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | TDX host: metadata reading tweaks, bug fix and info dump | expand |
On 24.09.24 г. 14:28 ч., Kai Huang wrote: > The TDX module provides a set of "Global Metadata Fields". They report > things like TDX module version, supported features, and fields related > to create/run TDX guests and so on. > > Currently the kernel only reads "TD Memory Region" (TDMR) related fields > for module initialization. There are immediate needs which require the > TDX module initialization to read more global metadata including module > version, supported features and "Convertible Memory Regions" (CMRs). > > Also, KVM will need to read more metadata fields to support baseline TDX > guests. In the longer term, other TDX features like TDX Connect (which > supports assigning trusted IO devices to TDX guest) may also require > other kernel components such as pci/vt-d to access global metadata. > > To meet all those requirements, the idea is the TDX host core-kernel to > to provide a centralized, canonical, and read-only structure for the > global metadata that comes out from the TDX module for all kernel > components to use. > > As the first step, introduce a new 'struct tdx_sys_info' to track all > global metadata fields. > > TDX categories global metadata fields into different "Classes". E.g., > the TDMR related fields are under class "TDMR Info". Instead of making > 'struct tdx_sys_info' a plain structure to contain all metadata fields, > organize them in smaller structures based on the "Class". > > This allows those metadata fields to be used in finer granularity thus > makes the code more clear. E.g., the construct_tdmr() can just take the > structure which contains "TDMR Info" metadata fields. > > Add a new function get_tdx_sys_info() as the placeholder to read all > metadata fields, and call it at the beginning of init_tdx_module(). For > now it only calls get_tdx_sys_info_tdmr() to read TDMR related fields. > > Note there is a functional change: get_tdx_sys_info_tdmr() is moved from > after build_tdx_memlist() to before it, but it is fine to do so. > > Signed-off-by: Kai Huang <kai.huang@intel.com> > Reviewed-by: Adrian Hunter <adrian.hunter@intel.com> Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index b5c8dde9caf0..44ef74d1fafb 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -314,6 +314,11 @@ static int get_tdx_sys_info_tdmr(struct tdx_sys_info_tdmr *sysinfo_tdmr) return ret; } +static int get_tdx_sys_info(struct tdx_sys_info *sysinfo) +{ + return get_tdx_sys_info_tdmr(&sysinfo->tdmr); +} + /* Calculate the actual TDMR size */ static int tdmr_size_single(u16 max_reserved_per_tdmr) { @@ -1086,9 +1091,13 @@ static int init_tdmrs(struct tdmr_info_list *tdmr_list) static int init_tdx_module(void) { - struct tdx_sys_info_tdmr sysinfo_tdmr; + struct tdx_sys_info sysinfo; int ret; + ret = get_tdx_sys_info(&sysinfo); + if (ret) + return ret; + /* * To keep things simple, assume that all TDX-protected memory * will come from the page allocator. Make sure all pages in the @@ -1105,17 +1114,13 @@ static int init_tdx_module(void) if (ret) goto out_put_tdxmem; - ret = get_tdx_sys_info_tdmr(&sysinfo_tdmr); - if (ret) - goto err_free_tdxmem; - /* Allocate enough space for constructing TDMRs */ - ret = alloc_tdmr_list(&tdx_tdmr_list, &sysinfo_tdmr); + ret = alloc_tdmr_list(&tdx_tdmr_list, &sysinfo.tdmr); if (ret) goto err_free_tdxmem; /* Cover all TDX-usable memory regions in TDMRs */ - ret = construct_tdmrs(&tdx_memlist, &tdx_tdmr_list, &sysinfo_tdmr); + ret = construct_tdmrs(&tdx_memlist, &tdx_tdmr_list, &sysinfo.tdmr); if (ret) goto err_free_tdmrs; diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h index 38f8656162e3..b9a89da39e1e 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -80,6 +80,35 @@ struct tdmr_info { DECLARE_FLEX_ARRAY(struct tdmr_reserved_area, reserved_areas); } __packed __aligned(TDMR_INFO_ALIGNMENT); +/* + * Data structures for "Global Scope Metadata". + * + * TDX global metadata fields are categorized by "Classes". See the + * "global_metadata.json" in the "TDX 1.5 ABI Definitions". + * + * 'struct tdx_sys_info' is the main structure to contain all metadata + * used by the kernel. It contains sub-structures with each reflecting + * the "Class" in the 'global_metadata.json'. + * + * Note the structure name may not exactly follow the name of the + * "Class" in the TDX spec, but the comment of that structure always + * reflect that. + * + * Also note not all metadata fields in each class are defined, only + * those used by the kernel are. + */ + +/* Class "TDMR info" */ +struct tdx_sys_info_tdmr { + u16 max_tdmrs; + u16 max_reserved_per_tdmr; + u16 pamt_entry_size[TDX_PS_NR]; +}; + +struct tdx_sys_info { + struct tdx_sys_info_tdmr tdmr; +}; + /* * Do not put any hardware-defined TDX structure representations below * this comment! @@ -99,13 +128,6 @@ struct tdx_memblock { int nid; }; -/* "TDMR info" part of "Global Scope Metadata" for constructing TDMRs */ -struct tdx_sys_info_tdmr { - u16 max_tdmrs; - u16 max_reserved_per_tdmr; - u16 pamt_entry_size[TDX_PS_NR]; -}; - /* Warn if kernel has less than TDMR_NR_WARN TDMRs after allocation */ #define TDMR_NR_WARN 4