[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Clean up and fix hypercall macros in XenLinux: we must assume that
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxx # Node ID 37e9c9cd6c14a26fa396a0439f91e16a820d4e34 # Parent 2b95125015a59eeb086b3748f9415ac440133b4d Clean up and fix hypercall macros in XenLinux: we must assume that all register parameters are clobbered on return. Furthermore, multicall arrays are clobbered on return from a multicall (only the result field can be trusted!). These restrictions are enforced by debug builds of Xen in the following ways: 1. On completion of a multicall, the call array is overwritten with garbage before writing in the result fields. 2. On completion of a hypercall, all parameter registers are overwritten with garbage. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> diff -r 2b95125015a5 -r 37e9c9cd6c14 linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Fri Aug 26 13:06:49 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Fri Aug 26 17:42:34 2005 @@ -63,16 +63,19 @@ "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx" : "=a" (ret) : "0" (&hypercall) : "memory" ); #elif defined (__x86_64__) - __asm__ __volatile__ ( - "movq %5,%%r10; movq %6,%%r8;" TRAP_INSTR - : "=a" (ret) - : "a" ((unsigned long)hypercall.op), - "D" ((unsigned long)hypercall.arg[0]), - "S" ((unsigned long)hypercall.arg[1]), - "d" ((unsigned long)hypercall.arg[2]), - "g" ((unsigned long)hypercall.arg[3]), - "g" ((unsigned long)hypercall.arg[4]) - : "r11","rcx","r8","r10","memory"); + { + long ign1, ign2, ign3; + __asm__ __volatile__ ( + "movq %5,%%r10; movq %6,%%r8;" TRAP_INSTR + : "=a" (ret), "=D" (ign1), "=S" (ign2), "=d" (ign3) + : "0" ((unsigned long)hypercall.op), + "1" ((unsigned long)hypercall.arg[0]), + "2" ((unsigned long)hypercall.arg[1]), + "3" ((unsigned long)hypercall.arg[2]), + "g" ((unsigned long)hypercall.arg[3]), + "g" ((unsigned long)hypercall.arg[4]) + : "r11","rcx","r8","r10","memory"); + } #endif } break; diff -r 2b95125015a5 -r 37e9c9cd6c14 linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h Fri Aug 26 13:06:49 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h Fri Aug 26 17:42:34 2005 @@ -29,551 +29,362 @@ #ifndef __HYPERCALL_H__ #define __HYPERCALL_H__ + #include <asm-xen/xen-public/xen.h> -/* - * Assembler stubs for hyper-calls. - */ +#define _hypercall0(type, name) \ +({ \ + long __res; \ + asm volatile ( \ + TRAP_INSTR \ + : "=a" (__res) \ + : "0" (__HYPERVISOR_##name) \ + : "memory" ); \ + (type)__res; \ +}) + +#define _hypercall1(type, name, a1) \ +({ \ + long __res, __ign1; \ + asm volatile ( \ + TRAP_INSTR \ + : "=a" (__res), "=b" (__ign1) \ + : "0" (__HYPERVISOR_##name), "1" ((long)(a1)) \ + : "memory" ); \ + (type)__res; \ +}) + +#define _hypercall2(type, name, a1, a2) \ +({ \ + long __res, __ign1, __ign2; \ + asm volatile ( \ + TRAP_INSTR \ + : "=a" (__res), "=b" (__ign1), "=c" (__ign2) \ + : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \ + "2" ((long)(a2)) \ + : "memory" ); \ + (type)__res; \ +}) + +#define _hypercall3(type, name, a1, a2, a3) \ +({ \ + long __res, __ign1, __ign2, __ign3; \ + asm volatile ( \ + TRAP_INSTR \ + : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ + "=d" (__ign3) \ + : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \ + "2" ((long)(a2)), "3" ((long)(a3)) \ + : "memory" ); \ + (type)__res; \ +}) + +#define _hypercall4(type, name, a1, a2, a3, a4) \ +({ \ + long __res, __ign1, __ign2, __ign3, __ign4; \ + asm volatile ( \ + TRAP_INSTR \ + : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ + "=d" (__ign3), "=S" (__ign4) \ + : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \ + "2" ((long)(a2)), "3" ((long)(a3)), \ + "4" ((long)(a4)) \ + : "memory" ); \ + (type)__res; \ +}) + +#define _hypercall5(type, name, a1, a2, a3, a4, a5) \ +({ \ + long __res, __ign1, __ign2, __ign3, __ign4, __ign5; \ + asm volatile ( \ + TRAP_INSTR \ + : "=a" (__res), "=b" (__ign1), "=c" (__ign2), \ + "=d" (__ign3), "=S" (__ign4), "=D" (__ign5) \ + : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \ + "2" ((long)(a2)), "3" ((long)(a3)), \ + "4" ((long)(a4)), "5" ((long)(a5)) \ + : "memory" ); \ + (type)__res; \ +}) static inline int HYPERVISOR_set_trap_table( - trap_info_t *table) -{ - int ret; - unsigned long ignore; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ignore) - : "0" (__HYPERVISOR_set_trap_table), "1" (table) - : "memory" ); - - return ret; + trap_info_t *table) +{ + return _hypercall1(int, set_trap_table, table); } static inline int HYPERVISOR_mmu_update( - mmu_update_t *req, int count, int *success_count, domid_t domid) -{ - int ret; - unsigned long ign1, ign2, ign3, ign4; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4) - : "0" (__HYPERVISOR_mmu_update), "1" (req), "2" (count), - "3" (success_count), "4" (domid) - : "memory" ); - - return ret; + mmu_update_t *req, int count, int *success_count, domid_t domid) +{ + return _hypercall4(int, mmu_update, req, count, success_count, domid); } static inline int HYPERVISOR_mmuext_op( - struct mmuext_op *op, int count, int *success_count, domid_t domid) -{ - int ret; - unsigned long ign1, ign2, ign3, ign4; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4) - : "0" (__HYPERVISOR_mmuext_op), "1" (op), "2" (count), - "3" (success_count), "4" (domid) - : "memory" ); - - return ret; + struct mmuext_op *op, int count, int *success_count, domid_t domid) +{ + return _hypercall4(int, mmuext_op, op, count, success_count, domid); } static inline int HYPERVISOR_set_gdt( - unsigned long *frame_list, int entries) -{ - int ret; - unsigned long ign1, ign2; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2) - : "0" (__HYPERVISOR_set_gdt), "1" (frame_list), "2" (entries) - : "memory" ); - - - return ret; + unsigned long *frame_list, int entries) +{ + return _hypercall2(int, set_gdt, frame_list, entries); } static inline int HYPERVISOR_stack_switch( - unsigned long ss, unsigned long esp) -{ - int ret; - unsigned long ign1, ign2; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2) - : "0" (__HYPERVISOR_stack_switch), "1" (ss), "2" (esp) - : "memory" ); - - return ret; + unsigned long ss, unsigned long esp) +{ + return _hypercall2(int, stack_switch, ss, esp); } static inline int HYPERVISOR_set_callbacks( - unsigned long event_selector, unsigned long event_address, - unsigned long failsafe_selector, unsigned long failsafe_address) -{ - int ret; - unsigned long ign1, ign2, ign3, ign4; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4) - : "0" (__HYPERVISOR_set_callbacks), "1" (event_selector), - "2" (event_address), "3" (failsafe_selector), "4" (failsafe_address) - : "memory" ); - - return ret; + unsigned long event_selector, unsigned long event_address, + unsigned long failsafe_selector, unsigned long failsafe_address) +{ + return _hypercall4(int, set_callbacks, + event_selector, event_address, + failsafe_selector, failsafe_address); } static inline int HYPERVISOR_fpu_taskswitch( - int set) -{ - int ret; - unsigned long ign; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign) - : "0" (__HYPERVISOR_fpu_taskswitch), "1" (set) - : "memory" ); - - return ret; + int set) +{ + return _hypercall1(int, fpu_taskswitch, set); } static inline int HYPERVISOR_yield( - void) -{ - int ret; - unsigned long ign; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign) - : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_yield) - : "memory", "ecx" ); - - return ret; + void) +{ + return _hypercall2(int, sched_op, SCHEDOP_yield, 0); } static inline int HYPERVISOR_block( - void) -{ - int ret; - unsigned long ign1; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1) - : "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_block) - : "memory", "ecx" ); - - return ret; + void) +{ + return _hypercall2(int, sched_op, SCHEDOP_block, 0); } static inline int HYPERVISOR_shutdown( - void) -{ - int ret; - unsigned long ign1; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1) - : "0" (__HYPERVISOR_sched_op), - "1" (SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift)) - : "memory", "ecx" ); - - return ret; + void) +{ + return _hypercall2(int, sched_op, SCHEDOP_shutdown | + (SHUTDOWN_poweroff << SCHEDOP_reasonshift), 0); } static inline int HYPERVISOR_reboot( - void) -{ - int ret; - unsigned long ign1; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1) - : "0" (__HYPERVISOR_sched_op), - "1" (SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift)) - : "memory", "ecx" ); - - return ret; -} - -static inline int -HYPERVISOR_suspend( - unsigned long srec) -{ - int ret; - unsigned long ign1, ign2; - - /* NB. On suspend, control software expects a suspend record in %esi. */ - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=S" (ign2) - : "0" (__HYPERVISOR_sched_op), - "b" (SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift)), - "S" (srec) : "memory", "ecx"); - - return ret; + void) +{ + return _hypercall2(int, sched_op, SCHEDOP_shutdown | + (SHUTDOWN_reboot << SCHEDOP_reasonshift), 0); } static inline int HYPERVISOR_crash( - void) -{ - int ret; - unsigned long ign1; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1) - : "0" (__HYPERVISOR_sched_op), - "1" (SCHEDOP_shutdown | (SHUTDOWN_crash << SCHEDOP_reasonshift)) - : "memory", "ecx" ); - - return ret; + void) +{ + return _hypercall2(int, sched_op, SCHEDOP_shutdown | + (SHUTDOWN_crash << SCHEDOP_reasonshift), 0); } static inline long HYPERVISOR_set_timer_op( - u64 timeout) -{ - int ret; - unsigned long timeout_hi = (unsigned long)(timeout>>32); - unsigned long timeout_lo = (unsigned long)timeout; - unsigned long ign1, ign2; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2) - : "0" (__HYPERVISOR_set_timer_op), "b" (timeout_lo), "c" (timeout_hi) - : "memory"); - - return ret; + 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); } static inline int HYPERVISOR_dom0_op( - dom0_op_t *dom0_op) -{ - int ret; - unsigned long ign1; - - dom0_op->interface_version = DOM0_INTERFACE_VERSION; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1) - : "0" (__HYPERVISOR_dom0_op), "1" (dom0_op) - : "memory"); - - return ret; + dom0_op_t *dom0_op) +{ + dom0_op->interface_version = DOM0_INTERFACE_VERSION; + return _hypercall1(int, dom0_op, dom0_op); } static inline int HYPERVISOR_set_debugreg( - int reg, unsigned long value) -{ - int ret; - unsigned long ign1, ign2; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2) - : "0" (__HYPERVISOR_set_debugreg), "1" (reg), "2" (value) - : "memory" ); - - return ret; + int reg, unsigned long value) +{ + return _hypercall2(int, set_debugreg, reg, value); } static inline unsigned long HYPERVISOR_get_debugreg( - int reg) -{ - unsigned long ret; - unsigned long ign; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign) - : "0" (__HYPERVISOR_get_debugreg), "1" (reg) - : "memory" ); - - return ret; + int reg) +{ + return _hypercall1(unsigned long, get_debugreg, reg); } static inline int HYPERVISOR_update_descriptor( - u64 ma, u64 desc) -{ - int ret; - unsigned long ign1, ign2, ign3, ign4; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4) - : "0" (__HYPERVISOR_update_descriptor), - "1" ((unsigned long)ma), "2" ((unsigned long)(ma>>32)), - "3" ((unsigned long)desc), "4" ((unsigned long)(desc>>32)) - : "memory" ); - - return ret; + u64 ma, u64 desc) +{ + return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32); } static inline int HYPERVISOR_dom_mem_op( - unsigned int op, unsigned long *extent_list, - unsigned long nr_extents, unsigned int extent_order) -{ - int ret; - unsigned long ign1, ign2, ign3, ign4, ign5; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4), - "=D" (ign5) - : "0" (__HYPERVISOR_dom_mem_op), "1" (op), "2" (extent_list), - "3" (nr_extents), "4" (extent_order), "5" (DOMID_SELF) - : "memory" ); - - return ret; + unsigned int op, unsigned long *extent_list, + unsigned long nr_extents, unsigned int extent_order) +{ + return _hypercall5(int, dom_mem_op, op, extent_list, + nr_extents, extent_order, DOMID_SELF); } static inline int HYPERVISOR_multicall( - void *call_list, int nr_calls) -{ - int ret; - unsigned long ign1, ign2; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2) - : "0" (__HYPERVISOR_multicall), "1" (call_list), "2" (nr_calls) - : "memory" ); - - return ret; + void *call_list, int nr_calls) +{ + return _hypercall2(int, multicall, call_list, nr_calls); } static inline int HYPERVISOR_update_va_mapping( - unsigned long va, pte_t new_val, unsigned long flags) -{ - int ret; - unsigned long ign1, ign2, ign3, ign4; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4) - : "0" (__HYPERVISOR_update_va_mapping), - "1" (va), "2" ((new_val).pte_low), + unsigned long va, pte_t new_val, unsigned long flags) +{ + unsigned long pte_hi = 0; #ifdef CONFIG_X86_PAE - "3" ((new_val).pte_high), -#else - "3" (0), + pte_hi = new_val.pte_high; #endif - "4" (flags) - : "memory" ); - - return ret; + return _hypercall4(int, update_va_mapping, va, + new_val.pte_low, pte_hi, flags); } static inline int HYPERVISOR_event_channel_op( - void *op) -{ - int ret; - unsigned long ignore; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ignore) - : "0" (__HYPERVISOR_event_channel_op), "1" (op) - : "memory" ); - - return ret; + void *op) +{ + return _hypercall1(int, event_channel_op, op); } static inline int HYPERVISOR_xen_version( - int cmd) -{ - int ret; - unsigned long ignore; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ignore) - : "0" (__HYPERVISOR_xen_version), "1" (cmd) - : "memory" ); - - return ret; + int cmd) +{ + return _hypercall1(int, xen_version, cmd); } static inline int HYPERVISOR_console_io( - int cmd, int count, char *str) -{ - int ret; - unsigned long ign1, ign2, ign3; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3) - : "0" (__HYPERVISOR_console_io), "1" (cmd), "2" (count), "3" (str) - : "memory" ); - - return ret; + int cmd, int count, char *str) +{ + return _hypercall3(int, console_io, cmd, count, str); } static inline int HYPERVISOR_physdev_op( - void *physdev_op) -{ - int ret; - unsigned long ign; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign) - : "0" (__HYPERVISOR_physdev_op), "1" (physdev_op) - : "memory" ); - - return ret; + void *physdev_op) +{ + return _hypercall1(int, physdev_op, physdev_op); } static inline int HYPERVISOR_grant_table_op( - unsigned int cmd, void *uop, unsigned int count) -{ - int ret; - unsigned long ign1, ign2, ign3; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3) - : "0" (__HYPERVISOR_grant_table_op), "1" (cmd), "2" (uop), "3" (count) - : "memory" ); - - return ret; + unsigned int cmd, void *uop, unsigned int count) +{ + return _hypercall3(int, grant_table_op, cmd, uop, count); } static inline int HYPERVISOR_update_va_mapping_otherdomain( - unsigned long va, pte_t new_val, unsigned long flags, domid_t domid) -{ - int ret; - unsigned long ign1, ign2, ign3, ign4, ign5; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), - "=S" (ign4), "=D" (ign5) - : "0" (__HYPERVISOR_update_va_mapping_otherdomain), - "1" (va), "2" ((new_val).pte_low), + unsigned long va, pte_t new_val, unsigned long flags, domid_t domid) +{ + unsigned long pte_hi = 0; #ifdef CONFIG_X86_PAE - "3" ((new_val).pte_high), -#else - "3" (0), + pte_hi = new_val.pte_high; #endif - "4" (flags), "5" (domid) : - "memory" ); - - return ret; + return _hypercall5(int, update_va_mapping_otherdomain, va, + new_val.pte_low, pte_hi, flags, domid); } static inline int HYPERVISOR_vm_assist( - unsigned int cmd, unsigned int type) -{ - int ret; - unsigned long ign1, ign2; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2) - : "0" (__HYPERVISOR_vm_assist), "1" (cmd), "2" (type) - : "memory" ); - - return ret; + unsigned int cmd, unsigned int type) +{ + return _hypercall2(int, vm_assist, cmd, type); } static inline int HYPERVISOR_boot_vcpu( - unsigned long vcpu, vcpu_guest_context_t *ctxt) -{ - int ret; - unsigned long ign1, ign2; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2) - : "0" (__HYPERVISOR_boot_vcpu), "1" (vcpu), "2" (ctxt) - : "memory"); - - return ret; + unsigned long vcpu, vcpu_guest_context_t *ctxt) +{ + return _hypercall2(int, boot_vcpu, vcpu, ctxt); +} + +static inline int +HYPERVISOR_vcpu_up( + int vcpu) +{ + return _hypercall2(int, sched_op, SCHEDOP_vcpu_up | + (vcpu << SCHEDOP_vcpushift), 0); +} + +static inline int +HYPERVISOR_vcpu_pickle( + int vcpu, vcpu_guest_context_t *ctxt) +{ + return _hypercall2(int, sched_op, SCHEDOP_vcpu_pickle | + (vcpu << SCHEDOP_vcpushift), ctxt); +} + +static inline int +HYPERVISOR_suspend( + unsigned long srec) +{ + int ret; + unsigned long ign1, ign2; + + /* On suspend, control software expects a suspend record in %esi. */ + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1), "=S" (ign2) + : "0" (__HYPERVISOR_sched_op), + "1" (SCHEDOP_shutdown | (SHUTDOWN_suspend << + SCHEDOP_reasonshift)), + "2" (srec) : "memory", "ecx"); + + return ret; } static inline int HYPERVISOR_vcpu_down( - int vcpu) -{ - int ret; - unsigned long ign1; - /* Yes, I really do want to clobber edx here: when we resume a - vcpu after unpickling a multi-processor domain, it returns - here, but clobbers all of the call clobbered registers. */ - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1) - : "0" (__HYPERVISOR_sched_op), - "1" (SCHEDOP_vcpu_down | (vcpu << SCHEDOP_vcpushift)) - : "memory", "ecx", "edx" ); - - return ret; -} - -static inline int -HYPERVISOR_vcpu_up( - int vcpu) -{ - int ret; - unsigned long ign1; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1) - : "0" (__HYPERVISOR_sched_op), - "1" (SCHEDOP_vcpu_up | (vcpu << SCHEDOP_vcpushift)) - : "memory", "ecx" ); - - return ret; -} - -static inline int -HYPERVISOR_vcpu_pickle( - int vcpu, vcpu_guest_context_t *ctxt) -{ - int ret; - unsigned long ign1, ign2; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2) - : "0" (__HYPERVISOR_sched_op), - "1" (SCHEDOP_vcpu_pickle | (vcpu << SCHEDOP_vcpushift)), - "2" (ctxt) - : "memory" ); - - return ret; + int vcpu) +{ + int ret; + unsigned long ign1; + /* Yes, I really do want to clobber edx here: when we resume a + vcpu after unpickling a multi-processor domain, it returns + here, but clobbers all of the call clobbered registers. */ + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ign1) + : "0" (__HYPERVISOR_sched_op), + "1" (SCHEDOP_vcpu_down | (vcpu << SCHEDOP_vcpushift)) + : "memory", "ecx", "edx" ); + return ret; } #endif /* __HYPERCALL_H__ */ + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 2b95125015a5 -r 37e9c9cd6c14 linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h Fri Aug 26 13:06:49 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h Fri Aug 26 17:42:34 2005 @@ -4,6 +4,10 @@ * Linux-specific hypervisor handling. * * Copyright (c) 2002-2004, K A Fraser + * + * 64-bit updates: + * Benjamin Liu <benjamin.liu@xxxxxxxxx> + * Jun Nakajima <jun.nakajima@xxxxxxxxx> * * This file may be distributed separately from the Linux kernel, or * incorporated into other software packages, subject to the following license: @@ -26,497 +30,331 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ -/* - * Benjamin Liu <benjamin.liu@xxxxxxxxx> - * Jun Nakajima <jun.nakajima@xxxxxxxxx> - * Ported to x86-64. - * - */ #ifndef __HYPERCALL_H__ #define __HYPERCALL_H__ + #include <asm-xen/xen-public/xen.h> #define __syscall_clobber "r11","rcx","memory" -/* - * Assembler stubs for hyper-calls. - */ +#define _hypercall0(type, name) \ +({ \ + long __res; \ + asm volatile ( \ + TRAP_INSTR \ + : "=a" (__res) \ + : "0" (__HYPERVISOR_##name) \ + : __syscall_clobber ); \ + (type)__res; \ +}) + +#define _hypercall1(type, name, a1) \ +({ \ + long __res, __ign1; \ + asm volatile ( \ + TRAP_INSTR \ + : "=a" (__res), "=D" (__ign1) \ + : "0" (__HYPERVISOR_##name), "1" ((long)(a1)) \ + : __syscall_clobber ); \ + (type)__res; \ +}) + +#define _hypercall2(type, name, a1, a2) \ +({ \ + long __res, __ign1, __ign2; \ + asm volatile ( \ + TRAP_INSTR \ + : "=a" (__res), "=D" (__ign1), "=S" (__ign2) \ + : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \ + "2" ((long)(a2)) \ + : __syscall_clobber ); \ + (type)__res; \ +}) + +#define _hypercall3(type, name, a1, a2, a3) \ +({ \ + long __res, __ign1, __ign2, __ign3; \ + asm volatile ( \ + TRAP_INSTR \ + : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ + "=d" (__ign3) \ + : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \ + "2" ((long)(a2)), "3" ((long)(a3)) \ + : __syscall_clobber ); \ + (type)__res; \ +}) + +#define _hypercall4(type, name, a1, a2, a3, a4) \ +({ \ + long __res, __ign1, __ign2, __ign3; \ + asm volatile ( \ + "movq %8,%%r10; " TRAP_INSTR \ + : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ + "=d" (__ign3) \ + : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \ + "2" ((long)(a2)), "3" ((long)(a3)), \ + "g" ((long)(a4)) \ + : __syscall_clobber, "r10" ); \ + (type)__res; \ +}) + +#define _hypercall5(type, name, a1, a2, a3, a4, a5) \ +({ \ + long __res, __ign1, __ign2, __ign3; \ + asm volatile ( \ + "movq %8,%%r10; movq %9,%%r8; " TRAP_INSTR \ + : "=a" (__res), "=D" (__ign1), "=S" (__ign2), \ + "=d" (__ign3) \ + : "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \ + "2" ((long)(a2)), "3" ((long)(a3)), \ + "g" ((long)(a4)), "g" ((long)(a5)) \ + : __syscall_clobber, "r10", "r8" ); \ + (type)__res; \ +}) + static inline int HYPERVISOR_set_trap_table( - trap_info_t *table) -{ - int ret; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_set_trap_table), "D" (table) - : __syscall_clobber ); - - return ret; + trap_info_t *table) +{ + return _hypercall1(int, set_trap_table, table); } static inline int HYPERVISOR_mmu_update( - mmu_update_t *req, int count, int *success_count, domid_t domid) -{ - int ret; - - __asm__ __volatile__ ( - "movq %5, %%r10;" TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_mmu_update), "D" (req), "S" ((long)count), - "d" (success_count), "g" ((unsigned long)domid) - : __syscall_clobber, "r10" ); - - return ret; + mmu_update_t *req, int count, int *success_count, domid_t domid) +{ + return _hypercall4(int, mmu_update, req, count, success_count, domid); } static inline int HYPERVISOR_mmuext_op( - struct mmuext_op *op, int count, int *success_count, domid_t domid) -{ - int ret; - - __asm__ __volatile__ ( - "movq %5, %%r10;" TRAP_INSTR - : "=a" (ret) - : "0" (__HYPERVISOR_mmuext_op), "D" (op), "S" ((long)count), - "d" (success_count), "g" ((unsigned long)domid) - : __syscall_clobber, "r10" ); - - return ret; + struct mmuext_op *op, int count, int *success_count, domid_t domid) +{ + return _hypercall4(int, mmuext_op, op, count, success_count, domid); } static inline int HYPERVISOR_set_gdt( - unsigned long *frame_list, int entries) -{ - int ret; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_set_gdt), "D" (frame_list), "S" ((long)entries) - : __syscall_clobber ); - - - return ret; -} + unsigned long *frame_list, int entries) +{ + return _hypercall2(int, set_gdt, frame_list, entries); +} + static inline int HYPERVISOR_stack_switch( - unsigned long ss, unsigned long esp) -{ - int ret; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_stack_switch), "D" (ss), "S" (esp) - : __syscall_clobber ); - - return ret; + unsigned long ss, unsigned long esp) +{ + return _hypercall2(int, stack_switch, ss, esp); } static inline int HYPERVISOR_set_callbacks( - unsigned long event_address, unsigned long failsafe_address, - unsigned long syscall_address) -{ - int ret; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_set_callbacks), "D" (event_address), - "S" (failsafe_address), "d" (syscall_address) - : __syscall_clobber ); - - return ret; + unsigned long event_address, unsigned long failsafe_address, + unsigned long syscall_address) +{ + return _hypercall3(int, set_callbacks, + event_address, failsafe_address, syscall_address); } static inline int HYPERVISOR_fpu_taskswitch( - int set) -{ - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) : "0" ((unsigned long)__HYPERVISOR_fpu_taskswitch), - "D" ((unsigned long) set) : __syscall_clobber ); - - return ret; + int set) +{ + return _hypercall1(int, fpu_taskswitch, set); } static inline int HYPERVISOR_yield( - void) -{ - int ret; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_sched_op), "D" ((unsigned long)SCHEDOP_yield) - : __syscall_clobber ); - - return ret; + void) +{ + return _hypercall2(int, sched_op, SCHEDOP_yield, 0); } static inline int HYPERVISOR_block( - void) -{ - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_sched_op), "D" ((unsigned long)SCHEDOP_block) - : __syscall_clobber ); - - return ret; + void) +{ + return _hypercall2(int, sched_op, SCHEDOP_block, 0); } static inline int HYPERVISOR_shutdown( - void) -{ - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_sched_op), - "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift))) - : __syscall_clobber ); - - return ret; + void) +{ + return _hypercall2(int, sched_op, SCHEDOP_shutdown | + (SHUTDOWN_poweroff << SCHEDOP_reasonshift), 0); } static inline int HYPERVISOR_reboot( - void) -{ - int ret; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_sched_op), - "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift))) - : __syscall_clobber ); - - return ret; -} - -static inline int -HYPERVISOR_suspend( - unsigned long srec) -{ - int ret; - - /* NB. On suspend, control software expects a suspend record in %esi. */ - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_sched_op), - "D" ((unsigned long)(SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift))), - "S" (srec) - : __syscall_clobber ); - - return ret; -} - -/* - * We can have the timeout value in a single argument for the hypercall, but - * that will break the common code. - */ + void) +{ + return _hypercall2(int, sched_op, SCHEDOP_shutdown | + (SHUTDOWN_reboot << SCHEDOP_reasonshift), 0); +} + static inline long HYPERVISOR_set_timer_op( - u64 timeout) -{ - int ret; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_set_timer_op), - "D" (timeout) - : __syscall_clobber ); - - return ret; + u64 timeout) +{ + return _hypercall1(long, set_timer_op, timeout); } static inline int HYPERVISOR_dom0_op( - dom0_op_t *dom0_op) -{ - int ret; - - dom0_op->interface_version = DOM0_INTERFACE_VERSION; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_dom0_op), "D" (dom0_op) - : __syscall_clobber ); - - return ret; + dom0_op_t *dom0_op) +{ + dom0_op->interface_version = DOM0_INTERFACE_VERSION; + return _hypercall1(int, dom0_op, dom0_op); } static inline int HYPERVISOR_set_debugreg( - int reg, unsigned long value) -{ - int ret; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_set_debugreg), "D" ((unsigned long)reg), "S" (value) - : __syscall_clobber ); - - return ret; + int reg, unsigned long value) +{ + return _hypercall2(int, set_debugreg, reg, value); } static inline unsigned long HYPERVISOR_get_debugreg( - int reg) -{ - unsigned long ret; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_get_debugreg), "D" ((unsigned long)reg) - : __syscall_clobber ); - - return ret; + int reg) +{ + return _hypercall1(unsigned long, get_debugreg, reg); } static inline int HYPERVISOR_update_descriptor( - unsigned long ma, unsigned long word) -{ - int ret; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_update_descriptor), "D" (ma), - "S" (word) - : __syscall_clobber ); - - return ret; + unsigned long ma, unsigned long word) +{ + return _hypercall2(int, update_descriptor, ma, word); } static inline int HYPERVISOR_dom_mem_op( - unsigned int op, unsigned long *extent_list, - unsigned long nr_extents, unsigned int extent_order) -{ - int ret; - - __asm__ __volatile__ ( - "movq %5,%%r10; movq %6,%%r8;" TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_dom_mem_op), "D" ((unsigned long)op), "S" (extent_list), - "d" (nr_extents), "g" ((unsigned long) extent_order), "g" ((unsigned long) DOMID_SELF) - : __syscall_clobber,"r8","r10"); - - return ret; + unsigned int op, unsigned long *extent_list, + unsigned long nr_extents, unsigned int extent_order) +{ + return _hypercall5(int, dom_mem_op, op, extent_list, + nr_extents, extent_order, DOMID_SELF); } static inline int HYPERVISOR_multicall( - void *call_list, int nr_calls) -{ - int ret; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_multicall), "D" (call_list), "S" ((unsigned long)nr_calls) - : __syscall_clobber); - - return ret; + void *call_list, int nr_calls) +{ + return _hypercall2(int, multicall, call_list, nr_calls); } static inline int HYPERVISOR_update_va_mapping( - unsigned long page_nr, pte_t new_val, unsigned long flags) -{ - int ret; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_update_va_mapping), - "D" (page_nr), "S" (new_val.pte), "d" (flags) - : __syscall_clobber); - - return ret; + unsigned long va, pte_t new_val, unsigned long flags) +{ + return _hypercall3(int, update_va_mapping, va, new_val.pte, flags); } static inline int HYPERVISOR_event_channel_op( - void *op) -{ - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_event_channel_op), "D" (op) - : __syscall_clobber); - - return ret; + void *op) +{ + return _hypercall1(int, event_channel_op, op); } static inline int HYPERVISOR_xen_version( - int cmd) -{ - int ret; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_xen_version), "D" ((unsigned long)cmd) - : __syscall_clobber); - - return ret; + int cmd) +{ + return _hypercall1(int, xen_version, cmd); } static inline int HYPERVISOR_console_io( - int cmd, int count, char *str) -{ - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_console_io), "D" ((unsigned long)cmd), "S" ((unsigned long)count), "d" (str) - : __syscall_clobber); - - return ret; + int cmd, int count, char *str) +{ + return _hypercall3(int, console_io, cmd, count, str); } static inline int HYPERVISOR_physdev_op( - void *physdev_op) -{ - int ret; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_physdev_op), "D" (physdev_op) - : __syscall_clobber); - - return ret; + void *physdev_op) +{ + return _hypercall1(int, physdev_op, physdev_op); } static inline int HYPERVISOR_grant_table_op( - unsigned int cmd, void *uop, unsigned int count) -{ - int ret; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_grant_table_op), "D" ((unsigned long)cmd), "S" ((unsigned long)uop), "d" (count) - : __syscall_clobber); - - return ret; + unsigned int cmd, void *uop, unsigned int count) +{ + return _hypercall3(int, grant_table_op, cmd, uop, count); } static inline int HYPERVISOR_update_va_mapping_otherdomain( - unsigned long page_nr, pte_t new_val, unsigned long flags, domid_t domid) -{ - int ret; - - __asm__ __volatile__ ( - "movq %5, %%r10;" TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_update_va_mapping_otherdomain), - "D" (page_nr), "S" (new_val.pte), "d" (flags), "g" ((unsigned long)domid) - : __syscall_clobber,"r10"); - - return ret; + unsigned long va, pte_t new_val, unsigned long flags, domid_t domid) +{ + return _hypercall4(int, update_va_mapping_otherdomain, va, + new_val.pte, flags, domid); } static inline int HYPERVISOR_vm_assist( - unsigned int cmd, unsigned int type) -{ - int ret; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_vm_assist), "D" ((unsigned long)cmd), "S" ((unsigned long)type) - : __syscall_clobber); - - return ret; + unsigned int cmd, unsigned int type) +{ + return _hypercall2(int, vm_assist, cmd, type); +} + +static inline int +HYPERVISOR_boot_vcpu( + unsigned long vcpu, vcpu_guest_context_t *ctxt) +{ + return _hypercall2(int, boot_vcpu, vcpu, ctxt); +} + +static inline int +HYPERVISOR_vcpu_up( + int vcpu) +{ + return _hypercall2(int, sched_op, SCHEDOP_vcpu_up | + (vcpu << SCHEDOP_vcpushift), 0); +} + +static inline int +HYPERVISOR_vcpu_pickle( + int vcpu, vcpu_guest_context_t *ctxt) +{ + return _hypercall2(int, sched_op, SCHEDOP_vcpu_pickle | + (vcpu << SCHEDOP_vcpushift), ctxt); } static inline int HYPERVISOR_switch_to_user(void) { - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) : "0" ((unsigned long)__HYPERVISOR_switch_to_user) : __syscall_clobber ); - - return ret; -} - -static inline int -HYPERVISOR_boot_vcpu( - unsigned long vcpu, vcpu_guest_context_t *ctxt) -{ - int ret; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" (__HYPERVISOR_boot_vcpu), "D" (vcpu), "S" (ctxt) - : __syscall_clobber); - - return ret; + return _hypercall0(int, switch_to_user); } static inline int HYPERVISOR_set_segment_base( - int reg, unsigned long value) -{ - int ret; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_set_segment_base), "D" ((unsigned long)reg), "S" (value) - : __syscall_clobber ); - - return ret; -} - -static inline int -HYPERVISOR_vcpu_pickle( - int vcpu, vcpu_guest_context_t *ctxt) -{ - int ret; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) - : "0" ((unsigned long)__HYPERVISOR_sched_op), - "D" ((unsigned long)SCHEDOP_vcpu_pickle | (vcpu << SCHEDOP_vcpushift)), - "S" ((unsigned long)ctxt) - : __syscall_clobber ); - - return ret; + int reg, unsigned long value) +{ + return _hypercall2(int, set_segment_base, reg, value); +} + +static inline int +HYPERVISOR_suspend( + unsigned long srec) +{ + return _hypercall2(int, sched_op, SCHEDOP_shutdown | + (SHUTDOWN_suspend << SCHEDOP_reasonshift), srec); } #endif /* __HYPERCALL_H__ */ + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 2b95125015a5 -r 37e9c9cd6c14 xen/arch/x86/x86_32/asm-offsets.c --- a/xen/arch/x86/x86_32/asm-offsets.c Fri Aug 26 13:06:49 2005 +++ b/xen/arch/x86/x86_32/asm-offsets.c Fri Aug 26 17:42:34 2005 @@ -71,6 +71,9 @@ OFFSET(VCPUINFO_upcall_mask, vcpu_info_t, evtchn_upcall_mask); BLANK(); + DEFINE(CPUINFO_sizeof, sizeof(struct cpu_info)); + BLANK(); + OFFSET(TRAPBOUNCE_error_code, struct trap_bounce, error_code); OFFSET(TRAPBOUNCE_cr2, struct trap_bounce, cr2); OFFSET(TRAPBOUNCE_flags, struct trap_bounce, flags); diff -r 2b95125015a5 -r 37e9c9cd6c14 xen/arch/x86/x86_32/entry.S --- a/xen/arch/x86/x86_32/entry.S Fri Aug 26 13:06:49 2005 +++ b/xen/arch/x86/x86_32/entry.S Fri Aug 26 17:42:34 2005 @@ -60,6 +60,11 @@ #include <asm/apicdef.h> #include <asm/page.h> #include <public/xen.h> + +#define GET_GUEST_REGS(reg) \ + movl $~(STACK_SIZE-1),reg; \ + andl %esp,reg; \ + orl $(STACK_SIZE-CPUINFO_sizeof),reg; #define GET_CURRENT(reg) \ movl $STACK_SIZE-4, reg; \ @@ -273,7 +278,41 @@ GET_CURRENT(%ebx) andl $(NR_hypercalls-1),%eax PERFC_INCR(PERFC_hypercalls, %eax) +#ifndef NDEBUG + /* Deliberately corrupt parameter regs not used by this hypercall. */ + pushl %eax + pushl UREGS_eip+4(%esp) + pushl 28(%esp) # EBP + pushl 28(%esp) # EDI + pushl 28(%esp) # ESI + pushl 28(%esp) # EDX + pushl 28(%esp) # ECX + pushl 28(%esp) # EBX + movzb hypercall_args_table(,%eax,1),%ecx + leal (%esp,%ecx,4),%edi + subl $6,%ecx + negl %ecx + movl %eax,%esi + movl $0xDEADBEEF,%eax + rep stosl + movl %esi,%eax +#endif call *hypercall_table(,%eax,4) +#ifndef NDEBUG + /* Deliberately corrupt parameter regs used by this hypercall. */ + addl $24,%esp # Shadow parameters + popl %ecx # Shadow EIP + cmpl %ecx,UREGS_eip(%esp) + popl %ecx # Shadow hypercall index + jne skip_clobber # If EIP has changed then don't clobber + movzb hypercall_args_table(,%ecx,1),%ecx + movl %esp,%edi + movl %eax,%esi + movl $0xDEADBEEF,%eax + rep stosl + movl %esi,%eax +skip_clobber: +#endif movl %eax,UREGS_eax(%esp) # save the return value test_all_events: @@ -674,12 +713,14 @@ do_arch_sched_op: # Ensure we return success even if we return via schedule_tail() xorl %eax,%eax - movl %eax,UREGS_eax+4(%esp) + GET_GUEST_REGS(%ecx) + movl %eax,UREGS_eax(%ecx) jmp do_sched_op do_switch_vm86: - # Discard the return address - addl $4,%esp + # Reset the stack pointer + GET_GUEST_REGS(%ecx) + movl %ecx,%esp # GS:ESI == Ring-1 stack activation movl UREGS_esp(%esp),%esi @@ -768,3 +809,36 @@ .rept NR_hypercalls-((.-hypercall_table)/4) .long do_ni_hypercall .endr + +ENTRY(hypercall_args_table) + .byte 1 /* do_set_trap_table */ /* 0 */ + .byte 4 /* do_mmu_update */ + .byte 2 /* do_set_gdt */ + .byte 2 /* do_stack_switch */ + .byte 4 /* do_set_callbacks */ + .byte 1 /* do_fpu_taskswitch */ /* 5 */ + .byte 2 /* do_arch_sched_op */ + .byte 1 /* do_dom0_op */ + .byte 2 /* do_set_debugreg */ + .byte 1 /* do_get_debugreg */ + .byte 4 /* do_update_descriptor */ /* 10 */ + .byte 0 /* do_ni_hypercall */ + .byte 5 /* do_dom_mem_op */ + .byte 2 /* do_multicall */ + .byte 4 /* do_update_va_mapping */ + .byte 2 /* do_set_timer_op */ /* 15 */ + .byte 1 /* do_event_channel_op */ + .byte 1 /* do_xen_version */ + .byte 3 /* do_console_io */ + .byte 1 /* do_physdev_op */ + .byte 3 /* do_grant_table_op */ /* 20 */ + .byte 2 /* do_vm_assist */ + .byte 5 /* do_update_va_mapping_otherdomain */ + .byte 0 /* do_switch_vm86 */ + .byte 2 /* do_boot_vcpu */ + .byte 0 /* do_ni_hypercall */ /* 25 */ + .byte 4 /* do_mmuext_op */ + .byte 1 /* do_acm_op */ + .rept NR_hypercalls-(.-hypercall_args_table) + .byte 0 /* do_ni_hypercall */ + .endr diff -r 2b95125015a5 -r 37e9c9cd6c14 xen/arch/x86/x86_64/asm-offsets.c --- a/xen/arch/x86/x86_64/asm-offsets.c Fri Aug 26 13:06:49 2005 +++ b/xen/arch/x86/x86_64/asm-offsets.c Fri Aug 26 17:42:34 2005 @@ -71,6 +71,9 @@ OFFSET(VCPUINFO_upcall_mask, vcpu_info_t, evtchn_upcall_mask); BLANK(); + DEFINE(CPUINFO_sizeof, sizeof(struct cpu_info)); + BLANK(); + OFFSET(TRAPBOUNCE_error_code, struct trap_bounce, error_code); OFFSET(TRAPBOUNCE_cr2, struct trap_bounce, cr2); OFFSET(TRAPBOUNCE_flags, struct trap_bounce, flags); diff -r 2b95125015a5 -r 37e9c9cd6c14 xen/arch/x86/x86_64/entry.S --- a/xen/arch/x86/x86_64/entry.S Fri Aug 26 13:06:49 2005 +++ b/xen/arch/x86/x86_64/entry.S Fri Aug 26 17:42:34 2005 @@ -11,6 +11,11 @@ #include <asm/apicdef.h> #include <asm/page.h> #include <public/xen.h> + +#define GET_GUEST_REGS(reg) \ + movq $~(STACK_SIZE-1),reg; \ + andq %rsp,reg; \ + orq $(STACK_SIZE-CPUINFO_sizeof),reg; #define GET_CURRENT(reg) \ movq $STACK_SIZE-8, reg; \ @@ -120,10 +125,42 @@ /*hypercall:*/ movq %r10,%rcx andq $(NR_hypercalls-1),%rax +#ifndef NDEBUG + /* Deliberately corrupt parameter regs not used by this hypercall. */ + pushq %rdi; pushq %rsi; pushq %rdx; pushq %rcx; pushq %r8 ; pushq %r9 + leaq hypercall_args_table(%rip),%r10 + movq $6,%rcx + sub (%r10,%rax,1),%cl + movq %rsp,%rdi + movl $0xDEADBEEF,%eax + rep stosq + popq %r9 ; popq %r8 ; popq %rcx; popq %rdx; popq %rsi; popq %rdi + movq UREGS_rax(%rsp),%rax + andq $(NR_hypercalls-1),%rax + pushq %rax + pushq UREGS_rip+8(%rsp) +#endif leaq hypercall_table(%rip),%r10 PERFC_INCR(PERFC_hypercalls, %rax) callq *(%r10,%rax,8) - movq %rax,UREGS_rax(%rsp) # save the return value +#ifndef NDEBUG + /* Deliberately corrupt parameter regs used by this hypercall. */ + popq %r10 # Shadow RIP + cmpq %r10,UREGS_rip(%rsp) + popq %rcx # Shadow hypercall index + jne skip_clobber /* If RIP has changed then don't clobber. */ + leaq hypercall_args_table(%rip),%r10 + movb (%r10,%rcx,1),%cl + movl $0xDEADBEEF,%r10d + cmpb $1,%cl; jb skip_clobber; movq %r10,UREGS_rdi(%rsp) + cmpb $2,%cl; jb skip_clobber; movq %r10,UREGS_rsi(%rsp) + cmpb $3,%cl; jb skip_clobber; movq %r10,UREGS_rdx(%rsp) + cmpb $4,%cl; jb skip_clobber; movq %r10,UREGS_r10(%rsp) + cmpb $5,%cl; jb skip_clobber; movq %r10,UREGS_r8(%rsp) + cmpb $6,%cl; jb skip_clobber; movq %r10,UREGS_r9(%rsp) +skip_clobber: +#endif + movq %rax,UREGS_rax(%rsp) # save the return value /* %rbx: struct vcpu */ test_all_events: @@ -538,7 +575,8 @@ do_arch_sched_op: # Ensure we return success even if we return via schedule_tail() xorl %eax,%eax - movq %rax,UREGS_rax+8(%rsp) + GET_GUEST_REGS(%r10) + movq %rax,UREGS_rax(%r10) jmp do_sched_op .data @@ -597,3 +635,36 @@ .rept NR_hypercalls-((.-hypercall_table)/4) .quad do_ni_hypercall .endr + +ENTRY(hypercall_args_table) + .byte 1 /* do_set_trap_table */ /* 0 */ + .byte 4 /* do_mmu_update */ + .byte 2 /* do_set_gdt */ + .byte 2 /* do_stack_switch */ + .byte 3 /* do_set_callbacks */ + .byte 1 /* do_fpu_taskswitch */ /* 5 */ + .byte 2 /* do_arch_sched_op */ + .byte 1 /* do_dom0_op */ + .byte 2 /* do_set_debugreg */ + .byte 1 /* do_get_debugreg */ + .byte 2 /* do_update_descriptor */ /* 10 */ + .byte 0 /* do_ni_hypercall */ + .byte 5 /* do_dom_mem_op */ + .byte 2 /* do_multicall */ + .byte 3 /* do_update_va_mapping */ + .byte 1 /* do_set_timer_op */ /* 15 */ + .byte 1 /* do_event_channel_op */ + .byte 1 /* do_xen_version */ + .byte 3 /* do_console_io */ + .byte 1 /* do_physdev_op */ + .byte 3 /* do_grant_table_op */ /* 20 */ + .byte 2 /* do_vm_assist */ + .byte 4 /* do_update_va_mapping_otherdomain */ + .byte 0 /* do_switch_to_user */ + .byte 2 /* do_boot_vcpu */ + .byte 2 /* do_set_segment_base */ /* 25 */ + .byte 4 /* do_mmuext_op */ + .byte 1 /* do_acm_op */ + .rept NR_hypercalls-(.-hypercall_args_table) + .byte 0 /* do_ni_hypercall */ + .endr diff -r 2b95125015a5 -r 37e9c9cd6c14 xen/common/multicall.c --- a/xen/common/multicall.c Fri Aug 26 13:06:49 2005 +++ b/xen/common/multicall.c Fri Aug 26 17:42:34 2005 @@ -45,6 +45,18 @@ do_multicall_call(&mcs->call); +#ifndef NDEBUG + { + /* + * Deliberately corrupt the contents of the multicall structure. + * The caller must depend only on the 'result' field on return. + */ + multicall_entry_t corrupt; + memset(&corrupt, 0xAA, sizeof(corrupt)); + (void)__copy_to_user(&call_list[i], &corrupt, sizeof(corrupt)); + } +#endif + if ( unlikely(__put_user(mcs->call.result, &call_list[i].result)) ) { DPRINTK("Error writing result back to multicall block.\n"); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |