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