• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  * hypercall.h
3  *
4  * Linux-specific hypervisor handling.
5  *
6  * Copyright (c) 2002-2004, K A Fraser
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License version 2
10  * as published by the Free Software Foundation; or, when distributed
11  * separately from the Linux kernel or incorporated into other
12  * software packages, subject to the following license:
13  *
14  * Permission is hereby granted, free of charge, to any person obtaining a copy
15  * of this source file (the "Software"), to deal in the Software without
16  * restriction, including without limitation the rights to use, copy, modify,
17  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
18  * and to permit persons to whom the Software is furnished to do so, subject to
19  * the following conditions:
20  *
21  * The above copyright notice and this permission notice shall be included in
22  * all copies or substantial portions of the Software.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30  * IN THE SOFTWARE.
31  */
32 
33 #ifndef __HYPERCALL_H__
34 #define __HYPERCALL_H__
35 
36 #include <linux/errno.h>
37 #include <linux/string.h>
38 
39 #include <xen/interface/xen.h>
40 #include <xen/interface/sched.h>
41 #include <xen/interface/physdev.h>
42 
43 extern struct { char _entry[32]; } hypercall_page[];
44 
45 #define _hypercall0(type, name)						\
46 ({									\
47 	long __res;							\
48 	asm volatile (							\
49 		"call %[call]"						\
50 		: "=a" (__res)						\
51 		: [call] "m" (hypercall_page[__HYPERVISOR_##name])	\
52 		: "memory" );						\
53 	(type)__res;							\
54 })
55 
56 #define _hypercall1(type, name, a1)					\
57 ({									\
58 	long __res, __ign1;						\
59 	asm volatile (							\
60 		"call %[call]"						\
61 		: "=a" (__res), "=b" (__ign1)				\
62 		: "1" ((long)(a1)),					\
63 		  [call] "m" (hypercall_page[__HYPERVISOR_##name])	\
64 		: "memory" );						\
65 	(type)__res;							\
66 })
67 
68 #define _hypercall2(type, name, a1, a2)					\
69 ({									\
70 	long __res, __ign1, __ign2;					\
71 	asm volatile (							\
72 		"call %[call]"						\
73 		: "=a" (__res), "=b" (__ign1), "=c" (__ign2)		\
74 		: "1" ((long)(a1)), "2" ((long)(a2)),			\
75 		  [call] "m" (hypercall_page[__HYPERVISOR_##name])	\
76 		: "memory" );						\
77 	(type)__res;							\
78 })
79 
80 #define _hypercall3(type, name, a1, a2, a3)				\
81 ({									\
82 	long __res, __ign1, __ign2, __ign3;				\
83 	asm volatile (							\
84 		"call %[call]"						\
85 		: "=a" (__res), "=b" (__ign1), "=c" (__ign2),		\
86 		"=d" (__ign3)						\
87 		: "1" ((long)(a1)), "2" ((long)(a2)),			\
88 		  "3" ((long)(a3)),					\
89 		  [call] "m" (hypercall_page[__HYPERVISOR_##name])	\
90 		: "memory" );						\
91 	(type)__res;							\
92 })
93 
94 #define _hypercall4(type, name, a1, a2, a3, a4)				\
95 ({									\
96 	long __res, __ign1, __ign2, __ign3, __ign4;			\
97 	asm volatile (							\
98 		"call %[call]"						\
99 		: "=a" (__res), "=b" (__ign1), "=c" (__ign2),		\
100 		"=d" (__ign3), "=S" (__ign4)				\
101 		: "1" ((long)(a1)), "2" ((long)(a2)),			\
102 		  "3" ((long)(a3)), "4" ((long)(a4)),			\
103 		  [call] "m" (hypercall_page[__HYPERVISOR_##name])	\
104 		: "memory" );						\
105 	(type)__res;							\
106 })
107 
108 #define _hypercall5(type, name, a1, a2, a3, a4, a5)			\
109 ({									\
110 	long __res, __ign1, __ign2, __ign3, __ign4, __ign5;		\
111 	asm volatile (							\
112 		"call %[call]"						\
113 		: "=a" (__res), "=b" (__ign1), "=c" (__ign2),		\
114 		"=d" (__ign3), "=S" (__ign4), "=D" (__ign5)		\
115 		: "1" ((long)(a1)), "2" ((long)(a2)),			\
116 		  "3" ((long)(a3)), "4" ((long)(a4)),			\
117 		  "5" ((long)(a5)),					\
118 		  [call] "m" (hypercall_page[__HYPERVISOR_##name])	\
119 		: "memory" );						\
120 	(type)__res;							\
121 })
122 
123 static inline int
HYPERVISOR_set_trap_table(struct trap_info * table)124 HYPERVISOR_set_trap_table(struct trap_info *table)
125 {
126 	return _hypercall1(int, set_trap_table, table);
127 }
128 
129 static inline int
HYPERVISOR_mmu_update(struct mmu_update * req,int count,int * success_count,domid_t domid)130 HYPERVISOR_mmu_update(struct mmu_update *req, int count,
131 		      int *success_count, domid_t domid)
132 {
133 	return _hypercall4(int, mmu_update, req, count, success_count, domid);
134 }
135 
136 static inline int
HYPERVISOR_mmuext_op(struct mmuext_op * op,int count,int * success_count,domid_t domid)137 HYPERVISOR_mmuext_op(struct mmuext_op *op, int count,
138 		     int *success_count, domid_t domid)
139 {
140 	return _hypercall4(int, mmuext_op, op, count, success_count, domid);
141 }
142 
143 static inline int
HYPERVISOR_set_gdt(unsigned long * frame_list,int entries)144 HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
145 {
146 	return _hypercall2(int, set_gdt, frame_list, entries);
147 }
148 
149 static inline int
HYPERVISOR_stack_switch(unsigned long ss,unsigned long esp)150 HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp)
151 {
152 	return _hypercall2(int, stack_switch, ss, esp);
153 }
154 
155 static inline int
HYPERVISOR_set_callbacks(unsigned long event_selector,unsigned long event_address,unsigned long failsafe_selector,unsigned long failsafe_address)156 HYPERVISOR_set_callbacks(unsigned long event_selector,
157 			 unsigned long event_address,
158 			 unsigned long failsafe_selector,
159 			 unsigned long failsafe_address)
160 {
161 	return _hypercall4(int, set_callbacks,
162 			   event_selector, event_address,
163 			   failsafe_selector, failsafe_address);
164 }
165 
166 static inline int
HYPERVISOR_fpu_taskswitch(int set)167 HYPERVISOR_fpu_taskswitch(int set)
168 {
169 	return _hypercall1(int, fpu_taskswitch, set);
170 }
171 
172 static inline int
HYPERVISOR_sched_op(int cmd,unsigned long arg)173 HYPERVISOR_sched_op(int cmd, unsigned long arg)
174 {
175 	return _hypercall2(int, sched_op, cmd, arg);
176 }
177 
178 static inline long
HYPERVISOR_set_timer_op(u64 timeout)179 HYPERVISOR_set_timer_op(u64 timeout)
180 {
181 	unsigned long timeout_hi = (unsigned long)(timeout>>32);
182 	unsigned long timeout_lo = (unsigned long)timeout;
183 	return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
184 }
185 
186 static inline int
HYPERVISOR_set_debugreg(int reg,unsigned long value)187 HYPERVISOR_set_debugreg(int reg, unsigned long value)
188 {
189 	return _hypercall2(int, set_debugreg, reg, value);
190 }
191 
192 static inline unsigned long
HYPERVISOR_get_debugreg(int reg)193 HYPERVISOR_get_debugreg(int reg)
194 {
195 	return _hypercall1(unsigned long, get_debugreg, reg);
196 }
197 
198 static inline int
HYPERVISOR_update_descriptor(u64 ma,u64 desc)199 HYPERVISOR_update_descriptor(u64 ma, u64 desc)
200 {
201 	return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
202 }
203 
204 static inline int
HYPERVISOR_memory_op(unsigned int cmd,void * arg)205 HYPERVISOR_memory_op(unsigned int cmd, void *arg)
206 {
207 	return _hypercall2(int, memory_op, cmd, arg);
208 }
209 
210 static inline int
HYPERVISOR_multicall(void * call_list,int nr_calls)211 HYPERVISOR_multicall(void *call_list, int nr_calls)
212 {
213 	return _hypercall2(int, multicall, call_list, nr_calls);
214 }
215 
216 static inline int
HYPERVISOR_update_va_mapping(unsigned long va,pte_t new_val,unsigned long flags)217 HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,
218 			     unsigned long flags)
219 {
220 	unsigned long pte_hi = 0;
221 #ifdef CONFIG_X86_PAE
222 	pte_hi = new_val.pte_high;
223 #endif
224 	return _hypercall4(int, update_va_mapping, va,
225 			   new_val.pte_low, pte_hi, flags);
226 }
227 
228 static inline int
HYPERVISOR_event_channel_op(int cmd,void * arg)229 HYPERVISOR_event_channel_op(int cmd, void *arg)
230 {
231 	int rc = _hypercall2(int, event_channel_op, cmd, arg);
232 	if (unlikely(rc == -ENOSYS)) {
233 		struct evtchn_op op;
234 		op.cmd = cmd;
235 		memcpy(&op.u, arg, sizeof(op.u));
236 		rc = _hypercall1(int, event_channel_op_compat, &op);
237 		memcpy(arg, &op.u, sizeof(op.u));
238 	}
239 	return rc;
240 }
241 
242 static inline int
HYPERVISOR_xen_version(int cmd,void * arg)243 HYPERVISOR_xen_version(int cmd, void *arg)
244 {
245 	return _hypercall2(int, xen_version, cmd, arg);
246 }
247 
248 static inline int
HYPERVISOR_console_io(int cmd,int count,char * str)249 HYPERVISOR_console_io(int cmd, int count, char *str)
250 {
251 	return _hypercall3(int, console_io, cmd, count, str);
252 }
253 
254 static inline int
HYPERVISOR_physdev_op(int cmd,void * arg)255 HYPERVISOR_physdev_op(int cmd, void *arg)
256 {
257 	int rc = _hypercall2(int, physdev_op, cmd, arg);
258 	if (unlikely(rc == -ENOSYS)) {
259 		struct physdev_op op;
260 		op.cmd = cmd;
261 		memcpy(&op.u, arg, sizeof(op.u));
262 		rc = _hypercall1(int, physdev_op_compat, &op);
263 		memcpy(arg, &op.u, sizeof(op.u));
264 	}
265 	return rc;
266 }
267 
268 static inline int
HYPERVISOR_grant_table_op(unsigned int cmd,void * uop,unsigned int count)269 HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
270 {
271 	return _hypercall3(int, grant_table_op, cmd, uop, count);
272 }
273 
274 static inline int
HYPERVISOR_update_va_mapping_otherdomain(unsigned long va,pte_t new_val,unsigned long flags,domid_t domid)275 HYPERVISOR_update_va_mapping_otherdomain(unsigned long va, pte_t new_val,
276 					 unsigned long flags, domid_t domid)
277 {
278 	unsigned long pte_hi = 0;
279 #ifdef CONFIG_X86_PAE
280 	pte_hi = new_val.pte_high;
281 #endif
282 	return _hypercall5(int, update_va_mapping_otherdomain, va,
283 			   new_val.pte_low, pte_hi, flags, domid);
284 }
285 
286 static inline int
HYPERVISOR_vm_assist(unsigned int cmd,unsigned int type)287 HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
288 {
289 	return _hypercall2(int, vm_assist, cmd, type);
290 }
291 
292 static inline int
HYPERVISOR_vcpu_op(int cmd,int vcpuid,void * extra_args)293 HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
294 {
295 	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
296 }
297 
298 static inline int
HYPERVISOR_suspend(unsigned long srec)299 HYPERVISOR_suspend(unsigned long srec)
300 {
301 	return _hypercall3(int, sched_op, SCHEDOP_shutdown,
302 			   SHUTDOWN_suspend, srec);
303 }
304 
305 static inline int
HYPERVISOR_nmi_op(unsigned long op,unsigned long arg)306 HYPERVISOR_nmi_op(unsigned long op, unsigned long arg)
307 {
308 	return _hypercall2(int, nmi_op, op, arg);
309 }
310 
311 static inline void
MULTI_update_va_mapping(struct multicall_entry * mcl,unsigned long va,pte_t new_val,unsigned long flags)312 MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
313 			pte_t new_val, unsigned long flags)
314 {
315 	mcl->op = __HYPERVISOR_update_va_mapping;
316 	mcl->args[0] = va;
317 #ifdef CONFIG_X86_PAE
318 	mcl->args[1] = new_val.pte_low;
319 	mcl->args[2] = new_val.pte_high;
320 #else
321 	mcl->args[1] = new_val.pte_low;
322 	mcl->args[2] = 0;
323 #endif
324 	mcl->args[3] = flags;
325 }
326 
327 static inline void
MULTI_grant_table_op(struct multicall_entry * mcl,unsigned int cmd,void * uop,unsigned int count)328 MULTI_grant_table_op(struct multicall_entry *mcl, unsigned int cmd,
329 		     void *uop, unsigned int count)
330 {
331 	mcl->op = __HYPERVISOR_grant_table_op;
332 	mcl->args[0] = cmd;
333 	mcl->args[1] = (unsigned long)uop;
334 	mcl->args[2] = count;
335 }
336 
337 static inline void
MULTI_update_va_mapping_otherdomain(struct multicall_entry * mcl,unsigned long va,pte_t new_val,unsigned long flags,domid_t domid)338 MULTI_update_va_mapping_otherdomain(struct multicall_entry *mcl, unsigned long va,
339 				    pte_t new_val, unsigned long flags,
340 				    domid_t domid)
341 {
342 	mcl->op = __HYPERVISOR_update_va_mapping_otherdomain;
343 	mcl->args[0] = va;
344 #ifdef CONFIG_X86_PAE
345 	mcl->args[1] = new_val.pte_low;
346 	mcl->args[2] = new_val.pte_high;
347 #else
348 	mcl->args[1] = new_val.pte_low;
349 	mcl->args[2] = 0;
350 #endif
351 	mcl->args[3] = flags;
352 	mcl->args[4] = domid;
353 }
354 
355 static inline void
MULTI_update_descriptor(struct multicall_entry * mcl,u64 maddr,struct desc_struct desc)356 MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr,
357 			struct desc_struct desc)
358 {
359 	mcl->op = __HYPERVISOR_update_descriptor;
360 	mcl->args[0] = maddr;
361 	mcl->args[1] = maddr >> 32;
362 	mcl->args[2] = desc.a;
363 	mcl->args[3] = desc.b;
364 }
365 
366 static inline void
MULTI_memory_op(struct multicall_entry * mcl,unsigned int cmd,void * arg)367 MULTI_memory_op(struct multicall_entry *mcl, unsigned int cmd, void *arg)
368 {
369 	mcl->op = __HYPERVISOR_memory_op;
370 	mcl->args[0] = cmd;
371 	mcl->args[1] = (unsigned long)arg;
372 }
373 
374 static inline void
MULTI_mmu_update(struct multicall_entry * mcl,struct mmu_update * req,int count,int * success_count,domid_t domid)375 MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
376 		 int count, int *success_count, domid_t domid)
377 {
378 	mcl->op = __HYPERVISOR_mmu_update;
379 	mcl->args[0] = (unsigned long)req;
380 	mcl->args[1] = count;
381 	mcl->args[2] = (unsigned long)success_count;
382 	mcl->args[3] = domid;
383 }
384 
385 static inline void
MULTI_mmuext_op(struct multicall_entry * mcl,struct mmuext_op * op,int count,int * success_count,domid_t domid)386 MULTI_mmuext_op(struct multicall_entry *mcl, struct mmuext_op *op, int count,
387 		int *success_count, domid_t domid)
388 {
389 	mcl->op = __HYPERVISOR_mmuext_op;
390 	mcl->args[0] = (unsigned long)op;
391 	mcl->args[1] = count;
392 	mcl->args[2] = (unsigned long)success_count;
393 	mcl->args[3] = domid;
394 }
395 
396 static inline void
MULTI_set_gdt(struct multicall_entry * mcl,unsigned long * frames,int entries)397 MULTI_set_gdt(struct multicall_entry *mcl, unsigned long *frames, int entries)
398 {
399 	mcl->op = __HYPERVISOR_set_gdt;
400 	mcl->args[0] = (unsigned long)frames;
401 	mcl->args[1] = entries;
402 }
403 
404 static inline void
MULTI_stack_switch(struct multicall_entry * mcl,unsigned long ss,unsigned long esp)405 MULTI_stack_switch(struct multicall_entry *mcl,
406 		   unsigned long ss, unsigned long esp)
407 {
408 	mcl->op = __HYPERVISOR_stack_switch;
409 	mcl->args[0] = ss;
410 	mcl->args[1] = esp;
411 }
412 
413 #endif /* __HYPERCALL_H__ */
414