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 <xen/interface/xen.h> 35 #include <xen/interface/sched.h> 36 37 #define __STR(x) #x 38 #define STR(x) __STR(x) 39 #define ENOXENSYS 38 40 #define CONFIG_XEN_COMPAT 0x030002 41 42 #define HYPERCALL_STR(name) \ 43 "call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)" 44 45 #define _hypercall0(type, name) \ 46 ({ \ 47 long __res; \ 48 __asm__ volatile ( \ 49 HYPERCALL_STR(name) \ 50 : "=a" (__res) \ 51 : \ 52 : "memory" ); \ 53 (type)__res; \ 54 }) 55 56 #define _hypercall1(type, name, a1) \ 57 ({ \ 58 long __res, __ign1; \ 59 __asm__ volatile ( \ 60 HYPERCALL_STR(name) \ 61 : "=a" (__res), "=b" (__ign1) \ 62 : "1" ((long)(a1)) \ 63 : "memory" ); \ 64 (type)__res; \ 65 }) 66 67 #define _hypercall2(type, name, a1, a2) \ 68 ({ \ 69 long __res, __ign1, __ign2; \ 70 __asm__ volatile ( \ 71 HYPERCALL_STR(name) \ 72 : "=a" (__res), "=b" (__ign1), "=c" (__ign2) \ 73 : "1" ((long)(a1)), "2" ((long)(a2)) \ 74 : "memory" ); \ 75 (type)__res; \ 76 }) 77 78 #define _hypercall3(type, name, a1, a2, a3) \ 79 ({ \ 80 long __res, __ign1, __ign2, __ign3; \ 81 __asm__ volatile ( \ 82 HYPERCALL_STR(name) \ 83 : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ 84 "=d" (__ign3) \ 85 : "1" ((long)(a1)), "2" ((long)(a2)), \ 86 "3" ((long)(a3)) \ 87 : "memory" ); \ 88 (type)__res; \ 89 }) 90 91 #define _hypercall4(type, name, a1, a2, a3, a4) \ 92 ({ \ 93 long __res, __ign1, __ign2, __ign3, __ign4; \ 94 __asm__ volatile ( \ 95 HYPERCALL_STR(name) \ 96 : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ 97 "=d" (__ign3), "=S" (__ign4) \ 98 : "1" ((long)(a1)), "2" ((long)(a2)), \ 99 "3" ((long)(a3)), "4" ((long)(a4)) \ 100 : "memory" ); \ 101 (type)__res; \ 102 }) 103 104 #define _hypercall5(type, name, a1, a2, a3, a4, a5) \ 105 ({ \ 106 long __res, __ign1, __ign2, __ign3, __ign4, __ign5; \ 107 __asm__ volatile ( \ 108 HYPERCALL_STR(name) \ 109 : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ 110 "=d" (__ign3), "=S" (__ign4), "=D" (__ign5) \ 111 : "1" ((long)(a1)), "2" ((long)(a2)), \ 112 "3" ((long)(a3)), "4" ((long)(a4)), \ 113 "5" ((long)(a5)) \ 114 : "memory" ); \ 115 (type)__res; \ 116 }) 117 118 static inline int 119 HYPERVISOR_set_trap_table( 120 trap_info_t *table) 121 { 122 return _hypercall1(int, set_trap_table, table); 123 } 124 125 static inline int 126 HYPERVISOR_mmu_update( 127 mmu_update_t *req, int count, int *success_count, domid_t domid) 128 { 129 return _hypercall4(int, mmu_update, req, count, success_count, domid); 130 } 131 132 static inline int 133 HYPERVISOR_mmuext_op( 134 mmuext_op_t *op, int count, int *success_count, domid_t domid) 135 { 136 return _hypercall4(int, mmuext_op, op, count, success_count, domid); 137 } 138 139 static inline int 140 HYPERVISOR_set_gdt( 141 unsigned long *frame_list, int entries) 142 { 143 return _hypercall2(int, set_gdt, frame_list, entries); 144 } 145 146 static inline int 147 HYPERVISOR_stack_switch( 148 unsigned long ss, unsigned long esp) 149 { 150 return _hypercall2(int, stack_switch, ss, esp); 151 } 152 153 static inline int 154 HYPERVISOR_set_callbacks( 155 unsigned long event_selector, unsigned long event_address, 156 unsigned long failsafe_selector, unsigned long failsafe_address) 157 { 158 return _hypercall4(int, set_callbacks, 159 event_selector, event_address, 160 failsafe_selector, failsafe_address); 161 } 162 163 static inline int 164 HYPERVISOR_fpu_taskswitch( 165 int set) 166 { 167 return _hypercall1(int, fpu_taskswitch, set); 168 } 169 170 static inline int 171 HYPERVISOR_sched_op_compat( 172 int cmd, unsigned long arg) 173 { 174 return _hypercall2(int, sched_op_compat, cmd, arg); 175 } 176 177 static inline int 178 HYPERVISOR_sched_op( 179 int cmd, void *arg) 180 { 181 return _hypercall2(int, sched_op, cmd, arg); 182 } 183 184 static inline long 185 HYPERVISOR_set_timer_op( 186 uint64_t timeout) 187 { 188 unsigned long timeout_hi = (unsigned long)(timeout>>32); 189 unsigned long timeout_lo = (unsigned long)timeout; 190 return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi); 191 } 192 #if 0 193 static inline int 194 HYPERVISOR_platform_op( 195 struct xen_platform_op *platform_op) 196 { 197 platform_op->interface_version = XENPF_INTERFACE_VERSION; 198 return _hypercall1(int, platform_op, platform_op); 199 } 200 #endif 201 static inline int 202 HYPERVISOR_set_debugreg( 203 int reg, unsigned long value) 204 { 205 return _hypercall2(int, set_debugreg, reg, value); 206 } 207 208 static inline unsigned long 209 HYPERVISOR_get_debugreg( 210 int reg) 211 { 212 return _hypercall1(unsigned long, get_debugreg, reg); 213 } 214 215 static inline int 216 HYPERVISOR_update_descriptor( 217 uint64_t ma, uint64_t desc) 218 { 219 return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32); 220 } 221 222 static inline int 223 HYPERVISOR_memory_op( 224 unsigned int cmd, void *arg) 225 { 226 return _hypercall2(int, memory_op, cmd, arg); 227 } 228 229 #if defined(XEN) 230 int HYPERVISOR_multicall(multicall_entry_t *, int); 231 static inline int 232 _HYPERVISOR_multicall( 233 #else /* XENHVM */ 234 static inline int 235 HYPERVISOR_multicall( 236 #endif 237 void *call_list, int nr_calls) 238 { 239 return _hypercall2(int, multicall, call_list, nr_calls); 240 } 241 242 static inline int 243 HYPERVISOR_update_va_mapping( 244 unsigned long va, uint64_t new_val, unsigned long flags) 245 { 246 uint32_t hi, lo; 247 248 lo = (uint32_t)(new_val & 0xffffffff); 249 hi = (uint32_t)(new_val >> 32); 250 251 return _hypercall4(int, update_va_mapping, va, 252 lo, hi, flags); 253 } 254 255 static inline int 256 HYPERVISOR_event_channel_op( 257 int cmd, void *arg) 258 { 259 int rc = _hypercall2(int, event_channel_op, cmd, arg); 260 261 #if CONFIG_XEN_COMPAT <= 0x030002 262 if (__predict_false(rc == -ENOXENSYS)) { 263 struct evtchn_op op; 264 op.cmd = cmd; 265 memcpy(&op.u, arg, sizeof(op.u)); 266 rc = _hypercall1(int, event_channel_op_compat, &op); 267 memcpy(arg, &op.u, sizeof(op.u)); 268 } 269 #endif 270 return (rc); 271 } 272 273 static inline int 274 HYPERVISOR_xen_version( 275 int cmd, void *arg) 276 { 277 return _hypercall2(int, xen_version, cmd, arg); 278 } 279 280 static inline int 281 HYPERVISOR_console_io( 282 int cmd, int count, char *str) 283 { 284 return _hypercall3(int, console_io, cmd, count, str); 285 } 286 287 static inline int 288 HYPERVISOR_physdev_op( 289 int cmd, void *arg) 290 { 291 int rc = _hypercall2(int, physdev_op, cmd, arg); 292 #if CONFIG_XEN_COMPAT <= 0x030002 293 if (__predict_false(rc == -ENOXENSYS)) { 294 struct physdev_op op; 295 op.cmd = cmd; 296 memcpy(&op.u, arg, sizeof(op.u)); 297 rc = _hypercall1(int, physdev_op_compat, &op); 298 memcpy(arg, &op.u, sizeof(op.u)); 299 } 300 #endif 301 return (rc); 302 } 303 304 static inline int 305 HYPERVISOR_grant_table_op( 306 unsigned int cmd, void *uop, unsigned int count) 307 { 308 return _hypercall3(int, grant_table_op, cmd, uop, count); 309 } 310 311 static inline int 312 HYPERVISOR_update_va_mapping_otherdomain( 313 unsigned long va, uint64_t new_val, unsigned long flags, domid_t domid) 314 { 315 uint32_t hi, lo; 316 317 lo = (uint32_t)(new_val & 0xffffffff); 318 hi = (uint32_t)(new_val >> 32); 319 320 return _hypercall5(int, update_va_mapping_otherdomain, va, 321 lo, hi, flags, domid); 322 } 323 324 static inline int 325 HYPERVISOR_vm_assist( 326 unsigned int cmd, unsigned int type) 327 { 328 return _hypercall2(int, vm_assist, cmd, type); 329 } 330 331 static inline int 332 HYPERVISOR_vcpu_op( 333 int cmd, int vcpuid, void *extra_args) 334 { 335 return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args); 336 } 337 338 static inline int 339 HYPERVISOR_suspend( 340 unsigned long srec) 341 { 342 struct sched_shutdown sched_shutdown = { 343 .reason = SHUTDOWN_suspend 344 }; 345 int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown, 346 &sched_shutdown, srec); 347 #if CONFIG_XEN_COMPAT <= 0x030002 348 if (rc == -ENOXENSYS) 349 rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown, 350 SHUTDOWN_suspend, srec); 351 #endif 352 return (rc); 353 } 354 355 #if CONFIG_XEN_COMPAT <= 0x030002 356 static inline int 357 HYPERVISOR_nmi_op( 358 unsigned long op, void *arg) 359 { 360 return _hypercall2(int, nmi_op, op, arg); 361 } 362 #endif 363 364 static inline int 365 HYPERVISOR_callback_op( 366 int cmd, void *arg) 367 { 368 return _hypercall2(int, callback_op, cmd, arg); 369 } 370 371 #ifndef CONFIG_XEN 372 static inline unsigned long 373 HYPERVISOR_hvm_op( 374 int op, void *arg) 375 { 376 return _hypercall2(unsigned long, hvm_op, op, arg); 377 } 378 #endif 379 380 static inline int 381 HYPERVISOR_xenoprof_op( 382 int op, void *arg) 383 { 384 return _hypercall2(int, xenoprof_op, op, arg); 385 } 386 387 static inline int 388 HYPERVISOR_kexec_op( 389 unsigned long op, void *args) 390 { 391 return _hypercall2(int, kexec_op, op, args); 392 } 393 #endif /* __HYPERCALL_H__ */ 394 395 /* 396 * Local variables: 397 * c-file-style: "linux" 398 * indent-tabs-mode: t 399 * c-indent-level: 8 400 * c-basic-offset: 8 401 * tab-width: 8 402 * End: 403 */ 404