Implement common helper functions to communicate with the TDX Module and VMM (using TDCALL instruction).
tdvmcall() function can be used to request services from VMM. tdcall() function can be used to communicate with the TDX Module. Using common helper functions makes the code more readable and less error prone compared to distributed and use case specific inline assembly code. Only downside in using this approach is, it adds a few extra instructions for every TDCALL use case when compared to distributed checks. Although it's a bit less efficient, it's worth it to make the code more readable. Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppusw...@linux.intel.com> --- Hi All, As you have suggested, I have created common helper functions for all tdcall() and tdvmcall() use cases. It uses inline assembly and passes GPRs R8-15 and r[a-c]x registers to TDX Module/VMM. Please take a look at it and let me know your comments. If you agree with the design, I can re-submit the patchset with changes related to using these new APIs. Please let me know. arch/x86/include/asm/tdx.h | 27 ++++++++++++++++++++ arch/x86/kernel/tdx.c | 52 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 0b9d571b1f95..311252a90cfb 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -3,8 +3,27 @@ #ifndef _ASM_X86_TDX_H #define _ASM_X86_TDX_H +#include <linux/types.h> + #define TDX_CPUID_LEAF_ID 0x21 +#define TDVMCALL 0 + +/* TDVMCALL R10 Input */ +#define TDVMCALL_STANDARD 0 + +/* + * TDCALL instruction is newly added in TDX architecture, + * used by TD for requesting the host VMM to provide + * (untrusted) services. Supported in Binutils >= 2.36 + */ +#define TDCALL ".byte 0x66,0x0f,0x01,0xcc" + +struct tdcall_regs { + u64 rax, rcx, rdx; + u64 r8, r9, r10, r11, r12, r13, r14, r15; +}; + #ifdef CONFIG_INTEL_TDX_GUEST /* Common API to check TDX support in decompression and common kernel code. */ @@ -12,6 +31,10 @@ bool is_tdx_guest(void); void __init tdx_early_init(void); +void tdcall(u64 leafid, struct tdcall_regs *regs); + +void tdvmcall(u64 subid, struct tdcall_regs *regs); + #else // !CONFIG_INTEL_TDX_GUEST static inline bool is_tdx_guest(void) @@ -21,6 +44,10 @@ static inline bool is_tdx_guest(void) static inline void tdx_early_init(void) { }; +static inline void tdcall(u64 leafid, struct tdcall_regs *regs) { }; + +static inline void tdvmcall(u64 subid, struct tdcall_regs *regs) { }; + #endif /* CONFIG_INTEL_TDX_GUEST */ #endif /* _ASM_X86_TDX_H */ diff --git a/arch/x86/kernel/tdx.c b/arch/x86/kernel/tdx.c index e44e55d1e519..7ae1d25e272b 100644 --- a/arch/x86/kernel/tdx.c +++ b/arch/x86/kernel/tdx.c @@ -4,6 +4,58 @@ #include <asm/tdx.h> #include <asm/cpufeature.h> +void tdcall(u64 leafid, struct tdcall_regs *regs) +{ + asm volatile( + /* RAX = leafid (TDCALL LEAF ID) */ + " movq %0, %%rax;" + /* Move regs->r[*] data to regs r[a-c]x, r8-r5 */ + " movq 8(%1), %%rcx;" + " movq 16(%1), %%rdx;" + " movq 24(%1), %%r8;" + " movq 32(%1), %%r9;" + " movq 40(%1), %%r10;" + " movq 48(%1), %%r11;" + " movq 56(%1), %%r12;" + " movq 64(%1), %%r13;" + " movq 72(%1), %%r14;" + " movq 80(%1), %%r15;" + TDCALL ";" + /* Save TDCALL success/failure to regs->rax */ + " movq %%rax, (%1);" + /* Save rcx and rdx contents to regs->r[c-d]x */ + " movq %%rcx, 8(%1);" + " movq %%rdx, 16(%1);" + /* Move content of registers R8-R15 regs->r[8-15] */ + " movq %%r8, 24(%1);" + " movq %%r9, 32(%1);" + " movq %%r10, 40(%1);" + " movq %%r11, 48(%1);" + " movq %%r12, 56(%1);" + " movq %%r13, 64(%1);" + " movq %%r14, 72(%1);" + " movq %%r15, 80(%1);" + + : + : "r" (leafid), "r" (regs) + : "memory", "rax", "rbx", "rcx", "rdx", "r8", + "r9", "r10", "r11", "r12", "r13", "r14", "r15" + ); + +} + +void tdvmcall(u64 subid, struct tdcall_regs *regs) +{ + /* Expose GPRs R8-R15 to VMM */ + regs->rcx = 0xff00; + /* R10 = 0 (standard TDVMCALL) */ + regs->r10 = TDVMCALL_STANDARD; + /* Save subid to r11 register */ + regs->r11 = subid; + + tdcall(TDVMCALL, regs); +} + static inline bool cpuid_has_tdx_guest(void) { u32 eax, signature[3]; -- 2.25.1