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 */
42static 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
57static 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
73static 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
91static 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
110static 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
131static 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
153static 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
176static inline bool kvm_check_and_clear_guest_paused(void)
177{
178	return false;
179}
180
181static inline unsigned int kvm_arch_para_features(void)
182{
183	return 0;
184}
185
186static inline unsigned int kvm_arch_para_hints(void)
187{
188	return 0;
189}
190
191#ifdef CONFIG_PARAVIRT_SPINLOCKS
192void __init kvm_spinlock_init(void);
193#else /* !CONFIG_PARAVIRT_SPINLOCKS */
194static inline void kvm_spinlock_init(void)
195{
196}
197#endif /* CONFIG_PARAVIRT_SPINLOCKS */
198
199#endif /* _ASM_LOONGARCH_KVM_PARA_H */
200