1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _ASM_LOONGARCH_KVM_PARA_H
3 #define _ASM_LOONGARCH_KVM_PARA_H
4 
5 #include <uapi/asm/kvm_para.h>
6 
7 #define KVM_HYPERCALL ".word 0x002b8000"
8 /*
9  * Hypcall code field
10  */
11 #define KVM_HC_CODE_SERIVCE	0x0
12 #define KVM_HC_CODE_SWDBG	0x5
13 /*
14  *	function id
15  *	0x00000 ~ 0xfffff      Standard Hypervisor Calls
16  */
17 #define KVM_HC_FUNC_FEATURE	0x0
18 #define KVM_HC_FUNC_NOTIFY	0x1
19 #define KVM_HC_FUNC_IPI		0x2
20 /*
21  * LoongArch support PV feature list
22  */
23 #define KVM_FEATURE_STEAL_TIME	0
24 #define KVM_FEATURE_MULTI_IPI	1
25 #define KVM_FEATURE_PARAVIRT_SPINLOCK 2
26 /*
27  * LoongArch hypcall return code
28  */
29 #define KVM_RET_SUC	1
30 #define KVM_RET_NOT_SUPPORTED	-1
31 
32 #define KVM_VCPU_PREEMPTED (1 << 0)
33 
34 /*
35  * Hypercalls interface for KVM.
36  *
37  * a0: function identifier
38  * a1-a6: args
39  * Return value will be placed in v0.
40  * Up to 6 arguments are passed in a1, a2, a3, a4, a5, a6.
41  */
kvm_hypercall0(u64 fid)42 static inline long kvm_hypercall0(u64 fid)
43 {
44 	register long ret asm("v0");
45 	register unsigned long fun asm("a0") = fid;
46 
47 	__asm__ __volatile__(
48 		KVM_HYPERCALL
49 		: "=r" (ret)
50 		: "r" (fun)
51 		: "memory"
52 	);
53 
54 	return ret;
55 }
56 
kvm_hypercall1(u64 fid, unsigned long arg0)57 static inline long kvm_hypercall1(u64 fid, unsigned long arg0)
58 {
59 	register long ret asm("v0");
60 	register unsigned long fun asm("a0") = fid;
61 	register unsigned long a1 asm("a1") = arg0;
62 
63 	__asm__ __volatile__(
64 		KVM_HYPERCALL
65 		: "=r" (ret)
66 		: "r" (fun), "r" (a1)
67 		: "memory"
68 	);
69 
70 	return ret;
71 }
72 
kvm_hypercall2(u64 fid, unsigned long arg0, unsigned long arg1)73 static inline long kvm_hypercall2(u64 fid,
74 					unsigned long arg0, unsigned long arg1)
75 {
76 	register long ret asm("v0");
77 	register unsigned long fun asm("a0") = fid;
78 	register unsigned long a1 asm("a1") = arg0;
79 	register unsigned long a2 asm("a2") = arg1;
80 
81 	__asm__ __volatile__(
82 		KVM_HYPERCALL
83 		: "=r" (ret)
84 		: "r" (fun), "r" (a1), "r" (a2)
85 		: "memory"
86 	);
87 
88 	return ret;
89 }
90 
kvm_hypercall3(u64 fid, unsigned long arg0, unsigned long arg1, unsigned long arg2)91 static inline long kvm_hypercall3(u64 fid,
92 	unsigned long arg0, unsigned long arg1, unsigned long arg2)
93 {
94 	register long ret asm("v0");
95 	register unsigned long fun asm("a0") = fid;
96 	register unsigned long a1 asm("a1") = arg0;
97 	register unsigned long a2 asm("a2") = arg1;
98 	register unsigned long a3 asm("a3") = arg2;
99 
100 	__asm__ __volatile__(
101 		KVM_HYPERCALL
102 		: "=r" (ret)
103 		: "r" (fun), "r" (a1), "r" (a2), "r" (a3)
104 		: "memory"
105 	);
106 
107 	return ret;
108 }
109 
kvm_hypercall4(u64 fid, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3)110 static inline long kvm_hypercall4(u64 fid,
111 	unsigned long arg0, unsigned long arg1, unsigned long arg2,
112 	unsigned long arg3)
113 {
114 	register long ret asm("v0");
115 	register unsigned long fun asm("a0") = fid;
116 	register unsigned long a1 asm("a1") = arg0;
117 	register unsigned long a2 asm("a2") = arg1;
118 	register unsigned long a3 asm("a3") = arg2;
119 	register unsigned long a4 asm("a4") = arg3;
120 
121 	__asm__ __volatile__(
122 		KVM_HYPERCALL
123 		: "=r" (ret)
124 		: "i"(fun), "r" (a1), "r" (a2), "r" (a3), "r" (a4)
125 		: "memory"
126 	);
127 
128 	return ret;
129 }
130 
kvm_hypercall5(u64 fid, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4)131 static inline long kvm_hypercall5(u64 fid,
132 	unsigned long arg0, unsigned long arg1, unsigned long arg2,
133 	unsigned long arg3, unsigned long arg4)
134 {
135 	register long ret asm("v0");
136 	register unsigned long fun asm("a0") = fid;
137 	register unsigned long a1 asm("a1") = arg0;
138 	register unsigned long a2 asm("a2") = arg1;
139 	register unsigned long a3 asm("a3") = arg2;
140 	register unsigned long a4 asm("a4") = arg3;
141 	register unsigned long a5 asm("a5") = arg4;
142 
143 	__asm__ __volatile__(
144 		KVM_HYPERCALL
145 		: "=r" (ret)
146 		: "i"(fun), "r" (a1), "r" (a2), "r" (a3), "r" (a4), "r" (a5)
147 		: "memory"
148 	);
149 
150 	return ret;
151 }
152 
kvm_hypercall6(u64 fid, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5)153 static inline long kvm_hypercall6(u64 fid,
154 	unsigned long arg0, unsigned long arg1, unsigned long arg2,
155 	unsigned long arg3, unsigned long arg4, unsigned long arg5)
156 {
157 	register long ret asm("v0");
158 	register unsigned long fun asm("a0") = fid;
159 	register unsigned long a1 asm("a1") = arg0;
160 	register unsigned long a2 asm("a2") = arg1;
161 	register unsigned long a3 asm("a3") = arg2;
162 	register unsigned long a4 asm("a4") = arg3;
163 	register unsigned long a5 asm("a5") = arg4;
164 	register unsigned long a6 asm("a6") = arg5;
165 
166 	__asm__ __volatile__(
167 		KVM_HYPERCALL
168 		: "=r" (ret)
169 		: "i"(fun), "r" (a1), "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6)
170 		: "memory"
171 	);
172 
173 	return ret;
174 }
175 
kvm_check_and_clear_guest_paused(void)176 static inline bool kvm_check_and_clear_guest_paused(void)
177 {
178 	return false;
179 }
180 
kvm_arch_para_features(void)181 static inline unsigned int kvm_arch_para_features(void)
182 {
183 	return 0;
184 }
185 
kvm_arch_para_hints(void)186 static inline unsigned int kvm_arch_para_hints(void)
187 {
188 	return 0;
189 }
190 
191 #ifdef CONFIG_PARAVIRT_SPINLOCKS
192 void __init kvm_spinlock_init(void);
193 #else /* !CONFIG_PARAVIRT_SPINLOCKS */
kvm_spinlock_init(void)194 static inline void kvm_spinlock_init(void)
195 {
196 }
197 #endif /* CONFIG_PARAVIRT_SPINLOCKS */
198 
199 #endif /* _ASM_LOONGARCH_KVM_PARA_H */
200