[PATCH v2 2/2] x86/vmware: VMware support for TDX userspace hypercalls
From: Tim Merrifield
Date: Fri Jul 26 2024 - 14:49:49 EST
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