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