# Machine Language Assist for UC Berkeley Virtual Vax/Unix
.set HIGH,31 # mask for total disable
.set MCKVEC,4 # offset into Scbbase of machine check vector
.set UPAGES,6 # size of user area, in pages
# ====================================
# Trap vectors and C interface for Vax
# ====================================
.set INTSTK,1 # handle this interrupt on the interrupt stack
.set HALT,3 # halt if this interrupt occurs
.long Xrandom + HALT # unused
.long Xmachcheck + HALT # machine check interrupt
.long Xkspnotval + HALT # kernel 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 and pt length violation
.long Xtransflt # address translation not valid fault
.long Xtracep # trace pending
.long Xbptflt # bpt instruction
.long Xcompatflt # compatibility mode fault
.long Xarithtrap # arithmetic trap
.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 # 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
.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 Xcnrint + INTSTK # console receiver
.long Xcnxint + INTSTK # console transmitter
.long X14stray + INTSTK # stray!
.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
.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
.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
.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
# =====================================
# Produce a core image dump on mag tape
# =====================================
movl sp,dumpstack # save stack pointer
movab dumpstack,sp # reinit stack
mfpr $PCBB,-(sp) # save u-area pointer
mfpr $MAPEN,-(sp) # save value
mtpr $0,$MAPEN # turn off memory mapping
mtpr $HIGH,$IPL # disable interrupts
pushr $0x3fff # save regs 0 - 13
calls $0,_dump # produce dump
.space 58*4 # separate stack for tape dumps
# Debugging print switches given here so they won't move around
# =============================
# I/O interrupt vector routines
# =============================
.set PHYSUBA,0x20006000 # uba 0
.set PHYSMBA0,0x20010000 # mba 0
.set PHYSMBA1,0x20012000 # mba 1
.set PHYSUMEM,0x2013e000 # unibus memory
# Catch random or unexpected interrupts
# Massbus 0 adapter interrupts
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
pushl MBA_SR(r0) # pass sr 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
pushr $0x3f # save regs 0-5
mfpr $IPL,r2 # get br level
movl UBA0+UBR_OFF-20*4[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. Get the service routine
# address and controller code from the UNIBUS vector area
# and service the interrupt.
extzv $27,$4,r1,r0 # controller code is in 4 most
# significant bits-1 of ISR addr
bicl2 $0x78000000,r1 # clear code
jlbc r1,ubanpdma # no pseudo dma here
jmp -1(r1) # branch to pseudo dma rtn
pushl r0 # controller code
brw int_ret # go to common interrupt return
# Come here for zero or negative UBA interrupt vector.
# Negative vector -> UBA requires service.
# The following 'printf' calls should probably be replaced
# with calls to an error logger and/or some corrective action.
bitl $CFGFLT,UBA0+UCN_OFF # any SBI faults ?
pushr $0xf # save regs 0-3
# No SBI fault bits set in UBA config reg - must be
# some error bits set in UBA status reg.
movl UBA0+UST_OFF,r2 # UBA status reg
pushr $0xf # save regs 0-3
movl r2,UBA0+UST_OFF # clear error bits
bicl2 $0x80000000,r3 # clear neg bit in vector
jneq ubanorm # branch if normal UBA interrupt
brw int_ret # restore regs and return
# Zero interrupt vector - print message & continue
# WE GET SO MANY OF THESE THAT WE ONLY COUNT THEM
# bisw2 $4,*_draddr # leading edge for dr11-c
movab _dzpdma(r0),r3 # pdma structure base
movl (r0)+,r1 # device register address
movzbl 1(r1),r2 # get line number
bicb2 $0xf8,r2 # clear garbage bits
addl2 r2,r0 # point at line's pdma structure
cmpl r2,(r0)+ # p_mem < p_end ?
bgequ dzpcall # no, go call dzxint
movb (r2)+,6(r1) # dztbuf = *p_mem++
brb dzploop # check for another line
# bicw2 $4,*_draddr # trailing edge for dr11-c
pushl (r0) # push tty address
calls $1,_dzxint # call interrupt rtn
brb dzploop # check for another line
# Console receiver interrupt
pushr $0x3f # save registers 0 - 5
# Console transmit interrupt
pushr $0x3f # save registers 0 - 5
pushr $0x3f # save regs 0 - 5
pushl 4+6*4(sp) # push psl
pushl 4+6*4(sp) # push pc
# Common code for interrupts.
# At this point, the interrupt stack looks like:
bbssi $0,idleflag,int_r0 # set idle escape flag (no wait instr)
popr $0x3f # restore regs 0 - 5
bitl $PSL_CURMOD,4(sp) # interrupt from user mode?
beql int_r1 # no, from kernel, 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 kernel mode, switch stacks, and format
# kernel stack for a `qswitch' trap to force a reschedule.
mtpr $3,$SIRR # request level 1 software interrupt
rei # return to interrupted process
# ==================================
# User area virtual addresses
# ==================================
.set kernsize,512 # number of pte's allocated to kernel
.set _u,0x80000000 + kernsize*NBPG
.set _umbabeg,_utilutl+16*NBPG
.set _umbaend,_umbabeg+6*16*NBPG
.set _swaputl,_u+128*NBPG
.set _forkutl,_swaputl+UPAGES*NBPG
.set _xswaputl,_forkutl+UPAGES*NBPG
.set _xswap2utl,_xswaputl+UPAGES*NBPG
.set _pushutl,_xswap2utl+UPAGES*NBPG
.set _vfutl,_pushutl+UPAGES*NBPG
.set _usrpt,_vfutl+UPAGES*NBPG
.set u_ptoffset,kernsize*4 # offset in _Sysmap of pte's of _u
.set CMAP1,u_ptoffset+16*4 # offset in _sysmap of 1st copyseg entry
.set CMAP2,CMAP1+4 # ... of 2nd copyseg entry
.set CADDR1,_u+16*NBPG # virtual address of 1st copy segment
.set CADDR2,CADDR1+NBPG # ... of second copy segment
.set uba_offset,u_ptoffset+32*4 # ... of uba entries
.set umem_offset,uba_offset+16*4 # ... of unibus device registers
.set mba0_offset,umem_offset+16*4 # ... of massbus 0
.set mba1_offset,mba0_offset+16*4 # ... of massbus 1
.set mba2_offset,mba1_offset+16*4 # ... of massbus 2
.set mba3_offset,mba2_offset+16*4 # ... of massbus 3
# ==========================
# Sysmap - system page table
# ==========================
# 4 pages of page table entries
# reserved for kernel text and data.
# 1 page to map u area and other utilities
# 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).
# used for phys & swap I/O
# 6*4 entries for various other utilities
# 4 pages to map user page tables of resident processes
.space 4*128*4 # four pages of pte's for kernel
.space 16*4 # u-area (could be just 6*4)
.space 16*4*7 # utility area & others
.space UPAGES*4 # swap utility area
.space UPAGES*4 # fork area
.space UPAGES*4 # xswap area
.space UPAGES*4 # xswap2 area
.space UPAGES*4 # pageout daemon utility
.space UPAGES*4 # vfork utility
.space 8*128*4 # user page table area
.set Syssize,13*128+6*UPAGES # number pt entries in sys page table
.set _mmap,_Sysmap+CMAP2+4
.set _mcrmap,_Sysmap+CMAP2+8
.set _mcr,CADDR2+(2*NBPG)
# ==============================
# Trap and fault vector routines
# ==============================
# Reschedule trap (Software level 3 interrupt)
# Privileged instruction fault
pushl $0 # push dummy code
pushl $PRIVINFLT # push type
pushl $0 # push dummy code value
pushl $XFCFLT # push type value
pushl $0 # push dummy code value
pushl $RESOPFLT # push type value
# Reserved addressing mode fault
pushl $0 # push dummy code value
pushl $RESADFLT # push type value
brw alltraps # merge with common code
pushl $0 # push dummy code value
pushl $BPTFLT # push type value
brw alltraps # merge with common code
# Compatibility mode fault
pushl $COMPATFLT # push type value
brw alltraps # merge with common code
pushl $0 # push dummy code value
pushl $TRCTRAP # push type value
pushl $ARITHTRAP # push type value
brw alltraps # merge with common code
# Protection and segmentation fault
blbs (sp),segflt # check for pt length violation
addl2 $4,sp # pop fault param word
# Translation Not Valid Fault
bbs $1,(sp),tableflt # check for page table fault
addl2 $4,sp # pop fault parameter word
pushl $PAGEFLT # push type value
bbs $31,4(sp),alltraps # is faulting address in kernel
brb usrtraps # page faults in user space
# even in kernel mode are ok
addl2 $4,sp # pop fault parameter word
pushl $TABLEFLT # push type value
cmpl _end,4(sp) # cannot tolerate sysmap faults
brb usrtraps # a table fault on a user page
# table in kernel mode is ok
# CHMK trap (syscall trap)
# Stack (parameters) at calls to _trap:
pushl $SYSCALL # push type value
bitl $PSL_CURMOD,12(sp) # from user mode?
# 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.
popr $0x3fff # restore regs 0 - 13
mtpr (sp)+,$USP # restore usp
addl2 $8,sp # pop type, code
mtpr $HIGH,$IPL # make sure we are not going to
# ``Trap from kernel mode'' -- one special case here is to ignore
# RESCHED traps which happen in the kernel... these happen only
# when a clock interrupt occured before the RESCHED AST could
# be delivered, and the clock interrupt lowered the ipl, usually
# because the addupc() in clock page faulted because the running
# process was profiling. In this case we are context switching
# away from the current process anyways, so ignoring the RESCHED
# trap is the right thing to do.
cmpl (sp),$RESCHED # spurious RESCHED traps from kernel
beql ignresch # ... can be ignored
movab emsg1,eptr # set message pointer
brb err_print # print message and halt
# print message on console and die
# message pointed to by eptr, terminated by zero byte.
mtpr $HIGH,$IPL # disable all interrupts
mtpr $0,$TXCS # dis. interrupts on cons. xmtr.
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
mtpr ewk1,$TXDB # give byte to transmitter
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 adapters.
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
tstl (r7) # this chunk really there?
acbl $8096*1024-1,$64*1024,r7,startlp # loop till mach check
brb startint # full load of memory
mtpr $0,$SBIFS # clear sbi fault status
movl r5,Scbbase+MCKVEC # restore machine check vector
movl $_intstack+2048,sp # reset interrupt stack pointer
# calculate size of cmap[] based on available memory, and allocate space for it
divl2 $(NBPG*CLSIZE)+CMSIZE,r1
# Clear memory starting with kernel bss
movab _ecmap,r5 # clear to end of cmap[]
# Initialize system page table
movab _etext+NBPG-1,r1 # end of kernel text segment
bbcc $31,r1,strt1 # turn off high order bit
ashl $-9,r1,r1 # last page of kernel text
clrl r2 # point at first kernel text page
bisl3 $PG_V|PG_KR,r2,_Sysmap[r2] # initialize page table entry
aoblss r1,r2,strtlp1 # fill text entries
addl3 _ecmap,$NBPG-1,r1 # end of cmap[]
bbcc $31,r1,strt2 # turn off high order bit
ashl $-9,r1,r1 # last page of kernel data
bisl3 $PG_V|PG_KW,r2,_Sysmap[r2] # fill data entries
# initialize memory controller mapping
movab _Sysmap+mcr_offset,r2
bisl3 $PG_V|PG_KW,r1,(r2)
# Initialize I/O space page table entries
movl $PHYSUBA/NBPG,r1 # page frame number for uba
movab _Sysmap+uba_offset,r2 # page table address
movab 15(r1),r3 # last pt entry
bisl3 $PG_V|PG_KW,r1,(r2)+ # init pt entry
movab _Sysmap+umem_offset,r2 # page table address
bisl3 $PG_V|PG_KW,r1,(r2)+
movab _Sysmap+mba0_offset,r2
bisl3 $PG_V|PG_KW,r1,(r2)+
movab _Sysmap+mba1_offset,r2
bisl3 $PG_V|PG_KW,r1,(r2)+
mtpr $1,$TBIA # invalidate all trans buffer entries
mtpr $1,$MAPEN # turn on memory mapping
jmp *$startmap # put system virtual address in pc
# Now we move forward, virtually.
ashl $-9,r7,_maxmem # set maxmem = btoc(r7)
# Setup context for proc[0] == Scheduler
# Address first page past _ecmap.
# This will be u area for proc[0].
# Initialize u area page table entries.
# Initialize (slightly) the pcb.
bicl2 $NBPG-1,r6 # make page boundary
# set up u area page table
ashl $-9,r6,r3 # r3 = btoc(r6)
bisl3 $PG_V|PG_KW,r3,_Sysmap+u_ptoffset # init first upt entry
movab _u,r1 # point at _u area
movab UPAGES*NBPG(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
# The shape of the following computation is historical...
# P0BR and P1BR should CLSIZE*NBPG bytes apart,
# otherwise their values are irrelevant.
movab _u+UPAGES*NBPG,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+(UPAGES+CLSIZE)*NBPG-0x800000,PCB_P1BR(r1) # p1 pt pointer
movl $0x200000,PCB_P1LR(r1) # invalid p1 pt length
movl $CLSIZE,PCB_SZPT(r1) # init u.u_pcb.pcb_szpt
bisl3 $PG_V|PG_KW,r3,_Sysmap+u_ptoffset[r2]
mtpr r6,$PCBB # first pcb
# set regs, p0br, p0lr, p1br, p1lr,
# astlvl, ksp, and change to kernel mode
addl2 $8,sp # pop dummy pc, psl
mtpr $0,$IPL # enable interrupts
addl3 _ecmap,$NBPG-1,r0 # calculate firstaddr
ashl $-9,r0,-(sp) # convert to clicks and stack
calls $1,_main # startup, fork off /etc/init.vm
# 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
movl 8(ap),r2 # &u.u_prof
subl3 8(r2),4(ap),r0 # corrected pc
extzv $1,$31,r0,r0 # logical right shift
extzv $1,$31,12(r2),r1 # ditto for scale
_fuibyte: .globl _fuibyte
prober $3,$1,*4(ap) # byte accessible ?
_suibyte: .globl _suibyte
probew $3,$1,*4(ap) # byte accessible ?
_fuiword: .globl _fuiword
_suiword: .globl _suiword
mnegl $1,r0 # error return
movl 12(ap),r0 # copy length
movl 4(ap),r1 # copy user address
cmpl $NBPG,r0 # probing one page or less ?
prober $3,$NBPG,(r1) # bytes accessible ?
addl2 $NBPG,r1 # incr user address ptr
acbl $NBPG+1,$-NBPG,r0,ciloop # reduce count and loop
prober $3,r0,(r1) # bytes accessible ?
movc3 12(ap),*4(ap),*8(ap)
_copyout: .globl _copyout
movl 12(ap),r0 # get count
movl 8(ap),r1 # get user address
cmpl $NBPG,r0 # can do in one probew?
probew $3,$NBPG,(r1) # bytes accessible?
addl2 $NBPG,r1 # increment user address
acbl $NBPG+1,$-NBPG,r0,coloop # reduce count and loop
probew $3,r0,(r1) # bytes accessible?
movc3 12(ap),*4(ap),*8(ap)
mtpr $0,$IPL # enable interrupts
blbc idleflag,waitloc # loop until interrupt
bbcci $0,idleflag,idle1 # clear idle escape flag
_ewaitloc: .long ewaitloc
# Save reg's and ret loc into save area - return 0.
# The contents of CMAP2 will be saved in the soft pcb extension.
movl _Sysmap+CMAP2,_u+PCB_CMAP2 # save copyseg mapping
movl 4(ap),r0 # save area addr
movab 3*4(ap),sp # restore stack to val before call
movl 8(fp),ap # restore ap " " "
movl 16(fp),r1 # restore pc " " "
movl 12(fp),fp # restore fp " " "
movl r1,(r0)+ # ret loc of call to 'save'
svpctx # save reg's -> PCB
movpsl -(sp) # set up for return
bicl2 $PSL_IS|PSL_IPL,(sp) # undo SVPCTX
# resume(proc_addr, save_addr)
# Switch to another process's '_u' area - return val 1
# restores CMAP2 contents from from software pcb
mtpr $HIGH,$IPL # inhibit interrupts
res1: cvtwl (r2)[r0],r3 # get u click number from proc
bisl3 $PG_V|PG_KW,r3,_Umap[r0]
# restore CMAP2 contents for copyseg
movl _u+PCB_CMAP2,_Sysmap+CMAP2
movl _u,sp # KSP from u-area
ashl $9,_Umap,r5 # pcb address
addl2 $8,sp # clear ps,pc from stack
movl retloc,r1 # 'ssav' or 'qsav' addr
jmp *(r1)+ # return to caller at 'save' address
mfpr $IPL,r0 # get IPL value
mtpr $2,$IPL # disable RESCHED & AST interrupts
mtpr $0x14,$IPL # disable bus level 4 interrupts
mtpr $0x15,$IPL # disable bus level 5 interrupts
mtpr $0x18,$IPL # disable bus level 7 and clock ints
# restore interrupt state
# Copy 1 relocation unit (NBPG bytes)
# from user virtual address to physical address
_copyseg: .globl _copyseg
mfpr $IPL,r0 # get current pri level
mtpr $HIGH,$IPL # turn off interrupts
bisl3 $PG_V|PG_KW,8(ap),_Sysmap+CMAP2
mtpr $CADDR2,$TBIS # invalidate entry for copy
movc3 $NBPG,*4(ap),CADDR2
bicl3 $PG_V|PG_M|PG_KW,_Sysmap+CMAP2,r1
mtpr r0,$IPL # restore pri level
# zero out physical memory
# specified in relocation units (NBPG bytes)
_clearseg: .globl _clearseg
mfpr $IPL,r0 # get current pri level
mtpr $HIGH,$IPL # extreme pri level
bisl3 $PG_V|PG_KW,4(ap),_Sysmap+CMAP1
movc5 $0,(sp),$0,$NBPG,CADDR1
mtpr r0,$IPL # restore pri level
# Given virtual address, byte count, and rw flag
# returns 0 on no access.
_useracc: .globl _useracc
tstl 12(ap) # test for read access ?
cmpl $NBPG,r1 # can we do it in one probe ?
acbl $NBPG+1,$-NBPG,r1,uaw1
acbl $NBPG+1,$-NBPG,r1,uar1
# kernacc - check for kernel access privileges
# We can't use the probe instruction directly because
# it ors together current and previous mode.
movl 4(ap),r0 # virtual address
mfpr $SBR,r2 # address and length of page table (system)
mfpr $P1BR,r2 # user P1 (stack)
addl3 8(ap),r0,r1 # ending virtual address
ashl $-9,r0,r0 # page number
blss kacerr # address too low
cmpl r1,r3 # compare last page to P0LR or SLR
bgeq kacerr # address too high
bbc $31,r3,kacerr # valid bit is off
cmpzv $27,$4,r3,$1 # check protection code
bleq kacerr # no access allowed
bneq kacc5 # only check read access
cmpzv $27,$2,r3,$3 # check low 2 bits of prot code
beql kacerr # no write access
aobleq r1,r0,kacc4 # next page
# (int) i = udiv( (int)dvdnd , (int) divis)
# unsigned int remainder:
# (int) j = urem( (int)dvdnd , (int) divis)
ediv 8(ap),r0,r0,r1 # quotient in r0
# ediv 8(ap),r0,r1,r0 # remainder in r0
emsg1: .asciz "\nTrap from kernel mode\n\r"
SBImsg: .asciz "SBI fault\n"
UBAmsg: .asciz "UBA error UBASR %X, FMER %X, FUBAR %X\n"
ZERmsg: .asciz "Zero vector\n"
straym: .asciz "Stray interrupt\n"
# these should be memall'ed
_buffers: .space NBUF*BSIZE