32V/usr/src/slowsys/sys/locore.s
.set HIGH,31 # mask for total disable
.set SZPT,4 # number of pages of user page table allocated per user
.set MCKVEC,4 # offset into Scbbase of machine check vector
# Trap vectors and C interface for Vax
#
#
#
# System control block
#
.set INTSTK,1 # handle this interrupt on the interrupt stack
.set HALT,3 # halt if this interrupt occurs
.align 9
.globl Scbbase
Scbbase:
.long Xrandom + HALT # unused
.long Xmachcheck + HALT # machine check interrupt
.long Xkspnotval + HALT # kernal stack not valid
.long Xpowfail + HALT # power fail
.long Xprivinflt # privileged instruction
.long Xxfcflt # xfc instruction
.long Xresopflt # reserved operand
.long Xresadflt # reserved addressing
.long Xprotflt # protection
.long Xsegflt # segmentation
.long Xtracep # trace pending
.long Xbptflt # bpt instruction
.long Xrandom + HALT # compatibility mode fault
.long Xarithtrap # arithmetic trap
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xsyscall # chmk
.long Xchme+HALT # chme
.long Xchms+HALT # chms
.long Xchmu+HALT # chmu
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # software level 1
.long Xrandom + HALT # software level 2 (asts)
.long Xresched # reschedule nudge
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
ubabase:
.long Xclockint + INTSTK # clock
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xconsrint + INTSTK # console receiver
.long Xconsxint + INTSTK # console transmitter
# I/O vectors
# IPL 14
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xua0int + INTSTK # UBA 0 br4
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
# IPL 15
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xua0int + INTSTK # UBA 0 br5
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xmba0int + INTSTK # mass bus adapter 0
.long Xmba1int + INTSTK # mass bus adapter 1
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
# IPL 16
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xua0int + INTSTK # UBA 0 br6
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
# IPL 17
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
.long Xrandom + HALT # unused
# 0x200
# Produce a core image dump on mag tape
.globl doadump
doadump:
movl sp,dumpstack # save stack pointer
movab dumpstack,sp # reinit sp
mfpr $PCBB,-(sp) # save u-area pointer
mfpr $MAPEN,-(sp) # save value
mfpr $IPL,-(sp) # ...
mtpr $0,$MAPEN # turn off memory mapping
mtpr $HIGH,$IPL # disable interrupts
pushr $0x3fff # save regs 0 - 13
calls $0,_dump # produce dump
halt
.data
.align 2
.space 58*4 # seperate stack for tape dumps
.globl dumpstack
dumpstack:
.space 4
.text
# I/O interrupt vector routines
#
# Catch random or unexpected interrupts
.align 2
Xrandom:
Xmachcheck:
Xkspnotval:
Xpowfail:
Xchme:
Xchms:
Xchmu:
halt
# Massbus 0 adapter interrupts
.align 2
Xmba0int:
pushr $0x3f # save r0 - r5
movab MBA0_CSR,r0 # point at mba regs
movl MBA_AS(r0),r1 # get attn summary bits
cvtwl r1,-(sp) # push attn summary as arg
pushl MBA_SR(r0) # pass sr as argument
mnegl $1,MBA_SR(r0) # clear attention bit
calls $2,_hpintr # call rp06 interrupt dispatcher
brw int_ret # merge with common interrupt code
# Massbus 1 adapter interrupts
.align 2
Xmba1int:
pushr $0x3f
movab MBA1_CSR,r0
pushl MBA_AS(r0)
mnegl $1,MBA_AS(r0)
pushl MBA_SR(r0) # pass cr as argument_
mnegl $1,MBA_SR(r0) # clear attention bit
calls $2,_htintr # call te16 interrupt dispatcher
brw int_ret # return from interrupt
# Unibus adapter interrupts
.align 2
Xua0int: # UBA 0 interrupts
pushr $0x3f # save regs 0-5
pushab UBA0 # save UBA base addr
brb Xuacom # jump to common code
Xua1int : # UBA 1 interrupts
Xuacom : # common code for UBA interrupts
popr $1 # UBA base addr
mfpr $IPL,r2 # get br level
movl UBR_OFF-20*4(r0)[r2],r3 # get unibus device vector
bleq ubasrv # branch if zero vector or UBA service required
# normal UBA interrupt point - device on a UBA has generated an
# interrupt - r3 holds interrupt vector
ubanorm :
movl _UNIvec(r3),r1 # get interrupt service routine address
# and controller code from UNIBUS vector area
extzv $27,$4,r1,-(sp) # controller code is in 4 most
# significant bits-1 of ISR addr
bicl2 $0x78000000,r1 # clear code
calls $1,(r1) # call ISR
brw int_ret # go to common interrupt return
# here for zero or negative UBA interrupt vector.
# negative vector -> UBA requires service
ubasrv :
beql ubapass
#
# UBA service required
# The following 'printf' calls should probably be replaced
# with calls to an error logger and/or some corrective action.
bitl $CFGFLT,UCN_OFF(r0) # any SBI faults ?
beql UBAflt
pushab SBImsg
calls $1,_printf
halt
#
# no SBI fault bits set in UBA config reg - must be
# some error bits set in UBA status reg
UBAflt :
movl UST_OFF(r0),r2 # UBA status reg
pushr r2
pushab UBAmsg
calls $2,_printf
movl r2,UST_OFF(r0) # clear error bits
bicl2 $0x80000000,r1 # clear neg bit in vector
bneq ubanorm # branch if normal UBA interrupt to process
brb int_ret # restore regs and return
#
# zero interrupt vector - print message & continue
ubapass :
pushab ZERmsg
calls $1,_printf
brb int_ret
# Console receiver interrupt
.align 2
Xconsrint:
pushr $0x3f # save registers 0 - 5
calls $0,_consrint
brb int_ret # merge
# Console transmit interrupt
.align 2
Xconsxint:
pushr $0x3f # save registers 0 - 5
calls $0,_consxint
brb int_ret
# Clock interrupt
.align 2
Xclockint:
pushr $0x3f # save regs 0 - 5
pushl 4+6*4(sp) # push psl
pushl 4+6*4(sp) # push pc
calls $2,_clock
brb int_ret
#
# Common code for interrupts
# At this point, the interrupt stack looks like:
#
# ___________
# | r0 | :isp
# |-----------|
# | ... |
# |-----------|
# | r13 |
# |-----------|
# | pc |
# |-----------|
# | psl |
# |___________|
int_ret:
bbssi $0,idleflag,int_r0 # set idle escape flag (no wait instr)
int_r0:
popr $0x3f # restore regs 0 - 5
bitl $PSL_CURMOD,4(sp) # interrupt from user mode?
beql int_r1 # no, from kernal, just rei
tstb _runrun # should we reschedule?
beql int_r1 # no, just rei
#
# If here, interrupt from user mode, and time to reschedule.
# to do this, we set a software level 3 interrupt to
# change to kernal mode, switch stacks,
# and format kernal stack for a `qswitch' trap to force
# a reschedule.
#
mtpr $3,$SIRR # request level 1 software interrupt
int_r1:
rei # return to interrupted process
#
# Trap and fault vector routines
#
# Reschedule trap (Software level 3 interrupt)
.align 2
Xresched:
movpsl -(sp) # get ps
bicl2 $PSL_IPL,(sp) # lower ipl
pushab resc1 # push pc
rei # lower ipl, jump to resc1
resc1:
pushl $0 # dummy code
pushl $RESCHED # type
brb alltraps # merge
# privileged instruction fault
.align 2
Xprivinflt:
pushl $0 # push dummy code
pushl $PRIVINFLT # push type
brb alltraps # merge
# xfc instruction fault
.align 2
Xxfcflt:
pushl $0 # push dummy code value
pushl $XFCFLT # push type value
brb alltraps # merge
# reserved operand fault
.align 2
Xresopflt:
pushl $0 # push dummy code value
pushl $RESOPFLT # push type value
brb alltraps # merge
# reserved addressing mode fault
.align 2
Xresadflt:
pushl $0 # push dummy code value
pushl $RESADFLT # push type value
brb alltraps # merge with common code
# bpt instruction fault
.align 2
Xbptflt:
pushl $0 # push dummy code value
pushl $BPTFLT # push type value
brb alltraps # merge with common code
# Trace trap
.align 2
Xtracep:
pushl $0 # push dummy code value
pushl $TRCTRAP # push type value
brb alltraps # go do it
# Arithmitic trap
.align 2
Xarithtrap:
pushl $ARITHTRAP # push type value
brb alltraps # merge with common code
# Protection fault
.align 2
Xprotflt:
blbs (sp),Xsegflt # check for pt length violation
addl2 $4,sp # pop fault param word
pushl $PROTFLT
brb alltraps
# Segmentation fault
.align 2
Xsegflt:
addl2 $4,sp
pushl $SEGFLT
brb alltraps
#
# CHMK trap (syscall trap)
# on entry, kernal stack:
#
# ___________
# | code | :ksp
# |-----------|
# | pc |
# |-----------|
# | psl |
# |___________|
#
#
#
# stack (parameters) at calls to _trap:
#
# ___________
# | ap | :ksp
# |-----------|
# | r0 |
# |-----------|
# | ... |
# |-----------|
# | r13 |
# |-----------|
# | usp |
# |-----------|
# | type |
# |-----------|
# | code |
# |-----------|
# | pc |
# |-----------|
# | psl |
# |___________|
#
.align 2
Xsyscall:
pushl $SYSCALL # push type value
alltraps:
movq 8(sp),_u+PCB_PC # save pc
bitl $PSL_CURMOD,12(sp) # from user mode?
beql sysc1 # no
# Prepare arguments to _trap, note that type has already been pushed
mfpr $USP,-(sp) # get usp
pushr $0x3fff # registers 0 - 13
pushl ap # ptr to syscall parameters
#
# Call _trap with wrong number of arguments
# so args not popped by ret
#
calls $1,_trap
# Restore
popr $0x3fff # restore regs 0 - 13
mtpr (sp)+,$USP # restore usp
addl2 $8,sp # pop type, code
#
bitl $PSL_CURMOD,4(sp) # are we returning to user mode?
beql sysc2 # no
# Return
rei
sysc1:
movab emsg1,eptr # set message pointer
brb err_print # print message and halt
sysc2:
movab emsg2,eptr # pointer to error message
brb err_print # print msg and halt
#
# err_print
# print message on console and die
# message pointed to by eptr, terminated by zero byte.
#
err_print:
mtpr $HIGH,$IPL # disable all interrupts
mtpr $0,$TXCS # disable interrupts on console transmitter
eloop1:
mfpr $TXCS,ewk1 # get transmitter status
bbc $TXCS_BRDY,ewk1,eloop1 # loop if not ready to transmit
tstb *eptr # end of message?
beql eout # yes, out of loop
movzbl *eptr,ewk1 # get byte of message
incl eptr # bump pointer
mtpr ewk1,$TXDB # give byte to transmitter
brb eloop1 # loop
eout:
halt
.data
eptr: .long 0
ewk1: .long 0
.text
#
# Initialization
#
# IPL == 1F
# MAPEN == off
# SCBB, PCBB not set
# SBR, SLR not set
# ISP, KSP not set
#
.globl start
start:
.word 0x0000
mtpr $HIGH,$IPL # no interrupts yet
mtpr $Scbbase,$SCBB # set SCBB
mtpr $_Sysmap,$SBR # set SBR
mtpr $Syssize,$SLR # set SLR
mtpr $_Sysmap,$P0BR # set temp P0BR
mtpr $Syssize,$P0LR # set temp P0LR
movl $_intstack+2048,sp # set ISP
# initialize i/o adatpers
movl $1,PHYSMBA0+4 # init & interrupt enable
movl $4,PHYSMBA0+4 # init & interrupt enable
movl $1,PHYSMBA1+4 # init interrupt enable
movl $4,PHYSMBA1+4 # init interrupt enable
movl $1,PHYSUBA+4 # init interrupt enable
movl $0x78,PHYSUBA+4 # init interrupt enable
movl Scbbase+MCKVEC,r5 # save machine check entry
movab startint+INTSTK,Scbbase+MCKVEC # set new vector address
#
# will now see how much memory there really is
# in 64kb chunks, save number of bytes in r7
#
mtpr $HIGH-1,$IPL # allow machine check interrupts
clrl r7
startlp:
tstl (r7) # this chunk really there?
acbl $8096*1024-1,$64*1024,r7,startlp # loop till machine check
brb startint # full load of memory, avoid .align
.align 2
startint:
mtpr $0,$SBIFS # clear sbi fault status
movl r5,Scbbase+MCKVEC # restore machine check vector
movl $_intstack+2048,sp # reset interrupt stack pointer
# clear memory starting with unitialized data (kernal)
movab _edata,r6
movab _end+8096,r5 # clear uninitialized data and some slop
strtclr:
clrq (r6)
acbl r5,$8,r6,strtclr
#
# initialize system page table
#
movab _etext+511,r1 # end of kernal text segment
bbcc $31,r1,strt1 # turn off high order bit
strt1:
ashl $-9,r1,r1 # last page of kernal text
clrl r2 # point at first kernal text page
strtlp1:
bisl3 $PG_V|PG_KR,r2,_Sysmap[r2] # initialize page table entry
aoblss r1,r2,strtlp1 # fill text entries
movab _end+511,r1 # end of kernal data segment
bbcc $31,r1,strt2 # turn off high order bit
strt2:
ashl $-9,r1,r1 # last page of kernal data
strtlp2:
bisl3 $PG_V|PG_KW,r2,_Sysmap[r2] # fill data entries
aoblss r1,r2,strtlp2
# init i/o space page table entries
movl $PHYSUBA/512,r1 # page frame number for uba
movab _Sysmap+uba_offset,r2 # page table address
movab 15(r1),r3 # last pt entry
strtlp3:
bisl3 $PG_V|PG_KW,r1,(r2)+ # init pt entry
aobleq r3,r1,strtlp3
movl $PHYSUMEM/512,r1
movab _Sysmap+umem_offset,r2 # page table address
movab 15(r1),r3 # limit
strtlp4:
bisl3 $PG_V|PG_KW,r1,(r2)+
aobleq r3,r1,strtlp4
movl $PHYSMBA0/512,r1
movab _Sysmap+mba0_offset,r2
movab 15(r1),r3
strtlp5:
bisl3 $PG_V|PG_KW,r1,(r2)+
aobleq r3,r1,strtlp5
movl $PHYSMBA1/512,r1
movab _Sysmap+mba1_offset,r2
movab 15(r1),r3
strtlp6:
bisl3 $PG_V|PG_KW,r1,(r2)+
aobleq r3,r1,strtlp6
mtpr $1,$TBIA # invalidate all trans buffer entries
mtpr $1,$MAPEN # turn on memory mapping
jmp *$startmap # put system virtual address in pc
startmap:
# set maxmem = btoc(r7)
ashl $-9,r7,_maxmem
#
# Setup context for proc[0] == Scheduler
#
# address first page past _end
# this will be u area for proc[0].
# initialize u area page table entries.
# initialize (slightly) the pcb.
movab _end+511,r6
bicl2 $0x1ff,r6 # make page boundary
# set up u area page table
bbcc $31,r6,strt3
strt3:
ashl $-9,r6,r3 # r3 = btoc(r6)
bisl3 $PG_V|PG_KW,r3,_Sysmap+u_ptoffset # init first u pt entry
movab _u,r1 # point at _u area
mtpr r1,$TBIS
movab usize*512(r1),PCB_KSP(r1) # init ksp
mnegl $1,PCB_ESP(r1) # invalidate esp
mnegl $1,PCB_SSP(r1) # invalidate ssp
movl $0x80000000,PCB_USP(r1) # set user sp
movab _u+usize*512,PCB_P0BR(r1) # p0 page table pointer
clrl PCB_P0LR(r1) # size zero page table
movb $4,PCB_P0LR+3(r1) # disable ast
movab _u+(usize+SZPT)*512-0x800000,PCB_P1BR(r1) # p1 page table pointer
movl $0x200000,PCB_P1LR(r1) # invalid p1 p t length
movl $SZPT,PCB_SZPT(r1) # init number pages usr page table
ashl $-9,r6,-(sp) # push arg for setupu
pushl $1 # ditto
movl sp,ap # set up arg pointer
bsbw setupu
addl2 $8,sp # pop stack
mtpr r6,$PCBB # first pcb
ldpctx # set regs, p0br, p0lr, p1br, p1lr,
# astlvl, ksp, and change to kernal mode
addl2 $8,sp # pop dummy pc, psl
mtpr $0,$IPL # enable interrupts
movab _end+511,r0 # calculate firstaddr
bbcc $31,r0,strt4
strt4:
ashl $-9,r0,-(sp) # convert to clicks and stack
calls $1,_main # startup, fork off /etc/init
#
# proc[1] == /etc/init now running here.
# execute code at location 0, in user mode.
#
pushl $PSL_CURMOD|PSL_PRVMOD # psl, user mode, ipl= 0
pushl $0 # pc, $location 0
rei # do /etc/init
#
# Primitives
#
_display: .globl _display
_savfp: .globl _savfp
_restfp: .globl _restfp
.word 0x0000
ret
_addupc: .globl _addupc
.word 0x0000
movl 8(ap),r2 # &u.u_prof
subl3 8(r2),4(ap),r0 # corrected pc
blss addret
extzv $1,$31,r0,r0 # logical right shift
extzv $1,$31,12(r2),r1 # ditto for scale
mull2 r1,r0
ashl $-14,r0,r0
incl r0
bicb2 $1,r0
cmpl r0,4(r2) # length
bgequ addret
addl2 (r2),r0 # base
probew $3,$2,(r0)
beql adderr
addw2 12(ap),(r0)
addret:
ret
adderr:
clrl 12(r2)
ret
_fubyte: .globl _fubyte
_fuibyte:.globl _fuibyte
.word 0x0000
prober $3,$1,*4(ap) # byte accessible ?
beql eret # no
movzbl *4(ap),r0
ret
_subyte: .globl _subyte
_suibyte:.globl _suibyte
.word 0x0000
probew $3,$1,*4(ap) # byte accessible ?
beql eret # no
movb 8(ap),*4(ap)
clrl r0
ret
_fuword: .globl _fuword
_fuiword:.globl _fuiword
.word 0x0000
prober $3,$4,*4(ap)
beql eret
movl *4(ap),r0
ret
_suword: .globl _suword
_suiword:.globl _suiword
.word 0x0000
probew $3,$4,*4(ap)
beql eret
movl 8(ap),*4(ap)
clrl r0
ret
eret:
mnegl $1,r0 # error return
ret
_copyin: .globl _copyin
_copyiin:.globl _copyiin
.word 0x0000
movl 12(ap),r0 # copy length
movl 4(ap),r1 # copy user address
cmpl $512,r0 # probing one page or less ?
bgeq cishort # yes
ciloop:
prober $3,$512,(r1) # bytes accessible ?
beql eret # no
addl2 $512,r1 # incr user address ptr
acbl $513,$-512,r0,ciloop # reduce count and loop
cishort:
prober $3,r0,(r1) # bytes accessible ?
beql eret # no
movc3 12(ap),*4(ap),*8(ap)
clrl r0
ret
_copyout: .globl _copyout
_copyiout:.globl _copyiout
.word 0x0000
movl 12(ap),r0 # get count
movl 8(ap),r1 # get user address
cmpl $512,r0 # can do in one probew?
bgeq coshort # yes
coloop:
probew $3,$512,(r1) # bytes accessible?
beql eret # no
addl2 $512,r1 # increment user address
acbl $513,$-512,r0,coloop # reduce count and loop
coshort:
probew $3,r0,(r1) # bytes accessible?
beql eret # no
movc3 12(ap),*4(ap),*8(ap)
clrl r0
ret
_idle: .globl _idle
.word 0x0000
mtpr $0,$IPL # enable interrupts
waitloc: blbc idleflag,waitloc # loop until interrupt
ewaitloc: bbcci $0,idleflag,idle1 # clear idle escape flag
idle1:
ret
.data
.globl _waitloc
.globl _ewaitloc
.align 2
_waitloc: .long waitloc
_ewaitloc: .long ewaitloc
idleflag: .long 0
.text
# save reg's and ret loc into save area - return 0
.globl _save
_save : # save(save_area)
.word 0x0
mtpr $HIGH,$IPL
movl 4(ap),r0 # save area addr
movab 2*4(ap),sp # restore stack to val before 'save' call
movl 8(fp),ap # restore ap " " "
movl 16(fp),r1 # restore pc " " "
movl 12(fp),fp # restore fp " " "
movq r6,(r0)+
movq r8,(r0)+
movq r10,(r0)+
movq ap,(r0)+ # ap & fp
movl sp,(r0)+
movl r1,(r0)+ # ret loc of call to 'save'
movpsl -(sp)
pushl r1
svpctx # save reg's -> PCB
movpsl -(sp) # set up for return
bicl2 $PSL_IS|PSL_IPL,(sp) # undo SVPCTX
pushl r1 # ret loc
clrl r0 # return val
rei
#
#
# switch to another process's '_u' area - return val 1
.globl _resume
_resume : # resume(proc_addr,save_addr)
.word 0x0
mtpr $HIGH,$IPL # inhibit interrupts
ashl $9,4(ap),r5 # proc byte addr
# area of proc argument
movl 8(ap),retloc
bsbw setupu # set up '_sysmap' PTE's to map into '_u'
movl _u,sp # KSP from u-area
mtpr r5,$PCBB
ldpctx
addl2 $8,sp # clear ps,pc from stack
movl retloc,r1 # 'ssav' or 'qsav' addr
movq (r1)+,r6
movq (r1)+,r8
movq (r1)+,r10
movq (r1)+,ap
movl (r1)+,sp
movl $1,r0 # return val
mtpr $0,$IPL
jmp *(r1)+ # return to caller at 'save' address
#
.data
.align 2
retloc: .space 1*4
.text
# initialize u area page table entries
setupu:
movl (sp)+,r0 # get return pc
addl3 $PG_V|PG_KW,4(ap),r1 # first pt entry of user area
movab usize(r1),r2 # one past last pt entry of user
movab _Sysmap+u_ptoffset,r3 # addr for 1st user pt entry
movab _u,r4
mtpr r4,$TBIS # invalidate old trans buffer entry
movl r1,(r3)+ # store page table entry
addl2 _u+PCB_SZPT,r2 # add on size of user page table
brb setulp1
setulp:
mtpr r4,$TBIS # ivalidate page table entry
movl r1,(r3)+ # store page table entry
setulp1:
addl2 $512,r4
aoblss r2,r1,setulp # -> till done
jmp (r0) # funny return in case of changing stacks
# disable interrupts
_spl1: .globl _spl1
.word 0x0000
mfpr $IPL,r0 # get IPL value
mtpr $2,$IPL # disable RESCHED & AST interrupts
ret
_spl4: .globl _spl4
.word 0x0000
mfpr $IPL,r0
mtpr $0x14,$IPL # disable bus level 4 interrupts
ret
_spl5: .globl _spl5
.word 0x0000
mfpr $IPL,r0
mtpr $0x15,$IPL # disable bus level 5 interrupts
ret
_spl6: .globl _spl6
_spl7: .globl _spl7
.word 0x0000
mfpr $IPL,r0
mtpr $0x18,$IPL # disable bus level 7 and clock interrupts
ret
# enable interrupts
_spl0: .globl _spl0
.word 0x0000
mfpr $IPL,r0
mtpr $0,$IPL
ret
# restore interrupt state
_splx: .globl _splx
.word 0x0000
mfpr $IPL,r0
mtpr 4(ap),$IPL
ret
#
# Copy 1 relocation unit (512 bytes)
# from one physical address to another
_copyseg: .globl _copyseg
.word 0x0000
mfpr $IPL,r0 # get current pri level
mtpr $HIGH,$IPL # turn off interrupts
bisl3 $PG_V|PG_KR,4(ap),_Sysmap+CMAP1
bisl3 $PG_V|PG_KW,8(ap),_Sysmap+CMAP2
mtpr $CADDR1,$TBIS # invalidate entry for copy
mtpr $CADDR2,$TBIS
movc3 $512,CADDR1,CADDR2
mtpr r0,$IPL # restore pri level
ret
# zero out physical memory
# specified in relocation units (512 bytes)
_clearseg: .globl _clearseg
.word 0x0000
mfpr $IPL,r0 # get current pri level
mtpr $HIGH,$IPL # extreme pri level
bisl3 $PG_V|PG_KW,4(ap),_Sysmap+CMAP1
mtpr $CADDR1,$TBIS
movc5 $0,(r0),$0,$512,CADDR1
mtpr r0,$IPL # restore pri level
ret
# Check address
# given virtual address, byte count, and rw flag
# returns 0 on no access
_useracc: .globl _useracc
.word 0x0000
movl 4(ap),r0 # get va
movl 8(ap),r1 # count
tstl 12(ap) # test for read access ?
bneq userar # yes
cmpl $512,r1 # can we do it in one probe ?
bgeq uaw2 # yes
uaw1:
probew $3,$512,(r0)
beql uaerr # no access
addl2 $512,r0
acbl $513,$-512,r1,uaw1
uaw2:
probew $3,r1,(r0)
beql uaerr
movl $1,r0
ret
userar:
cmpl $512,r1
bgeq uar2
uar1:
prober $3,$512,(r0)
beql uaerr
addl2 $512,r0
acbl $513,$-512,r1,uar1
uar2:
prober $3,r1,(r0)
beql uaerr
movl $1,r0
ret
uaerr:
clrl r0
ret
# kernacc
# check for kernal access privileges
#
.globl _kernacc
_kernacc:
.word 0x0000
movl 4(ap),r0 # virtual address
bbcc $31,r0,kacc1
mfpr $SBR,r2 # address and length of page table (system)
mfpr $SLR,r3
brb kacc2
kacc1:
bbsc $30,r0,kacc3
mfpr $P0BR,r2 # user P0
mfpr $P0LR,r3
brb kacc2
kacc3:
mfpr $P1BR,r2 # user P1 (stack)
mfpr $P1LR,r3
kacc2:
addl3 8(ap),r0,r1 # ending virtual address
ashl $-9,r0,r0 # page number
ashl $-9,r1,r1
bbc $30,4(ap),kacc6
cmpl r0,r3 # user stack
blss kacerr # address too low
brb kacc4
kacc6: cmpl r1,r3 # compare last page to P0LR or SLR
bgeq kacerr # address too high
kacc4:
movl (r2)[r0],r1
bbc $31,r1,kacerr # valid bit is off
cmpzv $27,$4,r1,$1 # check protection code
bleq kacerr # no access allowed
tstb 12(ap)
bneq kacc5 # only check read access
cmpzv $27,$2,r1,$3 # check low 2 bits of prot code
beql kacerr # no write access
kacc5:
aobleq r1,r0,kacc4 # next page
movl $1,r0 # no errors
ret
kacerr:
clrl r0 # error
ret
# calculate physical address of user virtual address
_realaddr: .globl _realaddr
.word 0x0000
movl 4(ap),r0 # virtual address
blss raerr # we don't map kernal virtual addresses
bbsc $30,r0,rasseg # stack segment address
mfpr $P0BR,r1
mfpr $P0LR,r2
ashl $-9,r0,r3 # get page number
cmpl r3,r2 # valid page number?
bgeq raerr # no
ra1:
movl (r1)[r3],r4 # get page table entry
bbc $31,r4,raerr # valid bit off - error
ashl $9,r4,r5 # construct physical address
extzv $0,$9,r0,r0 # offset within page
bisl2 r5,r0 # final physical address
ret
rasseg:
mfpr $P1BR,r1
mfpr $P1LR,r2
ashl $-9,r0,r3
cmpl r3,r2
bgeq ra1
raerr:
clrl r0
ret
#
# unsigned int divide :
# (int) i = udiv( (int)dvdnd , (int) divis)
#
# unsigned int remainder :
# (int) j = urem( (int)dvdnd , (int) divis)
#
.text
.align 1
.globl _udiv
.globl _urem
#
_udiv :
.word 0 # no reg save
movl 4(ap),r0 # dividend
clrl r1
ediv 8(ap),r0,r0,r1 # quotient in r0
ret
#
.align 1
_urem :
.word 0
movl 4(ap),r0
clrl r1
ediv 8(ap),r0,r1,r0 # remainder in r0
ret
# define user area virtual address
.set physpages,1024
.set kernsize,256 # number of page table entries allocated to kernal
.globl _u
.set usize,4 # size of user area, in pages
.set _u,0x80000000 + kernsize*512
.set u_ptoffset,256*4 # offset into _Sysmap of ptentries of _u
.set CMAP1,u_ptoffset + 16*4 # offset into _Sysmap of 1st seg copy entry
.set CMAP2,CMAP1+4 # ditto 2ed entry
.set CADDR1,_u + 16*512 # virtual address of 1st copy segment
.set CADDR2,CADDR1+512 # ditto second segment
.set PHYSUBA,0x20006000 # real address of uba
.set PHYSMBA0,0x20010000 # real addr of mba 0
.set PHYSMBA1,0x20012000 # real addre of mba1
.set PHYSUMEM,0x2013e000 # real address of unibus memory
.set uba_offset,CMAP1+16*4 # offset in Sysmap of uba entries
.set umem_offset,uba_offset+16*4 # ... unibus device registers
.set mba0_offset,umem_offset+16*4 # ... massbus 0
.set mba1_offset,mba0_offset+16*4 # ... massbus 1
.set mba2_offset,mba1_offset+16*4 # ... massbus 2
.set mba3_offset,mba2_offset+16*4 # ... massbus 3
.set qsoff,0x140 # offset to 'qsav' pcb in 'u' area
.set ssoff,360 #offset to "ssav' in u_area
#
# Error messages
#
.data
emsg1:
.byte 0xa,0xa,0xa,0xd,0x54,0x52,0x41,0x50,0x20
.byte 0x46,0x52,0x4f,0x4d,0x20
.byte 0x4b,0x45,0x52,0x4e,0x41,0x4c,0x20
.byte 0x4d,0x4f,0x44,0x45,0xa,0xa,0xd,0x0
emsg2:
.byte 0xa,0xa,0xa,0xd,0x54,0x52,0x41,0x50,0x20
.byte 0x52,0x45,0x54,0x55,0x52,0x4e,0x20
.byte 0x44,0x4f,0x20
.byte 0x4b,0x45,0x52,0x4e,0x41,0x4c,0x20
.byte 0x4d,0x4f,0x44,0x45,0xa,0xa,0xd,0x0
SBImsg :
.byte 'S,'B,'I,' ,'f,'a,'u,'l,'t,' ,012,0
UBAmsg :
.byte 'U,'B,'A,' ,'e,'r,'r,'o,'r,' ,'%,'x,012,0
ZERmsg :
.byte 'Z,'e,'r,'o,' ,'V,'e,'c,'t,'o,'r,012,0
#
# _Sysmap:
# system page table
#
# structure:
# 2 pages of page table entries
# reserved for kernal text and data.
# 1 additional page of page table entries
# used in mapping the u area (16 entries),
# utility entries (16 entries),
# unibus adapter (16 entries),
# unibus device memory (16 entries),
# massbus adapter 0 (16 entries),
# massbus adapter 1 (16 entries),
# massbus adapter 2 (16 entries),
# massbus adapter 3 (16 entries).
#
#
.align 2
.globl _Sysmap
_Sysmap:
.space 3*128*4 # 3 pages of page table entries for kernal
.set Syssize,3*128 # number pt entries in sys page table