On 27/08/24 10:14, Kai Huang wrote: > The TDX module provides a set of "global metadata fields". They report Global Metadata Fields > 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 "Class"es. E.g., "Classes" > 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@xxxxxxxxx> Notwithstanding minor cosmetic tweaks: Reviewed-by: Adrian Hunter <adrian.hunter@xxxxxxxxx> > --- > > v2 -> v3: > - Split out the part to rename 'struct tdx_tdmr_sysinfo' to 'struct > tdx_sys_info_tdmr'. > > > --- > arch/x86/virt/vmx/tdx/tdx.c | 19 ++++++++++++------- > arch/x86/virt/vmx/tdx/tdx.h | 36 +++++++++++++++++++++++++++++------- > 2 files changed, 41 insertions(+), 14 deletions(-) > > diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c > index 1cd9035c783f..24eb289c80e8 100644 > --- a/arch/x86/virt/vmx/tdx/tdx.c > +++ b/arch/x86/virt/vmx/tdx/tdx.c > @@ -318,6 +318,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) > { > @@ -1090,9 +1095,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 > @@ -1109,17 +1118,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 8aabd03d8bf5..4cddbb035b9f 100644 > --- a/arch/x86/virt/vmx/tdx/tdx.h > +++ b/arch/x86/virt/vmx/tdx/tdx.h > @@ -100,13 +100,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 > > @@ -119,4 +112,33 @@ struct tdmr_info_list { > int max_tdmrs; /* How many 'tdmr_info's are allocated */ > }; > > +/* > + * Kernel-defined structures to contain "Global Scope Metadata". > + * > + * TDX global metadata fields are categorized by "Class"es. See the "Classes" > + * "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; > +}; > + > #endif