Home | History | Annotate | Download | only in 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 __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
    124 HYPERVISOR_set_trap_table(struct trap_info *table)
    125 {
    126 	return _hypercall1(int, set_trap_table, table);
    127 }
    128 
    129 static inline int
    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
    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
    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
    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
    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
    167 HYPERVISOR_fpu_taskswitch(int set)
    168 {
    169 	return _hypercall1(int, fpu_taskswitch, set);
    170 }
    171 
    172 static inline int
    173 HYPERVISOR_sched_op(int cmd, unsigned long arg)
    174 {
    175 	return _hypercall2(int, sched_op, cmd, arg);
    176 }
    177 
    178 static inline long
    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
    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
    193 HYPERVISOR_get_debugreg(int reg)
    194 {
    195 	return _hypercall1(unsigned long, get_debugreg, reg);
    196 }
    197 
    198 static inline int
    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
    205 HYPERVISOR_memory_op(unsigned int cmd, void *arg)
    206 {
    207 	return _hypercall2(int, memory_op, cmd, arg);
    208 }
    209 
    210 static inline int
    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
    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
    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
    243 HYPERVISOR_xen_version(int cmd, void *arg)
    244 {
    245 	return _hypercall2(int, xen_version, cmd, arg);
    246 }
    247 
    248 static inline int
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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