Changeset View
Changeset View
Standalone View
Standalone View
sys/xen/hypercall.h
- This file was copied from sys/amd64/include/xen/hypercall.h.
/****************************************************************************** | /****************************************************************************** | ||||
* SPDX-License-Identifier: MIT OR GPL-2.0-only | |||||
* | |||||
* hypercall.h | * hypercall.h | ||||
* | * | ||||
* FreeBSD-specific hypervisor handling. | * FreeBSD-specific hypervisor handling. | ||||
* | * | ||||
* Copyright (c) 2002-2004, K A Fraser | * Copyright (c) 2002-2004, K A Fraser | ||||
* | * | ||||
* 64-bit updates: | * 64-bit updates: | ||||
* Benjamin Liu <benjamin.liu@intel.com> | * Benjamin Liu <benjamin.liu@intel.com> | ||||
* Jun Nakajima <jun.nakajima@intel.com> | * Jun Nakajima <jun.nakajima@intel.com> | ||||
* | * | ||||
* This program is free software; you can redistribute it and/or | * This program is free software; you can redistribute it and/or | ||||
* modify it under the terms of the GNU General Public License version 2 | * modify it under the terms of the GNU General Public License version 2 | ||||
* as published by the Free Software Foundation; or, when distributed | * as published by the Free Software Foundation; or, when distributed | ||||
* separately from the Linux kernel or incorporated into other | * separately from the Linux kernel or incorporated into other | ||||
* software packages, subject to the following license: | * software packages, subject to the following license: | ||||
* | * | ||||
* Permission is hereby granted, free of charge, to any person obtaining a copy | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this source file (the "Software"), to deal in the Software without | * of this source file (the "Software"), to deal in the Software without | ||||
* restriction, including without limitation the rights to use, copy, modify, | * restriction, including without limitation the rights to use, copy, modify, | ||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, | * merge, publish, distribute, sublicense, and/or sell copies of the Software, | ||||
* and to permit persons to whom the Software is furnished to do so, subject to | * and to permit persons to whom the Software is furnished to do so, subject to | ||||
* the following conditions: | * the following conditions: | ||||
* | * | ||||
* The above copyright notice and this permission notice shall be included in | * The above copyright notice and this permission notice shall be included in | ||||
* all copies or substantial portions of the Software. | * all copies or substantial portions of the Software. | ||||
* | * | ||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||||
* IN THE SOFTWARE. | * IN THE SOFTWARE. | ||||
* | * | ||||
* $FreeBSD$ | * $FreeBSD$ | ||||
*/ | */ | ||||
#ifndef __MACHINE_XEN_HYPERCALL_H__ | #ifndef __XEN_HYPERCALL_H__ | ||||
#define __MACHINE_XEN_HYPERCALL_H__ | #define __XEN_HYPERCALL_H__ | ||||
#include <sys/systm.h> | #ifndef __MACHINE_XEN_HYPERCALL_H__ | ||||
#ifndef __XEN_HYPERVISOR_H__ | |||||
# error "please don't include this file directly" | # error "please don't include this file directly" | ||||
#endif | #endif | ||||
extern char *hypercall_page; | /* | ||||
* Architecture hypercall.h must provide the following 7 macros/functions: | |||||
* | |||||
* _hypercall[0-5](type, name[, arg0[, arg1[, arg2[, arg3[, arg4]]]]]); | |||||
* int privcmd_hypercall(op, arg0, arg1, arg2, arg3, arg4); | |||||
* | |||||
* Where _hypercall#() returns "type", hypercall0() takes no arguments, and | |||||
* _hypercall5() takes 5 arguments. The "name" does not include the leading | |||||
* __HYPERVISOR_ for the Xen call name. | |||||
* | |||||
* All arguments to privcmd_hypercall() are assumed to be full register size | |||||
* (long). | |||||
*/ | |||||
#define __STR(x) #x | |||||
#define STR(x) __STR(x) | |||||
#define __must_check | #define __must_check | ||||
#define HYPERCALL_STR(name) \ | |||||
"call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)" | |||||
#define _hypercall0(type, name) \ | |||||
({ \ | |||||
type __res; \ | |||||
__asm__ volatile ( \ | |||||
HYPERCALL_STR(name) \ | |||||
: "=a" (__res) \ | |||||
: \ | |||||
: "memory" ); \ | |||||
__res; \ | |||||
}) | |||||
#define _hypercall1(type, name, a1) \ | |||||
({ \ | |||||
type __res; \ | |||||
long __ign1; \ | |||||
__asm__ volatile ( \ | |||||
HYPERCALL_STR(name) \ | |||||
: "=a" (__res), "=D" (__ign1) \ | |||||
: "1" ((long)(a1)) \ | |||||
: "memory" ); \ | |||||
__res; \ | |||||
}) | |||||
#define _hypercall2(type, name, a1, a2) \ | |||||
({ \ | |||||
type __res; \ | |||||
long __ign1, __ign2; \ | |||||
__asm__ volatile ( \ | |||||
HYPERCALL_STR(name) \ | |||||
: "=a" (__res), "=D" (__ign1), "=S" (__ign2) \ | |||||
: "1" ((long)(a1)), "2" ((long)(a2)) \ | |||||
: "memory" ); \ | |||||
__res; \ | |||||
}) | |||||
#define _hypercall3(type, name, a1, a2, a3) \ | |||||
({ \ | |||||
type __res; \ | |||||
long __ign1, __ign2, __ign3; \ | |||||
__asm__ volatile ( \ | |||||
HYPERCALL_STR(name) \ | |||||
: "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ | |||||
"=d" (__ign3) \ | |||||
: "1" ((long)(a1)), "2" ((long)(a2)), \ | |||||
"3" ((long)(a3)) \ | |||||
: "memory" ); \ | |||||
__res; \ | |||||
}) | |||||
#define _hypercall4(type, name, a1, a2, a3, a4) \ | |||||
({ \ | |||||
type __res; \ | |||||
long __ign1, __ign2, __ign3; \ | |||||
register long __arg4 __asm__("r10") = (long)(a4); \ | |||||
__asm__ volatile ( \ | |||||
HYPERCALL_STR(name) \ | |||||
: "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ | |||||
"=d" (__ign3), "+r" (__arg4) \ | |||||
: "1" ((long)(a1)), "2" ((long)(a2)), \ | |||||
"3" ((long)(a3)) \ | |||||
: "memory" ); \ | |||||
__res; \ | |||||
}) | |||||
#define _hypercall5(type, name, a1, a2, a3, a4, a5) \ | |||||
({ \ | |||||
type __res; \ | |||||
long __ign1, __ign2, __ign3; \ | |||||
register long __arg4 __asm__("r10") = (long)(a4); \ | |||||
register long __arg5 __asm__("r8") = (long)(a5); \ | |||||
__asm__ volatile ( \ | |||||
HYPERCALL_STR(name) \ | |||||
: "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ | |||||
"=d" (__ign3), "+r" (__arg4), "+r" (__arg5) \ | |||||
: "1" ((long)(a1)), "2" ((long)(a2)), \ | |||||
"3" ((long)(a3)) \ | |||||
: "memory" ); \ | |||||
__res; \ | |||||
}) | |||||
static inline int | |||||
privcmd_hypercall(long op, long a1, long a2, long a3, long a4, long a5) | |||||
{ | |||||
int __res; | |||||
long __ign1, __ign2, __ign3; | |||||
register long __arg4 __asm__("r10") = (long)(a4); | |||||
register long __arg5 __asm__("r8") = (long)(a5); | |||||
long __call = (long)&hypercall_page + (op * 32); | |||||
if (op >= PAGE_SIZE / 32) | |||||
return -EINVAL; | |||||
__asm__ volatile ( | |||||
"call *%[call]" | |||||
: "=a" (__res), "=D" (__ign1), "=S" (__ign2), | |||||
"=d" (__ign3), "+r" (__arg4), "+r" (__arg5) | |||||
: "1" ((long)(a1)), "2" ((long)(a2)), | |||||
"3" ((long)(a3)), [call] "a" (__call) | |||||
: "memory" ); | |||||
return (__res); | |||||
} | |||||
static inline int __must_check | static inline int __must_check | ||||
HYPERVISOR_set_trap_table( | |||||
const trap_info_t *table) | |||||
{ | |||||
return _hypercall1(int, set_trap_table, table); | |||||
} | |||||
static inline int __must_check | |||||
HYPERVISOR_mmu_update( | HYPERVISOR_mmu_update( | ||||
mmu_update_t *req, unsigned int count, unsigned int *success_count, | mmu_update_t *req, unsigned int count, unsigned int *success_count, | ||||
domid_t domid) | domid_t domid) | ||||
{ | { | ||||
return _hypercall4(int, mmu_update, req, count, success_count, domid); | return _hypercall4(int, mmu_update, req, count, success_count, domid); | ||||
} | } | ||||
static inline int __must_check | static inline int __must_check | ||||
HYPERVISOR_mmuext_op( | HYPERVISOR_mmuext_op( | ||||
struct mmuext_op *op, unsigned int count, unsigned int *success_count, | mmuext_op_t *op, unsigned int count, unsigned int *success_count, | ||||
domid_t domid) | domid_t domid) | ||||
{ | { | ||||
return _hypercall4(int, mmuext_op, op, count, success_count, domid); | return _hypercall4(int, mmuext_op, op, count, success_count, domid); | ||||
} | } | ||||
static inline int __must_check | static inline int __must_check | ||||
HYPERVISOR_set_gdt( | HYPERVISOR_set_gdt( | ||||
unsigned long *frame_list, unsigned int entries) | unsigned long *frame_list, unsigned int entries) | ||||
{ | { | ||||
return _hypercall2(int, set_gdt, frame_list, entries); | return _hypercall2(int, set_gdt, frame_list, entries); | ||||
} | } | ||||
static inline int __must_check | static inline int __must_check | ||||
HYPERVISOR_stack_switch( | HYPERVISOR_stack_switch( | ||||
unsigned long ss, unsigned long esp) | unsigned long ss, unsigned long esp) | ||||
{ | { | ||||
return _hypercall2(int, stack_switch, ss, esp); | return _hypercall2(int, stack_switch, ss, esp); | ||||
} | } | ||||
static inline int __must_check | static inline int __must_check | ||||
HYPERVISOR_set_callbacks( | HYPERVISOR_set_callbacks( | ||||
unsigned long event_address, unsigned long failsafe_address, | unsigned long event_selector, unsigned long event_address, | ||||
unsigned long syscall_address) | unsigned long failsafe_selector, unsigned long failsafe_address) | ||||
{ | { | ||||
return _hypercall3(int, set_callbacks, | return _hypercall4(int, set_callbacks, | ||||
event_address, failsafe_address, syscall_address); | event_selector, event_address, | ||||
failsafe_selector, failsafe_address); | |||||
} | } | ||||
static inline int | static inline int | ||||
HYPERVISOR_fpu_taskswitch( | HYPERVISOR_fpu_taskswitch( | ||||
int set) | int set) | ||||
{ | { | ||||
return _hypercall1(int, fpu_taskswitch, set); | return _hypercall1(int, fpu_taskswitch, set); | ||||
} | } | ||||
static inline int __must_check | static inline int __must_check | ||||
HYPERVISOR_sched_op( | HYPERVISOR_sched_op( | ||||
int cmd, void *arg) | int cmd, void *arg) | ||||
{ | { | ||||
return _hypercall2(int, sched_op, cmd, arg); | return _hypercall2(int, sched_op, cmd, arg); | ||||
} | } | ||||
static inline long __must_check | static inline long __must_check | ||||
HYPERVISOR_set_timer_op( | HYPERVISOR_set_timer_op( | ||||
uint64_t timeout) | uint64_t timeout) | ||||
{ | { | ||||
#ifndef __ILP32__ | |||||
return _hypercall1(long, set_timer_op, timeout); | return _hypercall1(long, set_timer_op, timeout); | ||||
#else | |||||
unsigned long timeout_hi = (unsigned long)(timeout>>32); | |||||
unsigned long timeout_lo = (unsigned long)timeout; | |||||
return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi); | |||||
#endif | |||||
} | } | ||||
static inline int __must_check | static inline int __must_check | ||||
HYPERVISOR_platform_op( | HYPERVISOR_platform_op( | ||||
struct xen_platform_op *platform_op) | xen_platform_op_t *platform_op) | ||||
{ | { | ||||
platform_op->interface_version = XENPF_INTERFACE_VERSION; | platform_op->interface_version = XENPF_INTERFACE_VERSION; | ||||
return _hypercall1(int, platform_op, platform_op); | return _hypercall1(int, platform_op, platform_op); | ||||
} | } | ||||
static inline int __must_check | static inline int __must_check | ||||
HYPERVISOR_set_debugreg( | HYPERVISOR_set_debugreg( | ||||
unsigned int reg, unsigned long value) | unsigned int reg, unsigned long value) | ||||
{ | { | ||||
return _hypercall2(int, set_debugreg, reg, value); | return _hypercall2(int, set_debugreg, reg, value); | ||||
} | } | ||||
static inline unsigned long __must_check | static inline unsigned long __must_check | ||||
HYPERVISOR_get_debugreg( | HYPERVISOR_get_debugreg( | ||||
unsigned int reg) | unsigned int reg) | ||||
{ | { | ||||
return _hypercall1(unsigned long, get_debugreg, reg); | return _hypercall1(unsigned long, get_debugreg, reg); | ||||
} | } | ||||
static inline int __must_check | static inline int __must_check | ||||
HYPERVISOR_update_descriptor( | HYPERVISOR_update_descriptor( | ||||
unsigned long ma, unsigned long word) | uint64_t ma, uint64_t desc) | ||||
{ | { | ||||
return _hypercall2(int, update_descriptor, ma, word); | #ifndef __ILP32__ | ||||
return _hypercall2(int, update_descriptor, ma, desc); | |||||
#else | |||||
return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32); | |||||
#endif | |||||
} | } | ||||
static inline int __must_check | static inline int __must_check | ||||
HYPERVISOR_memory_op( | HYPERVISOR_memory_op( | ||||
unsigned int cmd, void *arg) | unsigned int cmd, void *arg) | ||||
{ | { | ||||
return _hypercall2(int, memory_op, cmd, arg); | return _hypercall2(int, memory_op, cmd, arg); | ||||
} | } | ||||
static inline int __must_check | static inline int __must_check | ||||
HYPERVISOR_multicall( | HYPERVISOR_multicall( | ||||
multicall_entry_t *call_list, unsigned int nr_calls) | multicall_entry_t *call_list, unsigned int nr_calls) | ||||
{ | { | ||||
return _hypercall2(int, multicall, call_list, nr_calls); | return _hypercall2(int, multicall, call_list, nr_calls); | ||||
} | } | ||||
static inline int __must_check | static inline int __must_check | ||||
HYPERVISOR_update_va_mapping( | HYPERVISOR_update_va_mapping( | ||||
unsigned long va, uint64_t new_val, unsigned long flags) | unsigned long va, uint64_t new_val, unsigned long flags) | ||||
{ | { | ||||
#ifndef __ILP32__ | |||||
return _hypercall3(int, update_va_mapping, va, new_val, flags); | return _hypercall3(int, update_va_mapping, va, new_val, flags); | ||||
#else | |||||
uint32_t hi, lo; | |||||
lo = (uint32_t)(new_val & 0xffffffff); | |||||
hi = (uint32_t)(new_val >> 32); | |||||
return _hypercall4(int, update_va_mapping, va, lo, hi, flags); | |||||
#endif | |||||
} | } | ||||
static inline int __must_check | static inline int __must_check | ||||
HYPERVISOR_event_channel_op( | HYPERVISOR_event_channel_op( | ||||
int cmd, void *arg) | int cmd, void *arg) | ||||
{ | { | ||||
return _hypercall2(int, event_channel_op, cmd, arg); | return _hypercall2(int, event_channel_op, cmd, arg); | ||||
} | } | ||||
Show All 25 Lines | |||||
{ | { | ||||
return _hypercall3(int, grant_table_op, cmd, uop, count); | return _hypercall3(int, grant_table_op, cmd, uop, count); | ||||
} | } | ||||
static inline int __must_check | static inline int __must_check | ||||
HYPERVISOR_update_va_mapping_otherdomain( | HYPERVISOR_update_va_mapping_otherdomain( | ||||
unsigned long va, uint64_t new_val, unsigned long flags, domid_t domid) | unsigned long va, uint64_t new_val, unsigned long flags, domid_t domid) | ||||
{ | { | ||||
#ifndef __ILP32__ | |||||
return _hypercall4(int, update_va_mapping_otherdomain, va, | return _hypercall4(int, update_va_mapping_otherdomain, va, | ||||
new_val, flags, domid); | new_val, flags, domid); | ||||
#else | |||||
uint32_t hi, lo; | |||||
lo = (uint32_t)(new_val & 0xffffffff); | |||||
hi = (uint32_t)(new_val >> 32); | |||||
return _hypercall5(int, update_va_mapping_otherdomain, va, | |||||
lo, hi, flags, domid); | |||||
#endif | |||||
} | } | ||||
static inline int __must_check | static inline int __must_check | ||||
HYPERVISOR_vm_assist( | HYPERVISOR_vm_assist( | ||||
unsigned int cmd, unsigned int type) | unsigned int cmd, unsigned int type) | ||||
{ | { | ||||
return _hypercall2(int, vm_assist, cmd, type); | return _hypercall2(int, vm_assist, cmd, type); | ||||
} | } | ||||
Show All 11 Lines | |||||
{ | { | ||||
return _hypercall2(int, set_segment_base, reg, value); | return _hypercall2(int, set_segment_base, reg, value); | ||||
} | } | ||||
static inline int __must_check | static inline int __must_check | ||||
HYPERVISOR_suspend( | HYPERVISOR_suspend( | ||||
unsigned long srec) | unsigned long srec) | ||||
{ | { | ||||
struct sched_shutdown sched_shutdown = { | sched_shutdown_t sched_shutdown = { | ||||
.reason = SHUTDOWN_suspend | .reason = SHUTDOWN_suspend | ||||
}; | }; | ||||
return _hypercall3(int, sched_op, SCHEDOP_shutdown, | return _hypercall3(int, sched_op, SCHEDOP_shutdown, | ||||
&sched_shutdown, srec); | &sched_shutdown, srec); | ||||
} | } | ||||
static inline unsigned long __must_check | static inline unsigned long __must_check | ||||
HYPERVISOR_hvm_op( | HYPERVISOR_hvm_op( | ||||
int op, void *arg) | int op, void *arg) | ||||
{ | { | ||||
return _hypercall2(unsigned long, hvm_op, op, arg); | return _hypercall2(unsigned long, hvm_op, op, arg); | ||||
} | } | ||||
static inline int __must_check | static inline int __must_check | ||||
HYPERVISOR_callback_op( | HYPERVISOR_callback_op( | ||||
int cmd, const void *arg) | int cmd, const void *arg) | ||||
{ | { | ||||
return _hypercall2(int, callback_op, cmd, arg); | return _hypercall2(int, callback_op, cmd, arg); | ||||
} | } | ||||
Show All 16 Lines | |||||
HYPERVISOR_dm_op( | HYPERVISOR_dm_op( | ||||
domid_t domid, unsigned int nr_bufs, const void *bufs) | domid_t domid, unsigned int nr_bufs, const void *bufs) | ||||
{ | { | ||||
return _hypercall3(int, dm_op, domid, nr_bufs, bufs); | return _hypercall3(int, dm_op, domid, nr_bufs, bufs); | ||||
} | } | ||||
#undef __must_check | #undef __must_check | ||||
#endif /* __MACHINE_XEN_HYPERCALL_H__ */ | #endif /* __XEN_HYPERCALL_H__ */ |