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