diff options
Diffstat (limited to 'sys/ia64')
-rw-r--r-- | sys/ia64/ia64/exception.S | 246 | ||||
-rw-r--r-- | sys/ia64/ia64/exception.s | 246 | ||||
-rw-r--r-- | sys/ia64/ia64/genassym.c | 7 | ||||
-rw-r--r-- | sys/ia64/ia64/machdep.c | 8 | ||||
-rw-r--r-- | sys/ia64/ia64/swtch.s | 6 | ||||
-rw-r--r-- | sys/ia64/ia64/trap.c | 103 | ||||
-rw-r--r-- | sys/ia64/ia64/vm_machdep.c | 14 | ||||
-rw-r--r-- | sys/ia64/include/cpu.h | 4 | ||||
-rw-r--r-- | sys/ia64/include/frame.h | 2 |
9 files changed, 525 insertions, 111 deletions
diff --git a/sys/ia64/ia64/exception.S b/sys/ia64/ia64/exception.S index 8424a7e..118b7c2 100644 --- a/sys/ia64/ia64/exception.S +++ b/sys/ia64/ia64/exception.S @@ -53,13 +53,13 @@ mov b0=r17; \ br.sptk.few exception_save; \ 2: (p3) ssm psr.i; \ - alloc r14=ar.pfs,0,0,2,0; \ - movl r15=exception_restore; \ + alloc r15=ar.pfs,0,0,3,0; \ mov out0=_n_; \ - mov out1=sp;; \ + mov out1=r14; \ + mov out2=sp;; \ add sp=-16,sp;; \ - mov rp=r15; \ - br.call.sptk.few b6=trap + br.call.sptk.few rp=trap; \ +3: br.sptk.many exception_restore /* * The IA64 Interrupt Vector Table (IVT) contains 20 slots with 64 @@ -507,7 +507,24 @@ ia64_vector_table: /* 0x2c00: Break Instruction vector */ + mov r16=pr // save pr for a moment + mov r17=cr.iim;; // read break value + mov r18=0x100000;; // syscall number + cmp.eq p1,p2=r18,r17;; // check for syscall +(p2) br.dpnt.few 9f + + mov r17=cr.ipsr;; // check for user mode + extr.u r17=r17,32,2;; + cmp.eq p1,p2=r0,r17 +(p1) br.dpnt.few 9f // trap if kernel mode + + br.sptk.many do_syscall + ;; + +9: mov pr=r16,0x1ffff // restore pr + TRAP(11) + .align 1024 /* 0x3000: External Interrupt vector */ @@ -841,7 +858,7 @@ ia64_vhpt: .quad 0 #define rR2 r23 #define rBSPSTORE r22 #define rRNAT r21 -#define rBSP r27 /* overlay rPR */ +#define rNDIRTY r27 /* overlay rPR */ #define rRSC r20 #define rPFS r19 #define rB0 r31 /* overlay rIIP */ @@ -962,12 +979,12 @@ ENTRY(exception_restore, 0) ;; mov b0=r16 mov ar.fpsr=r17 - ld8 r18=[r1],-16 // r1=&tf_ar_bsp + ld8 r18=[r1],-16 // r1=&tf_ndirty ld8 r19=[r2],-16 // r2=&tf_ar_rnat ;; mov ar.ccv=r18 mov ar.unat=r19 - ld8 rBSP=[r1],-16 // r1=&tf_ar_bspstore + ld8 rNDIRTY=[r1],-16 // r1=&tf_ar_bspstore ld8 rRNAT=[r2],-16 // r2=&tf_cr_ifs ;; ld8 rBSPSTORE=[r1],-16 // r1=&tf_cr_pfs @@ -977,9 +994,7 @@ ENTRY(exception_restore, 0) ;; alloc r16=ar.pfs,0,0,0,0 // discard current frame ;; - sub r16=rBSP,rBSPSTORE // how many bytes to load? - ;; - shl r16=r16,16 // value for ar.rsc + shl r16=rNDIRTY,16 // value for ar.rsc ;; mov ar.rsc=r16 // setup for loadrs ;; @@ -1012,7 +1027,7 @@ ENTRY(exception_restore, 0) ;; rfi - END(exception_restore) +END(exception_restore) /* @@ -1023,6 +1038,7 @@ ENTRY(exception_restore, 0) * r16 saved b0 * * Return: + * r14 cr.iim value for break traps * sp kernel stack pointer * p1 true if user mode * p2 true if kernel mode @@ -1076,18 +1092,21 @@ ENTRY(exception_save, 0) ;; (p2) mov r16=ar.k5 // kernel backing store mov rRNAT=ar.rnat - mov rBSP=ar.bsp ;; (p2) mov ar.bspstore=r16 // switch bspstore st8 [r2]=rRSC,16 // r2=&tf_cr_ifs ;; st8 [r1]=rPFS,16 // r1=&tf_ar_bspstore st8 [r2]=rIFS,16 // r2=&tf_ar_rnat +(p2) mov r17=ar.bsp + ;; +(p2) sub r17=r17,r16 // ndirty (in bytes) +(p1) mov r17=r0 ;; - st8 [r1]=rBSPSTORE,16 // r1=&tf_ar_bsp + st8 [r1]=rBSPSTORE,16 // r1=&tf_ndirty st8 [r2]=rRNAT,16 // r2=&tf_ar_unat ;; - st8 [r1]=rBSP,16 // r1=&tf_ar_ccv + st8 [r1]=r17,16 // r1=&tf_ar_ccv mov ar.rsc=3 // switch RSE back on mov r16=ar.unat ;; @@ -1217,12 +1236,207 @@ ENTRY(exception_save, 0) ;; movl r1=__gp // kernel globals mov r13=ar.k4 // processor globals + mov r14=cr.iim // break immediate ssm psr.ic|psr.dt // enable interrupts & translation ;; srlz.d // serialize br.sptk.few b0 // not br.ret - we were not br.call'ed - END(exception_save) +END(exception_save) +/* + * System call entry point (via Break Instruction vector). + * + * Arguments: + * r16 saved predicates + */ +ENTRY(do_syscall, 0) + rsm psr.dt // physical addressing for a moment + mov r17=sp;; // save user sp + srlz.d // serialize psr.dt + mov sp=ar.k6;; // switch to kernel sp + add sp=-SIZEOF_TRAPFRAME,sp;; // reserve trapframe + dep r30=0,sp,61,3;; // physical address + add r31=8,r30;; // secondary pointer + + // save minimal state for syscall + mov r18=cr.iip + mov r19=cr.ipsr + mov r20=cr.isr + ;; + st8 [r30]=r18,16 // save cr.iip + st8 [r31]=r19,16 // save cr.ipsr + ;; + st8 [r30]=r20,16 // save cr.isr + add r31=16,r31 // skip cr.ifa + mov r18=ar.rsc + mov r19=ar.pfs + ;; + st8 [r30]=r16,16 // save pr + st8 [r31]=r18,16 // save ar.rsc + mov ar.rsc=0 // turn off rse + ;; + st8 [r30]=r19,16 // save ar.pfs + add r31=16,r31 // skip cr.ifs + mov r20=ar.bspstore + mov r21=ar.rnat + mov r22=ar.k5 + ;; + mov ar.bspstore=r22 // switch to kernel backing store + ;; + mov r23=ar.bsp // calculate ndirty + ;; + ;; + st8 [r30]=r20,16 // save ar.bspstore + st8 [r31]=r21,16 // save ar.rnat + sub r16=r23,r22 // bytes of dirty regs + mov r18=ar.unat + ;; + st8 [r30]=r16,16 // save ndirty + st8 [r31]=r18,16 // save ar.unat + mov r20=ar.ccv + mov r21=ar.fpsr + ;; + st8 [r30]=r20,16 // save ar.ccv + st8 [r31]=r21,16 // save ar.fpsr + mov r16=b0 + ;; + st8 [r30]=r16,TF_R-TF_B+FRAME_SP*8 // save b0, r1=&tf_r[FRAME_SP] + ;; + st8 [r30]=r17 // save user sp + ;; + bsw.1 // switch back to bank 1 + ;; + mov r18=sp // trapframe pointer + ;; + add sp=-(8*8),sp // reserve stack for arguments + ;; + br.call.sptk.few b0=Lsaveargs // dump args + ;; + mov r31=sp // point at args + mov r20=ar.bsp // record bsp before the cover + ;; + cover // preserve arguments + ;; + mov r22=cr.ifs // record user's CFM + add r23=TF_CR_IFS,r18 + ;; + ssm psr.dt|psr.ic|psr.i // safe to take interrupts again + ;; + srlz.d // serialize psr.dt and psr.ic + ;; + st8 [r23]=r22 // save cr.ifs + ;; + mov r21=ar.bsp // r21-r20 = size of user reg frame + add r22=TF_NDIRTY,r18 + ;; + sub r20=r21,r20 + ld8 r23=[r22] + ;; + add r23=r23,r20 // adjust ndirty + ;; + st8 [r22]=r23 + ;; + add sp=-16,sp // reserve scratch space + alloc r14=ar.pfs,0,3,3,0 + mov r13=ar.k4 // processor globals + ;; + mov loc0=r15 // save in case of restarts + mov loc1=r18 // save so we can restore + mov loc2=gp // save user gp + mov out0=r15 // syscall number (from user) + mov out1=r31 // arguments + mov out2=r18 // trapframe pointer + ;; + movl gp=__gp // kernel globals + ;; + br.call.sptk.many rp=syscall // do the work + + rsm psr.dt|psr.ic // get ready to restore + ;; + srlz.d // serialise psr.dt and psr.ic + dep r30=0,loc1,61,3 // physical address + mov gp=loc2 // restore user gp + ;; + add r30=TF_R+FRAME_SP*8,r30 // &tf_r[FRAME_SP] + mov r15=loc0 // saved syscall number + alloc r14=ar.pfs,0,0,0,0 // discard register frame + ;; + ld8 sp=[r30],-16 // restore user sp + ;; + ld8 r10=[r30],-8 // ret2 + ;; + ld8 r9=[r30],-8 // ret1 + ;; + ld8 r8=[r30],-(TF_R+7*8-TF_B) // ret0 + ;; + ld8 r16=[r30],-16 // restore b0 + ;; + mov b0=r16 + add r31=8,r30 // secondary pointer, &tf_fpsr + ;; + ld8 r16=[r31],-16 // restore ar.fpsr + ld8 r17=[r30],-16 // restore ar.ccv + ;; + ld8 r18=[r31],-16 // restore ar.unat + ld8 r19=[r30],-16 // restore ndirty + mov ar.fpsr=r16 + mov ar.ccv=r17 + ;; + ld8 r16=[r31],-16 // restore ar.rnat + ld8 r17=[r30],-16 // restore ar.bspstore + mov ar.unat=r18 + ;; + shl r19=r19,16 // value for ar.rsc + ;; + mov ar.rsc=r19 // setup for loadrs + ;; + loadrs // restore user registers + ;; + mov ar.bspstore=r17 + ;; + mov ar.rnat=r16 + ld8 r18=[r31],-16 // restore cr.ifs + ld8 r19=[r30],-16 // restore ar.pfs + ;; + ld8 r16=[r31],-32 // restore ar.rsc + ld8 r17=[r30],-32 // restore pr + mov cr.ifs=r18 + mov ar.pfs=r19 + ;; + ld8 r18=[r31],-16 // restore cr.ipsr + ld8 r19=[r30],-16 // restore cr.iip + mov ar.rsc=r16 + mov pr=r16,0x1ffff + ;; + mov cr.ipsr=r18 + mov cr.iip=r19 + ;; + rfi + // This is done as a function call to make sure that we only + // have output registers in the register frame. It also gives + // us a chance to use alloc to round up to 8 arguments for + // simplicity. + // + // We are still running in physical mode with psr.ic==0 because + // we haven't yet covered the user's register frame to get a + // value for cr.ifs +Lsaveargs: + alloc r14=ar.pfs,0,0,8,0 // round up to 8 outputs + ;; + extr.u r31=sp,0,61 // physical address + ;; + st8 [r31]=r32,8 + st8 [r31]=r33,8 + st8 [r31]=r34,8 + st8 [r31]=r35,8 + st8 [r31]=r36,8 + st8 [r31]=r37,8 + st8 [r31]=r38,8 + st8 [r31]=r39 + ;; + br.ret.sptk.many b0 + +END(do_syscall) diff --git a/sys/ia64/ia64/exception.s b/sys/ia64/ia64/exception.s index 8424a7e..118b7c2 100644 --- a/sys/ia64/ia64/exception.s +++ b/sys/ia64/ia64/exception.s @@ -53,13 +53,13 @@ mov b0=r17; \ br.sptk.few exception_save; \ 2: (p3) ssm psr.i; \ - alloc r14=ar.pfs,0,0,2,0; \ - movl r15=exception_restore; \ + alloc r15=ar.pfs,0,0,3,0; \ mov out0=_n_; \ - mov out1=sp;; \ + mov out1=r14; \ + mov out2=sp;; \ add sp=-16,sp;; \ - mov rp=r15; \ - br.call.sptk.few b6=trap + br.call.sptk.few rp=trap; \ +3: br.sptk.many exception_restore /* * The IA64 Interrupt Vector Table (IVT) contains 20 slots with 64 @@ -507,7 +507,24 @@ ia64_vector_table: /* 0x2c00: Break Instruction vector */ + mov r16=pr // save pr for a moment + mov r17=cr.iim;; // read break value + mov r18=0x100000;; // syscall number + cmp.eq p1,p2=r18,r17;; // check for syscall +(p2) br.dpnt.few 9f + + mov r17=cr.ipsr;; // check for user mode + extr.u r17=r17,32,2;; + cmp.eq p1,p2=r0,r17 +(p1) br.dpnt.few 9f // trap if kernel mode + + br.sptk.many do_syscall + ;; + +9: mov pr=r16,0x1ffff // restore pr + TRAP(11) + .align 1024 /* 0x3000: External Interrupt vector */ @@ -841,7 +858,7 @@ ia64_vhpt: .quad 0 #define rR2 r23 #define rBSPSTORE r22 #define rRNAT r21 -#define rBSP r27 /* overlay rPR */ +#define rNDIRTY r27 /* overlay rPR */ #define rRSC r20 #define rPFS r19 #define rB0 r31 /* overlay rIIP */ @@ -962,12 +979,12 @@ ENTRY(exception_restore, 0) ;; mov b0=r16 mov ar.fpsr=r17 - ld8 r18=[r1],-16 // r1=&tf_ar_bsp + ld8 r18=[r1],-16 // r1=&tf_ndirty ld8 r19=[r2],-16 // r2=&tf_ar_rnat ;; mov ar.ccv=r18 mov ar.unat=r19 - ld8 rBSP=[r1],-16 // r1=&tf_ar_bspstore + ld8 rNDIRTY=[r1],-16 // r1=&tf_ar_bspstore ld8 rRNAT=[r2],-16 // r2=&tf_cr_ifs ;; ld8 rBSPSTORE=[r1],-16 // r1=&tf_cr_pfs @@ -977,9 +994,7 @@ ENTRY(exception_restore, 0) ;; alloc r16=ar.pfs,0,0,0,0 // discard current frame ;; - sub r16=rBSP,rBSPSTORE // how many bytes to load? - ;; - shl r16=r16,16 // value for ar.rsc + shl r16=rNDIRTY,16 // value for ar.rsc ;; mov ar.rsc=r16 // setup for loadrs ;; @@ -1012,7 +1027,7 @@ ENTRY(exception_restore, 0) ;; rfi - END(exception_restore) +END(exception_restore) /* @@ -1023,6 +1038,7 @@ ENTRY(exception_restore, 0) * r16 saved b0 * * Return: + * r14 cr.iim value for break traps * sp kernel stack pointer * p1 true if user mode * p2 true if kernel mode @@ -1076,18 +1092,21 @@ ENTRY(exception_save, 0) ;; (p2) mov r16=ar.k5 // kernel backing store mov rRNAT=ar.rnat - mov rBSP=ar.bsp ;; (p2) mov ar.bspstore=r16 // switch bspstore st8 [r2]=rRSC,16 // r2=&tf_cr_ifs ;; st8 [r1]=rPFS,16 // r1=&tf_ar_bspstore st8 [r2]=rIFS,16 // r2=&tf_ar_rnat +(p2) mov r17=ar.bsp + ;; +(p2) sub r17=r17,r16 // ndirty (in bytes) +(p1) mov r17=r0 ;; - st8 [r1]=rBSPSTORE,16 // r1=&tf_ar_bsp + st8 [r1]=rBSPSTORE,16 // r1=&tf_ndirty st8 [r2]=rRNAT,16 // r2=&tf_ar_unat ;; - st8 [r1]=rBSP,16 // r1=&tf_ar_ccv + st8 [r1]=r17,16 // r1=&tf_ar_ccv mov ar.rsc=3 // switch RSE back on mov r16=ar.unat ;; @@ -1217,12 +1236,207 @@ ENTRY(exception_save, 0) ;; movl r1=__gp // kernel globals mov r13=ar.k4 // processor globals + mov r14=cr.iim // break immediate ssm psr.ic|psr.dt // enable interrupts & translation ;; srlz.d // serialize br.sptk.few b0 // not br.ret - we were not br.call'ed - END(exception_save) +END(exception_save) +/* + * System call entry point (via Break Instruction vector). + * + * Arguments: + * r16 saved predicates + */ +ENTRY(do_syscall, 0) + rsm psr.dt // physical addressing for a moment + mov r17=sp;; // save user sp + srlz.d // serialize psr.dt + mov sp=ar.k6;; // switch to kernel sp + add sp=-SIZEOF_TRAPFRAME,sp;; // reserve trapframe + dep r30=0,sp,61,3;; // physical address + add r31=8,r30;; // secondary pointer + + // save minimal state for syscall + mov r18=cr.iip + mov r19=cr.ipsr + mov r20=cr.isr + ;; + st8 [r30]=r18,16 // save cr.iip + st8 [r31]=r19,16 // save cr.ipsr + ;; + st8 [r30]=r20,16 // save cr.isr + add r31=16,r31 // skip cr.ifa + mov r18=ar.rsc + mov r19=ar.pfs + ;; + st8 [r30]=r16,16 // save pr + st8 [r31]=r18,16 // save ar.rsc + mov ar.rsc=0 // turn off rse + ;; + st8 [r30]=r19,16 // save ar.pfs + add r31=16,r31 // skip cr.ifs + mov r20=ar.bspstore + mov r21=ar.rnat + mov r22=ar.k5 + ;; + mov ar.bspstore=r22 // switch to kernel backing store + ;; + mov r23=ar.bsp // calculate ndirty + ;; + ;; + st8 [r30]=r20,16 // save ar.bspstore + st8 [r31]=r21,16 // save ar.rnat + sub r16=r23,r22 // bytes of dirty regs + mov r18=ar.unat + ;; + st8 [r30]=r16,16 // save ndirty + st8 [r31]=r18,16 // save ar.unat + mov r20=ar.ccv + mov r21=ar.fpsr + ;; + st8 [r30]=r20,16 // save ar.ccv + st8 [r31]=r21,16 // save ar.fpsr + mov r16=b0 + ;; + st8 [r30]=r16,TF_R-TF_B+FRAME_SP*8 // save b0, r1=&tf_r[FRAME_SP] + ;; + st8 [r30]=r17 // save user sp + ;; + bsw.1 // switch back to bank 1 + ;; + mov r18=sp // trapframe pointer + ;; + add sp=-(8*8),sp // reserve stack for arguments + ;; + br.call.sptk.few b0=Lsaveargs // dump args + ;; + mov r31=sp // point at args + mov r20=ar.bsp // record bsp before the cover + ;; + cover // preserve arguments + ;; + mov r22=cr.ifs // record user's CFM + add r23=TF_CR_IFS,r18 + ;; + ssm psr.dt|psr.ic|psr.i // safe to take interrupts again + ;; + srlz.d // serialize psr.dt and psr.ic + ;; + st8 [r23]=r22 // save cr.ifs + ;; + mov r21=ar.bsp // r21-r20 = size of user reg frame + add r22=TF_NDIRTY,r18 + ;; + sub r20=r21,r20 + ld8 r23=[r22] + ;; + add r23=r23,r20 // adjust ndirty + ;; + st8 [r22]=r23 + ;; + add sp=-16,sp // reserve scratch space + alloc r14=ar.pfs,0,3,3,0 + mov r13=ar.k4 // processor globals + ;; + mov loc0=r15 // save in case of restarts + mov loc1=r18 // save so we can restore + mov loc2=gp // save user gp + mov out0=r15 // syscall number (from user) + mov out1=r31 // arguments + mov out2=r18 // trapframe pointer + ;; + movl gp=__gp // kernel globals + ;; + br.call.sptk.many rp=syscall // do the work + + rsm psr.dt|psr.ic // get ready to restore + ;; + srlz.d // serialise psr.dt and psr.ic + dep r30=0,loc1,61,3 // physical address + mov gp=loc2 // restore user gp + ;; + add r30=TF_R+FRAME_SP*8,r30 // &tf_r[FRAME_SP] + mov r15=loc0 // saved syscall number + alloc r14=ar.pfs,0,0,0,0 // discard register frame + ;; + ld8 sp=[r30],-16 // restore user sp + ;; + ld8 r10=[r30],-8 // ret2 + ;; + ld8 r9=[r30],-8 // ret1 + ;; + ld8 r8=[r30],-(TF_R+7*8-TF_B) // ret0 + ;; + ld8 r16=[r30],-16 // restore b0 + ;; + mov b0=r16 + add r31=8,r30 // secondary pointer, &tf_fpsr + ;; + ld8 r16=[r31],-16 // restore ar.fpsr + ld8 r17=[r30],-16 // restore ar.ccv + ;; + ld8 r18=[r31],-16 // restore ar.unat + ld8 r19=[r30],-16 // restore ndirty + mov ar.fpsr=r16 + mov ar.ccv=r17 + ;; + ld8 r16=[r31],-16 // restore ar.rnat + ld8 r17=[r30],-16 // restore ar.bspstore + mov ar.unat=r18 + ;; + shl r19=r19,16 // value for ar.rsc + ;; + mov ar.rsc=r19 // setup for loadrs + ;; + loadrs // restore user registers + ;; + mov ar.bspstore=r17 + ;; + mov ar.rnat=r16 + ld8 r18=[r31],-16 // restore cr.ifs + ld8 r19=[r30],-16 // restore ar.pfs + ;; + ld8 r16=[r31],-32 // restore ar.rsc + ld8 r17=[r30],-32 // restore pr + mov cr.ifs=r18 + mov ar.pfs=r19 + ;; + ld8 r18=[r31],-16 // restore cr.ipsr + ld8 r19=[r30],-16 // restore cr.iip + mov ar.rsc=r16 + mov pr=r16,0x1ffff + ;; + mov cr.ipsr=r18 + mov cr.iip=r19 + ;; + rfi + // This is done as a function call to make sure that we only + // have output registers in the register frame. It also gives + // us a chance to use alloc to round up to 8 arguments for + // simplicity. + // + // We are still running in physical mode with psr.ic==0 because + // we haven't yet covered the user's register frame to get a + // value for cr.ifs +Lsaveargs: + alloc r14=ar.pfs,0,0,8,0 // round up to 8 outputs + ;; + extr.u r31=sp,0,61 // physical address + ;; + st8 [r31]=r32,8 + st8 [r31]=r33,8 + st8 [r31]=r34,8 + st8 [r31]=r35,8 + st8 [r31]=r36,8 + st8 [r31]=r37,8 + st8 [r31]=r38,8 + st8 [r31]=r39 + ;; + br.ret.sptk.many b0 + +END(do_syscall) diff --git a/sys/ia64/ia64/genassym.c b/sys/ia64/ia64/genassym.c index 17a4eb9..f68ab7b 100644 --- a/sys/ia64/ia64/genassym.c +++ b/sys/ia64/ia64/genassym.c @@ -87,6 +87,13 @@ ASSYM(VM_MAXUSER_ADDRESS, VM_MAXUSER_ADDRESS); ASSYM(SIZEOF_USER, sizeof(struct user)); ASSYM(TF_CR_IPSR, offsetof(struct trapframe, tf_cr_ipsr)); +ASSYM(TF_CR_IFS, offsetof(struct trapframe, tf_cr_ifs)); +ASSYM(TF_NDIRTY, offsetof(struct trapframe, tf_ndirty)); +ASSYM(TF_B, offsetof(struct trapframe, tf_b)); +ASSYM(TF_R, offsetof(struct trapframe, tf_r)); +ASSYM(TF_F, offsetof(struct trapframe, tf_f)); + +ASSYM(FRAME_SP, FRAME_SP); ASSYM(U_PCB_R4, offsetof(struct user, u_pcb.pcb_r4)); ASSYM(U_PCB_R5, offsetof(struct user, u_pcb.pcb_r5)); diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index 8aef59e..c034ba3 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -710,9 +710,10 @@ ia64_init() } /* - * Force verbose mode for a while. + * Force verbose mode and single-user for a while. */ bootverbose = 1; + boothowto |= RB_SINGLE; /* * Initialize debuggers, and break into them if appropriate. @@ -800,7 +801,8 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) sf.sf_uc.uc_mcontext.mc_cfm = 0; /* XXX */ sf.sf_uc.uc_mcontext.mc_um = frame->tf_cr_ipsr & 0x1fff; sf.sf_uc.uc_mcontext.mc_ar_rsc = frame->tf_ar_rsc; - sf.sf_uc.uc_mcontext.mc_ar_bsp = frame->tf_ar_bsp; + sf.sf_uc.uc_mcontext.mc_ar_bsp = (frame->tf_ar_bspstore + + frame->tf_ndirty); sf.sf_uc.uc_mcontext.mc_ar_rnat = frame->tf_ar_rnat; sf.sf_uc.uc_mcontext.mc_ar_ccv = frame->tf_ar_ccv; sf.sf_uc.uc_mcontext.mc_ar_unat = frame->tf_ar_unat; @@ -1048,7 +1050,7 @@ setregs(struct proc *p, u_long entry, u_long stack, u_long ps_strings) * starts executing with an empty register stack frame. */ frame->tf_ar_bspstore = p->p_md.md_bspstore; - frame->tf_ar_bsp = p->p_md.md_bspstore; + frame->tf_ndirty = 0; frame->tf_cr_ifs = (1L<<63); /* ifm=0, v=1 */ frame->tf_ar_rsc = 0xf; /* user mode rsc */ frame->tf_ar_fpsr = IA64_FPSR_DEFAULT; diff --git a/sys/ia64/ia64/swtch.s b/sys/ia64/ia64/swtch.s index 7adb66e..20160d0 100644 --- a/sys/ia64/ia64/swtch.s +++ b/sys/ia64/ia64/swtch.s @@ -234,9 +234,13 @@ ENTRY(cpu_switch, 0) #endif 1: - st8 [r14]=ret0 + st8 [r14]=ret0 // set r13->gd_curproc + add r15=@gprel(want_resched),gp + ;; + st4 [r15]=r0 // we've rescheduled mov ar.k7=ret0 mov r4=ret0 // save from call + ;; alloc r15=ar.pfs,0,0,1,0 // create temporary output frame ;; mov out0=r4 diff --git a/sys/ia64/ia64/trap.c b/sys/ia64/ia64/trap.c index 361c2cf..f157ed2 100644 --- a/sys/ia64/ia64/trap.c +++ b/sys/ia64/ia64/trap.c @@ -204,7 +204,7 @@ static const char *ia64_vector_names[] = { }; static void -printtrap(int vector, struct trapframe *framep, int isfatal, int user) +printtrap(int vector, int imm, struct trapframe *framep, int isfatal, int user) { printf("\n"); printf("%s %s trap:\n", isfatal? "fatal" : "handled", @@ -212,10 +212,11 @@ printtrap(int vector, struct trapframe *framep, int isfatal, int user) printf("\n"); printf(" trap vector = 0x%x (%s)\n", vector, ia64_vector_names[vector]); - printf(" iip = 0x%lx\n", framep->tf_cr_iip); - printf(" ipsr = 0x%lx\n", framep->tf_cr_ipsr); - printf(" isr = 0x%lx\n", framep->tf_cr_isr); - printf(" ifa = 0x%lx\n", framep->tf_cr_ifa); + printf(" cr.iip = 0x%lx\n", framep->tf_cr_iip); + printf(" cr.ipsr = 0x%lx\n", framep->tf_cr_ipsr); + printf(" cr.isr = 0x%lx\n", framep->tf_cr_isr); + printf(" cr.ifa = 0x%lx\n", framep->tf_cr_ifa); + printf(" cr.iim = 0x%x\n", imm); printf(" curproc = %p\n", curproc); if (curproc != NULL) printf(" pid = %d, comm = %s\n", curproc->p_pid, @@ -231,10 +232,10 @@ printtrap(int vector, struct trapframe *framep, int isfatal, int user) */ /*ARGSUSED*/ void -trap(int vector, struct trapframe *framep) +trap(int vector, int imm, struct trapframe *framep) { - register struct proc *p; - register int i; + struct proc *p; + int i; u_int64_t ucode; u_quad_t sticks; int user; @@ -298,13 +299,8 @@ trap(int vector, struct trapframe *framep) goto dopanic; case IA64_VEC_BREAK: - /* - * This should never happen. Breaks enter the kernel - * via break(). - */ goto dopanic; - case IA64_VEC_DISABLED_FP: /* * on exit from the kernel, if proc == fpcurproc, @@ -456,7 +452,7 @@ trap(int vector, struct trapframe *framep) ucode = va; i = SIGSEGV; #ifdef DEBUG - printtrap(vector, framep, 1, user); + printtrap(vector, imm, framep, 1, user); #endif break; } @@ -466,7 +462,7 @@ trap(int vector, struct trapframe *framep) } #ifdef DEBUG - printtrap(vector, framep, 1, user); + printtrap(vector, imm, framep, 1, user); #endif trapsignal(p, i, ucode); out: @@ -477,7 +473,7 @@ out: return; dopanic: - printtrap(vector, framep, 1, user); + printtrap(vector, imm, framep, 1, user); /* XXX dump registers */ @@ -492,46 +488,47 @@ dopanic: * Process a system call. * * System calls are strange beasts. They are passed the syscall number - * in v0, and the arguments in the registers (as normal). They return - * an error flag in a3 (if a3 != 0 on return, the syscall had an error), - * and the return value (if any) in v0. + * in r15, and the arguments in the registers (as normal). They return + * an error flag in r10 (if r10 != 0 on return, the syscall had an error), + * and the return value (if any) in r8 and r9. * * The assembly stub takes care of moving the call number into a register - * we can get to, and moves all of the argument registers into their places - * in the trap frame. On return, it restores the callee-saved registers, - * a3, and v0 from the frame before returning to the user process. + * we can get to, and moves all of the argument registers into a stack + * buffer. On return, it restores r8-r10 from the frame before + * returning to the user process. */ void -syscall(code, framep) - u_int64_t code; - struct trapframe *framep; +syscall(int code, u_int64_t *args, struct trapframe *framep) { struct sysent *callp; struct proc *p; int error = 0; - u_int64_t opc; + u_int64_t oldip, oldri; u_quad_t sticks; - u_int64_t args[10]; /* XXX */ - u_int hidden = 0, nargs; mtx_enter(&Giant, MTX_DEF); -#if notdef /* can't happen, ever. */ - if ((framep->tf_cr_ipsr & IA64_PSR_CPL) == IA64_PSR_CPL_KERN) - panic("syscall"); -#endif - cnt.v_syscall++; p = curproc; p->p_md.md_tf = framep; - opc = framep->tf_cr_iip; sticks = p->p_sticks; + /* + * Skip past the break instruction. Remember old address in case + * we have to restart. + */ + oldip = framep->tf_cr_iip; + oldri = framep->tf_cr_ipsr & IA64_PSR_RI; + framep->tf_cr_ipsr += IA64_PSR_RI_1; + if ((framep->tf_cr_ipsr & IA64_PSR_RI) > IA64_PSR_RI_2) { + framep->tf_cr_ipsr &= ~IA64_PSR_RI; + framep->tf_cr_iip += 16; + } + #ifdef DIAGNOSTIC ia64_fpstate_check(p); #endif -#if 0 if (p->p_sysent->sv_prepsyscall) { /* (*p->p_sysent->sv_prepsyscall)(framep, args, &code, ¶ms); */ panic("prepsyscall"); @@ -544,8 +541,8 @@ syscall(code, framep) /* * Code is first argument, followed by actual args. */ - code = framep->tf_regs[FRAME_A0]; - hidden = 1; + code = args[0]; + args++; } } @@ -557,33 +554,9 @@ syscall(code, framep) else callp = &p->p_sysent->sv_table[code]; - nargs = (callp->sy_narg & SYF_ARGMASK) + hidden; - switch (nargs) { - default: - if (nargs > 10) /* XXX */ - panic("syscall: too many args (%d)", nargs); - error = copyin((caddr_t)(alpha_pal_rdusp()), &args[6], - (nargs - 6) * sizeof(u_int64_t)); - case 6: - args[5] = framep->tf_regs[FRAME_A5]; - case 5: - args[4] = framep->tf_regs[FRAME_A4]; - case 4: - args[3] = framep->tf_regs[FRAME_A3]; - case 3: - args[2] = framep->tf_regs[FRAME_A2]; - case 2: - args[1] = framep->tf_regs[FRAME_A1]; - case 1: - args[0] = framep->tf_regs[FRAME_A0]; - case 0: - break; - } -#endif - #ifdef KTRACE if (KTRPOINT(p, KTR_SYSCALL)) - ktrsyscall(p->p_tracep, code, (callp->sy_narg & SYF_ARGMASK), args + hidden); + ktrsyscall(p->p_tracep, code, (callp->sy_narg & SYF_ARGMASK), args); #endif if (error == 0) { p->p_retval[0] = 0; @@ -591,7 +564,7 @@ syscall(code, framep) STOPEVENT(p, S_SCE, (callp->sy_narg & SYF_ARGMASK)); - error = (*callp->sy_call)(p, args + hidden); + error = (*callp->sy_call)(p, args); } @@ -602,7 +575,9 @@ syscall(code, framep) framep->tf_r[FRAME_R10] = 0; break; case ERESTART: - framep->tf_cr_iip = opc; + framep->tf_cr_iip = oldip; + framep->tf_cr_ipsr = + (framep->tf_cr_ipsr & ~IA64_PSR_RI) | oldri; break; case EJUSTRETURN: break; diff --git a/sys/ia64/ia64/vm_machdep.c b/sys/ia64/ia64/vm_machdep.c index b0a8955..e3b2f86 100644 --- a/sys/ia64/ia64/vm_machdep.c +++ b/sys/ia64/ia64/vm_machdep.c @@ -217,8 +217,7 @@ cpu_fork(p1, p2, flags) * Copy enough of p1's backing store to include all * the user's stacked regs. */ - bcopy(p1bs, p2bs, (p1->p_md.md_tf->tf_ar_bsp - - p1->p_md.md_tf->tf_ar_bspstore)); + bcopy(p1bs, p2bs, p1->p_md.md_tf->tf_ndirty); /* * To calculate the ar.rnat for p2, we need to decide @@ -228,9 +227,7 @@ cpu_fork(p1, p2, flags) * that one from memory, otherwise we take p1's * current ar.rnat. */ - rnatloc = (u_int64_t) - (p1bs + (p1->p_md.md_tf->tf_ar_bsp - - p1->p_md.md_tf->tf_ar_bspstore)); + rnatloc = (u_int64_t)p1bs + p1->p_md.md_tf->tf_ndirty; rnatloc |= 0x1f8; if (bspstore > rnatloc) rnat = *(u_int64_t *) rnatloc; @@ -248,9 +245,8 @@ cpu_fork(p1, p2, flags) * should work since the child will normally return * straight into exception_restore. */ - up->u_pcb.pcb_bspstore = (u_int64_t) - (p2bs + (p1->p_md.md_tf->tf_ar_bsp - - p1->p_md.md_tf->tf_ar_bspstore)); + up->u_pcb.pcb_bspstore = + (u_int64_t)p2bs + p1->p_md.md_tf->tf_ndirty; up->u_pcb.pcb_rnat = rnat; /* @@ -306,6 +302,8 @@ cpu_exit(p) ia64_fpstate_drop(p); (void) splhigh(); + mtx_enter(&sched_lock, MTX_SPIN); + mtx_exit(&Giant, MTX_DEF); cnt.v_swtch++; cpu_switch(); panic("cpu_exit"); diff --git a/sys/ia64/include/cpu.h b/sys/ia64/include/cpu.h index d1f4f86..d72f1d2 100644 --- a/sys/ia64/include/cpu.h +++ b/sys/ia64/include/cpu.h @@ -163,8 +163,8 @@ void restorectx __P((struct pcb *)); void set_iointr __P((void (*)(void *, unsigned long))); void switch_exit __P((struct proc *)); /* MAGIC */ void switch_trampoline __P((void)); /* MAGIC */ -void syscall __P((u_int64_t, struct trapframe *)); -void trap __P((int vector, struct trapframe *framep)); +void syscall __P((int, u_int64_t *, struct trapframe *)); +void trap __P((int vector, int imm, struct trapframe *framep)); #endif /* _KERNEL */ diff --git a/sys/ia64/include/frame.h b/sys/ia64/include/frame.h index 2304770..169dba6 100644 --- a/sys/ia64/include/frame.h +++ b/sys/ia64/include/frame.h @@ -48,7 +48,7 @@ struct trapframe { u_int64_t tf_cr_ifs; u_int64_t tf_ar_bspstore; u_int64_t tf_ar_rnat; - u_int64_t tf_ar_bsp; + u_int64_t tf_ndirty; u_int64_t tf_ar_unat; u_int64_t tf_ar_ccv; u_int64_t tf_ar_fpsr; |