[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [IA64] Hypercall optimizations
# HG changeset patch # User awilliam@xxxxxxxxxxxx # Date 1168559818 25200 # Node ID 01ea554f1c5e8bdbfa172349438298b15da6fc5c # Parent db72b85b81bb1478cb2e91b6411596648bdc9a2c [IA64] Hypercall optimizations provide hypercall the same path with system most of scrach registers don't need to be saved/restored it is good for performance Signed-off-by: Anthony Xu <anthony.xu@xxxxxxxxx> --- linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S | 7 linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c | 2 linux-2.6-xen-sparse/include/asm-ia64/hypercall.h | 108 +---- xen/arch/ia64/asm-offsets.c | 1 xen/arch/ia64/linux-xen/entry.S | 111 +++++ xen/arch/ia64/xen/faults.c | 23 - xen/arch/ia64/xen/hypercall.c | 172 ++------ xen/arch/ia64/xen/ivt.S | 430 +++++++++++++++++----- xen/include/asm-ia64/config.h | 6 xen/include/asm-ia64/hypercall.h | 2 xen/include/public/arch-ia64.h | 2 11 files changed, 541 insertions(+), 323 deletions(-) diff -r db72b85b81bb -r 01ea554f1c5e linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S --- a/linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S Thu Jan 11 14:42:24 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S Thu Jan 11 16:56:58 2007 -0700 @@ -306,4 +306,11 @@ GLOBAL_ENTRY(xen_ssm_i_1) brl.cond.sptk .vdso_ssm_i_1_ret ;; END(xen_ssm_i_1) + +GLOBAL_ENTRY(__hypercall) + mov r2=r37 + break 0x1000 + br.ret.sptk.many b0 + ;; +END(__hypercall) #endif diff -r db72b85b81bb -r 01ea554f1c5e linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c --- a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c Thu Jan 11 14:42:24 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c Thu Jan 11 16:56:58 2007 -0700 @@ -48,6 +48,8 @@ static int p2m_expose_init(void); #else #define p2m_expose_init() (-ENOSYS) #endif + +EXPORT_SYMBOL(__hypercall); //XXX same as i386, x86_64 contiguous_bitmap_set(), contiguous_bitmap_clear() // move those to lib/contiguous_bitmap? diff -r db72b85b81bb -r 01ea554f1c5e linux-2.6-xen-sparse/include/asm-ia64/hypercall.h --- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Thu Jan 11 14:42:24 2007 -0700 +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Thu Jan 11 16:56:58 2007 -0700 @@ -39,6 +39,9 @@ #include <asm/xen/xcom_hcall.h> struct xencomm_handle; +extern unsigned long __hypercall(unsigned long a1, unsigned long a2, + unsigned long a3, unsigned long a4, + unsigned long a5, unsigned long cmd); /* * Assembler stubs for hyper-calls. @@ -47,115 +50,58 @@ struct xencomm_handle; #define _hypercall0(type, name) \ ({ \ long __res; \ - __asm__ __volatile__ (";;\n" \ - "mov r2=%1\n" \ - "break 0x1000 ;;\n" \ - "mov %0=r8 ;;\n" \ - : "=r" (__res) \ - : "J" (__HYPERVISOR_##name) \ - : "r2","r8", \ - "memory" ); \ + __res=__hypercall(0, 0, 0, 0, 0, __HYPERVISOR_##name); \ (type)__res; \ }) #define _hypercall1(type, name, a1) \ ({ \ long __res; \ - __asm__ __volatile__ (";;\n" \ - "mov r14=%2\n" \ - "mov r2=%1\n" \ - "break 0x1000 ;;\n" \ - "mov %0=r8 ;;\n" \ - : "=r" (__res) \ - : "J" (__HYPERVISOR_##name), \ - "rI" ((unsigned long)(a1)) \ - : "r14","r2","r8", \ - "memory" ); \ + __res = __hypercall((unsigned long)a1, \ + 0, 0, 0, 0, __HYPERVISOR_##name); \ (type)__res; \ }) #define _hypercall2(type, name, a1, a2) \ ({ \ long __res; \ - __asm__ __volatile__ (";;\n" \ - "mov r14=%2\n" \ - "mov r15=%3\n" \ - "mov r2=%1\n" \ - "break 0x1000 ;;\n" \ - "mov %0=r8 ;;\n" \ - : "=r" (__res) \ - : "J" (__HYPERVISOR_##name), \ - "rI" ((unsigned long)(a1)), \ - "rI" ((unsigned long)(a2)) \ - : "r14","r15","r2","r8", \ - "memory" ); \ + __res = __hypercall((unsigned long)a1, \ + (unsigned long)a2, \ + 0, 0, 0, __HYPERVISOR_##name); \ (type)__res; \ }) #define _hypercall3(type, name, a1, a2, a3) \ ({ \ long __res; \ - __asm__ __volatile__ (";;\n" \ - "mov r14=%2\n" \ - "mov r15=%3\n" \ - "mov r16=%4\n" \ - "mov r2=%1\n" \ - "break 0x1000 ;;\n" \ - "mov %0=r8 ;;\n" \ - : "=r" (__res) \ - : "J" (__HYPERVISOR_##name), \ - "rI" ((unsigned long)(a1)), \ - "rI" ((unsigned long)(a2)), \ - "rI" ((unsigned long)(a3)) \ - : "r14","r15","r16","r2","r8", \ - "memory" ); \ - (type)__res; \ + __res = __hypercall((unsigned long)a1, \ + (unsigned long)a2, \ + (unsigned long)a3, \ + 0, 0, __HYPERVISOR_##name); \ + (type)__res; \ }) #define _hypercall4(type, name, a1, a2, a3, a4) \ ({ \ long __res; \ - __asm__ __volatile__ (";;\n" \ - "mov r14=%2\n" \ - "mov r15=%3\n" \ - "mov r16=%4\n" \ - "mov r17=%5\n" \ - "mov r2=%1\n" \ - "break 0x1000 ;;\n" \ - "mov %0=r8 ;;\n" \ - : "=r" (__res) \ - : "J" (__HYPERVISOR_##name), \ - "rI" ((unsigned long)(a1)), \ - "rI" ((unsigned long)(a2)), \ - "rI" ((unsigned long)(a3)), \ - "rI" ((unsigned long)(a4)) \ - : "r14","r15","r16","r2","r8", \ - "r17","memory" ); \ - (type)__res; \ + __res = __hypercall((unsigned long)a1, \ + (unsigned long)a2, \ + (unsigned long)a3, \ + (unsigned long)a4, \ + 0, __HYPERVISOR_##name); \ + (type)__res; \ }) #define _hypercall5(type, name, a1, a2, a3, a4, a5) \ ({ \ long __res; \ - __asm__ __volatile__ (";;\n" \ - "mov r14=%2\n" \ - "mov r15=%3\n" \ - "mov r16=%4\n" \ - "mov r17=%5\n" \ - "mov r18=%6\n" \ - "mov r2=%1\n" \ - "break 0x1000 ;;\n" \ - "mov %0=r8 ;;\n" \ - : "=r" (__res) \ - : "J" (__HYPERVISOR_##name), \ - "rI" ((unsigned long)(a1)), \ - "rI" ((unsigned long)(a2)), \ - "rI" ((unsigned long)(a3)), \ - "rI" ((unsigned long)(a4)), \ - "rI" ((unsigned long)(a5)) \ - : "r14","r15","r16","r2","r8", \ - "r17","r18","memory" ); \ - (type)__res; \ + __res = __hypercall((unsigned long)a1, \ + (unsigned long)a2, \ + (unsigned long)a3, \ + (unsigned long)a4, \ + (unsigned long)a5, \ + __HYPERVISOR_##name); \ + (type)__res; \ }) diff -r db72b85b81bb -r 01ea554f1c5e xen/arch/ia64/asm-offsets.c --- a/xen/arch/ia64/asm-offsets.c Thu Jan 11 14:42:24 2007 -0700 +++ b/xen/arch/ia64/asm-offsets.c Thu Jan 11 16:56:58 2007 -0700 @@ -56,6 +56,7 @@ void foo(void) DEFINE(IA64_TASK_THREAD_ON_USTACK_OFFSET, offsetof (struct vcpu, arch._thread.on_ustack)); DEFINE(IA64_VCPU_DOMAIN_OFFSET, offsetof (struct vcpu, domain)); + DEFINE(IA64_VCPU_HYPERCALL_CONTINUATION_OFS, offsetof (struct vcpu, arch.hypercall_continuation)); DEFINE(IA64_VCPU_META_RR0_OFFSET, offsetof (struct vcpu, arch.metaphysical_rr0)); DEFINE(IA64_VCPU_META_SAVED_RR0_OFFSET, offsetof (struct vcpu, arch.metaphysical_saved_rr0)); DEFINE(IA64_VCPU_BREAKIMM_OFFSET, offsetof (struct vcpu, arch.breakimm)); diff -r db72b85b81bb -r 01ea554f1c5e xen/arch/ia64/linux-xen/entry.S --- a/xen/arch/ia64/linux-xen/entry.S Thu Jan 11 14:42:24 2007 -0700 +++ b/xen/arch/ia64/linux-xen/entry.S Thu Jan 11 16:56:58 2007 -0700 @@ -676,7 +676,9 @@ GLOBAL_ENTRY(ia64_ret_from_syscall) cmp.ge p6,p7=r8,r0 // syscall executed successfully? adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8 mov r10=r0 // clear error indication in r10 +#ifndef XEN (p7) br.cond.spnt handle_syscall_error // handle potential syscall failure +#endif END(ia64_ret_from_syscall) // fall through /* @@ -764,7 +766,9 @@ ENTRY(ia64_leave_syscall) ld8 r19=[r2],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs" nop.i 0 ;; +#ifndef XEN mov r16=ar.bsp // M2 get existing backing store pointer +#endif ld8 r18=[r2],PT(R9)-PT(B6) // load b6 #ifndef XEN (p6) and r15=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE? @@ -814,7 +818,11 @@ ENTRY(ia64_leave_syscall) mov f8=f0 // F clear f8 ;; ld8.fill r12=[r2] // M0|1 restore r12 (sp) +#ifdef XEN + ld8.fill r2=[r3] // M0|1 +#else ld8.fill r15=[r3] // M0|1 restore r15 +#endif mov b6=r18 // I0 restore b6 #ifdef XEN @@ -827,7 +835,9 @@ ENTRY(ia64_leave_syscall) srlz.d // M0 ensure interruption collection is off (for cover) shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition +#ifndef XEN cover // B add current frame into dirty partition & set cr.ifs +#endif ;; (pUStk) ld4 r17=[r17] // M0|1 r17 = cpu_data->phys_stacked_size_p8 mov r19=ar.bsp // M2 get new backing store pointer @@ -893,23 +903,18 @@ GLOBAL_ENTRY(ia64_leave_kernel) .work_processed_kernel: #ifdef XEN ;; -(pUStk) ssm psr.i -(pUStk) br.call.sptk.many b0=do_softirq -(pUStk) rsm psr.i - ;; - alloc loc0=ar.pfs,0,1,1,0 - adds out0=16,r12 +(pUStk) ssm psr.i +(pUStk) br.call.sptk.many b0=do_softirq +(pUStk) ssm psr.i + ;; +(pUStk) br.call.sptk.many b0=reflect_event + ;; adds r7 = PT(EML_UNAT)+16,r12 ;; ld8 r7 = [r7] ;; -(pUStk) br.call.sptk.many b0=reflect_event -//(pUStk) br.call.sptk.many b0=deliver_pending_interrupt - ;; - mov ar.pfs=loc0 mov ar.unat=r7 /* load eml_unat */ mov r31=r0 - #else adds r17=TI_FLAGS+IA64_TASK_SIZE,r13 @@ -1184,8 +1189,11 @@ skip_rbs_switch: mov cr.ipsr=r29 // M2 mov ar.pfs=r26 // I0 (pLvSys)mov r17=r0 // A clear r17 for leave_syscall, no-op otherwise - +#ifdef XEN + mov cr.ifs=r30 // M2 +#else (p9) mov cr.ifs=r30 // M2 +#endif mov b0=r21 // I0 (pLvSys)mov r18=r0 // A clear r18 for leave_syscall, no-op otherwise @@ -1195,7 +1203,11 @@ skip_rbs_switch: ;; (pUStk) mov ar.rnat=r24 // M2 must happen with RSE in lazy mode nop 0 +#ifdef XEN +(pLvSys)mov r15=r0 +#else (pLvSys)mov r2=r0 +#endif mov ar.rsc=r27 // M2 mov pr=r31,-1 // I0 @@ -1459,7 +1471,80 @@ 1: mov gp=loc2 // restore gp br.ret.sptk.many rp END(unw_init_running) -#ifndef XEN +#ifdef XEN + .rodata + .align 8 + .globl ia64_hypercall_table +ia64_hypercall_table: + data8 do_ni_hypercall /* do_set_trap_table *//* 0 */ + data8 do_ni_hypercall /* do_mmu_update */ + data8 do_ni_hypercall /* do_set_gdt */ + data8 do_ni_hypercall /* do_stack_switch */ + data8 do_ni_hypercall /* do_set_callbacks */ + data8 do_ni_hypercall /* do_fpu_taskswitch *//* 5 */ + data8 do_sched_op_compat + data8 do_ni_hypercall + data8 do_ni_hypercall /* do_set_debugreg */ + data8 do_ni_hypercall /* do_get_debugreg */ + data8 do_ni_hypercall /* do_update_descriptor * 10 */ + data8 do_ni_hypercall /* do_ni_hypercall */ + data8 do_memory_op + data8 do_multicall + data8 do_ni_hypercall /* do_update_va_mapping */ + data8 do_ni_hypercall /* do_set_timer_op */ /* 15 */ + data8 do_ni_hypercall + data8 do_xen_version + data8 do_console_io + data8 do_ni_hypercall + data8 do_grant_table_op /* 20 */ + data8 do_ni_hypercall /* do_vm_assist */ + data8 do_ni_hypercall /* do_update_va_mapping_othe */ + data8 do_ni_hypercall /* (x86 only) */ + data8 do_ni_hypercall /* do_vcpu_op */ + data8 do_ni_hypercall /* (x86_64 only) */ /* 25 */ + data8 do_ni_hypercall /* do_mmuext_op */ + data8 do_ni_hypercall /* do_acm_op */ + data8 do_ni_hypercall /* do_nmi_op */ + data8 do_sched_op + data8 do_callback_op /* */ /* 30 */ + data8 do_xenoprof_op /* */ + data8 do_event_channel_op + data8 do_physdev_op + data8 do_hvm_op /* */ + data8 do_sysctl /* */ /* 35 */ + data8 do_domctl /* */ + data8 do_ni_hypercall /* */ + data8 do_ni_hypercall /* */ + data8 do_ni_hypercall /* */ + data8 do_ni_hypercall /* */ /* 40 */ + data8 do_ni_hypercall /* */ + data8 do_ni_hypercall /* */ + data8 do_ni_hypercall /* */ + data8 do_ni_hypercall /* */ + data8 do_ni_hypercall /* */ /* 45 */ + data8 do_ni_hypercall /* */ + data8 do_ni_hypercall /* */ + data8 do_dom0vp_op /* dom0vp_op */ + data8 do_pirq_guest_eoi /* arch_1 */ + data8 do_ni_hypercall /* arch_2 */ /* 50 */ + data8 do_ni_hypercall /* arch_3 */ + data8 do_ni_hypercall /* arch_4 */ + data8 do_ni_hypercall /* arch_5 */ + data8 do_ni_hypercall /* arch_6 */ + data8 do_ni_hypercall /* arch_7 */ /* 55 */ + data8 do_ni_hypercall + data8 do_ni_hypercall + data8 do_ni_hypercall + data8 do_ni_hypercall + data8 do_ni_hypercall /* 60 */ + data8 do_ni_hypercall + data8 do_ni_hypercall + data8 do_ni_hypercall + + // guard against failures to increase NR_hypercalls + .org ia64_hypercall_table + 8*NR_hypercalls + +#else .rodata .align 8 .globl sys_call_table diff -r db72b85b81bb -r 01ea554f1c5e xen/arch/ia64/xen/faults.c --- a/xen/arch/ia64/xen/faults.c Thu Jan 11 14:42:24 2007 -0700 +++ b/xen/arch/ia64/xen/faults.c Thu Jan 11 16:56:58 2007 -0700 @@ -83,8 +83,8 @@ void reflect_interruption(unsigned long check_bad_nested_interruption(isr, regs, vector); PSCB(v, unat) = regs->ar_unat; // not sure if this is really needed? PSCB(v, precover_ifs) = regs->cr_ifs; + PSCB(v, ipsr) = vcpu_get_ipsr_int_state(v, regs->cr_ipsr); vcpu_bsw0(v); - PSCB(v, ipsr) = vcpu_get_ipsr_int_state(v, regs->cr_ipsr); PSCB(v, isr) = isr; PSCB(v, iip) = regs->cr_iip; PSCB(v, ifs) = 0; @@ -120,24 +120,29 @@ void reflect_extint(struct pt_regs *regs reflect_interruption(isr, regs, IA64_EXTINT_VECTOR); } -void reflect_event(struct pt_regs *regs) -{ - unsigned long isr = regs->cr_ipsr & IA64_PSR_RI; - struct vcpu *v = current; +void reflect_event(void) +{ + struct vcpu *v = current; + struct pt_regs *regs; + unsigned long isr; + + if (!event_pending(v)) + return; /* Sanity check */ - if (is_idle_vcpu(v) || !user_mode(regs)) { + if (is_idle_vcpu(v)) { //printk("WARN: invocation to reflect_event in nested xen\n"); return; } - if (!event_pending(v)) - return; + regs = vcpu_regs(v); // can't inject event, when XEN is emulating rfi // and both PSCB(v, ifs) and regs->ifs are valid if (regs->cr_iip == *(unsigned long *)dorfirfi) return; + + isr = regs->cr_ipsr & IA64_PSR_RI; if (!PSCB(v, interrupt_collection_enabled)) printk("psr.ic off, delivering event, ipsr=%lx,iip=%lx," @@ -145,8 +150,8 @@ void reflect_event(struct pt_regs *regs) regs->cr_ipsr, regs->cr_iip, isr, PSCB(v, iip)); PSCB(v, unat) = regs->ar_unat; // not sure if this is really needed? PSCB(v, precover_ifs) = regs->cr_ifs; + PSCB(v, ipsr) = vcpu_get_ipsr_int_state(v, regs->cr_ipsr); vcpu_bsw0(v); - PSCB(v, ipsr) = vcpu_get_ipsr_int_state(v, regs->cr_ipsr); PSCB(v, isr) = isr; PSCB(v, iip) = regs->cr_iip; PSCB(v, ifs) = 0; diff -r db72b85b81bb -r 01ea554f1c5e xen/arch/ia64/xen/hypercall.c --- a/xen/arch/ia64/xen/hypercall.c Thu Jan 11 14:42:24 2007 -0700 +++ b/xen/arch/ia64/xen/hypercall.c Thu Jan 11 16:56:58 2007 -0700 @@ -17,6 +17,7 @@ #include <asm/sal.h> /* FOR struct ia64_sal_retval */ #include <asm/fpswa.h> /* FOR struct fpswa_ret_t */ +#include <asm/vmx_vcpu.h> #include <asm/vcpu.h> #include <asm/dom_fw.h> #include <public/domctl.h> @@ -32,94 +33,14 @@ #include <xen/event.h> #include <xen/perfc.h> -static long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg); -static long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg); - -const hypercall_t ia64_hypercall_table[NR_hypercalls] = -{ - (hypercall_t)do_ni_hypercall, /* do_set_trap_table *//* 0 */ - (hypercall_t)do_ni_hypercall, /* do_mmu_update */ - (hypercall_t)do_ni_hypercall, /* do_set_gdt */ - (hypercall_t)do_ni_hypercall, /* do_stack_switch */ - (hypercall_t)do_ni_hypercall, /* do_set_callbacks */ - (hypercall_t)do_ni_hypercall, /* do_fpu_taskswitch *//* 5 */ - (hypercall_t)do_sched_op_compat, - (hypercall_t)do_ni_hypercall, - (hypercall_t)do_ni_hypercall, /* do_set_debugreg */ - (hypercall_t)do_ni_hypercall, /* do_get_debugreg */ - (hypercall_t)do_ni_hypercall, /* do_update_descriptor * 10 */ - (hypercall_t)do_ni_hypercall, /* do_ni_hypercall */ - (hypercall_t)do_memory_op, - (hypercall_t)do_multicall, - (hypercall_t)do_ni_hypercall, /* do_update_va_mapping */ - (hypercall_t)do_ni_hypercall, /* do_set_timer_op */ /* 15 */ - (hypercall_t)do_ni_hypercall, - (hypercall_t)do_xen_version, - (hypercall_t)do_console_io, - (hypercall_t)do_ni_hypercall, - (hypercall_t)do_grant_table_op, /* 20 */ - (hypercall_t)do_ni_hypercall, /* do_vm_assist */ - (hypercall_t)do_ni_hypercall, /* do_update_va_mapping_othe */ - (hypercall_t)do_ni_hypercall, /* (x86 only) */ - (hypercall_t)do_ni_hypercall, /* do_vcpu_op */ - (hypercall_t)do_ni_hypercall, /* (x86_64 only) */ /* 25 */ - (hypercall_t)do_ni_hypercall, /* do_mmuext_op */ - (hypercall_t)do_ni_hypercall, /* do_acm_op */ - (hypercall_t)do_ni_hypercall, /* do_nmi_op */ - (hypercall_t)do_sched_op, - (hypercall_t)do_callback_op, /* */ /* 30 */ - (hypercall_t)do_xenoprof_op, /* */ - (hypercall_t)do_event_channel_op, - (hypercall_t)do_physdev_op, - (hypercall_t)do_hvm_op, /* */ - (hypercall_t)do_sysctl, /* */ /* 35 */ - (hypercall_t)do_domctl, /* */ - (hypercall_t)do_ni_hypercall, /* */ - (hypercall_t)do_ni_hypercall, /* */ - (hypercall_t)do_ni_hypercall, /* */ - (hypercall_t)do_ni_hypercall, /* */ /* 40 */ - (hypercall_t)do_ni_hypercall, /* */ - (hypercall_t)do_ni_hypercall, /* */ - (hypercall_t)do_ni_hypercall, /* */ - (hypercall_t)do_ni_hypercall, /* */ - (hypercall_t)do_ni_hypercall, /* */ /* 45 */ - (hypercall_t)do_ni_hypercall, /* */ - (hypercall_t)do_ni_hypercall, /* */ - (hypercall_t)do_dom0vp_op, /* dom0vp_op */ - (hypercall_t)do_ni_hypercall, /* arch_1 */ - (hypercall_t)do_ni_hypercall, /* arch_2 */ /* 50 */ - (hypercall_t)do_ni_hypercall, /* arch_3 */ - (hypercall_t)do_ni_hypercall, /* arch_4 */ - (hypercall_t)do_ni_hypercall, /* arch_5 */ - (hypercall_t)do_ni_hypercall, /* arch_6 */ - (hypercall_t)do_ni_hypercall, /* arch_7 */ /* 55 */ - (hypercall_t)do_ni_hypercall, - (hypercall_t)do_ni_hypercall, - (hypercall_t)do_ni_hypercall, - (hypercall_t)do_ni_hypercall, - (hypercall_t)do_ni_hypercall, /* 60 */ - (hypercall_t)do_ni_hypercall, - (hypercall_t)do_ni_hypercall, - (hypercall_t)do_ni_hypercall -}; +extern long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg); +extern long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg); static IA64FAULT xen_hypercall (struct pt_regs *regs) { uint32_t cmd = (uint32_t)regs->r2; - - if (cmd < NR_hypercalls) { - perfc_incra(hypercalls, cmd); - regs->r8 = (*ia64_hypercall_table[cmd])( - regs->r14, - regs->r15, - regs->r16, - regs->r17, - regs->r18, - regs->r19); - } else - regs->r8 = -ENOSYS; - + printk("Warning %s should not be called %d\n", __FUNCTION__, cmd); return IA64_NO_FAULT; } @@ -129,13 +50,20 @@ 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); + printk("Warning %s should not be called %d\n", + __FUNCTION__, cmd); break; default: regs->r8 = -ENOSYS; } return IA64_NO_FAULT; } + +long do_pirq_guest_eoi(int pirq) +{ + return pirq_guest_eoi(current->domain, pirq); +} + static void fw_hypercall_ipi (struct pt_regs *regs) @@ -320,42 +248,42 @@ unsigned long hypercall_create_continuat va_list args; va_start(args, format); - if ( test_bit(_MCSF_in_multicall, &mcs->flags) ) { - panic("PREEMPT happen in multicall\n"); // Not support yet - } else { - vcpu_set_gr(v, 2, op, 0); - for ( i = 0; *p != '\0'; i++) { - switch ( *p++ ) - { - case 'i': - arg = (unsigned long)va_arg(args, unsigned int); - break; - case 'l': - arg = (unsigned long)va_arg(args, unsigned long); - break; - case 'h': - arg = (unsigned long)va_arg(args, void *); - break; - default: - arg = 0; - BUG(); - } - switch (i) { - case 0: vcpu_set_gr(v, 14, arg, 0); - break; - case 1: vcpu_set_gr(v, 15, arg, 0); - break; - case 2: vcpu_set_gr(v, 16, arg, 0); - break; - case 3: vcpu_set_gr(v, 17, arg, 0); - break; - case 4: vcpu_set_gr(v, 18, arg, 0); - break; - default: panic("Too many args for hypercall continuation\n"); - break; - } - } - } + if (test_bit(_MCSF_in_multicall, &mcs->flags)) + panic("PREEMPT happen in multicall\n"); // Not support yet + + vcpu_set_gr(v, 15, op, 0); + + for (i = 0; *p != '\0'; i++) { + switch ( *p++ ) + { + case 'i': + arg = (unsigned long)va_arg(args, unsigned int); + break; + case 'l': + arg = (unsigned long)va_arg(args, unsigned long); + break; + case 'h': + arg = (unsigned long)va_arg(args, void *); + break; + default: + arg = 0; + BUG(); + } + vcpu_set_gr(v, 16 + i, arg, 0); + } + + if (i >= 6) + panic("Too many args for hypercall continuation\n"); + + // Clean other argument to 0 + while (i < 6) { + vcpu_set_gr(v, 16 + i, 0, 0); + i++; + } + + // re-execute break; + vcpu_decrement_iip(v); + v->arch.hypercall_continuation = 1; va_end(args); return op; @@ -369,7 +297,7 @@ iosapic_guest_write( iosapic_guest_write( unsigned long physbase, unsigned int reg, u32 pval); -static long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) +long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) { int irq; long ret; @@ -524,7 +452,7 @@ static long unregister_guest_callback(st /* First time to add callback to xen/ia64, so let's just stick to * the newer callback interface. */ -static long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg) +long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg) { long ret; diff -r db72b85b81bb -r 01ea554f1c5e xen/arch/ia64/xen/ivt.S --- a/xen/arch/ia64/xen/ivt.S Thu Jan 11 14:42:24 2007 -0700 +++ b/xen/arch/ia64/xen/ivt.S Thu Jan 11 16:56:58 2007 -0700 @@ -2,6 +2,7 @@ #include <asm/debugger.h> #include <asm/vhpt.h> #include <public/arch-ia64.h> +#include <asm/config.h> #endif /* * arch/ia64/kernel/ivt.S @@ -1055,7 +1056,6 @@ ENTRY(break_fault) * level. */ DBG_FAULT(11) -#ifdef XEN mov r16=cr.isr mov r17=cr.iim mov r31=pr @@ -1101,103 +1101,202 @@ ENTRY(break_fault) ;; ld8 r22 = [r22] ;; - adds r22=IA64_VCPU_BREAKIMM_OFFSET,r22 - ;; - ld4 r23=[r22];; + adds r23=IA64_VCPU_BREAKIMM_OFFSET,r22 + ;; + ld4 r23=[r23];; cmp4.eq p6,p7=r23,r17 // Xen-reserved breakimm? -(p6) br.spnt.many dispatch_break_fault +(p6) br.spnt.many fast_hypercall ;; br.sptk.many fast_break_reflect ;; -#else /* !XEN */ - movl r16=THIS_CPU(cpu_kr)+IA64_KR_CURRENT_OFFSET;; - ld8 r16=[r16] - mov r17=cr.iim - mov r18=__IA64_BREAK_SYSCALL - mov r21=ar.fpsr - mov r29=cr.ipsr - mov r19=b6 - mov r25=ar.unat - mov r27=ar.rsc - mov r26=ar.pfs - mov r28=cr.iip -#ifndef XEN - mov r31=pr // prepare to save predicates -#endif - mov r20=r1 - ;; + + +fast_hypercall: + shr r25=r2,8;; + cmp.ne p7,p0=r0,r25 +(p7) br.spnt.few dispatch_break_fault + ;; + // fall through + + + /* + * The streamlined system call entry/exit paths only save/restore the initial part + * of pt_regs. This implies that the callers of system-calls must adhere to the + * normal procedure calling conventions. + * + * Registers to be saved & restored: + * CR registers: cr.ipsr, cr.iip, cr.ifs + * AR registers: ar.unat, ar.pfs, ar.rsc, ar.rnat, ar.bspstore, ar.fpsr + * others: pr, b0, b6, loadrs, r1, r11, r12, r13, r15 + * Registers to be restored only: + * r8-r11: output value from the system call. + * + * During system call exit, scratch registers (including r15) are modified/cleared + * to prevent leaking bits from kernel to user level. + */ + +// DBG_FAULT(11) +// mov.m r16=IA64_KR(CURRENT) // M2 r16 <- current task (12 cyc) + mov r16=r22 + mov r29=cr.ipsr // M2 (12 cyc) +// mov r31=pr // I0 (2 cyc) + mov r15=r2 + +// mov r17=cr.iim // M2 (2 cyc) + mov.m r27=ar.rsc // M2 (12 cyc) +// mov r18=__IA64_BREAK_SYSCALL // A + + mov.m ar.rsc=0 // M2 + mov.m r21=ar.fpsr // M2 (12 cyc) + mov r19=b6 // I0 (2 cyc) + ;; + mov.m r23=ar.bspstore // M2 (12 cyc) + mov.m r24=ar.rnat // M2 (5 cyc) + mov.i r26=ar.pfs // I0 (2 cyc) + + invala // M0|1 + nop.m 0 // M + mov r20=r1 // A save r1 + + nop.m 0 +// movl r30=sys_call_table // X + movl r30=ia64_hypercall_table // X + + mov r28=cr.iip // M2 (2 cyc) +// cmp.eq p0,p7=r18,r17 // I0 is this a system call? +//(p7) br.cond.spnt non_syscall // B no -> + // + // From this point on, we are definitely on the syscall-path + // and we can use (non-banked) scratch registers. + // +/////////////////////////////////////////////////////////////////////// + mov r1=r16 // A move task-pointer to "addl"-addressable reg + mov r2=r16 // A setup r2 for ia64_syscall_setup +// add r9=TI_FLAGS+IA64_TASK_SIZE,r16 // A r9 = ¤t_thread_info()->flags + adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 - cmp.eq p0,p7=r18,r17 // is this a system call? - // (p7 <- false, if so) -(p7) br.cond.spnt non_syscall - ;; - ld1 r17=[r16] // load current->thread.on_ustack flag - st1 [r16]=r0 // clear current->thread.on_ustack flag - add r1=-IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 - // set r1 for - // MINSTATE_START_SAVE_MIN_VIRT - ;; - invala - - /* adjust return address so we skip over the break instruction: */ - - extr.u r8=r29,41,2 // extract ei field from cr.ipsr - ;; - cmp.eq p6,p7=2,r8 // isr.ei==2? - mov r2=r1 // setup r2 for ia64_syscall_setup - ;; -(p6) mov r8=0 // clear ei to 0 -(p6) adds r28=16,r28 // switch cr.iip to next bundle - // cr.ipsr.ei wrapped -(p7) adds r8=1,r8 // increment ei to next slot - ;; - cmp.eq pKStk,pUStk=r0,r17 // are we in kernel mode already? - dep r29=r8,r29,41,2 // insert new ei into cr.ipsr - ;; - - // switch from user to kernel RBS: - MINSTATE_START_SAVE_MIN_VIRT - br.call.sptk.many b7=ia64_syscall_setup - ;; - MINSTATE_END_SAVE_MIN_VIRT // switch to bank 1 - ssm psr.ic | PSR_DEFAULT_BITS - ;; - srlz.i // guarantee that interruption - // collection is on - mov r3=NR_syscalls - 1 - ;; -(p15) ssm psr.i // restore psr.i - // p10==true means out registers are more than 8 or r15's Nat is true -(p10) br.cond.spnt.many ia64_ret_from_syscall - ;; - movl r16=sys_call_table - - adds r15=-1024,r15 // r15 contains the syscall number -- - // subtract 1024 from it - movl r2=ia64_ret_from_syscall - ;; - shladd r20=r15,3,r16 // r20 = sys_call_table + - // 8*(syscall-1024) - cmp.leu p6,p7=r15,r3 // (syscall > 0 && syscall < 1024 + - // NR_syscalls) ? - mov rp=r2 // set the real return addr - ;; -(p6) ld8 r20=[r20] // load address of syscall entry point -(p7) movl r20=sys_ni_syscall - - add r2=TI_FLAGS+IA64_TASK_SIZE,r13 - ;; - ld4 r2=[r2] // r2 = current_thread_info()->flags - ;; - and r2=_TIF_SYSCALL_TRACEAUDIT,r2 // mask trace or audit - ;; - cmp.eq p8,p0=r2,r0 - mov b6=r20 - ;; -(p8) br.call.sptk.many b6=b6 // ignore this return addr - br.cond.sptk ia64_trace_syscall - // NOT REACHED -#endif +// adds r15=-1024,r15 // A subtract 1024 from syscall number +// mov r3=NR_syscalls - 1 + mov r3=NR_hypercalls - 1 + ;; + ld1.bias r17=[r16] // M0|1 r17 = current->thread.on_ustack flag +// ld4 r9=[r9] // M0|1 r9 = current_thread_info()->flags + mov r9=r0 // force flags = 0 + extr.u r8=r29,41,2 // I0 extract ei field from cr.ipsr + + shladd r30=r15,3,r30 // A r30 = sys_call_table + 8*(syscall-1024) + addl r22=IA64_RBS_OFFSET,r1 // A compute base of RBS + cmp.leu p6,p7=r15,r3 // A syscall number in range? + ;; + + lfetch.fault.excl.nt1 [r22] // M0|1 prefetch RBS +(p6) ld8 r30=[r30] // M0|1 load address of syscall entry point + tnat.nz.or p7,p0=r15 // I0 is syscall nr a NaT? + + mov.m ar.bspstore=r22 // M2 switch to kernel RBS + cmp.eq p8,p9=2,r8 // A isr.ei==2? + ;; + +(p8) mov r8=0 // A clear ei to 0 +//(p7) movl r30=sys_ni_syscall // X +(p7) movl r30=do_ni_hypercall // X + +(p8) adds r28=16,r28 // A switch cr.iip to next bundle +(p9) adds r8=1,r8 // A increment ei to next slot + nop.i 0 + ;; + + mov.m r25=ar.unat // M2 (5 cyc) + dep r29=r8,r29,41,2 // I0 insert new ei into cr.ipsr +// adds r15=1024,r15 // A restore original syscall number + // + // If any of the above loads miss in L1D, we'll stall here until + // the data arrives. + // +/////////////////////////////////////////////////////////////////////// + st1 [r16]=r0 // M2|3 clear current->thread.on_ustack flag + mov b6=r30 // I0 setup syscall handler branch reg early + cmp.eq pKStk,pUStk=r0,r17 // A were we on kernel stacks already? + +// and r9=_TIF_SYSCALL_TRACEAUDIT,r9 // A mask trace or audit + mov r18=ar.bsp // M2 (12 cyc) + ;; +(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1 // A compute base of memory stack +// cmp.eq p14,p0=r9,r0 // A are syscalls being traced/audited? + br.call.sptk.many b7=ia64_syscall_setup // B +1: + mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0 + nop 0 + bsw.1 // B (6 cyc) regs are saved, switch to bank 1 + ;; + + ssm psr.ic | PSR_DEFAULT_BITS // M2 now it's safe to re-enable intr.-collection +// movl r3=ia64_ret_from_syscall // X + ;; + + srlz.i // M0 ensure interruption collection is on +// mov rp=r3 // I0 set the real return addr +//(p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT +(p15) ssm psr.i // M2 restore psr.i +//(p14) br.call.sptk.many b6=b6 // B invoke syscall-handker (ignore return addr) +// br.call.sptk.many b6=b6 // B invoke syscall-handker (ignore return addr) + br.call.sptk.many b0=b6 // B invoke syscall-handker (ignore return addr) +// br.cond.spnt.many ia64_trace_syscall // B do syscall-tracing thingamagic + ;; + adds r2=PT(R8)+16,r12 + ;; + st8 [r2]=r8 + ;; + br.call.sptk.many b0=do_softirq + ;; + //restore hypercall argument if continuation + adds r2=IA64_VCPU_HYPERCALL_CONTINUATION_OFS,r13 + ;; + ld1 r20=[r2] + ;; + st1 [r2]=r0 + ;; + cmp.ne p6,p0=r20,r0 + ;; +(p6) adds r2=PT(R16)+16,r12 +(p6) adds r3=PT(R17)+16,r12 + ;; +(p6) ld8 r32=[r2],16 +(p6) ld8 r33=[r3],16 + ;; +(p6) ld8 r34=[r2],16 +(p6) ld8 r35=[r3],16 + ;; +(p6) ld8 r36=[r2],16 + ;; +//save ar.bsp before cover + mov r16=ar.bsp + add r2=PT(R14)+16,r12 + ;; + st8 [r2]=r16 + ;; + rsm psr.i|psr.ic + ;; + srlz.i + ;; + cover + ;; + mov r20=cr.ifs + adds r2=PT(CR_IFS)+16,r12 + ;; + st8 [r2]=r20 + ;; + br.call.sptk.many b0=reflect_event + ;; + adds r2=PT(R14)+16,r12 + adds r3=PT(R8)+16,r12 + ;; + //r16 contains ar.bsp before cover + ld8 r16=[r2] + ld8 r8=[r3] + ;; + br.sptk.many ia64_ret_from_syscall + ;; END(break_fault) .org ia64_ivt+0x3000 @@ -1297,7 +1396,150 @@ END(dispatch_break_fault) DBG_FAULT(14) FAULT(14) -#ifndef XEN +#ifdef XEN + // this code segment is from 2.6.16.13 + + /* + * There is no particular reason for this code to be here, other than that + * there happens to be space here that would go unused otherwise. If this + * fault ever gets "unreserved", simply moved the following code to a more + * suitable spot... + * + * ia64_syscall_setup() is a separate subroutine so that it can + * allocate stacked registers so it can safely demine any + * potential NaT values from the input registers. + * + * On entry: + * - executing on bank 0 or bank 1 register set (doesn't matter) + * - r1: stack pointer + * - r2: current task pointer + * - r3: preserved + * - r11: original contents (saved ar.pfs to be saved) + * - r12: original contents (sp to be saved) + * - r13: original contents (tp to be saved) + * - r15: original contents (syscall # to be saved) + * - r18: saved bsp (after switching to kernel stack) + * - r19: saved b6 + * - r20: saved r1 (gp) + * - r21: saved ar.fpsr + * - r22: kernel's register backing store base (krbs_base) + * - r23: saved ar.bspstore + * - r24: saved ar.rnat + * - r25: saved ar.unat + * - r26: saved ar.pfs + * - r27: saved ar.rsc + * - r28: saved cr.iip + * - r29: saved cr.ipsr + * - r31: saved pr + * - b0: original contents (to be saved) + * On exit: + * - p10: TRUE if syscall is invoked with more than 8 out + * registers or r15's Nat is true + * - r1: kernel's gp + * - r3: preserved (same as on entry) + * - r8: -EINVAL if p10 is true + * - r12: points to kernel stack + * - r13: points to current task + * - r14: preserved (same as on entry) + * - p13: preserved + * - p15: TRUE if interrupts need to be re-enabled + * - ar.fpsr: set to kernel settings + * - b6: preserved (same as on entry) + */ +GLOBAL_ENTRY(ia64_syscall_setup) +#if PT(B6) != 0 +# error This code assumes that b6 is the first field in pt_regs. +#endif + st8 [r1]=r19 // save b6 + add r16=PT(CR_IPSR),r1 // initialize first base pointer + add r17=PT(R11),r1 // initialize second base pointer + ;; + alloc r19=ar.pfs,8,0,0,0 // ensure in0-in7 are writable + st8 [r16]=r29,PT(AR_PFS)-PT(CR_IPSR) // save cr.ipsr + tnat.nz p8,p0=in0 + + st8.spill [r17]=r11,PT(CR_IIP)-PT(R11) // save r11 + tnat.nz p9,p0=in1 +(pKStk) mov r18=r0 // make sure r18 isn't NaT + ;; + + st8 [r16]=r26,PT(CR_IFS)-PT(AR_PFS) // save ar.pfs + st8 [r17]=r28,PT(AR_UNAT)-PT(CR_IIP) // save cr.iip + mov r28=b0 // save b0 (2 cyc) + ;; + + st8 [r17]=r25,PT(AR_RSC)-PT(AR_UNAT) // save ar.unat + dep r19=0,r19,38,26 // clear all bits but 0..37 [I0] +(p8) mov in0=-1 + ;; + + st8 [r16]=r19,PT(AR_RNAT)-PT(CR_IFS) // store ar.pfs.pfm in cr.ifs + extr.u r11=r19,7,7 // I0 // get sol of ar.pfs + and r8=0x7f,r19 // A // get sof of ar.pfs + + st8 [r17]=r27,PT(AR_BSPSTORE)-PT(AR_RSC)// save ar.rsc + tbit.nz p15,p0=r29,IA64_PSR_I_BIT // I0 +(p9) mov in1=-1 + ;; + +(pUStk) sub r18=r18,r22 // r18=RSE.ndirty*8 + tnat.nz p10,p0=in2 + add r11=8,r11 + ;; +(pKStk) adds r16=PT(PR)-PT(AR_RNAT),r16 // skip over ar_rnat field +(pKStk) adds r17=PT(B0)-PT(AR_BSPSTORE),r17 // skip over ar_bspstore field + tnat.nz p11,p0=in3 + ;; +(p10) mov in2=-1 + tnat.nz p12,p0=in4 // [I0] +(p11) mov in3=-1 + ;; +(pUStk) st8 [r16]=r24,PT(PR)-PT(AR_RNAT) // save ar.rnat +(pUStk) st8 [r17]=r23,PT(B0)-PT(AR_BSPSTORE) // save ar.bspstore + shl r18=r18,16 // compute ar.rsc to be used for "loadrs" + ;; + st8 [r16]=r31,PT(LOADRS)-PT(PR) // save predicates + st8 [r17]=r28,PT(R1)-PT(B0) // save b0 + tnat.nz p13,p0=in5 // [I0] + ;; + st8 [r16]=r18,PT(R12)-PT(LOADRS) // save ar.rsc value for "loadrs" + st8.spill [r17]=r20,PT(R13)-PT(R1) // save original r1 +(p12) mov in4=-1 + ;; + +.mem.offset 0,0; st8.spill [r16]=r12,PT(AR_FPSR)-PT(R12) // save r12 +.mem.offset 8,0; st8.spill [r17]=r13,PT(R15)-PT(R13) // save r13 +(p13) mov in5=-1 + ;; + st8 [r16]=r21,PT(R8)-PT(AR_FPSR) // save ar.fpsr + tnat.nz p13,p0=in6 + cmp.lt p10,p9=r11,r8 // frame size can't be more than local+8 + ;; + mov r8=1 +(p9) tnat.nz p10,p0=r15 + adds r12=-16,r1 // switch to kernel memory stack (with 16 bytes of scratch) + + st8.spill [r17]=r15 // save r15 + tnat.nz p8,p0=in7 + nop.i 0 + + mov r13=r2 // establish `current' + movl r1=__gp // establish kernel global pointer + ;; + st8 [r16]=r8 // ensure pt_regs.r8 != 0 (see handle_syscall_error) +(p13) mov in6=-1 +(p8) mov in7=-1 + + cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0 + movl r17=FPSR_DEFAULT + ;; + mov.m ar.fpsr=r17 // set ar.fpsr to kernel default value +(p10) mov r8=-EINVAL + br.ret.sptk.many b7 +END(ia64_syscall_setup) + + +#else /* * There is no particular reason for this code to be here, other * than that there happens to be space here that would go unused diff -r db72b85b81bb -r 01ea554f1c5e xen/include/asm-ia64/config.h --- a/xen/include/asm-ia64/config.h Thu Jan 11 14:42:24 2007 -0700 +++ b/xen/include/asm-ia64/config.h Thu Jan 11 16:56:58 2007 -0700 @@ -51,6 +51,9 @@ #endif #define CONFIG_VGA 1 + + +#define NR_hypercalls 64 #ifndef __ASSEMBLY__ @@ -107,9 +110,6 @@ extern char _end[]; /* standard ELF symb // xen/include/asm/config.h //#define HZ 1000 // FIXME SMP: leave SMP for a later time - -#define NR_hypercalls 64 - /////////////////////////////////////////////////////////////// // xen/include/asm/config.h // Natural boundary upon TR size to define xenheap space diff -r db72b85b81bb -r 01ea554f1c5e xen/include/asm-ia64/hypercall.h --- a/xen/include/asm-ia64/hypercall.h Thu Jan 11 14:42:24 2007 -0700 +++ b/xen/include/asm-ia64/hypercall.h Thu Jan 11 16:56:58 2007 -0700 @@ -13,6 +13,8 @@ do_event_channel_op_compat( do_event_channel_op_compat( XEN_GUEST_HANDLE(evtchn_op_t) uop); +extern long do_pirq_guest_eoi(int pirq); + extern int vmx_do_mmu_update( mmu_update_t *ureqs, diff -r db72b85b81bb -r 01ea554f1c5e xen/include/public/arch-ia64.h --- a/xen/include/public/arch-ia64.h Thu Jan 11 14:42:24 2007 -0700 +++ b/xen/include/public/arch-ia64.h Thu Jan 11 16:56:58 2007 -0700 @@ -463,7 +463,7 @@ struct xen_ia64_boot_param { #define HYPERPRIVOP_MAX (0x19) /* Fast and light hypercalls. */ -#define __HYPERVISOR_ia64_fast_eoi 0x0200 +#define __HYPERVISOR_ia64_fast_eoi __HYPERVISOR_arch_1 /* Xencomm macros. */ #define XENCOMM_INLINE_MASK 0xf800000000000000UL _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |