xref: /OK3568_Linux_fs/kernel/arch/x86/include/asm/xen/hypercall.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /******************************************************************************
2*4882a593Smuzhiyun  * hypercall.h
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Linux-specific hypervisor handling.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Copyright (c) 2002-2004, K A Fraser
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * This program is free software; you can redistribute it and/or
9*4882a593Smuzhiyun  * modify it under the terms of the GNU General Public License version 2
10*4882a593Smuzhiyun  * as published by the Free Software Foundation; or, when distributed
11*4882a593Smuzhiyun  * separately from the Linux kernel or incorporated into other
12*4882a593Smuzhiyun  * software packages, subject to the following license:
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining a copy
15*4882a593Smuzhiyun  * of this source file (the "Software"), to deal in the Software without
16*4882a593Smuzhiyun  * restriction, including without limitation the rights to use, copy, modify,
17*4882a593Smuzhiyun  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
18*4882a593Smuzhiyun  * and to permit persons to whom the Software is furnished to do so, subject to
19*4882a593Smuzhiyun  * the following conditions:
20*4882a593Smuzhiyun  *
21*4882a593Smuzhiyun  * The above copyright notice and this permission notice shall be included in
22*4882a593Smuzhiyun  * all copies or substantial portions of the Software.
23*4882a593Smuzhiyun  *
24*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25*4882a593Smuzhiyun  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26*4882a593Smuzhiyun  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27*4882a593Smuzhiyun  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28*4882a593Smuzhiyun  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29*4882a593Smuzhiyun  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30*4882a593Smuzhiyun  * IN THE SOFTWARE.
31*4882a593Smuzhiyun  */
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #ifndef _ASM_X86_XEN_HYPERCALL_H
34*4882a593Smuzhiyun #define _ASM_X86_XEN_HYPERCALL_H
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #include <linux/kernel.h>
37*4882a593Smuzhiyun #include <linux/spinlock.h>
38*4882a593Smuzhiyun #include <linux/errno.h>
39*4882a593Smuzhiyun #include <linux/string.h>
40*4882a593Smuzhiyun #include <linux/types.h>
41*4882a593Smuzhiyun #include <linux/pgtable.h>
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun #include <trace/events/xen.h>
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun #include <asm/page.h>
46*4882a593Smuzhiyun #include <asm/smap.h>
47*4882a593Smuzhiyun #include <asm/nospec-branch.h>
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun #include <xen/interface/xen.h>
50*4882a593Smuzhiyun #include <xen/interface/sched.h>
51*4882a593Smuzhiyun #include <xen/interface/physdev.h>
52*4882a593Smuzhiyun #include <xen/interface/platform.h>
53*4882a593Smuzhiyun #include <xen/interface/xen-mca.h>
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun struct xen_dm_op_buf;
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun /*
58*4882a593Smuzhiyun  * The hypercall asms have to meet several constraints:
59*4882a593Smuzhiyun  * - Work on 32- and 64-bit.
60*4882a593Smuzhiyun  *    The two architectures put their arguments in different sets of
61*4882a593Smuzhiyun  *    registers.
62*4882a593Smuzhiyun  *
63*4882a593Smuzhiyun  * - Work around asm syntax quirks
64*4882a593Smuzhiyun  *    It isn't possible to specify one of the rNN registers in a
65*4882a593Smuzhiyun  *    constraint, so we use explicit register variables to get the
66*4882a593Smuzhiyun  *    args into the right place.
67*4882a593Smuzhiyun  *
68*4882a593Smuzhiyun  * - Mark all registers as potentially clobbered
69*4882a593Smuzhiyun  *    Even unused parameters can be clobbered by the hypervisor, so we
70*4882a593Smuzhiyun  *    need to make sure gcc knows it.
71*4882a593Smuzhiyun  *
72*4882a593Smuzhiyun  * - Avoid compiler bugs.
73*4882a593Smuzhiyun  *    This is the tricky part.  Because x86_32 has such a constrained
74*4882a593Smuzhiyun  *    register set, gcc versions below 4.3 have trouble generating
75*4882a593Smuzhiyun  *    code when all the arg registers and memory are trashed by the
76*4882a593Smuzhiyun  *    asm.  There are syntactically simpler ways of achieving the
77*4882a593Smuzhiyun  *    semantics below, but they cause the compiler to crash.
78*4882a593Smuzhiyun  *
79*4882a593Smuzhiyun  *    The only combination I found which works is:
80*4882a593Smuzhiyun  *     - assign the __argX variables first
81*4882a593Smuzhiyun  *     - list all actually used parameters as "+r" (__argX)
82*4882a593Smuzhiyun  *     - clobber the rest
83*4882a593Smuzhiyun  *
84*4882a593Smuzhiyun  * The result certainly isn't pretty, and it really shows up cpp's
85*4882a593Smuzhiyun  * weakness as a macro language.  Sorry.  (But let's just give thanks
86*4882a593Smuzhiyun  * there aren't more than 5 arguments...)
87*4882a593Smuzhiyun  */
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun extern struct { char _entry[32]; } hypercall_page[];
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun #define __HYPERCALL		"call hypercall_page+%c[offset]"
92*4882a593Smuzhiyun #define __HYPERCALL_ENTRY(x)						\
93*4882a593Smuzhiyun 	[offset] "i" (__HYPERVISOR_##x * sizeof(hypercall_page[0]))
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun #ifdef CONFIG_X86_32
96*4882a593Smuzhiyun #define __HYPERCALL_RETREG	"eax"
97*4882a593Smuzhiyun #define __HYPERCALL_ARG1REG	"ebx"
98*4882a593Smuzhiyun #define __HYPERCALL_ARG2REG	"ecx"
99*4882a593Smuzhiyun #define __HYPERCALL_ARG3REG	"edx"
100*4882a593Smuzhiyun #define __HYPERCALL_ARG4REG	"esi"
101*4882a593Smuzhiyun #define __HYPERCALL_ARG5REG	"edi"
102*4882a593Smuzhiyun #else
103*4882a593Smuzhiyun #define __HYPERCALL_RETREG	"rax"
104*4882a593Smuzhiyun #define __HYPERCALL_ARG1REG	"rdi"
105*4882a593Smuzhiyun #define __HYPERCALL_ARG2REG	"rsi"
106*4882a593Smuzhiyun #define __HYPERCALL_ARG3REG	"rdx"
107*4882a593Smuzhiyun #define __HYPERCALL_ARG4REG	"r10"
108*4882a593Smuzhiyun #define __HYPERCALL_ARG5REG	"r8"
109*4882a593Smuzhiyun #endif
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun #define __HYPERCALL_DECLS						\
112*4882a593Smuzhiyun 	register unsigned long __res  asm(__HYPERCALL_RETREG);		\
113*4882a593Smuzhiyun 	register unsigned long __arg1 asm(__HYPERCALL_ARG1REG) = __arg1; \
114*4882a593Smuzhiyun 	register unsigned long __arg2 asm(__HYPERCALL_ARG2REG) = __arg2; \
115*4882a593Smuzhiyun 	register unsigned long __arg3 asm(__HYPERCALL_ARG3REG) = __arg3; \
116*4882a593Smuzhiyun 	register unsigned long __arg4 asm(__HYPERCALL_ARG4REG) = __arg4; \
117*4882a593Smuzhiyun 	register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun #define __HYPERCALL_0PARAM	"=r" (__res), ASM_CALL_CONSTRAINT
120*4882a593Smuzhiyun #define __HYPERCALL_1PARAM	__HYPERCALL_0PARAM, "+r" (__arg1)
121*4882a593Smuzhiyun #define __HYPERCALL_2PARAM	__HYPERCALL_1PARAM, "+r" (__arg2)
122*4882a593Smuzhiyun #define __HYPERCALL_3PARAM	__HYPERCALL_2PARAM, "+r" (__arg3)
123*4882a593Smuzhiyun #define __HYPERCALL_4PARAM	__HYPERCALL_3PARAM, "+r" (__arg4)
124*4882a593Smuzhiyun #define __HYPERCALL_5PARAM	__HYPERCALL_4PARAM, "+r" (__arg5)
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun #define __HYPERCALL_0ARG()
127*4882a593Smuzhiyun #define __HYPERCALL_1ARG(a1)						\
128*4882a593Smuzhiyun 	__HYPERCALL_0ARG()		__arg1 = (unsigned long)(a1);
129*4882a593Smuzhiyun #define __HYPERCALL_2ARG(a1,a2)						\
130*4882a593Smuzhiyun 	__HYPERCALL_1ARG(a1)		__arg2 = (unsigned long)(a2);
131*4882a593Smuzhiyun #define __HYPERCALL_3ARG(a1,a2,a3)					\
132*4882a593Smuzhiyun 	__HYPERCALL_2ARG(a1,a2)		__arg3 = (unsigned long)(a3);
133*4882a593Smuzhiyun #define __HYPERCALL_4ARG(a1,a2,a3,a4)					\
134*4882a593Smuzhiyun 	__HYPERCALL_3ARG(a1,a2,a3)	__arg4 = (unsigned long)(a4);
135*4882a593Smuzhiyun #define __HYPERCALL_5ARG(a1,a2,a3,a4,a5)				\
136*4882a593Smuzhiyun 	__HYPERCALL_4ARG(a1,a2,a3,a4)	__arg5 = (unsigned long)(a5);
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun #define __HYPERCALL_CLOBBER5	"memory"
139*4882a593Smuzhiyun #define __HYPERCALL_CLOBBER4	__HYPERCALL_CLOBBER5, __HYPERCALL_ARG5REG
140*4882a593Smuzhiyun #define __HYPERCALL_CLOBBER3	__HYPERCALL_CLOBBER4, __HYPERCALL_ARG4REG
141*4882a593Smuzhiyun #define __HYPERCALL_CLOBBER2	__HYPERCALL_CLOBBER3, __HYPERCALL_ARG3REG
142*4882a593Smuzhiyun #define __HYPERCALL_CLOBBER1	__HYPERCALL_CLOBBER2, __HYPERCALL_ARG2REG
143*4882a593Smuzhiyun #define __HYPERCALL_CLOBBER0	__HYPERCALL_CLOBBER1, __HYPERCALL_ARG1REG
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun #define _hypercall0(type, name)						\
146*4882a593Smuzhiyun ({									\
147*4882a593Smuzhiyun 	__HYPERCALL_DECLS;						\
148*4882a593Smuzhiyun 	__HYPERCALL_0ARG();						\
149*4882a593Smuzhiyun 	asm volatile (__HYPERCALL					\
150*4882a593Smuzhiyun 		      : __HYPERCALL_0PARAM				\
151*4882a593Smuzhiyun 		      : __HYPERCALL_ENTRY(name)				\
152*4882a593Smuzhiyun 		      : __HYPERCALL_CLOBBER0);				\
153*4882a593Smuzhiyun 	(type)__res;							\
154*4882a593Smuzhiyun })
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun #define _hypercall1(type, name, a1)					\
157*4882a593Smuzhiyun ({									\
158*4882a593Smuzhiyun 	__HYPERCALL_DECLS;						\
159*4882a593Smuzhiyun 	__HYPERCALL_1ARG(a1);						\
160*4882a593Smuzhiyun 	asm volatile (__HYPERCALL					\
161*4882a593Smuzhiyun 		      : __HYPERCALL_1PARAM				\
162*4882a593Smuzhiyun 		      : __HYPERCALL_ENTRY(name)				\
163*4882a593Smuzhiyun 		      : __HYPERCALL_CLOBBER1);				\
164*4882a593Smuzhiyun 	(type)__res;							\
165*4882a593Smuzhiyun })
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun #define _hypercall2(type, name, a1, a2)					\
168*4882a593Smuzhiyun ({									\
169*4882a593Smuzhiyun 	__HYPERCALL_DECLS;						\
170*4882a593Smuzhiyun 	__HYPERCALL_2ARG(a1, a2);					\
171*4882a593Smuzhiyun 	asm volatile (__HYPERCALL					\
172*4882a593Smuzhiyun 		      : __HYPERCALL_2PARAM				\
173*4882a593Smuzhiyun 		      : __HYPERCALL_ENTRY(name)				\
174*4882a593Smuzhiyun 		      : __HYPERCALL_CLOBBER2);				\
175*4882a593Smuzhiyun 	(type)__res;							\
176*4882a593Smuzhiyun })
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun #define _hypercall3(type, name, a1, a2, a3)				\
179*4882a593Smuzhiyun ({									\
180*4882a593Smuzhiyun 	__HYPERCALL_DECLS;						\
181*4882a593Smuzhiyun 	__HYPERCALL_3ARG(a1, a2, a3);					\
182*4882a593Smuzhiyun 	asm volatile (__HYPERCALL					\
183*4882a593Smuzhiyun 		      : __HYPERCALL_3PARAM				\
184*4882a593Smuzhiyun 		      : __HYPERCALL_ENTRY(name)				\
185*4882a593Smuzhiyun 		      : __HYPERCALL_CLOBBER3);				\
186*4882a593Smuzhiyun 	(type)__res;							\
187*4882a593Smuzhiyun })
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun #define _hypercall4(type, name, a1, a2, a3, a4)				\
190*4882a593Smuzhiyun ({									\
191*4882a593Smuzhiyun 	__HYPERCALL_DECLS;						\
192*4882a593Smuzhiyun 	__HYPERCALL_4ARG(a1, a2, a3, a4);				\
193*4882a593Smuzhiyun 	asm volatile (__HYPERCALL					\
194*4882a593Smuzhiyun 		      : __HYPERCALL_4PARAM				\
195*4882a593Smuzhiyun 		      : __HYPERCALL_ENTRY(name)				\
196*4882a593Smuzhiyun 		      : __HYPERCALL_CLOBBER4);				\
197*4882a593Smuzhiyun 	(type)__res;							\
198*4882a593Smuzhiyun })
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun static inline long
xen_single_call(unsigned int call,unsigned long a1,unsigned long a2,unsigned long a3,unsigned long a4,unsigned long a5)201*4882a593Smuzhiyun xen_single_call(unsigned int call,
202*4882a593Smuzhiyun 		unsigned long a1, unsigned long a2,
203*4882a593Smuzhiyun 		unsigned long a3, unsigned long a4,
204*4882a593Smuzhiyun 		unsigned long a5)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun 	__HYPERCALL_DECLS;
207*4882a593Smuzhiyun 	__HYPERCALL_5ARG(a1, a2, a3, a4, a5);
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	if (call >= PAGE_SIZE / sizeof(hypercall_page[0]))
210*4882a593Smuzhiyun 		return -EINVAL;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	asm volatile(CALL_NOSPEC
213*4882a593Smuzhiyun 		     : __HYPERCALL_5PARAM
214*4882a593Smuzhiyun 		     : [thunk_target] "a" (&hypercall_page[call])
215*4882a593Smuzhiyun 		     : __HYPERCALL_CLOBBER5);
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	return (long)__res;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun 
__xen_stac(void)220*4882a593Smuzhiyun static __always_inline void __xen_stac(void)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun 	/*
223*4882a593Smuzhiyun 	 * Suppress objtool seeing the STAC/CLAC and getting confused about it
224*4882a593Smuzhiyun 	 * calling random code with AC=1.
225*4882a593Smuzhiyun 	 */
226*4882a593Smuzhiyun 	asm volatile(ANNOTATE_IGNORE_ALTERNATIVE
227*4882a593Smuzhiyun 		     ASM_STAC ::: "memory", "flags");
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun 
__xen_clac(void)230*4882a593Smuzhiyun static __always_inline void __xen_clac(void)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun 	asm volatile(ANNOTATE_IGNORE_ALTERNATIVE
233*4882a593Smuzhiyun 		     ASM_CLAC ::: "memory", "flags");
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun static inline long
privcmd_call(unsigned int call,unsigned long a1,unsigned long a2,unsigned long a3,unsigned long a4,unsigned long a5)237*4882a593Smuzhiyun privcmd_call(unsigned int call,
238*4882a593Smuzhiyun 	     unsigned long a1, unsigned long a2,
239*4882a593Smuzhiyun 	     unsigned long a3, unsigned long a4,
240*4882a593Smuzhiyun 	     unsigned long a5)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun 	long res;
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	__xen_stac();
245*4882a593Smuzhiyun 	res = xen_single_call(call, a1, a2, a3, a4, a5);
246*4882a593Smuzhiyun 	__xen_clac();
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	return res;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun static inline int
HYPERVISOR_set_trap_table(struct trap_info * table)252*4882a593Smuzhiyun HYPERVISOR_set_trap_table(struct trap_info *table)
253*4882a593Smuzhiyun {
254*4882a593Smuzhiyun 	return _hypercall1(int, set_trap_table, table);
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun static inline int
HYPERVISOR_mmu_update(struct mmu_update * req,int count,int * success_count,domid_t domid)258*4882a593Smuzhiyun HYPERVISOR_mmu_update(struct mmu_update *req, int count,
259*4882a593Smuzhiyun 		      int *success_count, domid_t domid)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun 	return _hypercall4(int, mmu_update, req, count, success_count, domid);
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun static inline int
HYPERVISOR_mmuext_op(struct mmuext_op * op,int count,int * success_count,domid_t domid)265*4882a593Smuzhiyun HYPERVISOR_mmuext_op(struct mmuext_op *op, int count,
266*4882a593Smuzhiyun 		     int *success_count, domid_t domid)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun 	return _hypercall4(int, mmuext_op, op, count, success_count, domid);
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun static inline int
HYPERVISOR_set_gdt(unsigned long * frame_list,int entries)272*4882a593Smuzhiyun HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun 	return _hypercall2(int, set_gdt, frame_list, entries);
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun static inline int
HYPERVISOR_callback_op(int cmd,void * arg)278*4882a593Smuzhiyun HYPERVISOR_callback_op(int cmd, void *arg)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun 	return _hypercall2(int, callback_op, cmd, arg);
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun static inline int
HYPERVISOR_sched_op(int cmd,void * arg)284*4882a593Smuzhiyun HYPERVISOR_sched_op(int cmd, void *arg)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun 	return _hypercall2(int, sched_op, cmd, arg);
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun static inline long
HYPERVISOR_set_timer_op(u64 timeout)290*4882a593Smuzhiyun HYPERVISOR_set_timer_op(u64 timeout)
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun 	unsigned long timeout_hi = (unsigned long)(timeout>>32);
293*4882a593Smuzhiyun 	unsigned long timeout_lo = (unsigned long)timeout;
294*4882a593Smuzhiyun 	return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun static inline int
HYPERVISOR_mca(struct xen_mc * mc_op)298*4882a593Smuzhiyun HYPERVISOR_mca(struct xen_mc *mc_op)
299*4882a593Smuzhiyun {
300*4882a593Smuzhiyun 	mc_op->interface_version = XEN_MCA_INTERFACE_VERSION;
301*4882a593Smuzhiyun 	return _hypercall1(int, mca, mc_op);
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun static inline int
HYPERVISOR_platform_op(struct xen_platform_op * op)305*4882a593Smuzhiyun HYPERVISOR_platform_op(struct xen_platform_op *op)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun 	op->interface_version = XENPF_INTERFACE_VERSION;
308*4882a593Smuzhiyun 	return _hypercall1(int, platform_op, op);
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun static inline int
HYPERVISOR_set_debugreg(int reg,unsigned long value)312*4882a593Smuzhiyun HYPERVISOR_set_debugreg(int reg, unsigned long value)
313*4882a593Smuzhiyun {
314*4882a593Smuzhiyun 	return _hypercall2(int, set_debugreg, reg, value);
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun static inline unsigned long
HYPERVISOR_get_debugreg(int reg)318*4882a593Smuzhiyun HYPERVISOR_get_debugreg(int reg)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun 	return _hypercall1(unsigned long, get_debugreg, reg);
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun static inline int
HYPERVISOR_update_descriptor(u64 ma,u64 desc)324*4882a593Smuzhiyun HYPERVISOR_update_descriptor(u64 ma, u64 desc)
325*4882a593Smuzhiyun {
326*4882a593Smuzhiyun 	if (sizeof(u64) == sizeof(long))
327*4882a593Smuzhiyun 		return _hypercall2(int, update_descriptor, ma, desc);
328*4882a593Smuzhiyun 	return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun static inline long
HYPERVISOR_memory_op(unsigned int cmd,void * arg)332*4882a593Smuzhiyun HYPERVISOR_memory_op(unsigned int cmd, void *arg)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun 	return _hypercall2(long, memory_op, cmd, arg);
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun static inline int
HYPERVISOR_multicall(void * call_list,uint32_t nr_calls)338*4882a593Smuzhiyun HYPERVISOR_multicall(void *call_list, uint32_t nr_calls)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun 	return _hypercall2(int, multicall, call_list, nr_calls);
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun static inline int
HYPERVISOR_update_va_mapping(unsigned long va,pte_t new_val,unsigned long flags)344*4882a593Smuzhiyun HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,
345*4882a593Smuzhiyun 			     unsigned long flags)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun 	if (sizeof(new_val) == sizeof(long))
348*4882a593Smuzhiyun 		return _hypercall3(int, update_va_mapping, va,
349*4882a593Smuzhiyun 				   new_val.pte, flags);
350*4882a593Smuzhiyun 	else
351*4882a593Smuzhiyun 		return _hypercall4(int, update_va_mapping, va,
352*4882a593Smuzhiyun 				   new_val.pte, new_val.pte >> 32, flags);
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun static inline int
HYPERVISOR_event_channel_op(int cmd,void * arg)356*4882a593Smuzhiyun HYPERVISOR_event_channel_op(int cmd, void *arg)
357*4882a593Smuzhiyun {
358*4882a593Smuzhiyun 	return _hypercall2(int, event_channel_op, cmd, arg);
359*4882a593Smuzhiyun }
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun static inline int
HYPERVISOR_xen_version(int cmd,void * arg)362*4882a593Smuzhiyun HYPERVISOR_xen_version(int cmd, void *arg)
363*4882a593Smuzhiyun {
364*4882a593Smuzhiyun 	return _hypercall2(int, xen_version, cmd, arg);
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun static inline int
HYPERVISOR_console_io(int cmd,int count,char * str)368*4882a593Smuzhiyun HYPERVISOR_console_io(int cmd, int count, char *str)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun 	return _hypercall3(int, console_io, cmd, count, str);
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun static inline int
HYPERVISOR_physdev_op(int cmd,void * arg)374*4882a593Smuzhiyun HYPERVISOR_physdev_op(int cmd, void *arg)
375*4882a593Smuzhiyun {
376*4882a593Smuzhiyun 	return _hypercall2(int, physdev_op, cmd, arg);
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun static inline int
HYPERVISOR_grant_table_op(unsigned int cmd,void * uop,unsigned int count)380*4882a593Smuzhiyun HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun 	return _hypercall3(int, grant_table_op, cmd, uop, count);
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun static inline int
HYPERVISOR_vm_assist(unsigned int cmd,unsigned int type)386*4882a593Smuzhiyun HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
387*4882a593Smuzhiyun {
388*4882a593Smuzhiyun 	return _hypercall2(int, vm_assist, cmd, type);
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun static inline int
HYPERVISOR_vcpu_op(int cmd,int vcpuid,void * extra_args)392*4882a593Smuzhiyun HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun 	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun #ifdef CONFIG_X86_64
398*4882a593Smuzhiyun static inline int
HYPERVISOR_set_segment_base(int reg,unsigned long value)399*4882a593Smuzhiyun HYPERVISOR_set_segment_base(int reg, unsigned long value)
400*4882a593Smuzhiyun {
401*4882a593Smuzhiyun 	return _hypercall2(int, set_segment_base, reg, value);
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun #endif
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun static inline int
HYPERVISOR_suspend(unsigned long start_info_mfn)406*4882a593Smuzhiyun HYPERVISOR_suspend(unsigned long start_info_mfn)
407*4882a593Smuzhiyun {
408*4882a593Smuzhiyun 	struct sched_shutdown r = { .reason = SHUTDOWN_suspend };
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	/*
411*4882a593Smuzhiyun 	 * For a PV guest the tools require that the start_info mfn be
412*4882a593Smuzhiyun 	 * present in rdx/edx when the hypercall is made. Per the
413*4882a593Smuzhiyun 	 * hypercall calling convention this is the third hypercall
414*4882a593Smuzhiyun 	 * argument, which is start_info_mfn here.
415*4882a593Smuzhiyun 	 */
416*4882a593Smuzhiyun 	return _hypercall3(int, sched_op, SCHEDOP_shutdown, &r, start_info_mfn);
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun static inline unsigned long __must_check
HYPERVISOR_hvm_op(int op,void * arg)420*4882a593Smuzhiyun HYPERVISOR_hvm_op(int op, void *arg)
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun        return _hypercall2(unsigned long, hvm_op, op, arg);
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun static inline int
HYPERVISOR_tmem_op(struct tmem_op * op)426*4882a593Smuzhiyun HYPERVISOR_tmem_op(
427*4882a593Smuzhiyun 	struct tmem_op *op)
428*4882a593Smuzhiyun {
429*4882a593Smuzhiyun 	return _hypercall1(int, tmem_op, op);
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun static inline int
HYPERVISOR_xenpmu_op(unsigned int op,void * arg)433*4882a593Smuzhiyun HYPERVISOR_xenpmu_op(unsigned int op, void *arg)
434*4882a593Smuzhiyun {
435*4882a593Smuzhiyun 	return _hypercall2(int, xenpmu_op, op, arg);
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun static inline int
HYPERVISOR_dm_op(domid_t dom,unsigned int nr_bufs,struct xen_dm_op_buf * bufs)439*4882a593Smuzhiyun HYPERVISOR_dm_op(
440*4882a593Smuzhiyun 	domid_t dom, unsigned int nr_bufs, struct xen_dm_op_buf *bufs)
441*4882a593Smuzhiyun {
442*4882a593Smuzhiyun 	int ret;
443*4882a593Smuzhiyun 	__xen_stac();
444*4882a593Smuzhiyun 	ret = _hypercall3(int, dm_op, dom, nr_bufs, bufs);
445*4882a593Smuzhiyun 	__xen_clac();
446*4882a593Smuzhiyun 	return ret;
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun static inline void
MULTI_fpu_taskswitch(struct multicall_entry * mcl,int set)450*4882a593Smuzhiyun MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
451*4882a593Smuzhiyun {
452*4882a593Smuzhiyun 	mcl->op = __HYPERVISOR_fpu_taskswitch;
453*4882a593Smuzhiyun 	mcl->args[0] = set;
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 	trace_xen_mc_entry(mcl, 1);
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun static inline void
MULTI_update_va_mapping(struct multicall_entry * mcl,unsigned long va,pte_t new_val,unsigned long flags)459*4882a593Smuzhiyun MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
460*4882a593Smuzhiyun 			pte_t new_val, unsigned long flags)
461*4882a593Smuzhiyun {
462*4882a593Smuzhiyun 	mcl->op = __HYPERVISOR_update_va_mapping;
463*4882a593Smuzhiyun 	mcl->args[0] = va;
464*4882a593Smuzhiyun 	if (sizeof(new_val) == sizeof(long)) {
465*4882a593Smuzhiyun 		mcl->args[1] = new_val.pte;
466*4882a593Smuzhiyun 		mcl->args[2] = flags;
467*4882a593Smuzhiyun 	} else {
468*4882a593Smuzhiyun 		mcl->args[1] = new_val.pte;
469*4882a593Smuzhiyun 		mcl->args[2] = new_val.pte >> 32;
470*4882a593Smuzhiyun 		mcl->args[3] = flags;
471*4882a593Smuzhiyun 	}
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun 	trace_xen_mc_entry(mcl, sizeof(new_val) == sizeof(long) ? 3 : 4);
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun static inline void
MULTI_update_descriptor(struct multicall_entry * mcl,u64 maddr,struct desc_struct desc)477*4882a593Smuzhiyun MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr,
478*4882a593Smuzhiyun 			struct desc_struct desc)
479*4882a593Smuzhiyun {
480*4882a593Smuzhiyun 	mcl->op = __HYPERVISOR_update_descriptor;
481*4882a593Smuzhiyun 	if (sizeof(maddr) == sizeof(long)) {
482*4882a593Smuzhiyun 		mcl->args[0] = maddr;
483*4882a593Smuzhiyun 		mcl->args[1] = *(unsigned long *)&desc;
484*4882a593Smuzhiyun 	} else {
485*4882a593Smuzhiyun 		u32 *p = (u32 *)&desc;
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 		mcl->args[0] = maddr;
488*4882a593Smuzhiyun 		mcl->args[1] = maddr >> 32;
489*4882a593Smuzhiyun 		mcl->args[2] = *p++;
490*4882a593Smuzhiyun 		mcl->args[3] = *p;
491*4882a593Smuzhiyun 	}
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun 	trace_xen_mc_entry(mcl, sizeof(maddr) == sizeof(long) ? 2 : 4);
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun static inline void
MULTI_mmu_update(struct multicall_entry * mcl,struct mmu_update * req,int count,int * success_count,domid_t domid)497*4882a593Smuzhiyun MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
498*4882a593Smuzhiyun 		 int count, int *success_count, domid_t domid)
499*4882a593Smuzhiyun {
500*4882a593Smuzhiyun 	mcl->op = __HYPERVISOR_mmu_update;
501*4882a593Smuzhiyun 	mcl->args[0] = (unsigned long)req;
502*4882a593Smuzhiyun 	mcl->args[1] = count;
503*4882a593Smuzhiyun 	mcl->args[2] = (unsigned long)success_count;
504*4882a593Smuzhiyun 	mcl->args[3] = domid;
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	trace_xen_mc_entry(mcl, 4);
507*4882a593Smuzhiyun }
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun static inline void
MULTI_mmuext_op(struct multicall_entry * mcl,struct mmuext_op * op,int count,int * success_count,domid_t domid)510*4882a593Smuzhiyun MULTI_mmuext_op(struct multicall_entry *mcl, struct mmuext_op *op, int count,
511*4882a593Smuzhiyun 		int *success_count, domid_t domid)
512*4882a593Smuzhiyun {
513*4882a593Smuzhiyun 	mcl->op = __HYPERVISOR_mmuext_op;
514*4882a593Smuzhiyun 	mcl->args[0] = (unsigned long)op;
515*4882a593Smuzhiyun 	mcl->args[1] = count;
516*4882a593Smuzhiyun 	mcl->args[2] = (unsigned long)success_count;
517*4882a593Smuzhiyun 	mcl->args[3] = domid;
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun 	trace_xen_mc_entry(mcl, 4);
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun static inline void
MULTI_stack_switch(struct multicall_entry * mcl,unsigned long ss,unsigned long esp)523*4882a593Smuzhiyun MULTI_stack_switch(struct multicall_entry *mcl,
524*4882a593Smuzhiyun 		   unsigned long ss, unsigned long esp)
525*4882a593Smuzhiyun {
526*4882a593Smuzhiyun 	mcl->op = __HYPERVISOR_stack_switch;
527*4882a593Smuzhiyun 	mcl->args[0] = ss;
528*4882a593Smuzhiyun 	mcl->args[1] = esp;
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 	trace_xen_mc_entry(mcl, 2);
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun #endif /* _ASM_X86_XEN_HYPERCALL_H */
534