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