From: Kai Huang <kai.huang@xxxxxxxxx> The TDX host tracks all global metadata fields in 'struct tdx_sys_info'. For now they are only used by module initialization and are not shared to other kernel components. Future changes to support KVM TDX will need to read more global metadata fields, e.g., those in "TD Control Structures" and "TD Configurability". In the longer term, other TDX features like TDX Connect (which supports assigning trusted devices to TDX guests) will 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. To achieve "read-only", the ideal way is to annotate the whole structure with __ro_after_init. However currently all global metadata fields are read by tdx_enable(), which could be called at any time at runtime thus isn't annotated with __init. The __ro_after_init can be done eventually, but it can only be done after moving VMXON out of KVM to the core-kernel: after that we can read all metadata during kernel boot (thus __ro_after_init), but doesn't necessarily have to do it in tdx_enable(). For now, add a helper function to return a 'const struct tdx_sys_info *' and export it for KVM to use. Note, KVM doesn't need to access all global metadata for TDX, thus exporting the entire 'struct tdx_sys_info' is overkill. Another option is to export sub-structures on demand. But this will result in more exports. Given the export is done via a const pointer thus the other in-kernel TDX won't be able to write to global metadata, simply export all global metadata fields in one function. The auto-generated 'tdx_global_metadata.h' contains declarations of 'struct tdx_sys_info' and its sub-structures. Move it to arch/x86/include/asm/ and include it to <asm/tdx.h> to expose those structures. Include 'tdx_global_metadata.h' inside the '#ifndef __ASSEMBLY__' since otherwise there will be build warning due to <asm/tdx.h> is also included by assembly. Signed-off-by: Kai Huang <kai.huang@xxxxxxxxx> Signed-off-by: Rick Edgecombe <rick.p.edgecombe@xxxxxxxxx> --- uAPI breakout v2: - New patch --- arch/x86/include/asm/tdx.h | 3 ++ .../tdx => include/asm}/tdx_global_metadata.h | 0 arch/x86/virt/vmx/tdx/tdx.c | 28 +++++++++++++++---- arch/x86/virt/vmx/tdx/tdx.h | 1 - 4 files changed, 25 insertions(+), 7 deletions(-) rename arch/x86/{virt/vmx/tdx => include/asm}/tdx_global_metadata.h (100%) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index eba178996d84..b9758369d82c 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -33,6 +33,7 @@ #ifndef __ASSEMBLY__ #include <uapi/asm/mce.h> +#include "tdx_global_metadata.h" /* * Used by the #VE exception handler to gather the #VE exception @@ -116,11 +117,13 @@ static inline u64 sc_retry(sc_func_t func, u64 fn, int tdx_cpu_enable(void); int tdx_enable(void); const char *tdx_dump_mce_info(struct mce *m); +const struct tdx_sys_info *tdx_get_sysinfo(void); #else static inline void tdx_init(void) { } static inline int tdx_cpu_enable(void) { return -ENODEV; } static inline int tdx_enable(void) { return -ENODEV; } static inline const char *tdx_dump_mce_info(struct mce *m) { return NULL; } +static inline const struct tdx_sys_info *tdx_get_sysinfo(void) { return NULL; } #endif /* CONFIG_INTEL_TDX_HOST */ #endif /* !__ASSEMBLY__ */ diff --git a/arch/x86/virt/vmx/tdx/tdx_global_metadata.h b/arch/x86/include/asm/tdx_global_metadata.h similarity index 100% rename from arch/x86/virt/vmx/tdx/tdx_global_metadata.h rename to arch/x86/include/asm/tdx_global_metadata.h diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 6982e100536d..7589c75eaa6c 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -52,6 +52,8 @@ static DEFINE_MUTEX(tdx_module_lock); /* All TDX-usable memory regions. Protected by mem_hotplug_lock. */ static LIST_HEAD(tdx_memlist); +static struct tdx_sys_info tdx_sysinfo; + typedef void (*sc_err_func_t)(u64 fn, u64 err, struct tdx_module_args *args); static inline void seamcall_err(u64 fn, u64 err, struct tdx_module_args *args) @@ -1132,15 +1134,14 @@ static int init_tdmrs(struct tdmr_info_list *tdmr_list) static int init_tdx_module(void) { - struct tdx_sys_info sysinfo; int ret; - ret = init_tdx_sys_info(&sysinfo); + ret = init_tdx_sys_info(&tdx_sysinfo); if (ret) return ret; /* Check whether the kernel can support this module */ - ret = check_features(&sysinfo); + ret = check_features(&tdx_sysinfo); if (ret) return ret; @@ -1161,13 +1162,14 @@ static int init_tdx_module(void) goto out_put_tdxmem; /* Allocate enough space for constructing TDMRs */ - ret = alloc_tdmr_list(&tdx_tdmr_list, &sysinfo.tdmr); + ret = alloc_tdmr_list(&tdx_tdmr_list, &tdx_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, - &sysinfo.cmr); + ret = construct_tdmrs(&tdx_memlist, &tdx_tdmr_list, + &tdx_sysinfo.tdmr, &tdx_sysinfo.cmr); + if (ret) goto err_free_tdmrs; @@ -1529,3 +1531,17 @@ void __init tdx_init(void) check_tdx_erratum(); } + +const struct tdx_sys_info *tdx_get_sysinfo(void) +{ + const struct tdx_sys_info *p = NULL; + + /* Make sure all fields in @tdx_sysinfo have been populated */ + mutex_lock(&tdx_module_lock); + if (tdx_module_status == TDX_MODULE_INITIALIZED) + p = (const struct tdx_sys_info *)&tdx_sysinfo; + mutex_unlock(&tdx_module_lock); + + return p; +} +EXPORT_SYMBOL_GPL(tdx_get_sysinfo); diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h index c8be00f6b15a..9b708a8fb568 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -6,7 +6,6 @@ #include <linux/compiler_attributes.h> #include <linux/stddef.h> #include <linux/bits.h> -#include "tdx_global_metadata.h" /* * This file contains both macros and data structures defined by the TDX -- 2.47.0