direct-io.hg

changeset 13869:18a8e34e1211

[IA64] Optimize VTI domain hypercall path

Signed-off-by: Anthony Xu <anthony.xu@intel.com>
author awilliam@xenbuild2.aw
date Thu Feb 01 12:53:34 2007 -0700 (2007-02-01)
parents ef646312685f
children 0df9dc2f1d03
files xen/arch/ia64/vmx/vmx_entry.S xen/arch/ia64/vmx/vmx_ivt.S xen/arch/ia64/vmx/vmx_minstate.h xen/arch/ia64/vmx/vmx_process.c
line diff
     1.1 --- a/xen/arch/ia64/vmx/vmx_entry.S	Wed Jan 31 10:59:56 2007 -0700
     1.2 +++ b/xen/arch/ia64/vmx/vmx_entry.S	Thu Feb 01 12:53:34 2007 -0700
     1.3 @@ -190,12 +190,8 @@ GLOBAL_ENTRY(ia64_leave_hypervisor)
     1.4      PT_REGS_UNWIND_INFO(0)
     1.5      rsm psr.i
     1.6      ;;
     1.7 -    alloc loc0=ar.pfs,0,1,1,0
     1.8 -    ;;
     1.9 -    adds out0=16,r12
    1.10      br.call.sptk.many b0=leave_hypervisor_tail
    1.11      ;;
    1.12 -    mov ar.pfs=loc0
    1.13      adds r20=PT(PR)+16,r12
    1.14      adds r8=PT(EML_UNAT)+16,r12
    1.15      ;;
    1.16 @@ -302,11 +298,9 @@ GLOBAL_ENTRY(ia64_leave_hypervisor)
    1.17      ;;
    1.18      mov ar.fpsr=r19
    1.19      mov ar.ccv=r18
    1.20 -    ;;
    1.21 -//rbs_switch
    1.22 -    
    1.23      shr.u r18=r20,16
    1.24      ;;
    1.25 +vmx_rbs_switch:    
    1.26      movl r19= THIS_CPU(ia64_phys_stacked_size_p8)
    1.27      ;;
    1.28      ld4 r19=[r19]
    1.29 @@ -368,7 +362,7 @@ vmx_rse_clear_invalid:
    1.30      ;;
    1.31      mov cr.ipsr=r31
    1.32      mov cr.iip=r30
    1.33 -    mov cr.ifs=r29
    1.34 +(pNonSys) mov cr.ifs=r29
    1.35      mov ar.pfs=r27
    1.36      adds r18=IA64_VPD_BASE_OFFSET,r21
    1.37      ;;
    1.38 @@ -425,6 +419,188 @@ ia64_vmm_entry_out:
    1.39  END(ia64_vmm_entry)
    1.40  
    1.41  
    1.42 +
    1.43 +/*
    1.44 + * ia64_leave_syscall(): Same as ia64_leave_kernel, except that it doesn't
    1.45 + *  need to switch to bank 0 and doesn't restore the scratch registers.
    1.46 + *  To avoid leaking kernel bits, the scratch registers are set to
    1.47 + *  the following known-to-be-safe values:
    1.48 + *
    1.49 + *        r1: restored (global pointer)
    1.50 + *        r2: cleared
    1.51 + *        r3: 1 (when returning to user-level)
    1.52 + *        r8-r11: restored (syscall return value(s))
    1.53 + *       r12: restored (user-level stack pointer)
    1.54 + *       r13: restored (user-level thread pointer)
    1.55 + *       r14: set to __kernel_syscall_via_epc
    1.56 + *       r15: restored (syscall #)
    1.57 + *       r16-r17: cleared
    1.58 + *       r18: user-level b6
    1.59 + *       r19: cleared
    1.60 + *       r20: user-level ar.fpsr
    1.61 + *       r21: user-level b0
    1.62 + *       r22: cleared
    1.63 + *       r23: user-level ar.bspstore
    1.64 + *       r24: user-level ar.rnat
    1.65 + *       r25: user-level ar.unat
    1.66 + *       r26: user-level ar.pfs
    1.67 + *       r27: user-level ar.rsc
    1.68 + *       r28: user-level ip
    1.69 + *       r29: user-level psr
    1.70 + *       r30: user-level cfm
    1.71 + *       r31: user-level pr
    1.72 + *        f6-f11: cleared
    1.73 + *        pr: restored (user-level pr)
    1.74 + *        b0: restored (user-level rp)
    1.75 + *        b6: restored
    1.76 + *        b7: set to __kernel_syscall_via_epc
    1.77 + *        ar.unat: restored (user-level ar.unat)
    1.78 + *        ar.pfs: restored (user-level ar.pfs)
    1.79 + *        ar.rsc: restored (user-level ar.rsc)
    1.80 + *        ar.rnat: restored (user-level ar.rnat)
    1.81 + *        ar.bspstore: restored (user-level ar.bspstore)
    1.82 + *        ar.fpsr: restored (user-level ar.fpsr)
    1.83 + *        ar.ccv: cleared
    1.84 + *        ar.csd: cleared
    1.85 + *        ar.ssd: cleared
    1.86 + */
    1.87 +GLOBAL_ENTRY(ia64_leave_hypercall)
    1.88 +    PT_REGS_UNWIND_INFO(0)
    1.89 +    /*
    1.90 +     * work.need_resched etc. mustn't get changed by this CPU before it returns to
    1.91 +     * user- or fsys-mode, hence we disable interrupts early on.
    1.92 +     *
    1.93 +     * p6 controls whether current_thread_info()->flags needs to be check for
    1.94 +     * extra work.  We always check for extra work when returning to user-level.
    1.95 +     * With CONFIG_PREEMPT, we also check for extra work when the preempt_count
    1.96 +     * is 0.  After extra work processing has been completed, execution
    1.97 +     * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check
    1.98 +     * needs to be redone.
    1.99 +     */
   1.100 +(pUStk) rsm psr.i
   1.101 +    cmp.eq pLvSys,p0=r0,r0		// pLvSys=1: leave from syscall
   1.102 +(pUStk) cmp.eq.unc p6,p0=r0,r0		// p6 <- pUStk
   1.103 +    ;;
   1.104 +    br.call.sptk.many b0=leave_hypervisor_tail
   1.105 +.work_processed_syscall:
   1.106 +    //clean up bank 1 registers
   1.107 +    mov r16=r0
   1.108 +    mov r17=r0
   1.109 +    mov r18=r0
   1.110 +    mov r19=r0
   1.111 +    mov r20=r0
   1.112 +    mov r21=r0
   1.113 +    mov r22=r0
   1.114 +    mov r23=r0
   1.115 +    mov r24=r0
   1.116 +    mov r25=r0
   1.117 +    mov r26=r0
   1.118 +    mov r27=r0
   1.119 +    mov r28=r0
   1.120 +    mov r29=r0
   1.121 +    mov r30=r0
   1.122 +    mov r31=r0
   1.123 +    bsw.0
   1.124 +    ;;
   1.125 +    adds r2=PT(LOADRS)+16,r12
   1.126 +    adds r3=PT(AR_BSPSTORE)+16,r12
   1.127 +#ifndef XEN
   1.128 +    adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
   1.129 +    ;;
   1.130 +(p6) ld4 r31=[r18]				// load current_thread_info()->flags
   1.131 +#endif
   1.132 +    ;;
   1.133 +    ld8 r20=[r2],PT(B6)-PT(LOADRS)		// load ar.rsc value for "loadrs"
   1.134 +    nop.i 0
   1.135 +    ;;
   1.136 +//  mov r16=ar.bsp				// M2  get existing backing store pointer
   1.137 +    ld8 r18=[r2],PT(R9)-PT(B6)		// load b6
   1.138 +#ifndef XEN
   1.139 +(p6)    and r15=TIF_WORK_MASK,r31		// any work other than TIF_SYSCALL_TRACE?
   1.140 +#endif
   1.141 +    ;;
   1.142 +    ld8 r24=[r3],PT(R11)-PT(AR_BSPSTORE)	// load ar.bspstore (may be garbage)
   1.143 +#ifndef XEN
   1.144 +(p6)    cmp4.ne.unc p6,p0=r15, r0		// any special work pending?
   1.145 +(p6)    br.cond.spnt .work_pending_syscall
   1.146 +#endif
   1.147 +    ;;
   1.148 +    // start restoring the state saved on the kernel stack (struct pt_regs):
   1.149 +    ld8 r9=[r2],PT(CR_IPSR)-PT(R9)
   1.150 +    ld8 r11=[r3],PT(CR_IIP)-PT(R11)
   1.151 +//(pNonSys) break 0		//      bug check: we shouldn't be here if pNonSys is TRUE!
   1.152 +    ;;
   1.153 +    invala			// M0|1 invalidate ALAT
   1.154 +    rsm psr.i | psr.ic	// M2   turn off interrupts and interruption collection
   1.155 +    cmp.eq p9,p0=r0,r0	// A    set p9 to indicate that we should restore cr.ifs
   1.156 +
   1.157 +    ld8 r31=[r2],32		// M0|1 load cr.ipsr
   1.158 +    ld8 r30=[r3],16		// M0|1 load cr.iip
   1.159 +    ;;
   1.160 +//  ld8 r29=[r2],16		// M0|1 load cr.ifs
   1.161 +    ld8 r28=[r3],16		// M0|1 load ar.unat
   1.162 +//(pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
   1.163 +    ;;
   1.164 +    ld8 r27=[r2],PT(B0)-PT(AR_PFS)	// M0|1 load ar.pfs
   1.165 +(pKStk) mov r22=psr			// M2   read PSR now that interrupts are disabled
   1.166 +    nop 0
   1.167 +    ;;
   1.168 +    ld8 r22=[r2],PT(AR_RNAT)-PT(B0) // M0|1 load b0
   1.169 +    ld8 r26=[r3],PT(PR)-PT(AR_RSC)	// M0|1 load ar.rsc
   1.170 +    mov f6=f0			// F    clear f6
   1.171 +    ;;
   1.172 +    ld8 r25=[r2],PT(AR_FPSR)-PT(AR_RNAT)	// M0|1 load ar.rnat (may be garbage)
   1.173 +    ld8 r23=[r3],PT(R1)-PT(PR)		// M0|1 load predicates
   1.174 +    mov f7=f0				// F    clear f7
   1.175 +    ;;
   1.176 +    ld8 r20=[r2],PT(R12)-PT(AR_FPSR)	// M0|1 load ar.fpsr
   1.177 +    ld8.fill r1=[r3],16			// M0|1 load r1
   1.178 +//(pUStk) mov r17=1				// A
   1.179 +    ;;
   1.180 +//(pUStk) st1 [r14]=r17				// M2|3
   1.181 +    ld8.fill r13=[r3],16			// M0|1
   1.182 +    mov f8=f0				// F    clear f8
   1.183 +    ;;
   1.184 +    ld8.fill r12=[r2]			// M0|1 restore r12 (sp)
   1.185 +#ifdef XEN    
   1.186 +    ld8.fill r2=[r3]			// M0|1
   1.187 +#else    
   1.188 +    ld8.fill r15=[r3]			// M0|1 restore r15
   1.189 +#endif    
   1.190 +    mov b6=r18				// I0   restore b6
   1.191 +    mov ar.fpsr=r20
   1.192 +//  addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0 // A
   1.193 +    mov f9=f0					// F    clear f9
   1.194 +//(pKStk) br.cond.dpnt.many skip_rbs_switch		// B
   1.195 +
   1.196 +//  srlz.d				// M0   ensure interruption collection is off (for cover)
   1.197 +//  shr.u r18=r19,16		// I0|1 get byte size of existing "dirty" partition
   1.198 +    cover				// B    add current frame into dirty partition & set cr.ifs
   1.199 +    ;;
   1.200 +//(pUStk) ld4 r17=[r17]			// M0|1 r17 = cpu_data->phys_stacked_size_p8
   1.201 +    mov r19=ar.bsp			// M2   get new backing store pointer
   1.202 +    adds r18=IA64_RBS_OFFSET, r21
   1.203 +    ;;
   1.204 +    sub r18=r19,r18     // get byte size of existing "dirty" partition
   1.205 +    ;;
   1.206 +    shl r20=r18,16     // set rsc.load 
   1.207 +    mov f10=f0			// F    clear f10
   1.208 +#ifdef XEN
   1.209 +    mov r14=r0
   1.210 +#else
   1.211 +    movl r14=__kernel_syscall_via_epc // X
   1.212 +#endif
   1.213 +    ;;
   1.214 +    mov.m ar.csd=r0			// M2   clear ar.csd
   1.215 +    mov.m ar.ccv=r0			// M2   clear ar.ccv
   1.216 +    mov b7=r14			// I0   clear b7 (hint with __kernel_syscall_via_epc)
   1.217 +
   1.218 +    mov.m ar.ssd=r0			// M2   clear ar.ssd
   1.219 +    mov f11=f0			// F    clear f11
   1.220 +    br.cond.sptk.many vmx_rbs_switch	// B
   1.221 +END(ia64_leave_hypercall)
   1.222 +
   1.223 +
   1.224  /*
   1.225   * in0: new rr7
   1.226   * in1: virtual address of shared_info
     2.1 --- a/xen/arch/ia64/vmx/vmx_ivt.S	Wed Jan 31 10:59:56 2007 -0700
     2.2 +++ b/xen/arch/ia64/vmx/vmx_ivt.S	Thu Feb 01 12:53:34 2007 -0700
     2.3 @@ -59,6 +59,14 @@
     2.4  #include <asm/unistd.h>
     2.5  #include <asm/vhpt.h>
     2.6  #include <asm/virt_event.h>
     2.7 +#include <xen/errno.h>
     2.8 +
     2.9 +#if 1
    2.10 +# define PSR_DEFAULT_BITS   psr.ac
    2.11 +#else
    2.12 +# define PSR_DEFAULT_BITS   0
    2.13 +#endif
    2.14 +
    2.15  
    2.16  #ifdef VTI_DEBUG
    2.17    /*
    2.18 @@ -431,17 +439,152 @@ ENTRY(vmx_break_fault)
    2.19      VMX_DBG_FAULT(11)
    2.20      mov r31=pr
    2.21      mov r19=11
    2.22 -    mov r30=cr.iim
    2.23 +    mov r17=cr.iim
    2.24      ;;
    2.25  #ifdef VTI_DEBUG
    2.26      // break 0 is already handled in vmx_ia64_handle_break.
    2.27 -    cmp.eq p6,p7=r30,r0
    2.28 +    cmp.eq p6,p7=r17,r0
    2.29      (p6) br.sptk vmx_fault_11
    2.30      ;;
    2.31  #endif
    2.32 -    br.sptk.many vmx_dispatch_break_fault
    2.33 +    mov r29=cr.ipsr
    2.34 +    adds r22=IA64_VCPU_BREAKIMM_OFFSET, r21
    2.35 +    ;;
    2.36 +    ld4 r22=[r22]
    2.37 +    extr.u r24=r29,IA64_PSR_CPL0_BIT,2
    2.38 +    cmp.eq p0,p6=r0,r0
    2.39 +    ;;
    2.40 +    cmp.ne.or p6,p0=r22,r17
    2.41 +    cmp.ne.or p6,p0=r0,r24
    2.42 +(p6) br.sptk.many vmx_dispatch_break_fault
    2.43 +    ;;
    2.44 +   /*
    2.45 +    * The streamlined system call entry/exit paths only save/restore the initial part
    2.46 +    * of pt_regs.  This implies that the callers of system-calls must adhere to the
    2.47 +    * normal procedure calling conventions.
    2.48 +    *
    2.49 +    *   Registers to be saved & restored:
    2.50 +    *   CR registers: cr.ipsr, cr.iip, cr.ifs
    2.51 +    *   AR registers: ar.unat, ar.pfs, ar.rsc, ar.rnat, ar.bspstore, ar.fpsr
    2.52 +    *   others: pr, b0, b6, loadrs, r1, r11, r12, r13, r15
    2.53 +    *   Registers to be restored only:
    2.54 +    *   r8-r11: output value from the system call.
    2.55 +    *
    2.56 +    * During system call exit, scratch registers (including r15) are modified/cleared
    2.57 +    * to prevent leaking bits from kernel to user level.
    2.58 +    */
    2.59 +   
    2.60 +//  mov.m r16=IA64_KR(CURRENT)		// M2 r16 <- current task (12 cyc)
    2.61 +    mov r14=r21
    2.62 +    bsw.1					// B (6 cyc) regs are saved, switch to bank 1
    2.63 +    ;;   
    2.64 +    mov r29=cr.ipsr				// M2 (12 cyc)
    2.65 +    mov r31=pr				// I0 (2 cyc)
    2.66 +    mov r16=r14
    2.67 +    mov r15=r2
    2.68 +
    2.69 +    mov r17=cr.iim				// M2 (2 cyc)
    2.70 +    mov.m r27=ar.rsc			// M2 (12 cyc)
    2.71 +//  mov r18=__IA64_BREAK_SYSCALL		// A
    2.72 +
    2.73 +    mov.m ar.rsc=0				// M2
    2.74 +    mov.m r21=ar.fpsr			// M2 (12 cyc)
    2.75 +    mov r19=b6				// I0 (2 cyc)
    2.76      ;;
    2.77 -    VMX_FAULT(11);
    2.78 +    mov.m r23=ar.bspstore			// M2 (12 cyc)
    2.79 +    mov.m r24=ar.rnat			// M2 (5 cyc)
    2.80 +    mov.i r26=ar.pfs			// I0 (2 cyc)
    2.81 +
    2.82 +    invala					// M0|1
    2.83 +    nop.m 0					// M
    2.84 +    mov r20=r1				// A			save r1
    2.85 +
    2.86 +    nop.m 0
    2.87 +//  movl r30=sys_call_table			// X
    2.88 +    movl r30=ia64_hypercall_table			// X
    2.89 +
    2.90 +    mov r28=cr.iip				// M2 (2 cyc)
    2.91 +//  cmp.eq p0,p7=r18,r17			// I0 is this a system call?
    2.92 +//(p7)  br.cond.spnt non_syscall		// B  no ->
    2.93 +   //
    2.94 +   // From this point on, we are definitely on the syscall-path
    2.95 +   // and we can use (non-banked) scratch registers.
    2.96 +   //
    2.97 +///////////////////////////////////////////////////////////////////////
    2.98 +    mov r1=r16				// A    move task-pointer to "addl"-addressable reg
    2.99 +    mov r2=r16				// A    setup r2 for ia64_syscall_setup
   2.100 +//  add r9=TI_FLAGS+IA64_TASK_SIZE,r16	// A	r9 = &current_thread_info()->flags
   2.101 +
   2.102 +//  adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16
   2.103 +//  adds r15=-1024,r15			// A    subtract 1024 from syscall number
   2.104 +//  mov r3=NR_syscalls - 1
   2.105 +    mov r3=NR_hypercalls - 1
   2.106 +    ;;
   2.107 +//  ld1.bias r17=[r16]			// M0|1 r17 = current->thread.on_ustack flag
   2.108 +//  ld4 r9=[r9]				// M0|1 r9 = current_thread_info()->flags
   2.109 +    mov r9=r0               // force flags = 0
   2.110 +    extr.u r8=r29,41,2			// I0   extract ei field from cr.ipsr
   2.111 +
   2.112 +    shladd r30=r15,3,r30			// A    r30 = sys_call_table + 8*(syscall-1024)
   2.113 +    addl r22=IA64_RBS_OFFSET,r1		// A    compute base of RBS
   2.114 +    cmp.leu p6,p7=r15,r3			// A    syscall number in range?
   2.115 +    ;;
   2.116 +
   2.117 +    lfetch.fault.excl.nt1 [r22]		// M0|1 prefetch RBS
   2.118 +(p6) ld8 r30=[r30]				// M0|1 load address of syscall entry point
   2.119 +    tnat.nz.or p7,p0=r15			// I0	is syscall nr a NaT?
   2.120 +
   2.121 +    mov.m ar.bspstore=r22			// M2   switch to kernel RBS
   2.122 +    cmp.eq p8,p9=2,r8			// A    isr.ei==2?
   2.123 +    ;;
   2.124 +
   2.125 +(p8) mov r8=0				// A    clear ei to 0
   2.126 +//(p7)  movl r30=sys_ni_syscall			// X
   2.127 +(p7) movl r30=do_ni_hypercall			// X
   2.128 +
   2.129 +(p8) adds r28=16,r28				// A    switch cr.iip to next bundle
   2.130 +(p9) adds r8=1,r8				// A    increment ei to next slot
   2.131 +    nop.i 0
   2.132 +    ;;
   2.133 +
   2.134 +    mov.m r25=ar.unat			// M2 (5 cyc)
   2.135 +    dep r29=r8,r29,41,2			// I0   insert new ei into cr.ipsr
   2.136 +//  adds r15=1024,r15			// A    restore original syscall number
   2.137 +   //
   2.138 +   // If any of the above loads miss in L1D, we'll stall here until
   2.139 +   // the data arrives.
   2.140 +   //
   2.141 +///////////////////////////////////////////////////////////////////////
   2.142 +//    st1 [r16]=r0				// M2|3 clear current->thread.on_ustack flag
   2.143 +    mov b6=r30				// I0   setup syscall handler branch reg early
   2.144 +    cmp.ne pKStk,pUStk=r0,r0		// A    were we on kernel stacks already?
   2.145 +
   2.146 +//  and r9=_TIF_SYSCALL_TRACEAUDIT,r9	// A    mask trace or audit
   2.147 +    mov r18=ar.bsp				// M2 (12 cyc)
   2.148 +   ;;
   2.149 +(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1 // A    compute base of memory stack
   2.150 +//  cmp.eq p14,p0=r9,r0			// A    are syscalls being traced/audited?
   2.151 +//    br.call.sptk.many b7=ia64_syscall_setup	// B
   2.152 +    br.call.sptk.many b7=ia64_hypercall_setup	// B
   2.153 +1:
   2.154 +    mov ar.rsc=0x3				// M2   set eager mode, pl 0, LE, loadrs=0
   2.155 +//    nop 0
   2.156 +//    bsw.1					// B (6 cyc) regs are saved, switch to bank 1
   2.157 +    ;;
   2.158 +    ssm psr.ic | PSR_DEFAULT_BITS		// M2	now it's safe to re-enable intr.-collection
   2.159 +//    movl r3=ia64_ret_from_syscall		// X
   2.160 +    movl r3=ia64_leave_hypercall		// X
   2.161 +    ;;
   2.162 +
   2.163 +    srlz.i					// M0   ensure interruption collection is on
   2.164 +    mov rp=r3				// I0   set the real return addr
   2.165 +    //(p10) br.cond.spnt.many ia64_ret_from_syscall	// B    return if bad call-frame or r15 is a NaT
   2.166 +    (p15)   ssm psr.i				// M2   restore psr.i
   2.167 +    //(p14) br.call.sptk.many b6=b6			// B    invoke syscall-handker (ignore return addr)
   2.168 +    br.call.sptk.many b6=b6			// B    invoke syscall-handker (ignore return addr)
   2.169 +//  br.cond.spnt.many ia64_trace_syscall	// B	do syscall-tracing thingamagic
   2.170 +   ;;
   2.171 +   VMX_FAULT(11)
   2.172  END(vmx_break_fault)
   2.173  
   2.174      .org vmx_ia64_ivt+0x3000
   2.175 @@ -613,6 +756,146 @@ END(vmx_virtual_exirq)
   2.176  // 0x3800 Entry 14 (size 64 bundles) Reserved
   2.177      VMX_DBG_FAULT(14)
   2.178      VMX_FAULT(14)
   2.179 +    // this code segment is from 2.6.16.13
   2.180 +    
   2.181 +    /*
   2.182 +     * There is no particular reason for this code to be here, other than that
   2.183 +     * there happens to be space here that would go unused otherwise.  If this
   2.184 +     * fault ever gets "unreserved", simply moved the following code to a more
   2.185 +     * suitable spot...
   2.186 +     *
   2.187 +     * ia64_syscall_setup() is a separate subroutine so that it can
   2.188 +     *	allocate stacked registers so it can safely demine any
   2.189 +     *	potential NaT values from the input registers.
   2.190 +     *
   2.191 +     * On entry:
   2.192 +     *	- executing on bank 0 or bank 1 register set (doesn't matter)
   2.193 +     *	-  r1: stack pointer
   2.194 +     *	-  r2: current task pointer
   2.195 +     *	-  r3: preserved
   2.196 +     *	- r11: original contents (saved ar.pfs to be saved)
   2.197 +     *	- r12: original contents (sp to be saved)
   2.198 +     *	- r13: original contents (tp to be saved)
   2.199 +     *	- r15: original contents (syscall # to be saved)
   2.200 +     *	- r18: saved bsp (after switching to kernel stack)
   2.201 +     *	- r19: saved b6
   2.202 +     *	- r20: saved r1 (gp)
   2.203 +     *	- r21: saved ar.fpsr
   2.204 +     *	- r22: kernel's register backing store base (krbs_base)
   2.205 +     *	- r23: saved ar.bspstore
   2.206 +     *	- r24: saved ar.rnat
   2.207 +     *	- r25: saved ar.unat
   2.208 +     *	- r26: saved ar.pfs
   2.209 +     *	- r27: saved ar.rsc
   2.210 +     *	- r28: saved cr.iip
   2.211 +     *	- r29: saved cr.ipsr
   2.212 +     *	- r31: saved pr
   2.213 +     *	-  b0: original contents (to be saved)
   2.214 +     * On exit:
   2.215 +     *	-  p10: TRUE if syscall is invoked with more than 8 out
   2.216 +     *		registers or r15's Nat is true
   2.217 +     *	-  r1: kernel's gp
   2.218 +     *	-  r3: preserved (same as on entry)
   2.219 +     *	-  r8: -EINVAL if p10 is true
   2.220 +     *	- r12: points to kernel stack
   2.221 +     *	- r13: points to current task
   2.222 +     *	- r14: preserved (same as on entry)
   2.223 +     *	- p13: preserved
   2.224 +     *	- p15: TRUE if interrupts need to be re-enabled
   2.225 +     *	- ar.fpsr: set to kernel settings
   2.226 +     *	-  b6: preserved (same as on entry)
   2.227 +     */
   2.228 +GLOBAL_ENTRY(ia64_hypercall_setup)
   2.229 +#if PT(B6) != 0
   2.230 +# error This code assumes that b6 is the first field in pt_regs.
   2.231 +#endif
   2.232 +    st8 [r1]=r19				// save b6
   2.233 +    add r16=PT(CR_IPSR),r1			// initialize first base pointer
   2.234 +    add r17=PT(R11),r1			// initialize second base pointer
   2.235 +    ;;
   2.236 +    alloc r19=ar.pfs,8,0,0,0		// ensure in0-in7 are writable
   2.237 +    st8 [r16]=r29,PT(AR_PFS)-PT(CR_IPSR)	// save cr.ipsr
   2.238 +    tnat.nz p8,p0=in0
   2.239 +
   2.240 +    st8.spill [r17]=r11,PT(CR_IIP)-PT(R11)	// save r11
   2.241 +    tnat.nz p9,p0=in1
   2.242 +(pKStk) mov r18=r0				// make sure r18 isn't NaT
   2.243 +    ;;
   2.244 +
   2.245 +    st8 [r16]=r26,PT(CR_IFS)-PT(AR_PFS)	// save ar.pfs
   2.246 +    st8 [r17]=r28,PT(AR_UNAT)-PT(CR_IIP)	// save cr.iip
   2.247 +    mov r28=b0				// save b0 (2 cyc)
   2.248 +    ;;
   2.249 +
   2.250 +    st8 [r17]=r25,PT(AR_RSC)-PT(AR_UNAT)	// save ar.unat
   2.251 +    dep r19=0,r19,38,26			// clear all bits but 0..37 [I0]
   2.252 +(p8)    mov in0=-1
   2.253 +    ;;
   2.254 +
   2.255 +    st8 [r16]=r19,PT(AR_RNAT)-PT(CR_IFS)	// store ar.pfs.pfm in cr.ifs
   2.256 +    extr.u r11=r19,7,7	// I0		// get sol of ar.pfs
   2.257 +    and r8=0x7f,r19		// A		// get sof of ar.pfs
   2.258 +
   2.259 +    st8 [r17]=r27,PT(AR_BSPSTORE)-PT(AR_RSC)// save ar.rsc
   2.260 +    tbit.nz p15,p0=r29,IA64_PSR_I_BIT // I0
   2.261 +(p9)    mov in1=-1
   2.262 +    ;;
   2.263 +
   2.264 +(pUStk) sub r18=r18,r22				// r18=RSE.ndirty*8
   2.265 +    tnat.nz p10,p0=in2
   2.266 +    add r11=8,r11
   2.267 +    ;;
   2.268 +(pKStk) adds r16=PT(PR)-PT(AR_RNAT),r16		// skip over ar_rnat field
   2.269 +(pKStk) adds r17=PT(B0)-PT(AR_BSPSTORE),r17	// skip over ar_bspstore field
   2.270 +    tnat.nz p11,p0=in3
   2.271 +    ;;
   2.272 +(p10)   mov in2=-1
   2.273 +    tnat.nz p12,p0=in4				// [I0]
   2.274 +(p11)   mov in3=-1
   2.275 +    ;;
   2.276 +(pUStk) st8 [r16]=r24,PT(PR)-PT(AR_RNAT)	// save ar.rnat
   2.277 +(pUStk) st8 [r17]=r23,PT(B0)-PT(AR_BSPSTORE)	// save ar.bspstore
   2.278 +    shl r18=r18,16				// compute ar.rsc to be used for "loadrs"
   2.279 +    ;;
   2.280 +    st8 [r16]=r31,PT(LOADRS)-PT(PR)		// save predicates
   2.281 +    st8 [r17]=r28,PT(R1)-PT(B0)		// save b0
   2.282 +    tnat.nz p13,p0=in5				// [I0]
   2.283 +    ;;
   2.284 +    st8 [r16]=r18,PT(R12)-PT(LOADRS)	// save ar.rsc value for "loadrs"
   2.285 +    st8.spill [r17]=r20,PT(R13)-PT(R1)	// save original r1
   2.286 +(p12)   mov in4=-1
   2.287 +    ;;
   2.288 +
   2.289 +.mem.offset 0,0; st8.spill [r16]=r12,PT(AR_FPSR)-PT(R12)	// save r12
   2.290 +.mem.offset 8,0; st8.spill [r17]=r13,PT(R15)-PT(R13)		// save r13
   2.291 +(p13)   mov in5=-1
   2.292 +    ;;
   2.293 +    st8 [r16]=r21,PT(R8)-PT(AR_FPSR)	// save ar.fpsr
   2.294 +    tnat.nz p13,p0=in6
   2.295 +    cmp.lt p10,p9=r11,r8	// frame size can't be more than local+8
   2.296 +    ;;
   2.297 +    mov r8=1
   2.298 +(p9)    tnat.nz p10,p0=r15
   2.299 +    adds r12=-16,r1		// switch to kernel memory stack (with 16 bytes of scratch)
   2.300 +
   2.301 +    st8.spill [r17]=r15			// save r15
   2.302 +    tnat.nz p8,p0=in7
   2.303 +    nop.i 0
   2.304 +
   2.305 +    mov r13=r2				// establish `current'
   2.306 +    movl r1=__gp				// establish kernel global pointer
   2.307 +    ;;
   2.308 +    st8 [r16]=r8		// ensure pt_regs.r8 != 0 (see handle_syscall_error)
   2.309 +(p13)   mov in6=-1
   2.310 +(p8)    mov in7=-1
   2.311 +
   2.312 +    cmp.eq pSys,pNonSys=r0,r0		// set pSys=1, pNonSys=0
   2.313 +    movl r17=FPSR_DEFAULT
   2.314 +    ;;
   2.315 +    mov.m ar.fpsr=r17			// set ar.fpsr to kernel default value
   2.316 +(p10)   mov r8=-EINVAL
   2.317 +    br.ret.sptk.many b7
   2.318 +END(ia64_hypercall_setup)
   2.319  
   2.320  
   2.321      .org vmx_ia64_ivt+0x3c00
     3.1 --- a/xen/arch/ia64/vmx/vmx_minstate.h	Wed Jan 31 10:59:56 2007 -0700
     3.2 +++ b/xen/arch/ia64/vmx/vmx_minstate.h	Thu Feb 01 12:53:34 2007 -0700
     3.3 @@ -174,6 +174,7 @@
     3.4      ;;                                          \
     3.5      st8 [r16]=r29,16;   /* save b0 */                           \
     3.6      st8 [r17]=r18,16;   /* save ar.rsc value for "loadrs" */                \
     3.7 +    cmp.eq pNonSys,pSys=r0,r0   /* initialize pSys=0, pNonSys=1 */          \
     3.8      ;;                                          \
     3.9  .mem.offset 0,0; st8.spill [r16]=r20,16;    /* save original r1 */              \
    3.10  .mem.offset 8,0; st8.spill [r17]=r12,16;                            \
     4.1 --- a/xen/arch/ia64/vmx/vmx_process.c	Wed Jan 31 10:59:56 2007 -0700
     4.2 +++ b/xen/arch/ia64/vmx/vmx_process.c	Thu Feb 01 12:53:34 2007 -0700
     4.3 @@ -214,7 +214,7 @@ void save_banked_regs_to_vpd(VCPU *v, RE
     4.4  // ONLY gets called from ia64_leave_kernel
     4.5  // ONLY call with interrupts disabled?? (else might miss one?)
     4.6  // NEVER successful if already reflecting a trap/fault because psr.i==0
     4.7 -void leave_hypervisor_tail(struct pt_regs *regs)
     4.8 +void leave_hypervisor_tail(void)
     4.9  {
    4.10      struct domain *d = current->domain;
    4.11      struct vcpu *v = current;