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
43extern 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
123static inline int
124HYPERVISOR_set_trap_table(struct trap_info *table)
125{
126	return _hypercall1(int, set_trap_table, table);
127}
128
129static inline int
130HYPERVISOR_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
136static inline int
137HYPERVISOR_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
143static inline int
144HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
145{
146	return _hypercall2(int, set_gdt, frame_list, entries);
147}
148
149static inline int
150HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp)
151{
152	return _hypercall2(int, stack_switch, ss, esp);
153}
154
155static inline int
156HYPERVISOR_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
166static inline int
167HYPERVISOR_fpu_taskswitch(int set)
168{
169	return _hypercall1(int, fpu_taskswitch, set);
170}
171
172static inline int
173HYPERVISOR_sched_op(int cmd, unsigned long arg)
174{
175	return _hypercall2(int, sched_op, cmd, arg);
176}
177
178static inline long
179HYPERVISOR_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
186static inline int
187HYPERVISOR_set_debugreg(int reg, unsigned long value)
188{
189	return _hypercall2(int, set_debugreg, reg, value);
190}
191
192static inline unsigned long
193HYPERVISOR_get_debugreg(int reg)
194{
195	return _hypercall1(unsigned long, get_debugreg, reg);
196}
197
198static inline int
199HYPERVISOR_update_descriptor(u64 ma, u64 desc)
200{
201	return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
202}
203
204static inline int
205HYPERVISOR_memory_op(unsigned int cmd, void *arg)
206{
207	return _hypercall2(int, memory_op, cmd, arg);
208}
209
210static inline int
211HYPERVISOR_multicall(void *call_list, int nr_calls)
212{
213	return _hypercall2(int, multicall, call_list, nr_calls);
214}
215
216static inline int
217HYPERVISOR_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
228static inline int
229HYPERVISOR_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
242static inline int
243HYPERVISOR_xen_version(int cmd, void *arg)
244{
245	return _hypercall2(int, xen_version, cmd, arg);
246}
247
248static inline int
249HYPERVISOR_console_io(int cmd, int count, char *str)
250{
251	return _hypercall3(int, console_io, cmd, count, str);
252}
253
254static inline int
255HYPERVISOR_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
268static inline int
269HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
270{
271	return _hypercall3(int, grant_table_op, cmd, uop, count);
272}
273
274static inline int
275HYPERVISOR_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
286static inline int
287HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
288{
289	return _hypercall2(int, vm_assist, cmd, type);
290}
291
292static inline int
293HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
294{
295	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
296}
297
298static inline int
299HYPERVISOR_suspend(unsigned long srec)
300{
301	return _hypercall3(int, sched_op, SCHEDOP_shutdown,
302			   SHUTDOWN_suspend, srec);
303}
304
305static inline int
306HYPERVISOR_nmi_op(unsigned long op, unsigned long arg)
307{
308	return _hypercall2(int, nmi_op, op, arg);
309}
310
311static inline void
312MULTI_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
327static inline void
328MULTI_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
337static inline void
338MULTI_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
355static inline void
356MULTI_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
366static inline void
367MULTI_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
374static inline void
375MULTI_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
385static inline void
386MULTI_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
396static inline void
397MULTI_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
404static inline void
405MULTI_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