This change adds a handler for tdx_hcall in the x86_hyper_runtime type for VMware hypervisors which will ultimately invoke __tdx_hypercall. The handler (vmware_tdx_user_hcall) does not reuse the existing vmware_tdx_hypercall for a couple of reasons. First, while the few hypercalls that are invoked from the kernel expect uint32 outputs, this may not be the case for every backdoor userspace may call. So the existing interface is not sufficient. Additionally, we don't require the branches based on output arguments. Finally, the VMWARE_CMD_MASK employed in vmware_tdx_hypercall is applicable to only hypercalls expected from the kernel. Signed-off-by: Tim Merrifield <tim.merrifield@xxxxxxxxxxxx> --- arch/x86/kernel/cpu/vmware.c | 51 ++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index 00189cdeb775..e379facc3a5b 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c @@ -494,6 +494,24 @@ static bool __init vmware_legacy_x2apic_available(void) * TDCALL[TDG.VP.VMCALL] uses %rax (arg0) and %rcx (arg2). Therefore, * we remap those registers to %r12 and %r13, respectively. */ +static inline void vmware_init_tdx_args(struct tdx_module_args *args, bool is_user, + unsigned long cmd, unsigned long in1, + unsigned long in3, unsigned long in4, + unsigned long in5, unsigned long in6) +{ + args->rbx = in1; + args->rdx = in3; + args->rsi = in4; + args->rdi = in5; + args->r10 = VMWARE_TDX_VENDOR_LEAF; + args->r11 = VMWARE_TDX_HCALL_FUNC; + args->r12 = VMWARE_HYPERVISOR_MAGIC; + args->r13 = cmd; + args->r14 = in6; + /* CPL */ + args->r15 = is_user ? 3 : 0; +} + unsigned long vmware_tdx_hypercall(unsigned long cmd, unsigned long in1, unsigned long in3, unsigned long in4, unsigned long in5, @@ -512,17 +530,7 @@ unsigned long vmware_tdx_hypercall(unsigned long cmd, return ULONG_MAX; } - args.rbx = in1; - args.rdx = in3; - args.rsi = in4; - args.rdi = in5; - args.r10 = VMWARE_TDX_VENDOR_LEAF; - args.r11 = VMWARE_TDX_HCALL_FUNC; - args.r12 = VMWARE_HYPERVISOR_MAGIC; - args.r13 = cmd; - /* CPL */ - args.r15 = 0; - + vmware_init_tdx_args(&args, false, cmd, in1, in3, in4, in5, 0); __tdx_hypercall(&args); if (out1) @@ -539,6 +547,24 @@ unsigned long vmware_tdx_hypercall(unsigned long cmd, return args.r12; } EXPORT_SYMBOL_GPL(vmware_tdx_hypercall); + +static int vmware_tdx_user_hcall(struct pt_regs *regs) +{ + struct tdx_module_args args = {}; + + vmware_init_tdx_args(&args, true, regs->cx, regs->bx, + regs->dx, regs->si, regs->di, regs->bp); + __tdx_hypercall(&args); + regs->ax = args.r12; + regs->bx = args.rbx; + regs->cx = args.r13; + regs->dx = args.rdx; + regs->si = args.rsi; + regs->di = args.rdi; + regs->bp = args.r14; + + return 0; +} #endif #ifdef CONFIG_AMD_MEM_ENCRYPT @@ -586,4 +612,7 @@ const __initconst struct hypervisor_x86 x86_hyper_vmware = { .runtime.sev_es_hcall_prepare = vmware_sev_es_hcall_prepare, .runtime.sev_es_hcall_finish = vmware_sev_es_hcall_finish, #endif +#ifdef CONFIG_INTEL_TDX_GUEST + .runtime.tdx_hcall = vmware_tdx_user_hcall, +#endif }; -- 2.40.1