# HG changeset patch # User gingold@virtu10 # Node ID 31aabe5545898c442dab522fd20256ac4cb3cb26 # Parent 2c71300a2ed817cdd3f40ec82faf864eb7e746b1 Implement fast hypercall for physdevop eoi. Eoi is a very frequent hypercall which has only one argument passed through a structure. To avoid the xencomm overhead, a new hypercall is created and the argument is passed by value. Signed-off-by: Tristan Gingold diff -r 2c71300a2ed8 -r 31aabe554589 linux-2.6-xen-sparse/include/asm-ia64/hypercall.h --- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Wed Sep 27 08:04:47 2006 +0200 +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Wed Sep 27 08:32:30 2006 +0200 @@ -170,44 +170,44 @@ HYPERVISOR_set_timer_op( HYPERVISOR_set_timer_op( u64 timeout) { - 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); + 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); } static inline int xencomm_arch_hypercall_dom0_op( struct xencomm_handle *op) { - return _hypercall1(int, dom0_op, op); + return _hypercall1(int, dom0_op, op); } static inline int xencomm_arch_hypercall_sysctl( struct xencomm_handle *op) { - return _hypercall1(int, sysctl, op); + return _hypercall1(int, sysctl, op); } static inline int xencomm_arch_hypercall_domctl( struct xencomm_handle *op) { - return _hypercall1(int, domctl, op); + return _hypercall1(int, domctl, op); } static inline int xencomm_arch_hypercall_multicall( struct xencomm_handle *call_list, int nr_calls) { - return _hypercall2(int, multicall, call_list, nr_calls); + return _hypercall2(int, multicall, call_list, nr_calls); } static inline int xencomm_arch_hypercall_memory_op( unsigned int cmd, struct xencomm_handle *arg) { - return _hypercall2(int, memory_op, cmd, arg); + return _hypercall2(int, memory_op, cmd, arg); } #include @@ -221,58 +221,58 @@ HYPERVISOR_memory_op( HYPERVISOR_memory_op( unsigned int cmd, void *arg) { - switch (cmd) { - case XENMEM_increase_reservation: - case XENMEM_decrease_reservation: - case XENMEM_populate_physmap: - return ia64_xenmem_reservation_op(cmd, - (struct xen_memory_reservation*)arg); - default: - return xencomm_hypercall_memory_op(cmd, arg); - } - /* NOTREACHED */ + switch (cmd) { + case XENMEM_increase_reservation: + case XENMEM_decrease_reservation: + case XENMEM_populate_physmap: + return ia64_xenmem_reservation_op + (cmd, (struct xen_memory_reservation*)arg); + default: + return xencomm_hypercall_memory_op(cmd, arg); + } + /* NOTREACHED */ } static inline int xencomm_arch_hypercall_event_channel_op( int cmd, struct xencomm_handle *arg) { - return _hypercall2(int, event_channel_op, cmd, arg); + return _hypercall2(int, event_channel_op, cmd, arg); } static inline int xencomm_arch_hypercall_acm_op( unsigned int cmd, struct xencomm_handle *arg) { - return _hypercall2(int, acm_op, cmd, arg); + return _hypercall2(int, acm_op, cmd, arg); } static inline int xencomm_arch_hypercall_xen_version( int cmd, struct xencomm_handle *arg) { - return _hypercall2(int, xen_version, cmd, arg); + return _hypercall2(int, xen_version, cmd, arg); } static inline int xencomm_arch_hypercall_console_io( int cmd, int count, struct xencomm_handle *str) { - return _hypercall3(int, console_io, cmd, count, str); + return _hypercall3(int, console_io, cmd, count, str); } static inline int xencomm_arch_hypercall_physdev_op( int cmd, struct xencomm_handle *arg) { - return _hypercall2(int, physdev_op, cmd, arg); + return _hypercall2(int, physdev_op, cmd, arg); } static inline int xencomm_arch_hypercall_grant_table_op( unsigned int cmd, struct xencomm_handle *uop, unsigned int count) { - return _hypercall3(int, grant_table_op, cmd, uop, count); + return _hypercall3(int, grant_table_op, cmd, uop, count); } int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count); @@ -293,6 +293,19 @@ xencomm_arch_hypercall_hvm_op( int cmd, void *arg) { return _hypercall2(unsigned long, hvm_op, cmd, arg); +} + +static inline int +HYPERVISOR_physdev_op( + int cmd, void *arg) +{ + switch (cmd) { + case PHYSDEVOP_eoi: + return _hypercall1(int, ia64_fast_eoi, + ((struct physdev_eoi *)arg)->irq); + default: + return xencomm_hypercall_physdev_op(cmd, arg); + } } extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs); @@ -413,7 +426,6 @@ HYPERVISOR_add_physmap(unsigned long gpf #define HYPERVISOR_multicall xencomm_mini_hypercall_multicall #define HYPERVISOR_xen_version xencomm_mini_hypercall_xen_version #define HYPERVISOR_console_io xencomm_mini_hypercall_console_io -#define HYPERVISOR_physdev_op xencomm_mini_hypercall_physdev_op #define HYPERVISOR_hvm_op xencomm_mini_hypercall_hvm_op #else #define HYPERVISOR_sched_op xencomm_hypercall_sched_op @@ -422,7 +434,6 @@ HYPERVISOR_add_physmap(unsigned long gpf #define HYPERVISOR_multicall xencomm_hypercall_multicall #define HYPERVISOR_xen_version xencomm_hypercall_xen_version #define HYPERVISOR_console_io xencomm_hypercall_console_io -#define HYPERVISOR_physdev_op xencomm_hypercall_physdev_op #define HYPERVISOR_hvm_op xencomm_hypercall_hvm_op #endif diff -r 2c71300a2ed8 -r 31aabe554589 xen/arch/ia64/xen/hypercall.c --- a/xen/arch/ia64/xen/hypercall.c Wed Sep 27 08:04:47 2006 +0200 +++ b/xen/arch/ia64/xen/hypercall.c Wed Sep 27 08:32:30 2006 +0200 @@ -120,6 +120,20 @@ xen_hypercall (struct pt_regs *regs) } else regs->r8 = -ENOSYS; + return IA64_NO_FAULT; +} + +static IA64FAULT +xen_fast_hypercall (struct pt_regs *regs) +{ + uint32_t cmd = (uint32_t)regs->r2; + switch (cmd) { + case __HYPERVISOR_ia64_fast_eoi: + regs->r8 = pirq_guest_eoi(current->domain, regs->r14); + break; + default: + regs->r8 = -ENOSYS; + } return IA64_NO_FAULT; } @@ -187,8 +201,8 @@ fw_hypercall_fpswa (struct vcpu *v) return PSCBX(v, fpswa_ret); } -static IA64FAULT -fw_hypercall (struct pt_regs *regs) +IA64FAULT +ia64_hypercall (struct pt_regs *regs) { struct vcpu *v = current; struct sal_ret_values x; @@ -199,6 +213,12 @@ fw_hypercall (struct pt_regs *regs) perfc_incra(fw_hypercall, index >> 8); switch (index) { + case FW_HYPERCALL_XEN: + return xen_hypercall (regs); + + case FW_HYPERCALL_XEN_FAST: + return xen_fast_hypercall (regs); + case FW_HYPERCALL_PAL_CALL: //printf("*** PAL hypercall: index=%d\n",regs->r28); //FIXME: This should call a C routine @@ -287,17 +307,6 @@ fw_hypercall (struct pt_regs *regs) return IA64_NO_FAULT; } -IA64FAULT -ia64_hypercall (struct pt_regs *regs) -{ - unsigned long index = regs->r2; - - if (index >= FW_HYPERCALL_FIRST_ARCH) - return fw_hypercall (regs); - else - return xen_hypercall (regs); -} - unsigned long hypercall_create_continuation( unsigned int op, const char *format, ...) { diff -r 2c71300a2ed8 -r 31aabe554589 xen/include/asm-ia64/dom_fw.h --- a/xen/include/asm-ia64/dom_fw.h Wed Sep 27 08:04:47 2006 +0200 +++ b/xen/include/asm-ia64/dom_fw.h Wed Sep 27 08:32:30 2006 +0200 @@ -38,6 +38,13 @@ The high part is the class (xen/pal/sal/efi). */ #define FW_HYPERCALL_NUM_MASK_HIGH ~0xffUL #define FW_HYPERCALL_NUM_MASK_LOW 0xffUL + +/* Xen hypercalls are 0-63. */ +#define FW_HYPERCALL_XEN 0x0000UL + +/* Define some faster and lighter hypercalls. + See definitions in arch-ia64.h */ +#define FW_HYPERCALL_XEN_FAST 0x0200UL /* * PAL can be called in physical or virtual mode simply by diff -r 2c71300a2ed8 -r 31aabe554589 xen/include/public/arch-ia64.h --- a/xen/include/public/arch-ia64.h Wed Sep 27 08:04:47 2006 +0200 +++ b/xen/include/public/arch-ia64.h Wed Sep 27 08:32:30 2006 +0200 @@ -432,6 +432,9 @@ struct xen_ia64_boot_param { #define HYPERPRIVOP_GET_PSR 0x19 #define HYPERPRIVOP_MAX 0x19 +/* Fast and light hypercalls. */ +#define __HYPERVISOR_ia64_fast_eoi 0x0200 + /* Xencomm macros. */ #define XENCOMM_INLINE_MASK 0xf800000000000000UL #define XENCOMM_INLINE_FLAG 0x8000000000000000UL