summaryrefslogtreecommitdiffstats
path: root/sys/ia64
diff options
context:
space:
mode:
Diffstat (limited to 'sys/ia64')
-rw-r--r--sys/ia64/ia64/exception.S246
-rw-r--r--sys/ia64/ia64/exception.s246
-rw-r--r--sys/ia64/ia64/genassym.c7
-rw-r--r--sys/ia64/ia64/machdep.c8
-rw-r--r--sys/ia64/ia64/swtch.s6
-rw-r--r--sys/ia64/ia64/trap.c103
-rw-r--r--sys/ia64/ia64/vm_machdep.c14
-rw-r--r--sys/ia64/include/cpu.h4
-rw-r--r--sys/ia64/include/frame.h2
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, &params); */
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;
OpenPOWER on IntegriCloud