Home | History | Annotate | Line # | Download | only in xen
      1 /*	$NetBSD: hypercalls.h,v 1.2 2020/04/25 15:26:17 bouyer Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2006 Manuel Bouyer.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  *
     26  */
     27 
     28 /*
     29  *
     30  * Communication to/from hypervisor.
     31  *
     32  * Copyright (c) 2002-2004, K A Fraser
     33  *
     34  * Permission is hereby granted, free of charge, to any person obtaining a copy
     35  * of this source file (the "Software"), to deal in the Software without
     36  * restriction, including without limitation the rights to use, copy, modify,
     37  * merge, publish, distribute, sublicense, and/or sell copies of the Software,
     38  * and to permit persons to whom the Software is furnished to do so, subject to
     39  * the following conditions:
     40  *
     41  * The above copyright notice and this permission notice shall be included in
     42  * all copies or substantial portions of the Software.
     43  *
     44  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     45  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     46  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     47  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     48  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     49  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     50  * IN THE SOFTWARE.
     51  */
     52 
     53 
     54 #ifndef _XENI386_HYPERVISOR_H_
     55 #define _XENI386_HYPERVISOR_H_
     56 /*
     57  * Assembler stubs for hyper-calls.
     58  */
     59 
     60 #include <machine/pte.h> /* pt_entry_t */
     61 
     62 /* hypercall via the hypercall call page */
     63 #define __str(x) #x
     64 #define _str(x) __str(x)
     65 #define _hypercall(name, input_const, output_const) \
     66 	__asm volatile ( \
     67 	    "call hypercall_page + ("_str(name)" * 32)" \
     68 	    : output_const \
     69 	    : input_const \
     70 	    : "memory" )
     71 
     72 #define _harg(...) __VA_ARGS__
     73 
     74 
     75 static __inline int
     76 HYPERVISOR_set_trap_table(trap_info_t *table)
     77 {
     78     int ret;
     79     unsigned long ign1;
     80 
     81 	_hypercall(__HYPERVISOR_set_trap_table, _harg("1" (table)),
     82 	    _harg("=a" (ret), "=b" (ign1)));
     83 
     84     return ret;
     85 }
     86 
     87 static __inline int
     88 HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
     89 {
     90     int ret;
     91     unsigned long ign1, ign2;
     92 
     93     _hypercall(__HYPERVISOR_set_gdt, _harg("1" (frame_list), "2" (entries)),
     94 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
     95 
     96     return ret;
     97 }
     98 
     99 static __inline int
    100 HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp)
    101 {
    102     int ret;
    103     unsigned long ign1, ign2;
    104 
    105     _hypercall(__HYPERVISOR_stack_switch, _harg("1" (ss), "2" (esp)),
    106 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    107 
    108     return ret;
    109 }
    110 
    111 static __inline int
    112 HYPERVISOR_set_callbacks(
    113     unsigned long event_selector, unsigned long event_address,
    114     unsigned long failsafe_selector, unsigned long failsafe_address)
    115 {
    116     int ret;
    117     unsigned long ign1, ign2, ign3, ign4;
    118 
    119     _hypercall(__HYPERVISOR_set_callbacks,
    120 	_harg("1" (event_selector),"2" (event_address),
    121 	    "3" (failsafe_selector), "4" (failsafe_address)),
    122 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
    123 
    124     return ret;
    125 }
    126 
    127 #if __XEN_INTERFACE_VERSION__ < 0x00030204
    128 static __inline int
    129 HYPERVISOR_dom0_op(dom0_op_t *dom0_op)
    130 {
    131     int ret;
    132     unsigned long ign1;
    133 
    134     dom0_op->interface_version = DOM0_INTERFACE_VERSION;
    135     _hypercall(__HYPERVISOR_dom0_op, _harg("1" (dom0_op)),
    136 	_harg("=a" (ret), "=b" (ign1)));
    137 
    138     return ret;
    139 }
    140 #endif	/* __XEN_INTERFACE_VERSION__ */
    141 
    142 static __inline int
    143 HYPERVISOR_set_debugreg(int reg, unsigned long value)
    144 {
    145     int ret;
    146     unsigned long ign1, ign2;
    147 
    148     _hypercall(__HYPERVISOR_set_debugreg, _harg("1" (reg), "2" (value)),
    149 	 _harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    150 
    151     return ret;
    152 }
    153 
    154 static __inline unsigned long
    155 HYPERVISOR_get_debugreg(int reg)
    156 {
    157     unsigned long ret;
    158     unsigned long ign1;
    159 
    160     _hypercall(__HYPERVISOR_get_debugreg, _harg("1" (reg)),
    161 	_harg("=a" (ret), "=b" (ign1)));
    162 
    163     return ret;
    164 }
    165 
    166 #include <xen/include/public/arch-x86/xen-mca.h>
    167 
    168 static __inline int
    169 HYPERVISOR_machine_check(struct xen_mc *mc)
    170 {
    171      int ret;
    172      unsigned long ign1;
    173 
    174      mc->interface_version = XEN_MCA_INTERFACE_VERSION;
    175      _hypercall(__HYPERVISOR_mca, _harg("1" (mc)),
    176 	  _harg("=a" (ret), "=b" (ign1)));
    177 
    178      return ret;
    179 }
    180 
    181 static __inline int
    182 HYPERVISOR_hvm_op(int cmd, void *arg)
    183 {
    184     int ret;
    185     unsigned long ign1, ign2;
    186 
    187     _hypercall(__HYPERVISOR_hvm_op, _harg("1" (cmd), "2" (arg)),
    188 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    189 
    190     return ret;
    191 }
    192 
    193 static __inline int
    194 HYPERVISOR_mmu_update(mmu_update_t *req, int count, int *success_count,
    195     domid_t domid)
    196 {
    197     int ret;
    198     unsigned long ign1, ign2, ign3, ign4;
    199 
    200     _hypercall(__HYPERVISOR_mmu_update,
    201 	_harg("1" (req), "2" (count), "3" (success_count), "4" (domid)),
    202 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
    203 
    204     return ret;
    205 }
    206 
    207 static __inline int
    208 HYPERVISOR_mmuext_op(struct mmuext_op *op, int count, int *success_count,
    209     domid_t domid)
    210 {
    211     int ret;
    212     unsigned long ign1, ign2, ign3, ign4;
    213 
    214     _hypercall(__HYPERVISOR_mmuext_op,
    215 	_harg("1" (op), "2" (count), "3" (success_count), "4" (domid)),
    216 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
    217 
    218     return ret;
    219 }
    220 
    221 static __inline int
    222 HYPERVISOR_fpu_taskswitch(int set)
    223 {
    224     long ret;
    225     long ign1;
    226 
    227     _hypercall(__HYPERVISOR_fpu_taskswitch, _harg("1" (set)),
    228 	_harg("=a" (ret), "=b" (ign1)));
    229 
    230     return ret;
    231 }
    232 
    233 static __inline int
    234 HYPERVISOR_update_descriptor(uint64_t ma, uint32_t word1, uint32_t word2)
    235 {
    236     int ret;
    237     unsigned long ign1, ign2, ign3, ign4;
    238     int ma1 = ma & 0xffffffff;
    239     int ma2 = (ma >> 32) & 0xffffffff;
    240 
    241     _hypercall(__HYPERVISOR_update_descriptor,
    242 	_harg("1" (ma1), "2" (ma2), "3" (word1), "4" (word2)),
    243 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
    244 
    245     return ret;
    246 }
    247 
    248 static __inline int
    249 HYPERVISOR_memory_op(unsigned int cmd, void *arg)
    250 {
    251     int ret;
    252     unsigned long ign1, ign2;
    253 
    254     _hypercall(__HYPERVISOR_memory_op, _harg("1" (cmd), "2" (arg)),
    255 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    256 
    257     return ret;
    258 }
    259 
    260 #ifdef XENPV
    261 static __inline int
    262 HYPERVISOR_update_va_mapping(unsigned long page_nr, pt_entry_t new_val,
    263     unsigned long flags)
    264 {
    265     int ret;
    266     unsigned long ign1, ign2, ign3, ign4;
    267     unsigned long pte_low, pte_hi;
    268 
    269     pte_low = new_val & 0xffffffff;
    270     pte_hi = new_val >> 32;
    271 
    272     _hypercall(__HYPERVISOR_update_va_mapping,
    273 	_harg("1" (page_nr), "2" (pte_low), "3" (pte_hi), "4" (flags)),
    274 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)));
    275 
    276 #ifdef notdef
    277     if (__predict_false(ret < 0))
    278         panic("Failed update VA mapping: %08lx, %08lx, %08lx",
    279               page_nr, new_val, flags);
    280 #endif
    281 
    282     return ret;
    283 }
    284 
    285 static __inline int
    286 HYPERVISOR_update_va_mapping_otherdomain(unsigned long page_nr,
    287     pt_entry_t new_val, unsigned long flags, domid_t domid)
    288 {
    289     int ret;
    290     unsigned long ign1, ign2, ign3, ign4, ign5;
    291     unsigned long pte_low, pte_hi;
    292 
    293     pte_low = new_val & 0xffffffff;
    294     pte_hi = new_val >> 32;
    295 
    296     _hypercall(__HYPERVISOR_update_va_mapping_otherdomain,
    297 	_harg("1" (page_nr), "2" (pte_low), "3" (pte_hi), "4" (flags), "5" (domid)),
    298 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4),
    299 	    "=D" (ign5)));
    300 
    301     return ret;
    302 }
    303 #endif /* XENPV */
    304 
    305 static __inline int
    306 HYPERVISOR_xen_version(int cmd, void *arg)
    307 {
    308     int ret;
    309     unsigned long ign1, ign2;
    310 
    311     _hypercall(__HYPERVISOR_xen_version, _harg("1" (cmd), "2" (arg)),
    312 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    313 
    314     return ret;
    315 }
    316 
    317 static __inline int
    318 HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
    319 {
    320     int ret;
    321     unsigned long ign1, ign2, ign3;
    322 
    323     _hypercall(__HYPERVISOR_grant_table_op,
    324 	_harg("1" (cmd), "2" (uop), "3" (count)),
    325 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
    326 
    327     return ret;
    328 }
    329 
    330 
    331 static __inline int
    332 HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
    333 {
    334     long ret;
    335     unsigned long ign1, ign2, ign3;
    336 
    337     _hypercall(__HYPERVISOR_vcpu_op,
    338 	_harg("1" (cmd), "2" (vcpuid), "3" (extra_args)),
    339 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
    340 
    341     return ret;
    342 }
    343 
    344 static __inline long
    345 HYPERVISOR_yield(void)
    346 {
    347     long ret;
    348     unsigned long ign1, ign2;
    349 
    350     _hypercall(__HYPERVISOR_sched_op, _harg("1" (SCHEDOP_yield), "2" (0)),
    351 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    352 
    353     return ret;
    354 }
    355 
    356 static __inline long
    357 HYPERVISOR_block(void)
    358 {
    359     long ret;
    360     unsigned long ign1, ign2;
    361 
    362     _hypercall(__HYPERVISOR_sched_op, _harg("1" (SCHEDOP_block), "2" (0)),
    363 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    364 
    365     return ret;
    366 }
    367 
    368 static __inline long
    369 HYPERVISOR_shutdown(void)
    370 {
    371     long ret;
    372     unsigned long ign1, ign2;
    373 
    374 #if __XEN_INTERFACE_VERSION__ >= 0x00030201
    375 
    376     struct sched_shutdown shutdown_reason = {
    377 	    .reason = SHUTDOWN_poweroff
    378     };
    379 
    380     _hypercall(__HYPERVISOR_sched_op,
    381 	_harg("1" (SCHEDOP_shutdown), "2"  (&shutdown_reason)),
    382 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    383 #else
    384      _hypercall(__HYPERVISOR_sched_op,
    385 	_harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_poweroff)),
    386  	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    387 
    388 #endif
    389 
    390     return ret;
    391 }
    392 
    393 static __inline long
    394 HYPERVISOR_crash(void)
    395 {
    396     long ret;
    397     unsigned long ign1, ign2;
    398 
    399 #if __XEN_INTERFACE_VERSION__ >= 0x00030201
    400 
    401     struct sched_shutdown shutdown_reason = {
    402 	    .reason = SHUTDOWN_crash
    403     };
    404 
    405     _hypercall(__HYPERVISOR_sched_op,
    406 	_harg("1" (SCHEDOP_shutdown), "2"  (&shutdown_reason)),
    407 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    408 #else
    409     _hypercall(__HYPERVISOR_sched_op,
    410 	_harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_crash)),
    411 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    412 #endif
    413 
    414     return ret;
    415 }
    416 
    417 static __inline long
    418 HYPERVISOR_reboot(void)
    419 {
    420     long ret;
    421     unsigned long ign1, ign2;
    422 
    423 #if __XEN_INTERFACE_VERSION__ >= 0x00030201
    424 
    425     struct sched_shutdown shutdown_reason = {
    426 	    .reason = SHUTDOWN_reboot
    427     };
    428 
    429     _hypercall(__HYPERVISOR_sched_op,
    430 	_harg("1" (SCHEDOP_shutdown), "2"  (&shutdown_reason)),
    431 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    432 #else
    433     _hypercall(__HYPERVISOR_sched_op,
    434 	_harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_reboot)),
    435 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    436 #endif
    437 
    438     return ret;
    439 }
    440 
    441 static __inline long
    442 HYPERVISOR_suspend(unsigned long srec)
    443 {
    444     long ret;
    445     unsigned long ign1, ign2, ign3;
    446 
    447 #if __XEN_INTERFACE_VERSION__ >= 0x00030201
    448 
    449     struct sched_shutdown shutdown_reason = {
    450 	    .reason = SHUTDOWN_suspend
    451     };
    452 
    453     _hypercall(__HYPERVISOR_sched_op,
    454 	_harg("1" (SCHEDOP_shutdown), "2"  (&shutdown_reason), "3" (srec)),
    455 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
    456 #else
    457     _hypercall(__HYPERVISOR_sched_op,
    458 	_harg("1" (SCHEDOP_shutdown), "2" (SHUTDOWN_suspend), "3" (srec)),
    459 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
    460 #endif
    461 
    462     return ret;
    463 }
    464 
    465 static __inline long
    466 HYPERVISOR_set_timer_op(uint64_t timeout)
    467 {
    468     long ret;
    469     unsigned long timeout_hi = (unsigned long)(timeout>>32);
    470     unsigned long timeout_lo = (unsigned long)timeout;
    471     unsigned long ign1, ign2;
    472 
    473     _hypercall(__HYPERVISOR_set_timer_op,
    474 	 _harg("1" (timeout_lo), "2" (timeout_hi)),
    475 	 _harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    476 
    477     return ret;
    478 }
    479 
    480 static __inline int
    481 HYPERVISOR_platform_op(struct xen_platform_op *platform_op)
    482 {
    483     int ret;
    484     unsigned long ign1;
    485 
    486     platform_op->interface_version = XENPF_INTERFACE_VERSION;
    487     _hypercall(__HYPERVISOR_platform_op, _harg("1" (platform_op)),
    488 	_harg("=a" (ret), "=b" (ign1)));
    489 
    490     return ret;
    491 }
    492 
    493 static __inline int
    494 HYPERVISOR_multicall(void *call_list, int nr_calls)
    495 {
    496     int ret;
    497     unsigned long ign1, ign2;
    498 
    499     _hypercall(__HYPERVISOR_multicall,
    500 	 _harg("1" (call_list), "2" (nr_calls)),
    501 	 _harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    502 
    503     return ret;
    504 }
    505 
    506 
    507 static __inline int
    508 HYPERVISOR_event_channel_op(evtchn_op_t *op)
    509 {
    510     int ret;
    511     unsigned long ign1;
    512 
    513 #if __XEN_INTERFACE_VERSION__ < 0x00030202
    514     _hypercall(__HYPERVISOR_event_channel_op, _harg("1" (op)),
    515 	_harg("=a" (ret), "=b" (ign1)));
    516 #else
    517     unsigned long ign2;
    518 
    519     _hypercall(__HYPERVISOR_event_channel_op, _harg("1" (op->cmd), "2" (&op->u)),
    520 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    521 #endif
    522     return ret;
    523 }
    524 
    525 static __inline int
    526 HYPERVISOR_console_io(int cmd, int count, char *str)
    527 {
    528     int ret;
    529     unsigned long ign1, ign2, ign3;
    530 
    531     _hypercall(__HYPERVISOR_console_io,
    532 	_harg("1" (cmd), "2" (count), "3" (str)),
    533 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)));
    534 
    535     return ret;
    536 }
    537 
    538 static __inline int
    539 HYPERVISOR_physdev_op(int cmd, void *physdev_op)
    540 {
    541     int ret;
    542     unsigned long ign1, ign2;
    543 
    544     _hypercall(__HYPERVISOR_physdev_op, _harg("1" (cmd), "2" (physdev_op)),
    545 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    546 
    547     return ret;
    548 }
    549 
    550 static __inline int
    551 HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
    552 {
    553     int ret;
    554     unsigned long ign1, ign2;
    555 
    556     _hypercall(__HYPERVISOR_vm_assist, _harg("1" (cmd), "2" (type)),
    557 	_harg("=a" (ret), "=b" (ign1), "=c" (ign2)));
    558 
    559     return ret;
    560 }
    561 
    562 static __inline int
    563 HYPERVISOR_sysctl(void *sysctl)
    564 {
    565     int ret;
    566     unsigned long ign1;
    567 
    568     _hypercall(__HYPERVISOR_sysctl, _harg("1" (sysctl)),
    569 	_harg("=a" (ret), "=b" (ign1)));
    570 
    571     return ret;
    572 }
    573 #endif /* _XENI386_HYPERVISOR_H_ */
    574