• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/arch/x86/include/asm/xen/
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 _ASM_X86_XEN_HYPERCALL_H
34#define _ASM_X86_XEN_HYPERCALL_H
35
36#include <linux/kernel.h>
37#include <linux/spinlock.h>
38#include <linux/errno.h>
39#include <linux/string.h>
40#include <linux/types.h>
41
42#include <asm/page.h>
43#include <asm/pgtable.h>
44
45#include <xen/interface/xen.h>
46#include <xen/interface/sched.h>
47#include <xen/interface/physdev.h>
48
49
50extern struct { char _entry[32]; } hypercall_page[];
51
52#define __HYPERCALL		"call hypercall_page+%c[offset]"
53#define __HYPERCALL_ENTRY(x)						\
54	[offset] "i" (__HYPERVISOR_##x * sizeof(hypercall_page[0]))
55
56#ifdef CONFIG_X86_32
57#define __HYPERCALL_RETREG	"eax"
58#define __HYPERCALL_ARG1REG	"ebx"
59#define __HYPERCALL_ARG2REG	"ecx"
60#define __HYPERCALL_ARG3REG	"edx"
61#define __HYPERCALL_ARG4REG	"esi"
62#define __HYPERCALL_ARG5REG	"edi"
63#else
64#define __HYPERCALL_RETREG	"rax"
65#define __HYPERCALL_ARG1REG	"rdi"
66#define __HYPERCALL_ARG2REG	"rsi"
67#define __HYPERCALL_ARG3REG	"rdx"
68#define __HYPERCALL_ARG4REG	"r10"
69#define __HYPERCALL_ARG5REG	"r8"
70#endif
71
72#define __HYPERCALL_DECLS						\
73	register unsigned long __res  asm(__HYPERCALL_RETREG);		\
74	register unsigned long __arg1 asm(__HYPERCALL_ARG1REG) = __arg1; \
75	register unsigned long __arg2 asm(__HYPERCALL_ARG2REG) = __arg2; \
76	register unsigned long __arg3 asm(__HYPERCALL_ARG3REG) = __arg3; \
77	register unsigned long __arg4 asm(__HYPERCALL_ARG4REG) = __arg4; \
78	register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5;
79
80#define __HYPERCALL_0PARAM	"=r" (__res)
81#define __HYPERCALL_1PARAM	__HYPERCALL_0PARAM, "+r" (__arg1)
82#define __HYPERCALL_2PARAM	__HYPERCALL_1PARAM, "+r" (__arg2)
83#define __HYPERCALL_3PARAM	__HYPERCALL_2PARAM, "+r" (__arg3)
84#define __HYPERCALL_4PARAM	__HYPERCALL_3PARAM, "+r" (__arg4)
85#define __HYPERCALL_5PARAM	__HYPERCALL_4PARAM, "+r" (__arg5)
86
87#define __HYPERCALL_0ARG()
88#define __HYPERCALL_1ARG(a1)						\
89	__HYPERCALL_0ARG()		__arg1 = (unsigned long)(a1);
90#define __HYPERCALL_2ARG(a1,a2)						\
91	__HYPERCALL_1ARG(a1)		__arg2 = (unsigned long)(a2);
92#define __HYPERCALL_3ARG(a1,a2,a3)					\
93	__HYPERCALL_2ARG(a1,a2)		__arg3 = (unsigned long)(a3);
94#define __HYPERCALL_4ARG(a1,a2,a3,a4)					\
95	__HYPERCALL_3ARG(a1,a2,a3)	__arg4 = (unsigned long)(a4);
96#define __HYPERCALL_5ARG(a1,a2,a3,a4,a5)				\
97	__HYPERCALL_4ARG(a1,a2,a3,a4)	__arg5 = (unsigned long)(a5);
98
99#define __HYPERCALL_CLOBBER5	"memory"
100#define __HYPERCALL_CLOBBER4	__HYPERCALL_CLOBBER5, __HYPERCALL_ARG5REG
101#define __HYPERCALL_CLOBBER3	__HYPERCALL_CLOBBER4, __HYPERCALL_ARG4REG
102#define __HYPERCALL_CLOBBER2	__HYPERCALL_CLOBBER3, __HYPERCALL_ARG3REG
103#define __HYPERCALL_CLOBBER1	__HYPERCALL_CLOBBER2, __HYPERCALL_ARG2REG
104#define __HYPERCALL_CLOBBER0	__HYPERCALL_CLOBBER1, __HYPERCALL_ARG1REG
105
106#define _hypercall0(type, name)						\
107({									\
108	__HYPERCALL_DECLS;						\
109	__HYPERCALL_0ARG();						\
110	asm volatile (__HYPERCALL					\
111		      : __HYPERCALL_0PARAM				\
112		      : __HYPERCALL_ENTRY(name)				\
113		      : __HYPERCALL_CLOBBER0);				\
114	(type)__res;							\
115})
116
117#define _hypercall1(type, name, a1)					\
118({									\
119	__HYPERCALL_DECLS;						\
120	__HYPERCALL_1ARG(a1);						\
121	asm volatile (__HYPERCALL					\
122		      : __HYPERCALL_1PARAM				\
123		      : __HYPERCALL_ENTRY(name)				\
124		      : __HYPERCALL_CLOBBER1);				\
125	(type)__res;							\
126})
127
128#define _hypercall2(type, name, a1, a2)					\
129({									\
130	__HYPERCALL_DECLS;						\
131	__HYPERCALL_2ARG(a1, a2);					\
132	asm volatile (__HYPERCALL					\
133		      : __HYPERCALL_2PARAM				\
134		      : __HYPERCALL_ENTRY(name)				\
135		      : __HYPERCALL_CLOBBER2);				\
136	(type)__res;							\
137})
138
139#define _hypercall3(type, name, a1, a2, a3)				\
140({									\
141	__HYPERCALL_DECLS;						\
142	__HYPERCALL_3ARG(a1, a2, a3);					\
143	asm volatile (__HYPERCALL					\
144		      : __HYPERCALL_3PARAM				\
145		      : __HYPERCALL_ENTRY(name)				\
146		      : __HYPERCALL_CLOBBER3);				\
147	(type)__res;							\
148})
149
150#define _hypercall4(type, name, a1, a2, a3, a4)				\
151({									\
152	__HYPERCALL_DECLS;						\
153	__HYPERCALL_4ARG(a1, a2, a3, a4);				\
154	asm volatile (__HYPERCALL					\
155		      : __HYPERCALL_4PARAM				\
156		      : __HYPERCALL_ENTRY(name)				\
157		      : __HYPERCALL_CLOBBER4);				\
158	(type)__res;							\
159})
160
161#define _hypercall5(type, name, a1, a2, a3, a4, a5)			\
162({									\
163	__HYPERCALL_DECLS;						\
164	__HYPERCALL_5ARG(a1, a2, a3, a4, a5);				\
165	asm volatile (__HYPERCALL					\
166		      : __HYPERCALL_5PARAM				\
167		      : __HYPERCALL_ENTRY(name)				\
168		      : __HYPERCALL_CLOBBER5);				\
169	(type)__res;							\
170})
171
172static inline int
173HYPERVISOR_set_trap_table(struct trap_info *table)
174{
175	return _hypercall1(int, set_trap_table, table);
176}
177
178static inline int
179HYPERVISOR_mmu_update(struct mmu_update *req, int count,
180		      int *success_count, domid_t domid)
181{
182	return _hypercall4(int, mmu_update, req, count, success_count, domid);
183}
184
185static inline int
186HYPERVISOR_mmuext_op(struct mmuext_op *op, int count,
187		     int *success_count, domid_t domid)
188{
189	return _hypercall4(int, mmuext_op, op, count, success_count, domid);
190}
191
192static inline int
193HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
194{
195	return _hypercall2(int, set_gdt, frame_list, entries);
196}
197
198static inline int
199HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp)
200{
201	return _hypercall2(int, stack_switch, ss, esp);
202}
203
204#ifdef CONFIG_X86_32
205static inline int
206HYPERVISOR_set_callbacks(unsigned long event_selector,
207			 unsigned long event_address,
208			 unsigned long failsafe_selector,
209			 unsigned long failsafe_address)
210{
211	return _hypercall4(int, set_callbacks,
212			   event_selector, event_address,
213			   failsafe_selector, failsafe_address);
214}
215#else  /* CONFIG_X86_64 */
216static inline int
217HYPERVISOR_set_callbacks(unsigned long event_address,
218			unsigned long failsafe_address,
219			unsigned long syscall_address)
220{
221	return _hypercall3(int, set_callbacks,
222			   event_address, failsafe_address,
223			   syscall_address);
224}
225#endif  /* CONFIG_X86_{32,64} */
226
227static inline int
228HYPERVISOR_callback_op(int cmd, void *arg)
229{
230	return _hypercall2(int, callback_op, cmd, arg);
231}
232
233static inline int
234HYPERVISOR_fpu_taskswitch(int set)
235{
236	return _hypercall1(int, fpu_taskswitch, set);
237}
238
239static inline int
240HYPERVISOR_sched_op(int cmd, void *arg)
241{
242	return _hypercall2(int, sched_op_new, cmd, arg);
243}
244
245static inline long
246HYPERVISOR_set_timer_op(u64 timeout)
247{
248	unsigned long timeout_hi = (unsigned long)(timeout>>32);
249	unsigned long timeout_lo = (unsigned long)timeout;
250	return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
251}
252
253static inline int
254HYPERVISOR_set_debugreg(int reg, unsigned long value)
255{
256	return _hypercall2(int, set_debugreg, reg, value);
257}
258
259static inline unsigned long
260HYPERVISOR_get_debugreg(int reg)
261{
262	return _hypercall1(unsigned long, get_debugreg, reg);
263}
264
265static inline int
266HYPERVISOR_update_descriptor(u64 ma, u64 desc)
267{
268	if (sizeof(u64) == sizeof(long))
269		return _hypercall2(int, update_descriptor, ma, desc);
270	return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
271}
272
273static inline int
274HYPERVISOR_memory_op(unsigned int cmd, void *arg)
275{
276	return _hypercall2(int, memory_op, cmd, arg);
277}
278
279static inline int
280HYPERVISOR_multicall(void *call_list, int nr_calls)
281{
282	return _hypercall2(int, multicall, call_list, nr_calls);
283}
284
285static inline int
286HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,
287			     unsigned long flags)
288{
289	if (sizeof(new_val) == sizeof(long))
290		return _hypercall3(int, update_va_mapping, va,
291				   new_val.pte, flags);
292	else
293		return _hypercall4(int, update_va_mapping, va,
294				   new_val.pte, new_val.pte >> 32, flags);
295}
296
297static inline int
298HYPERVISOR_event_channel_op(int cmd, void *arg)
299{
300	int rc = _hypercall2(int, event_channel_op, cmd, arg);
301	if (unlikely(rc == -ENOSYS)) {
302		struct evtchn_op op;
303		op.cmd = cmd;
304		memcpy(&op.u, arg, sizeof(op.u));
305		rc = _hypercall1(int, event_channel_op_compat, &op);
306		memcpy(arg, &op.u, sizeof(op.u));
307	}
308	return rc;
309}
310
311static inline int
312HYPERVISOR_xen_version(int cmd, void *arg)
313{
314	return _hypercall2(int, xen_version, cmd, arg);
315}
316
317static inline int
318HYPERVISOR_console_io(int cmd, int count, char *str)
319{
320	return _hypercall3(int, console_io, cmd, count, str);
321}
322
323static inline int
324HYPERVISOR_physdev_op(int cmd, void *arg)
325{
326	int rc = _hypercall2(int, physdev_op, cmd, arg);
327	if (unlikely(rc == -ENOSYS)) {
328		struct physdev_op op;
329		op.cmd = cmd;
330		memcpy(&op.u, arg, sizeof(op.u));
331		rc = _hypercall1(int, physdev_op_compat, &op);
332		memcpy(arg, &op.u, sizeof(op.u));
333	}
334	return rc;
335}
336
337static inline int
338HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
339{
340	return _hypercall3(int, grant_table_op, cmd, uop, count);
341}
342
343static inline int
344HYPERVISOR_update_va_mapping_otherdomain(unsigned long va, pte_t new_val,
345					 unsigned long flags, domid_t domid)
346{
347	if (sizeof(new_val) == sizeof(long))
348		return _hypercall4(int, update_va_mapping_otherdomain, va,
349				   new_val.pte, flags, domid);
350	else
351		return _hypercall5(int, update_va_mapping_otherdomain, va,
352				   new_val.pte, new_val.pte >> 32,
353				   flags, domid);
354}
355
356static inline int
357HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
358{
359	return _hypercall2(int, vm_assist, cmd, type);
360}
361
362static inline int
363HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
364{
365	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
366}
367
368#ifdef CONFIG_X86_64
369static inline int
370HYPERVISOR_set_segment_base(int reg, unsigned long value)
371{
372	return _hypercall2(int, set_segment_base, reg, value);
373}
374#endif
375
376static inline int
377HYPERVISOR_suspend(unsigned long srec)
378{
379	return _hypercall3(int, sched_op, SCHEDOP_shutdown,
380			   SHUTDOWN_suspend, srec);
381}
382
383static inline int
384HYPERVISOR_nmi_op(unsigned long op, unsigned long arg)
385{
386	return _hypercall2(int, nmi_op, op, arg);
387}
388
389static inline unsigned long __must_check
390HYPERVISOR_hvm_op(int op, void *arg)
391{
392       return _hypercall2(unsigned long, hvm_op, op, arg);
393}
394
395static inline void
396MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
397{
398	mcl->op = __HYPERVISOR_fpu_taskswitch;
399	mcl->args[0] = set;
400}
401
402static inline void
403MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
404			pte_t new_val, unsigned long flags)
405{
406	mcl->op = __HYPERVISOR_update_va_mapping;
407	mcl->args[0] = va;
408	if (sizeof(new_val) == sizeof(long)) {
409		mcl->args[1] = new_val.pte;
410		mcl->args[2] = flags;
411	} else {
412		mcl->args[1] = new_val.pte;
413		mcl->args[2] = new_val.pte >> 32;
414		mcl->args[3] = flags;
415	}
416}
417
418static inline void
419MULTI_grant_table_op(struct multicall_entry *mcl, unsigned int cmd,
420		     void *uop, unsigned int count)
421{
422	mcl->op = __HYPERVISOR_grant_table_op;
423	mcl->args[0] = cmd;
424	mcl->args[1] = (unsigned long)uop;
425	mcl->args[2] = count;
426}
427
428static inline void
429MULTI_update_va_mapping_otherdomain(struct multicall_entry *mcl, unsigned long va,
430				    pte_t new_val, unsigned long flags,
431				    domid_t domid)
432{
433	mcl->op = __HYPERVISOR_update_va_mapping_otherdomain;
434	mcl->args[0] = va;
435	if (sizeof(new_val) == sizeof(long)) {
436		mcl->args[1] = new_val.pte;
437		mcl->args[2] = flags;
438		mcl->args[3] = domid;
439	} else {
440		mcl->args[1] = new_val.pte;
441		mcl->args[2] = new_val.pte >> 32;
442		mcl->args[3] = flags;
443		mcl->args[4] = domid;
444	}
445}
446
447static inline void
448MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr,
449			struct desc_struct desc)
450{
451	mcl->op = __HYPERVISOR_update_descriptor;
452	if (sizeof(maddr) == sizeof(long)) {
453		mcl->args[0] = maddr;
454		mcl->args[1] = *(unsigned long *)&desc;
455	} else {
456		mcl->args[0] = maddr;
457		mcl->args[1] = maddr >> 32;
458		mcl->args[2] = desc.a;
459		mcl->args[3] = desc.b;
460	}
461}
462
463static inline void
464MULTI_memory_op(struct multicall_entry *mcl, unsigned int cmd, void *arg)
465{
466	mcl->op = __HYPERVISOR_memory_op;
467	mcl->args[0] = cmd;
468	mcl->args[1] = (unsigned long)arg;
469}
470
471static inline void
472MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
473		 int count, int *success_count, domid_t domid)
474{
475	mcl->op = __HYPERVISOR_mmu_update;
476	mcl->args[0] = (unsigned long)req;
477	mcl->args[1] = count;
478	mcl->args[2] = (unsigned long)success_count;
479	mcl->args[3] = domid;
480}
481
482static inline void
483MULTI_mmuext_op(struct multicall_entry *mcl, struct mmuext_op *op, int count,
484		int *success_count, domid_t domid)
485{
486	mcl->op = __HYPERVISOR_mmuext_op;
487	mcl->args[0] = (unsigned long)op;
488	mcl->args[1] = count;
489	mcl->args[2] = (unsigned long)success_count;
490	mcl->args[3] = domid;
491}
492
493static inline void
494MULTI_set_gdt(struct multicall_entry *mcl, unsigned long *frames, int entries)
495{
496	mcl->op = __HYPERVISOR_set_gdt;
497	mcl->args[0] = (unsigned long)frames;
498	mcl->args[1] = entries;
499}
500
501static inline void
502MULTI_stack_switch(struct multicall_entry *mcl,
503		   unsigned long ss, unsigned long esp)
504{
505	mcl->op = __HYPERVISOR_stack_switch;
506	mcl->args[0] = ss;
507	mcl->args[1] = esp;
508}
509
510#endif /* _ASM_X86_XEN_HYPERCALL_H */
511