Message ID | a33f372df345f6232b55e26d498ea67d4adc18f0.1687784645.git.kai.huang@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | TDX host kernel support | expand |
On Tue, Jun 27, 2023 at 02:12:38AM +1200, Kai Huang wrote: > static int init_tdx_module(void) > { > + struct tdsysinfo_struct *sysinfo; > + struct cmr_info *cmr_array; > + int ret; > + > + /* > + * Get the TDSYSINFO_STRUCT and CMRs from the TDX module. > + * > + * The buffers of the TDSYSINFO_STRUCT and the CMR array passed > + * to the TDX module must be 1024-bytes and 512-bytes aligned > + * respectively. Allocate one page to accommodate them both and > + * also meet those alignment requirements. > + */ > + sysinfo = (struct tdsysinfo_struct *)__get_free_page(GFP_KERNEL); > + if (!sysinfo) > + return -ENOMEM; > + cmr_array = (struct cmr_info *)((unsigned long)sysinfo + PAGE_SIZE / 2); > + > + BUILD_BUG_ON(PAGE_SIZE / 2 < TDSYSINFO_STRUCT_SIZE); > + BUILD_BUG_ON(PAGE_SIZE / 2 < sizeof(struct cmr_info) * MAX_CMRS); This works, but why not just use slab for this? kmalloc has 512 and 1024 pools already and you won't waste memory for rounding up. Something like this: sysinfo = kmalloc(TDSYSINFO_STRUCT_SIZE, GFP_KERNEL); if (!sysinfo) return -ENOMEM; cmr_array_size = sizeof(struct cmr_info) * MAX_CMRS; /* CMR array has to be 512-aligned */ cmr_array_size = round_up(cmr_array_size, 512); cmr_array = kmalloc(cmr_array_size, GFP_KERNEL); if (!cmr_array) { kfree(sysinfo); return -ENOMEM; } ?
On Tue, 2023-06-27 at 12:51 +0300, kirill.shutemov@linux.intel.com wrote: > On Tue, Jun 27, 2023 at 02:12:38AM +1200, Kai Huang wrote: > > static int init_tdx_module(void) > > { > > + struct tdsysinfo_struct *sysinfo; > > + struct cmr_info *cmr_array; > > + int ret; > > + > > + /* > > + * Get the TDSYSINFO_STRUCT and CMRs from the TDX module. > > + * > > + * The buffers of the TDSYSINFO_STRUCT and the CMR array passed > > + * to the TDX module must be 1024-bytes and 512-bytes aligned > > + * respectively. Allocate one page to accommodate them both and > > + * also meet those alignment requirements. > > + */ > > + sysinfo = (struct tdsysinfo_struct *)__get_free_page(GFP_KERNEL); > > + if (!sysinfo) > > + return -ENOMEM; > > + cmr_array = (struct cmr_info *)((unsigned long)sysinfo + PAGE_SIZE / 2); > > + > > + BUILD_BUG_ON(PAGE_SIZE / 2 < TDSYSINFO_STRUCT_SIZE); > > + BUILD_BUG_ON(PAGE_SIZE / 2 < sizeof(struct cmr_info) * MAX_CMRS); > > This works, but why not just use slab for this? kmalloc has 512 and 1024 > pools already and you won't waste memory for rounding up. > > Something like this: > > sysinfo = kmalloc(TDSYSINFO_STRUCT_SIZE, GFP_KERNEL); > if (!sysinfo) > return -ENOMEM; > > cmr_array_size = sizeof(struct cmr_info) * MAX_CMRS; > > /* CMR array has to be 512-aligned */ > cmr_array_size = round_up(cmr_array_size, 512); Should we define a macro for 512 +#define CMR_INFO_ARRAY_ALIGNMENT 512 And get rid of this comment? AFAICT Dave didn't like such comment mentioning 512-bytes aligned if we have a macro for that. > > cmr_array = kmalloc(cmr_array_size, GFP_KERNEL); > if (!cmr_array) { > kfree(sysinfo); > return -ENOMEM; > } > > ? > I confess the reason I used __get_free_page() was to avoid having to allocate twice, and in case of failure, I need to handle additional memory free. But I can do if you think it's clearer? I wouldn't worry about wasting memory. The buffer is freed anyway for now. Long-termly it's just 4K.
On Tue, Jun 27, 2023 at 10:45:33AM +0000, Huang, Kai wrote: > On Tue, 2023-06-27 at 12:51 +0300, kirill.shutemov@linux.intel.com wrote: > > On Tue, Jun 27, 2023 at 02:12:38AM +1200, Kai Huang wrote: > > > static int init_tdx_module(void) > > > { > > > + struct tdsysinfo_struct *sysinfo; > > > + struct cmr_info *cmr_array; > > > + int ret; > > > + > > > + /* > > > + * Get the TDSYSINFO_STRUCT and CMRs from the TDX module. > > > + * > > > + * The buffers of the TDSYSINFO_STRUCT and the CMR array passed > > > + * to the TDX module must be 1024-bytes and 512-bytes aligned > > > + * respectively. Allocate one page to accommodate them both and > > > + * also meet those alignment requirements. > > > + */ > > > + sysinfo = (struct tdsysinfo_struct *)__get_free_page(GFP_KERNEL); > > > + if (!sysinfo) > > > + return -ENOMEM; > > > + cmr_array = (struct cmr_info *)((unsigned long)sysinfo + PAGE_SIZE / 2); > > > + > > > + BUILD_BUG_ON(PAGE_SIZE / 2 < TDSYSINFO_STRUCT_SIZE); > > > + BUILD_BUG_ON(PAGE_SIZE / 2 < sizeof(struct cmr_info) * MAX_CMRS); > > > > This works, but why not just use slab for this? kmalloc has 512 and 1024 > > pools already and you won't waste memory for rounding up. > > > > Something like this: > > > > sysinfo = kmalloc(TDSYSINFO_STRUCT_SIZE, GFP_KERNEL); > > if (!sysinfo) > > return -ENOMEM; > > > > cmr_array_size = sizeof(struct cmr_info) * MAX_CMRS; > > > > /* CMR array has to be 512-aligned */ > > cmr_array_size = round_up(cmr_array_size, 512); > > Should we define a macro for 512 > > +#define CMR_INFO_ARRAY_ALIGNMENT 512 > > And get rid of this comment? AFAICT Dave didn't like such comment mentioning > 512-bytes aligned if we have a macro for that. Good idea. > > cmr_array = kmalloc(cmr_array_size, GFP_KERNEL); > > if (!cmr_array) { > > kfree(sysinfo); > > return -ENOMEM; > > } > > > > ? > > > > I confess the reason I used __get_free_page() was to avoid having to allocate > twice, and in case of failure, I need to handle additional memory free. But I > can do if you think it's clearer? Less trickery is always cleaner. Especially if the trick is not justified. > I wouldn't worry about wasting memory. The buffer is freed anyway for now. > Long-termly it's just 4K.
On Tue, 2023-06-27 at 14:37 +0300, kirill.shutemov@linux.intel.com wrote: > On Tue, Jun 27, 2023 at 10:45:33AM +0000, Huang, Kai wrote: > > On Tue, 2023-06-27 at 12:51 +0300, kirill.shutemov@linux.intel.com wrote: > > > On Tue, Jun 27, 2023 at 02:12:38AM +1200, Kai Huang wrote: > > > > static int init_tdx_module(void) > > > > { > > > > + struct tdsysinfo_struct *sysinfo; > > > > + struct cmr_info *cmr_array; > > > > + int ret; > > > > + > > > > + /* > > > > + * Get the TDSYSINFO_STRUCT and CMRs from the TDX module. > > > > + * > > > > + * The buffers of the TDSYSINFO_STRUCT and the CMR array passed > > > > + * to the TDX module must be 1024-bytes and 512-bytes aligned > > > > + * respectively. Allocate one page to accommodate them both and > > > > + * also meet those alignment requirements. > > > > + */ > > > > + sysinfo = (struct tdsysinfo_struct *)__get_free_page(GFP_KERNEL); > > > > + if (!sysinfo) > > > > + return -ENOMEM; > > > > + cmr_array = (struct cmr_info *)((unsigned long)sysinfo + PAGE_SIZE / 2); > > > > + > > > > + BUILD_BUG_ON(PAGE_SIZE / 2 < TDSYSINFO_STRUCT_SIZE); > > > > + BUILD_BUG_ON(PAGE_SIZE / 2 < sizeof(struct cmr_info) * MAX_CMRS); > > > > > > This works, but why not just use slab for this? kmalloc has 512 and 1024 > > > pools already and you won't waste memory for rounding up. > > > > > > Something like this: > > > > > > sysinfo = kmalloc(TDSYSINFO_STRUCT_SIZE, GFP_KERNEL); > > > if (!sysinfo) > > > return -ENOMEM; > > > > > > cmr_array_size = sizeof(struct cmr_info) * MAX_CMRS; > > > > > > /* CMR array has to be 512-aligned */ > > > cmr_array_size = round_up(cmr_array_size, 512); > > > > Should we define a macro for 512 > > > > +#define CMR_INFO_ARRAY_ALIGNMENT 512 > > > > And get rid of this comment? AFAICT Dave didn't like such comment mentioning > > 512-bytes aligned if we have a macro for that. > > Good idea. > > > > cmr_array = kmalloc(cmr_array_size, GFP_KERNEL); > > > if (!cmr_array) { > > > kfree(sysinfo); > > > return -ENOMEM; > > > } > > > > > > ? > > > > > > > I confess the reason I used __get_free_page() was to avoid having to allocate > > twice, and in case of failure, I need to handle additional memory free. But I > > can do if you think it's clearer? > > Less trickery is always cleaner. Especially if the trick is not justified. > > Alright. I'll change to allocating them separately if no opinion from others.
On Tue, Jun 27, 2023 at 02:12:38AM +1200, Kai Huang wrote: > +static int tdx_get_sysinfo(struct tdsysinfo_struct *sysinfo, > + struct cmr_info *cmr_array) > +{ > + struct tdx_module_output out; > + u64 sysinfo_pa, cmr_array_pa; > + int ret; > + > + sysinfo_pa = __pa(sysinfo); > + cmr_array_pa = __pa(cmr_array); > + ret = seamcall(TDH_SYS_INFO, sysinfo_pa, TDSYSINFO_STRUCT_SIZE, > + cmr_array_pa, MAX_CMRS, NULL, &out); > + if (ret) > + return ret; > + > + pr_info("TDX module: attributes 0x%x, vendor_id 0x%x, major_version %u, minor_version %u, build_date %u, build_num %u", > + sysinfo->attributes, sysinfo->vendor_id, > + sysinfo->major_version, sysinfo->minor_version, > + sysinfo->build_date, sysinfo->build_num); > + > + /* R9 contains the actual entries written to the CMR array. */ So I'm vexed by this comment; it's either not enough or too much. I mean, as given you assume we all know about the magic parameters to TDH_SYS_INFO but then somehow need an explanation for how %r9 is changed from the array size to the number of used entries. Either describe the whole thing or none of it. Me, I would prefer all of it, because I've no idea where to begin looking for any of this, SDM doesn't seem to be the place. That doesn't even list TDCALL/SEAMCALL in Volume 2 :-( Let alone describe the magic values. > + print_cmrs(cmr_array, out.r9); > + > + return 0; > +}
On Wed, 2023-06-28 at 16:10 +0200, Peter Zijlstra wrote: > On Tue, Jun 27, 2023 at 02:12:38AM +1200, Kai Huang wrote: > > +static int tdx_get_sysinfo(struct tdsysinfo_struct *sysinfo, > > + struct cmr_info *cmr_array) > > +{ > > + struct tdx_module_output out; > > + u64 sysinfo_pa, cmr_array_pa; > > + int ret; > > + > > + sysinfo_pa = __pa(sysinfo); > > + cmr_array_pa = __pa(cmr_array); > > + ret = seamcall(TDH_SYS_INFO, sysinfo_pa, TDSYSINFO_STRUCT_SIZE, > > + cmr_array_pa, MAX_CMRS, NULL, &out); > > + if (ret) > > + return ret; > > + > > + pr_info("TDX module: attributes 0x%x, vendor_id 0x%x, major_version %u, minor_version %u, build_date %u, build_num %u", > > + sysinfo->attributes, sysinfo->vendor_id, > > + sysinfo->major_version, sysinfo->minor_version, > > + sysinfo->build_date, sysinfo->build_num); > > + > > + /* R9 contains the actual entries written to the CMR array. */ > > So I'm vexed by this comment; it's either not enough or too much. > > I mean, as given you assume we all know about the magic parameters to > TDH_SYS_INFO but then somehow need an explanation for how %r9 is changed > from the array size to the number of used entries. > > Either describe the whole thing or none of it. > > Me, I would prefer all of it, because I've no idea where to begin > looking for any of this, > Sure. How about below? + /* + * TDH.SYS.INFO writes the TDSYSINFO_STRUCT and the CMR array + * to the buffers provided by the kernel (via RCX and R8 + * respectively). The buffer size of the TDSYSINFO_STRUCT + * (via RDX) and the maximum entries of the CMR array (via R9) + * passed to this SEAMCALL must be at least the size of + * TDSYSINFO_STRUCT and MAX_CMRS respectively. + * + * Upon a successful return, R9 contains the actual entries + * written to the CMR array. + */ sysinfo_pa = __pa(sysinfo); cmr_array_pa = __pa(cmr_array); ret = seamcall(TDH_SYS_INFO, sysinfo_pa, TDSYSINFO_STRUCT_SIZE, @@ -228,7 +239,6 @@ static int tdx_get_sysinfo(struct tdsysinfo_struct *sysinfo, sysinfo->major_version, sysinfo->minor_version, sysinfo->build_date, sysinfo->build_num); - /* R9 contains the actual entries written to the CMR array. */ print_cmrs(cmr_array, out.r9); Or should I just repeat the spec like below? + /* + * TDH.SYS.INFO writes the TDSYSINFO_STRUCT and the CMR array + * to the buffers provided by the kernel: + * + * Input: + * - RCX: The buffer of TDSYSINFO_STRUCT + * - RDX: The size of the TDSYSINFO_STRUCT buffer, must be at + * at least the size of TDSYSINFO_STRUCT + * - R8: The buffer of the CMR array + * - R9: The entry number of the array, must be at least + * MAX_CMRS. + * + * Output (successful): + * - RDX: The actual bytes written to the TDSYSINFO_STRUCT + * buffer + * - R9: The actual entries written to the CMR array. + */ sysinfo_pa = __pa(sysinfo); cmr_array_pa = __pa(cmr_array); ret = seamcall(TDH_SYS_INFO, sysinfo_pa, TDSYSINFO_STRUCT_SIZE, @@ -228,7 +245,6 @@ static int tdx_get_sysinfo(struct tdsysinfo_struct *sysinfo, sysinfo->major_version, sysinfo->minor_version, sysinfo->build_date, sysinfo->build_num); - /* R9 contains the actual entries written to the CMR array. */ print_cmrs(cmr_array, out.r9); > SDM doesn't seem to be the place. That doesn't > even list TDCALL/SEAMCALL in Volume 2 :-( Let alone describe the magic > values. > TDX has it's own specs at here: https://www.intel.com/content/www/us/en/developer/articles/technical/intel-trust-domain-extensions.html For this one you can find it in here: https://cdrdv2.intel.com/v1/dl/getContent/733568
On Thu, Jun 29, 2023 at 09:15:39AM +0000, Huang, Kai wrote: > Sure. How about below? > > + /* > + * TDH.SYS.INFO writes the TDSYSINFO_STRUCT and the CMR array > + * to the buffers provided by the kernel (via RCX and R8 > + * respectively). The buffer size of the TDSYSINFO_STRUCT > + * (via RDX) and the maximum entries of the CMR array (via R9) > + * passed to this SEAMCALL must be at least the size of > + * TDSYSINFO_STRUCT and MAX_CMRS respectively. > + * > + * Upon a successful return, R9 contains the actual entries > + * written to the CMR array. > + */ > sysinfo_pa = __pa(sysinfo); > cmr_array_pa = __pa(cmr_array); > ret = seamcall(TDH_SYS_INFO, sysinfo_pa, TDSYSINFO_STRUCT_SIZE, > Or should I just repeat the spec like below? > + /* > + * TDH.SYS.INFO writes the TDSYSINFO_STRUCT and the CMR array > + * to the buffers provided by the kernel: > + * > + * Input: > + * - RCX: The buffer of TDSYSINFO_STRUCT > + * - RDX: The size of the TDSYSINFO_STRUCT buffer, must be at > + * at least the size of TDSYSINFO_STRUCT > + * - R8: The buffer of the CMR array > + * - R9: The entry number of the array, must be at least > + * MAX_CMRS. > + * > + * Output (successful): > + * - RDX: The actual bytes written to the TDSYSINFO_STRUCT > + * buffer > + * - R9: The actual entries written to the CMR array. > + */ > sysinfo_pa = __pa(sysinfo); > cmr_array_pa = __pa(cmr_array); > ret = seamcall(TDH_SYS_INFO, sysinfo_pa, TDSYSINFO_STRUCT_SIZE, Either of them work for me, thanks! > > SDM doesn't seem to be the place. That doesn't > > even list TDCALL/SEAMCALL in Volume 2 :-( Let alone describe the magic > > values. > > > > TDX has it's own specs at here: > > https://www.intel.com/content/www/us/en/developer/articles/technical/intel-trust-domain-extensions.html > > For this one you can find it in here: > > https://cdrdv2.intel.com/v1/dl/getContent/733568 Yeah, eventually found it. I still think both TDCALL and SEAMCALL should be listed in SDM Vol.2 instruction listing -- every valid instruction should be found there IMO. I also feel strongly that a global ABI should be decided upon for them and the SDM would be a good place to mention that. leaving this to individual calls like now is a giant pain in the rear. As is, we have TDCALL leaf-0 with a giant regset but every other leaf has (c,d,8,9) for input and +(10,11) for output. Lets fix that in stone. Obviously I also very strongly feel any such ABI must not confict with pre-existing calling conventions -- IOW, using BP is out, must not happen.
On Fri, 2023-06-30 at 11:34 +0200, Peter Zijlstra wrote: > On Thu, Jun 29, 2023 at 09:15:39AM +0000, Huang, Kai wrote: > > > Sure. How about below? > > > > + /* > > + * TDH.SYS.INFO writes the TDSYSINFO_STRUCT and the CMR array > > + * to the buffers provided by the kernel (via RCX and R8 > > + * respectively). The buffer size of the TDSYSINFO_STRUCT > > + * (via RDX) and the maximum entries of the CMR array (via R9) > > + * passed to this SEAMCALL must be at least the size of > > + * TDSYSINFO_STRUCT and MAX_CMRS respectively. > > + * > > + * Upon a successful return, R9 contains the actual entries > > + * written to the CMR array. > > + */ > > sysinfo_pa = __pa(sysinfo); > > cmr_array_pa = __pa(cmr_array); > > ret = seamcall(TDH_SYS_INFO, sysinfo_pa, TDSYSINFO_STRUCT_SIZE, > > > Or should I just repeat the spec like below? > > > + /* > > + * TDH.SYS.INFO writes the TDSYSINFO_STRUCT and the CMR array > > + * to the buffers provided by the kernel: > > + * > > + * Input: > > + * - RCX: The buffer of TDSYSINFO_STRUCT > > + * - RDX: The size of the TDSYSINFO_STRUCT buffer, must be at > > + * at least the size of TDSYSINFO_STRUCT > > + * - R8: The buffer of the CMR array > > + * - R9: The entry number of the array, must be at least > > + * MAX_CMRS. > > + * > > + * Output (successful): > > + * - RDX: The actual bytes written to the TDSYSINFO_STRUCT > > + * buffer > > + * - R9: The actual entries written to the CMR array. > > + */ > > sysinfo_pa = __pa(sysinfo); > > cmr_array_pa = __pa(cmr_array); > > ret = seamcall(TDH_SYS_INFO, sysinfo_pa, TDSYSINFO_STRUCT_SIZE, > > Either of them work for me, thanks! I will choose the first one since it's shorter. Thanks! > > > > SDM doesn't seem to be the place. That doesn't > > > even list TDCALL/SEAMCALL in Volume 2 :-( Let alone describe the magic > > > values. > > > > > > > TDX has it's own specs at here: > > > > https://www.intel.com/content/www/us/en/developer/articles/technical/intel-trust-domain-extensions.html > > > > For this one you can find it in here: > > > > https://cdrdv2.intel.com/v1/dl/getContent/733568 > > Yeah, eventually found it. I still think both TDCALL and SEAMCALL should > be listed in SDM Vol.2 instruction listing -- every valid instruction > should be found there IMO. > > I also feel strongly that a global ABI should be decided upon for them > and the SDM would be a good place to mention that. leaving this to > individual calls like now is a giant pain in the rear. Yeah I agree how the specs are organized is not ideal. We have been having pain during our development too. > > As is, we have TDCALL leaf-0 with a giant regset but every other leaf > has (c,d,8,9) for input and +(10,11) for output. Lets fix that in stone. > > Obviously I also very strongly feel any such ABI must not confict with > pre-existing calling conventions -- IOW, using BP is out, must not > happen. Fully agreed.
diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 29ca18f66d61..a2129cbe056e 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -20,6 +20,7 @@ #include <asm/msr-index.h> #include <asm/msr.h> #include <asm/archrandom.h> +#include <asm/page.h> #include <asm/tdx.h> #include "tdx.h" @@ -159,12 +160,79 @@ int tdx_cpu_enable(void) } EXPORT_SYMBOL_GPL(tdx_cpu_enable); +static void print_cmrs(struct cmr_info *cmr_array, int nr_cmrs) +{ + int i; + + for (i = 0; i < nr_cmrs; i++) { + struct cmr_info *cmr = &cmr_array[i]; + + /* + * The array of CMRs reported via TDH.SYS.INFO can + * contain tail empty CMRs. Don't print them. + */ + if (!cmr->size) + break; + + pr_info("CMR: [0x%llx, 0x%llx)\n", cmr->base, + cmr->base + cmr->size); + } +} + +static int tdx_get_sysinfo(struct tdsysinfo_struct *sysinfo, + struct cmr_info *cmr_array) +{ + struct tdx_module_output out; + u64 sysinfo_pa, cmr_array_pa; + int ret; + + sysinfo_pa = __pa(sysinfo); + cmr_array_pa = __pa(cmr_array); + ret = seamcall(TDH_SYS_INFO, sysinfo_pa, TDSYSINFO_STRUCT_SIZE, + cmr_array_pa, MAX_CMRS, NULL, &out); + if (ret) + return ret; + + pr_info("TDX module: attributes 0x%x, vendor_id 0x%x, major_version %u, minor_version %u, build_date %u, build_num %u", + sysinfo->attributes, sysinfo->vendor_id, + sysinfo->major_version, sysinfo->minor_version, + sysinfo->build_date, sysinfo->build_num); + + /* R9 contains the actual entries written to the CMR array. */ + print_cmrs(cmr_array, out.r9); + + return 0; +} + static int init_tdx_module(void) { + struct tdsysinfo_struct *sysinfo; + struct cmr_info *cmr_array; + int ret; + + /* + * Get the TDSYSINFO_STRUCT and CMRs from the TDX module. + * + * The buffers of the TDSYSINFO_STRUCT and the CMR array passed + * to the TDX module must be 1024-bytes and 512-bytes aligned + * respectively. Allocate one page to accommodate them both and + * also meet those alignment requirements. + */ + sysinfo = (struct tdsysinfo_struct *)__get_free_page(GFP_KERNEL); + if (!sysinfo) + return -ENOMEM; + cmr_array = (struct cmr_info *)((unsigned long)sysinfo + PAGE_SIZE / 2); + + BUILD_BUG_ON(PAGE_SIZE / 2 < TDSYSINFO_STRUCT_SIZE); + BUILD_BUG_ON(PAGE_SIZE / 2 < sizeof(struct cmr_info) * MAX_CMRS); + + ret = tdx_get_sysinfo(sysinfo, cmr_array); + if (ret) + goto out; + /* * TODO: * - * - Get TDX module information and TDX-capable memory regions. * - Build the list of TDX-usable memory regions. * - Construct a list of "TD Memory Regions" (TDMRs) to cover * all TDX-usable memory regions. @@ -174,7 +242,14 @@ static int init_tdx_module(void) * * Return error before all steps are done. */ - return -EINVAL; + ret = -EINVAL; +out: + /* + * For now both @sysinfo and @cmr_array are only used during + * module initialization, so always free them. + */ + free_page((unsigned long)sysinfo); + return ret; } static int __tdx_enable(void) diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h index 9fb46033c852..8ab2d40971ea 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -3,6 +3,8 @@ #define _X86_VIRT_TDX_H #include <linux/types.h> +#include <linux/stddef.h> +#include <linux/compiler_attributes.h> /* * This file contains both macros and data structures defined by the TDX @@ -19,9 +21,67 @@ /* * TDX module SEAMCALL leaf functions */ +#define TDH_SYS_INFO 32 #define TDH_SYS_INIT 33 #define TDH_SYS_LP_INIT 35 +struct cmr_info { + u64 base; + u64 size; +} __packed; + +#define MAX_CMRS 32 + +struct cpuid_config { + u32 leaf; + u32 sub_leaf; + u32 eax; + u32 ebx; + u32 ecx; + u32 edx; +} __packed; + +#define TDSYSINFO_STRUCT_SIZE 1024 + +/* + * The size of this structure itself is flexible. The actual structure + * passed to TDH.SYS.INFO must be padded to 1024 bytes and be 1204-bytes + * aligned. + */ +struct tdsysinfo_struct { + /* TDX-SEAM Module Info */ + u32 attributes; + u32 vendor_id; + u32 build_date; + u16 build_num; + u16 minor_version; + u16 major_version; + u8 reserved0[14]; + /* Memory Info */ + u16 max_tdmrs; + u16 max_reserved_per_tdmr; + u16 pamt_entry_size; + u8 reserved1[10]; + /* Control Struct Info */ + u16 tdcs_base_size; + u8 reserved2[2]; + u16 tdvps_base_size; + u8 tdvps_xfam_dependent_size; + u8 reserved3[9]; + /* TD Capabilities */ + u64 attributes_fixed0; + u64 attributes_fixed1; + u64 xfam_fixed0; + u64 xfam_fixed1; + u8 reserved4[32]; + u32 num_cpuid_config; + /* + * The actual number of CPUID_CONFIG depends on above + * 'num_cpuid_config'. + */ + DECLARE_FLEX_ARRAY(struct cpuid_config, cpuid_configs); +} __packed; + /* * Do not put any hardware-defined TDX structure representations below * this comment!