#ifndef _BITS_XEN_H #define _BITS_XEN_H /** @file * * Xen interface * */ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /* Hypercall registers */ #ifdef __x86_64__ #define XEN_REG1 "rdi" #define XEN_REG2 "rsi" #define XEN_REG3 "rdx" #define XEN_REG4 "r10" #define XEN_REG5 "r8" #else #define XEN_REG1 "ebx" #define XEN_REG2 "ecx" #define XEN_REG3 "edx" #define XEN_REG4 "esi" #define XEN_REG5 "edi" #endif /** A hypercall entry point */ struct xen_hypercall { /** Code generated by hypervisor */ uint8_t code[32]; } __attribute__ (( packed )); /** * Issue hypercall with one argument * * @v xen Xen hypervisor * @v hypercall Hypercall number * @v arg1 First argument * @ret retval Return value */ static inline __attribute__ (( always_inline )) unsigned long xen_hypercall_1 ( struct xen_hypervisor *xen, unsigned int hypercall, unsigned long arg1 ) { register unsigned long reg1 asm ( XEN_REG1 ) = arg1; unsigned long retval; __asm__ __volatile__ ( "call *%2" : "=a" ( retval ), "+r" ( reg1 ) : "r" ( &xen->hypercall[hypercall] ) : XEN_REG2, XEN_REG3, XEN_REG4, XEN_REG5, "memory" ); return retval; } /** * Issue hypercall with two arguments * * @v xen Xen hypervisor * @v hypercall Hypercall number * @v arg1 First argument * @v arg2 Second argument * @ret retval Return value */ static inline __attribute__ (( always_inline )) unsigned long xen_hypercall_2 ( struct xen_hypervisor *xen, unsigned int hypercall, unsigned long arg1, unsigned long arg2 ) { register unsigned long reg1 asm ( XEN_REG1 ) = arg1; register unsigned long reg2 asm ( XEN_REG2 ) = arg2; unsigned long retval; __asm__ __volatile__ ( "call *%3" : "=a" ( retval ), "+r" ( reg1 ), "+r" ( reg2 ) : "r" ( &xen->hypercall[hypercall] ) : XEN_REG3, XEN_REG4, XEN_REG5, "memory" ); return retval; } /** * Issue hypercall with three arguments * * @v xen Xen hypervisor * @v hypercall Hypercall number * @v arg1 First argument * @v arg2 Second argument * @v arg3 Third argument * @ret retval Return value */ static inline __attribute__ (( always_inline )) unsigned long xen_hypercall_3 ( struct xen_hypervisor *xen, unsigned int hypercall, unsigned long arg1, unsigned long arg2, unsigned long arg3 ) { register unsigned long reg1 asm ( XEN_REG1 ) = arg1; register unsigned long reg2 asm ( XEN_REG2 ) = arg2; register unsigned long reg3 asm ( XEN_REG3 ) = arg3; unsigned long retval; __asm__ __volatile__ ( "call *%4" : "=a" ( retval ), "+r" ( reg1 ), "+r" ( reg2 ), "+r" ( reg3 ) : "r" ( &xen->hypercall[hypercall] ) : XEN_REG4, XEN_REG5, "memory" ); return retval; } /** * Issue hypercall with four arguments * * @v xen Xen hypervisor * @v hypercall Hypercall number * @v arg1 First argument * @v arg2 Second argument * @v arg3 Third argument * @v arg4 Fourth argument * @ret retval Return value */ static inline __attribute__ (( always_inline )) unsigned long xen_hypercall_4 ( struct xen_hypervisor *xen, unsigned int hypercall, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4 ) { register unsigned long reg1 asm ( XEN_REG1 ) = arg1; register unsigned long reg2 asm ( XEN_REG2 ) = arg2; register unsigned long reg3 asm ( XEN_REG3 ) = arg3; register unsigned long reg4 asm ( XEN_REG4 ) = arg4; unsigned long retval; __asm__ __volatile__ ( "call *%5" : "=a" ( retval ), "+r" ( reg1 ), "+r" ( reg2 ), "+r" ( reg3 ), "+r" ( reg4 ) : "r" ( &xen->hypercall[hypercall] ) : XEN_REG5, "memory" ); return retval; } /** * Issue hypercall with five arguments * * @v xen Xen hypervisor * @v hypercall Hypercall number * @v arg1 First argument * @v arg2 Second argument * @v arg3 Third argument * @v arg4 Fourth argument * @v arg5 Fifth argument * @ret retval Return value */ static inline __attribute__ (( always_inline )) unsigned long xen_hypercall_5 ( struct xen_hypervisor *xen, unsigned int hypercall, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5 ) { register unsigned long reg1 asm ( XEN_REG1 ) = arg1; register unsigned long reg2 asm ( XEN_REG2 ) = arg2; register unsigned long reg3 asm ( XEN_REG3 ) = arg3; register unsigned long reg4 asm ( XEN_REG4 ) = arg4; register unsigned long reg5 asm ( XEN_REG5 ) = arg5; unsigned long retval; __asm__ __volatile__ ( "call *%6" : "=a" ( retval ), "+r" ( reg1 ), "+r" ( reg2 ), "+r" ( reg3 ), "+r" ( reg4 ), "+r" ( reg5 ) : "r" ( &xen->hypercall[hypercall] ) : "memory" ); return retval; } /** * Test and clear pending event * * @v xen Xen hypervisor * @v port Event channel port * @ret pending Event was pending */ static inline __attribute__ (( always_inline )) uint8_t xenevent_pending ( struct xen_hypervisor *xen, evtchn_port_t port ) { uint8_t pending; __asm__ __volatile__ ( "lock btr %2, %0\n\t" "setc %1\n\t" : "+m" ( xen->shared->evtchn_pending ), "=a" ( pending ) : "Ir" ( port ) ); return pending; } #endif /* _BITS_XEN_H */