Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | /* SPDX-License-Identifier: GPL-2.0 */ #ifndef _ASM_X86_KVM_PARA_H #define _ASM_X86_KVM_PARA_H #include <asm/processor.h> #include <asm/alternative.h> #include <linux/interrupt.h> #include <uapi/asm/kvm_para.h> #include <asm/tdx.h> #ifdef CONFIG_KVM_GUEST bool kvm_check_and_clear_guest_paused(void); #else static inline bool kvm_check_and_clear_guest_paused(void) { return false; } #endif /* CONFIG_KVM_GUEST */ #define KVM_HYPERCALL \ ALTERNATIVE("vmcall", "vmmcall", X86_FEATURE_VMMCALL) /* For KVM hypercalls, a three-byte sequence of either the vmcall or the vmmcall * instruction. The hypervisor may replace it with something else but only the * instructions are guaranteed to be supported. * * Up to four arguments may be passed in rbx, rcx, rdx, and rsi respectively. * The hypercall number should be placed in rax and the return value will be * placed in rax. No other registers will be clobbered unless explicitly * noted by the particular hypercall. */ static inline long kvm_hypercall0(unsigned int nr) { long ret; if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) return tdx_kvm_hypercall(nr, 0, 0, 0, 0); asm volatile(KVM_HYPERCALL : "=a"(ret) : "a"(nr) : "memory"); return ret; } static inline long kvm_hypercall1(unsigned int nr, unsigned long p1) { long ret; if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) return tdx_kvm_hypercall(nr, p1, 0, 0, 0); asm volatile(KVM_HYPERCALL : "=a"(ret) : "a"(nr), "b"(p1) : "memory"); return ret; } static inline long kvm_hypercall2(unsigned int nr, unsigned long p1, unsigned long p2) { long ret; if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) return tdx_kvm_hypercall(nr, p1, p2, 0, 0); asm volatile(KVM_HYPERCALL : "=a"(ret) : "a"(nr), "b"(p1), "c"(p2) : "memory"); return ret; } static inline long kvm_hypercall3(unsigned int nr, unsigned long p1, unsigned long p2, unsigned long p3) { long ret; if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) return tdx_kvm_hypercall(nr, p1, p2, p3, 0); asm volatile(KVM_HYPERCALL : "=a"(ret) : "a"(nr), "b"(p1), "c"(p2), "d"(p3) : "memory"); return ret; } static inline long kvm_hypercall4(unsigned int nr, unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4) { long ret; if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) return tdx_kvm_hypercall(nr, p1, p2, p3, p4); asm volatile(KVM_HYPERCALL : "=a"(ret) : "a"(nr), "b"(p1), "c"(p2), "d"(p3), "S"(p4) : "memory"); return ret; } static inline long kvm_sev_hypercall3(unsigned int nr, unsigned long p1, unsigned long p2, unsigned long p3) { long ret; asm volatile("vmmcall" : "=a"(ret) : "a"(nr), "b"(p1), "c"(p2), "d"(p3) : "memory"); return ret; } #ifdef CONFIG_KVM_GUEST void kvmclock_init(void); void kvmclock_disable(void); bool kvm_para_available(void); unsigned int kvm_arch_para_features(void); unsigned int kvm_arch_para_hints(void); void kvm_async_pf_task_wait_schedule(u32 token); void kvm_async_pf_task_wake(u32 token); u32 kvm_read_and_reset_apf_flags(void); bool __kvm_handle_async_pf(struct pt_regs *regs, u32 token); DECLARE_STATIC_KEY_FALSE(kvm_async_pf_enabled); static __always_inline bool kvm_handle_async_pf(struct pt_regs *regs, u32 token) { if (static_branch_unlikely(&kvm_async_pf_enabled)) return __kvm_handle_async_pf(regs, token); else return false; } #ifdef CONFIG_PARAVIRT_SPINLOCKS void __init kvm_spinlock_init(void); #else /* !CONFIG_PARAVIRT_SPINLOCKS */ static inline void kvm_spinlock_init(void) { } #endif /* CONFIG_PARAVIRT_SPINLOCKS */ #else /* CONFIG_KVM_GUEST */ #define kvm_async_pf_task_wait_schedule(T) do {} while(0) #define kvm_async_pf_task_wake(T) do {} while(0) static inline bool kvm_para_available(void) { return false; } static inline unsigned int kvm_arch_para_features(void) { return 0; } static inline unsigned int kvm_arch_para_hints(void) { return 0; } static inline u32 kvm_read_and_reset_apf_flags(void) { return 0; } static __always_inline bool kvm_handle_async_pf(struct pt_regs *regs, u32 token) { return false; } #endif #endif /* _ASM_X86_KVM_PARA_H */ |