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