V10/sys/ml/swtch.s
/*
* The following primitives use the fancy VAX instructions
* much like VMS does. _whichqs tells which of the 32 queues _qs
* have processes in them. Setrq puts processes into queues, Remrq
* removes them from queues. The running process is on no queue,
* other processes are on a queue related to p->p_pri, divided by 4
* actually to shrink the 0-127 range of priorities into the 32 available
* queues.
*/
.comm _noproc,4
.comm _runrun,4
.text
/*
* Setrq(p), using fancy VAX instructions.
*
* Call should be made at spl6(), and p->p_stat should be SRUN
*/
.globl _Setrq # <<<massaged to jsb by "asm.sed">>>
_Setrq:
tstl P_RLINK(r0) ## firewall: p->p_rlink must be 0
beql set1 ##
pushab set3 ##
calls $1,_panic ##
set1:
bitl $SPROCIO,P_FLAG(r0) # if he's getting PROCIO'd,
bneq set2 # we leave him alone
movzbl P_PRI(r0),r1 # put on queue which is p->p_pri / 4
ashl $-2,r1,r1
movaq _qs[r1],r2
insque (r0),*4(r2) # at end of queue
bbss r1,_whichqs,set2 # mark queue non-empty
set2:
rsb
set3: .asciz "setrq"
/*
* Remrq(p), using fancy VAX instructions
*
* Call should be made at spl6().
*/
.globl _Remrq # <<<massaged to jsb by "asm.sed">>>
_Remrq:
bitl $SPROCIO,P_FLAG(r0) # if he's getting PROCIO'd,
bneq rem2a # we leave him alone
movzbl P_PRI(r0),r1
ashl $-2,r1,r1
bbsc r1,_whichqs,rem1
pushab rem3 # it wasn't recorded to be on its q
calls $1,_panic
rem1:
remque (r0),r2
beql rem2
bbss r1,_whichqs,rem2
rem2:
clrl P_RLINK(r0) ## for firewall checking
rem2a:
rsb
rem3: .asciz "remrq"
/*
* Masterpaddr is the p->p_addr of the running process on the master
* processor. When a multiprocessor system, the slave processors will have
* an array of slavepaddr's.
*/
.globl _masterpaddr
.data
_masterpaddr:
.long 0
.text
sw0: .asciz "swtch"
/*
* Swtch(), using fancy VAX instructions
*/
.globl _Swtch
_Swtch: # <<<massaged to jsb by "asm.sed">>>
movl $1,_noproc
clrl _runrun
sw1: ffs $0,$32,_whichqs,r0 # look for non-empty queue
bneq sw1a
mtpr $0,$IPL # must allow interrupts here
brw sw1 # this is an idle loop!
sw1a: mtpr $0x18,$IPL # lock out all so _whichqs==_qs
bbcc r0,_whichqs,sw1 # proc moved via lbolt interrupt
movaq _qs[r0],r1
remque *(r1),r2 # r2 = p = highest pri process
bvc sw2 # make sure something was there
sw1b: pushab sw0
calls $1,_panic
sw2: beql sw3
insv $1,r0,$1,_whichqs # still more procs in this queue
sw3:
clrl _noproc
movzbl P_STAT(r2),r3 ## firewalls
cmpl $SRUN,r3 ##
bneq sw1b ##
clrl P_RLINK(r2) ##
movl *P_ADDR(r2),r0
movl r0,_masterpaddr
ashl $PGSHIFT,r0,r0 # r0 = pcbb(p)
# mfpr $PCBB,r1 # resume of current proc is easy
# cmpl r0,r1
# beql res0
# incl _cnt+V_SWTCH
/* fall into... */
/*
* Resume(pf)
*/
.globl _Resume # <<<massaged to jsb by "asm.sed">>>
_Resume:
mtpr $0x18,$IPL # no interrupts, please
pushl _nofault
pushl _CMAP2 # yech
svpctx
mtpr r0,$PCBB
ldpctx
movl (sp)+,_CMAP2 # yech
mtpr $_CADDR2,$TBIS
movl (sp)+,_nofault
res0:
tstl _u+PCB_SSWAP
bneq res1
rei
res1:
movl _u+PCB_SSWAP,r0 # longjmp to saved context
clrl _u+PCB_SSWAP
movq (r0)+,r6
movq (r0)+,r8
movq (r0)+,r10
movq (r0)+,r12
movl (r0)+,r1
cmpl r1,sp # must be a pop
bgequ 1f
pushab 2f
calls $1,_panic
/* NOTREACHED */
1:
movl r1,sp
movl (r0),(sp) # address to return to
movl $PSL_PRVMOD,4(sp) # ``cheating'' (jfr)
rei
2: .asciz "ldctx"