Messages in this thread | | | Date | Sun, 8 Oct 2023 18:23:41 -0700 | Subject | Re: [PATCH v4] x86/tdx: Dump TDX version During the TD Bootup | From | Kuppuswamy Sathyanarayanan <> |
| |
On 10/5/2023 11:28 PM, Yi Sun wrote: > It is essential for TD users to be aware of the vendor and version of > the current TDX. Additionally, they can reference the TDX version when > reporting bugs or issues. > > Furthermore, the applications or device drivers running in TD can achieve > enhanced reliability and flexibility by following the TDX Module ABI > specification, because there are significant differences between different > versions of TDX, as mentioned in the "Intel® TDX Module Incompatibilities > between v1.0 and v1.5" reference. Here are a few examples: > > MSR Name Index Reason > ---------------------------------------------- > IA32_UARCH_MISC_CTL 0x1B01 From v1.5 > IA32_ARCH_CAPABILITIES 0x010A Changed in v1.5 > IA32_TSX_CTRL 0x0122 Changed in v1.5 > > CPUID Leaf Sub-leaf Reason > --------------------------------------- > 0x7 2 From v1.5 > 0x22 0 From v1.5 > 0x23 0~3 From v1.5 > 0x80000007 0 From v1.5 > > During TD initialization, the TDX version info can be obtained by calling > TDG.SYS.RD. This will fetch the current version of TDX, including the major > and minor version numbers and vendor ID. > > The TDCALL TDG.SYS.RD originates from TDX version 1.5. If the error > TDCALL_INVALID_OPERAND occurs, it should be treated as TDX version 1.0. > > If the __tdcall_ret fails, expect a zero value for all tdx sys info. > No additional error code is necessary to avoid introducing noise during > the bootup. > > Co-developed-by: Dongcheng Yan <dongcheng.yan@intel.com> > Signed-off-by: Dongcheng Yan <dongcheng.yan@intel.com> > Signed-off-by: Yi Sun <yi.sun@intel.com> > > diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c > index 3e6dbd2199cf..991f7dc695bd 100644 > --- a/arch/x86/coco/tdx/tdx.c > +++ b/arch/x86/coco/tdx/tdx.c > @@ -37,6 +37,24 @@ > > #define TDREPORT_SUBTYPE_0 0 > > +/* > + * TDX metadata base field id, used by TDCALL TDG.SYS.RD > + * See TDX ABI Spec section 3.3.2.3 Global Metadata Fields > + */ > +#define TDX_SYS_VENDOR_ID_FID 0x0800000200000000ULL > +#define TDX_SYS_MINOR_FID 0x0800000100000003ULL > +#define TDX_SYS_MAJOR_FID 0x0800000100000004ULL > +#define TDX_VENDOR_INTEL 0x8086 > + > +/* > + * The global-scope metadata field via TDG.SYS.RD TDCALL > + */
I think you can just say "struct used to cache TDX Module version info"
> +struct tdg_sys_info { > + u32 vendor_id; > + u16 major_version; > + u16 minor_version; > +}; > + > /* Called from __tdx_hypercall() for unrecoverable failure */ > noinstr void __noreturn __tdx_hypercall_failed(void) > { > @@ -800,6 +818,60 @@ static bool tdx_enc_status_change_finish(unsigned long vaddr, int numpages, > return true; > } > > +/* > + * Parse the tdx module version info from the global-scope metadata fields. > + * > + * Refer to Intel TDX Application Binary Interface (ABI) section > + * "TDG.SYS.RD". > + */
How about "Parse TDX Module version info from TDG.SYS.RD TDCALL"?
> +static void tdg_get_sysinfo(struct tdg_sys_info *td_sys) > +{ > + u64 ret; > + struct tdx_module_args args = { > + .rdx = TDX_SYS_VENDOR_ID_FID, > + }; > + > + if (!td_sys) > + return;
This check can be removed. It will never be NULL as per current usage.
> + > + memset(td_sys, 0, sizeof(struct tdg_sys_info)); > + > + /* > + * TDCALL leaf TDX_SYS_RD > + * Input Field Identifier via RDX and get the output via R8. > + */
Since you are using a wrapper, I think you don't need to explain the register details here.
> + ret = __tdcall_ret(TDX_SYS_RD, &args); > + /* > + * The TDCALL TDG.SYS.RD originates from TDX version 1.5. > + * Treat TDCALL_INVALID_OPERAND error as TDX version 1.0. > + * If other errors occur, return with zero td_sys. > + */ > + if (TDCALL_RETURN_CODE(ret) == TDCALL_INVALID_OPERAND) > + goto version_1_0; > + else if (ret) > + return; > + > + td_sys->vendor_id = (u32)args.r8; > + > + args.rdx = TDX_SYS_MAJOR_FID; > + __tdcall_ret(TDX_SYS_RD, &args);
Why not check the return value?
> + > + td_sys->major_version = (u16)args.r8; > + > + args.rdx = TDX_SYS_MINOR_FID; > + __tdcall_ret(TDX_SYS_RD, &args);
Same as above.
> + > + td_sys->minor_version = (u16)args.r8;
I recommend updating td_sys after executing both TDCALLs.
> + > + return; > + > + /* TDX 1.0 does not have the TDCALL TDG.SYS.RD */ > +version_1_0: > + td_sys->vendor_id = TDX_VENDOR_INTEL; > + td_sys->major_version = 1; > + td_sys->minor_version = 0; > +} > + > void __init tdx_early_init(void) > { > struct tdx_module_args args = { > @@ -808,6 +880,7 @@ void __init tdx_early_init(void) > }; > u64 cc_mask; > u32 eax, sig[3]; > + struct tdg_sys_info td_sys_info; > > cpuid_count(TDX_CPUID_LEAF_ID, 0, &eax, &sig[0], &sig[2], &sig[1]); > > @@ -867,5 +940,9 @@ void __init tdx_early_init(void) > */ > x86_cpuinit.parallel_bringup = false; > > - pr_info("Guest detected\n"); > + tdg_get_sysinfo(&td_sys_info); > + > + pr_info("Guest detected. TDX version:%u.%u VendorID: %x\n", > + td_sys_info.major_version, td_sys_info.minor_version, > + td_sys_info.vendor_id); > } > diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/shared/tdx.h > index f74695dea217..d326509832e6 100644 > --- a/arch/x86/include/asm/shared/tdx.h > +++ b/arch/x86/include/asm/shared/tdx.h > @@ -17,6 +17,7 @@ > #define TDG_MR_REPORT 4 > #define TDG_MEM_PAGE_ACCEPT 6 > #define TDG_VM_WR 8 > +#define TDX_SYS_RD 11 > > /* TDCS fields. To be used by TDG.VM.WR and TDG.VM.RD module calls */ > #define TDCS_NOTIFY_ENABLES 0x9100000000000010
-- Sathyanarayanan Kuppuswamy Linux Kernel Developer
| |