* 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 :-).
This commit is contained in:
parent
6409a78036
commit
af713edef9
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 @@ trap(int vector, struct trapframe *framep)
|
||||
return;
|
||||
|
||||
dopanic:
|
||||
printtrap(vector, framep, 1, user);
|
||||
printtrap(vector, imm, framep, 1, user);
|
||||
|
||||
/* XXX dump registers */
|
||||
|
||||
@ -492,46 +488,47 @@ trap(int vector, struct trapframe *framep)
|
||||
* 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;
|
||||
|
@ -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");
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user