Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/tdx: Wire up KVM hypercalls

KVM hypercalls use the VMCALL or VMMCALL instructions. Although the ABI
is similar, those instructions no longer function for TDX guests.

Make vendor-specific TDVMCALLs instead of VMCALL. This enables TDX
guests to run with KVM acting as the hypervisor.

Among other things, KVM hypercall is used to send IPIs.

Since the KVM driver can be built as a kernel module, export
tdx_kvm_hypercall() to make the symbols visible to kvm.ko.

Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20220405232939.73860-20-kirill.shutemov@linux.intel.com

authored by

Kuppuswamy Sathyanarayanan and committed by
Dave Hansen
cfb8ec7a 32e72854

+50
+17
arch/x86/coco/tdx/tdx.c
··· 64 64 return exit_reason; 65 65 } 66 66 67 + #ifdef CONFIG_KVM_GUEST 68 + long tdx_kvm_hypercall(unsigned int nr, unsigned long p1, unsigned long p2, 69 + unsigned long p3, unsigned long p4) 70 + { 71 + struct tdx_hypercall_args args = { 72 + .r10 = nr, 73 + .r11 = p1, 74 + .r12 = p2, 75 + .r13 = p3, 76 + .r14 = p4, 77 + }; 78 + 79 + return __tdx_hypercall(&args, 0); 80 + } 81 + EXPORT_SYMBOL_GPL(tdx_kvm_hypercall); 82 + #endif 83 + 67 84 /* 68 85 * Used for TDX guests to make calls directly to the TD module. This 69 86 * should only be used for calls that have no legitimate reason to fail
+22
arch/x86/include/asm/kvm_para.h
··· 7 7 #include <linux/interrupt.h> 8 8 #include <uapi/asm/kvm_para.h> 9 9 10 + #include <asm/tdx.h> 11 + 10 12 #ifdef CONFIG_KVM_GUEST 11 13 bool kvm_check_and_clear_guest_paused(void); 12 14 #else ··· 34 32 static inline long kvm_hypercall0(unsigned int nr) 35 33 { 36 34 long ret; 35 + 36 + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) 37 + return tdx_kvm_hypercall(nr, 0, 0, 0, 0); 38 + 37 39 asm volatile(KVM_HYPERCALL 38 40 : "=a"(ret) 39 41 : "a"(nr) ··· 48 42 static inline long kvm_hypercall1(unsigned int nr, unsigned long p1) 49 43 { 50 44 long ret; 45 + 46 + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) 47 + return tdx_kvm_hypercall(nr, p1, 0, 0, 0); 48 + 51 49 asm volatile(KVM_HYPERCALL 52 50 : "=a"(ret) 53 51 : "a"(nr), "b"(p1) ··· 63 53 unsigned long p2) 64 54 { 65 55 long ret; 56 + 57 + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) 58 + return tdx_kvm_hypercall(nr, p1, p2, 0, 0); 59 + 66 60 asm volatile(KVM_HYPERCALL 67 61 : "=a"(ret) 68 62 : "a"(nr), "b"(p1), "c"(p2) ··· 78 64 unsigned long p2, unsigned long p3) 79 65 { 80 66 long ret; 67 + 68 + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) 69 + return tdx_kvm_hypercall(nr, p1, p2, p3, 0); 70 + 81 71 asm volatile(KVM_HYPERCALL 82 72 : "=a"(ret) 83 73 : "a"(nr), "b"(p1), "c"(p2), "d"(p3) ··· 94 76 unsigned long p4) 95 77 { 96 78 long ret; 79 + 80 + if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) 81 + return tdx_kvm_hypercall(nr, p1, p2, p3, p4); 82 + 97 83 asm volatile(KVM_HYPERCALL 98 84 : "=a"(ret) 99 85 : "a"(nr), "b"(p1), "c"(p2), "d"(p3), "S"(p4)
+11
arch/x86/include/asm/tdx.h
··· 76 76 77 77 #endif /* CONFIG_INTEL_TDX_GUEST */ 78 78 79 + #if defined(CONFIG_KVM_GUEST) && defined(CONFIG_INTEL_TDX_GUEST) 80 + long tdx_kvm_hypercall(unsigned int nr, unsigned long p1, unsigned long p2, 81 + unsigned long p3, unsigned long p4); 82 + #else 83 + static inline long tdx_kvm_hypercall(unsigned int nr, unsigned long p1, 84 + unsigned long p2, unsigned long p3, 85 + unsigned long p4) 86 + { 87 + return -ENODEV; 88 + } 89 + #endif /* CONFIG_INTEL_TDX_GUEST && CONFIG_KVM_GUEST */ 79 90 #endif /* !__ASSEMBLY__ */ 80 91 #endif /* _ASM_X86_TDX_H */