summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordfr <dfr@FreeBSD.org>2000-10-16 08:54:40 +0000
committerdfr <dfr@FreeBSD.org>2000-10-16 08:54:40 +0000
commiteff8f28a1d7344917be2f3c7bc8c3595cc1f95a6 (patch)
tree11df3db4b13e94c772920d3c8303aa26089f1b48 /sys
parent4585a8bcedebb58812522ee2a8c36552e4acb11f (diff)
downloadFreeBSD-src-eff8f28a1d7344917be2f3c7bc8c3595cc1f95a6.zip
FreeBSD-src-eff8f28a1d7344917be2f3c7bc8c3595cc1f95a6.tar.gz
* Correct some of my misunderstandings about how best to switch to the
kernel backing store. * Implement syscalls via break instructions. * Fix backing store copying in cpu_fork() so that the child gets the right register values. This thing is actually starting to work now. This set of changes takes me up to the second execve (the one which runs the first shell). Next stop single-user mode :-).
Diffstat (limited to 'sys')
-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