asm(".set U_QSAVE,-1881318947");
* This has to get loaded first (physical 0) as 780 memory restart rom
* only looks for rpb on a 64K page boundary (doc isn't wrong,
* it never says what size "page boundary" rpb has to be on).
.set INTSTK
,1 # handle this interrupt on the interrupt stack
.set HALT
,3 # halt if this interrupt occurs
#define STRAY .long _Xstray+INTSTK
#define STRAY8 STRAY;STRAY;STRAY;STRAY;STRAY;STRAY;STRAY;STRAY
#define STRAY15 STRAY;STRAY;STRAY;STRAY;STRAY;STRAY;STRAY;STRAY8
#define KS(a) .long _X/**/a
#define IS(a) .long _X/**/a+INTSTK
#define STOP(a) .long _X/**/a+HALT
/* 000 */ STRAY
; IS(machcheck
); IS(kspnotval
); STOP(powfail
);
/* 010 */ KS(privinflt
); KS(xfcflt
); KS(resopflt
); KS(resadflt
);
/* 020 */ KS(protflt
); KS(transflt
); KS(tracep
); KS(bptflt
);
/* 030 */ KS(compatflt
); KS(arithtrap
); STRAY
; STRAY
;
/* 040 */ KS(syscall
); KS(chme
); KS(chms
); KS(chmu
);
/* 050 */ STRAY
; IS(cmrd
); STRAY
; STRAY
;
/* 060 */ IS(wtime
); STRAY
; STRAY
; STRAY
;
/* 070 */ STRAY
; STRAY
; STRAY
; STRAY
;
/* 080 */ STRAY
; STRAY
; KS(astflt
); STRAY
;
/* 090 */ STRAY
; STRAY
; STRAY
; STRAY
;
/* 0a0 */ IS(softclock
); STRAY
; STRAY
; STRAY
;
/* 0b0 */ IS(netintr
); STRAY
; STRAY
; STRAY
;
/* 0c0 */ IS(hardclock
); STRAY
; STRAY
; STRAY
;
/* 0d0 */ STRAY
; STRAY
; STRAY
; STRAY
;
/* 0e0 */ STRAY
; STRAY
; STRAY
; STRAY
;
/* 0f0 */ IS(consdin
); IS(consdout
); IS(cnrint
); IS(cnxint
);
/* 100 */ IS(nexzvec
); STRAY15
; /* ipl 0x14, nexus 0-15 */
/* 140 */ IS(nexzvec
); STRAY15
; /* ipl 0x15, nexus 0-15 */
/* 180 */ IS(nexzvec
); STRAY15
; /* ipl 0x16, nexus 0-15 */
/* 1c0 */ IS(nexzvec
); STRAY15
; /* ipl 0x17, nexus 0-15 */
_UNIvec
: .space
512 # 750 unibus intr vector
# 1st UBA jump table on 780's
_UNI1vec: .space 512 # 750 second unibus intr vector
# 2nd UBA jump table on 780's
/* locore.s 6.3 83/08/12 */
#include "../machine/psl.h"
#include "../machine/pte.h"
#include "../vax/nexus.h"
#include "../vax/clock.h"
#include "../vaxuba/ubareg.h"
.set HIGH
,0x1f # mask for total disable
.set MCKVEC
,4 # offset into scb of machine check vector
.set NISP
,3 # number of interrupt stack pages
* User structure is UPAGES at top of user space.
.set _u
,0x80000000 - UPAGES
*NBPG
* Called by auto-restart.
* May be called manually.
#define _rpbmap _Sysmap # rpb, scb, UNI*vec, istack*4
tstl _rpb
+RP_FLAG
# dump only once!
* Interrupt vector routines
#define SCBVEC(name) .align 2; .globl _X/**/name; _X/**/name
#define PANIC(msg) clrl _waittime; pushab 1f; \
calls $1,_panic; 1: .asciz msg
#define PRINTF(n,msg) pushab 1f; calls $n+1,_printf; MSG(msg)
#define MSG(msg) .data; 1: .asciz msg; .text
#define PUSHR pushr $0x3f
PUSHR
; pushab
6*4(sp
); calls $
1,_machinecheck
; POPR
;
PUSHR
; PANIC("KSP not valid");
SCBVEC(chme
): SCBVEC(chms
): SCBVEC(chmu
):
PUSHR
; PANIC("CHM? in kernel");
PUSHR
; PRINTF(0, "stray scb interrupt\n"); POPR
;
PUSHR
; mfpr $IPL
,-(sp
); PRINTF(1, "nexus stray intr ipl%x\n"); POPR
; rei
PUSHR
; calls $
0,_memerr
; POPR
; rei
PUSHR
; pushl
6*4(sp
); PRINTF(1,"write timeout %x\n"); POPR
;
* Registers for the uba handling code
PUSHR
; movl $
3,rUBANUM
; moval _uba_hd
+(3*UH_SIZE
),rUBAHD
; brb
1f
PUSHR
; movl $
2,rUBANUM
; moval _uba_hd
+(2*UH_SIZE
),rUBAHD
; brb
1f
PUSHR
; movl $
1,rUBANUM
; moval _uba_hd
+(1*UH_SIZE
),rUBAHD
; brb
1f
PUSHR
; movl $
0,rUBANUM
; moval _uba_hd
+(0*UH_SIZE
),rUBAHD
;
mfpr $IPL
,r2
/* r2 = mfpr(IPL); */
movl
UH_UBA(rUBAHD
),rUBA
/* uba = uhp->uh_uba; */
movl UBA_BRRVR
-0x14*4(rUBA
)[r2
],rUVEC
/* uvec = uba->uba_brrvr[r2-0x14] */
addl2
UH_VEC(rUBAHD
),rUVEC
/* uvec += uh->uh_vec */
jmp
2(r1
) /* 2 skips ``pushr $0x3f'' */
PUSHR
; calls $
0,_ubaerror
; POPR
/* ubaerror r/w's r0-r5 */
tstl rUVEC
; jneq ubanorm
/* rUVEC contains result */
PUSHR
; calls $
0,_cnrint
; POPR
; incl _cnt
+V_INTR
; rei
PUSHR
; calls $
0,_cnxint
; POPR
; incl _cnt
+V_INTR
; rei
mtpr $ICCS_RUN
|ICCS_IE
|ICCS_INT
|ICCS_ERR
,$ICCS
pushl
4+6*4(sp
); pushl
4+6*4(sp
);
calls $
2,_hardclock
# hardclock(pc,psl)
pushl
4+6*4(sp
); pushl
4+6*4(sp
);
incl _cnt
+V_INTR
## temp so not to break vmstat -= HZ
pushl
4+6*4(sp
); pushl
4+6*4(sp
);
calls $
2,_softclock
# softclock(pc,psl)
#include "../net/netisr.h"
bbcc $NETISR_RAW
,_netisr
,1f
; calls $
0,_rawintr
; 1:
#include "../netinet/in_systm.h"
bbcc $NETISR_IP
,_netisr
,1f
; calls $
0,_ipintr
; 1:
bbcc $NETISR_NS
,_netisr
,1f
; calls $
0,_nsintr
; 1:
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) && !defined(VAX730) && !defined(MRSP)
PUSHR
; calls $
0,_tuxintr
; POPR
; incl _cnt
+V_INTR
; rei
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
pushl (r0)+ # push tty address
calls $1,*(r0) # call interrupt rtn
brb dzploop # check for another line
#if NUU > 0 && defined(UUDMA)
* Pseudo DMA routine for tu58 (on DL11)
movl 16(r2),r2 # r2 = uuaddr
movab _uu_softc(r3),r5 # r5 = uuc
cvtwl 2(r2),r1 # c = uuaddr->rdb
bbc $15,r1,1f # if (c & UUDB_ERROR)
movl $13,16(r5) # uuc->tu_state = TUC_RCVERR;
rsb # let uurintr handle it
tstl 4(r5) # if (uuc->tu_rcnt) {
movb r1,*0(r5) # *uuc->tu_rbptr++ = r1
decl 4(r5) # if (--uuc->tu_rcnt)
POPR # registers saved in ubglue.s
cmpl 16(r5),$8 # if (uuc->tu_state != TUS_GETH)
beql 2f # let uurintr handle it
mull2 $14,r0 # sizeof(uudata[ctlr]) = 14
movab _uudata(r0),r4 # data = &uudata[ctlr];
cmpb $1,(r4) # if (data->pk_flag != TUF_DATA)
/* this is for command packets */
beql 1f # r0 = uuc->tu_rbptr
movl 24(r5),r0 # r0 = uuc->tu_addr
movzbl 1(r4),r3 # counter to r3 (data->pk_count)
movzwl (r4),r1 # first word of checksum (=header)
mfpr $IPL,-(sp) # s = spl5();
mtpr $0x15,$IPL # to keep disk interrupts out
clrw (r2) # disable receiver interrupts
3: bbc $7,(r2),3b # while ((uuaddr->rcs & UUCS_READY)==0);
cvtwb 2(r2),(r0)+ # *buffer = uuaddr->rdb & 0xff
sobgtr r3,1f # continue with next byte ...
addw2 2(r2),r1 # unless this was the last (odd count)
1: bbc $7,(r2),1b # while ((uuaddr->rcs & UUCS_READY)==0);
cvtwb 2(r2),(r0)+ # *buffer = uuaddr->rdb & 0xff
addw2 -2(r0),r1 # add to checksum..
adwc $0,r1 # get the carry
sobgtr r3,3b # loop while r3 > 0
* We're ready to get the checksum
1: bbc $
7,(r2
),1b
# while ((uuaddr->rcs & UUCS_READY)==0);
cvtwb
2(r2
),12(r4
) # get first (lower) byte
cvtwb
2(r2
),13(r4
) # ..and second
cmpw
12(r4
),r1
# is checksum ok?
movl $
14,16(r5
) # uuc->tu_state = TUS_CHKERR
movl $
11,16(r5
) # uuc->tu_state = TUS_GET (ok)
movw $
0x40,(r2
) # enable receiver interrupts
mtpr (sp
)+,$IPL
# splx(s);
rsb
# continue processing in uurintr
#if defined(VAX750) && !defined(VAX730) && !defined(MRSP)
* Pseudo DMA routine for VAX-11/750 console tu58
tstl
4(r5
) # if (tu.tu_rcnt) {
mfpr $CSRD
,r1
# get data from tu58
movb r1
,*0(r5
) # *tu.tu_rbptr++ = r1
decl
4(r5
) # if (--tu.tu_rcnt)
POPR
# registers saved in ubglue.s
cmpl
16(r5
),$
8 # if (tu.tu_state != TUS_GETH)
beql
2f
# let turintr handle it
movab _tudata
,r4
# r4 = tudata
cmpb $
1,(r4
) # if (tudata.pk_flag != TUF_DATA)
bneq
3b
# let turintr handle it
movl
24(r5
),r1
# get buffer pointer to r1
movzbl
1(r4
),r3
# counter to r3
movzwl (r4
),r0
# first word of checksum (=header)
mtpr $
0,$CSRS
# disable receiver interrupts
bsbw
5f
# wait for next byte
movb r5
,(r1
)+ # *buffer = rdb
sobgtr r3
,1f
# continue with next byte ...
mfpr $CSRD
,r2
# unless this was the last (odd count)
1: bsbw
5f
# wait for next byte
movb r5
,(r1
)+ # *buffer = rdb
movzwl
-2(r1
),r2
# get the last word back from memory
addw2 r2
,r0
# add to checksum..
adwc $
0,r0
# get the carry
sobgtr r3
,3b
# loop while r3 > 0
* We're ready to get the checksum.
movb r5
,12(r4
) # get first (lower) byte
movb r5
,13(r4
) # ..and second
cmpw
12(r4
),r0
# is checksum ok?
movl $
14,16(r5
) # tu.tu_state = TUS_CHKERR
movl $
11,16(r5
) # tu.tu_state = TUS_GET
mtpr $
0x40,$CSRS
# enable receiver interrupts
rsb
# continue processing in turintr
* Loop until a new byte is ready from
* the tu58, make sure we don't loop forever
movl $
5000,r5
# loop max 5000 times
movl $
13,16(r5
) # return TUS_RCVERR
tstl (sp
)+ # and let turintr handle it
* Stray UNIBUS interrupt catch routines
#define PJ PUSHR;jsb _Xustray
PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
;PJ
subl3 $_catcher
+8,(sp
)+,r10
subl3 $_catcher
+8,(sp
)+,r0
PRINTF(2, "uba?: stray intr ipl %x vec %o\n")
* Trap and fault vector routines
#define TRAP(a) pushl $T_/**/a; jbr alltraps
* Ast delivery (profiling and/or reschedule)
pushl $
0; TRAP(PRIVINFLT
)
jsb Fastreclaim
# try and avoid pagein
mfpr $USP
,-(sp
); calls $
0,_trap
; mtpr (sp
)+,$USP
addl2 $
8,sp
# pop type, code
mtpr $HIGH
,$IPL
## dont go to a higher IPL (GROT)
mfpr $USP
,-(sp
); calls $
0,_syscall
; mtpr (sp
)+,$USP
addl2 $
8,sp
# pop type, code
mtpr $HIGH
,$IPL
## dont go to a higher IPL (GROT)
#define vaddr(x) ((((x)-_Sysmap)/4)*NBPG+0x80000000)
#define SYSMAP(mname, vname, npte) \
_/**/mname: .globl _/**/mname; \
.set _/**/vname,vaddr(_/**/mname)
SYSMAP(Sysmap
,Sysbase
,SYSPTSIZE
)
SYSMAP(UMBAbeg
,umbabeg
,0 )
SYSMAP(Nexmap
,nexus
,16*MAXNNEXUS
)
SYSMAP(UMEMmap
,umem
,512*MAXNUBA
)
SYSMAP(UMBAend
,umbaend
,0 )
SYSMAP(Usrptmap
,usrpt
,USRPTSIZE
)
SYSMAP(Forkmap
,forkutl
,UPAGES
)
SYSMAP(Xswapmap
,xswaputl
,UPAGES
)
SYSMAP(Xswap2map
,xswap2utl
,UPAGES
)
SYSMAP(Swapmap
,swaputl
,UPAGES
)
SYSMAP(Pushmap
,pushutl
,UPAGES
)
SYSMAP(Vfmap
,vfutl
,UPAGES
)
SYSMAP(CMAP1
,CADDR1
,1 )
SYSMAP(CMAP2
,CADDR2
,1 )
SYSMAP(msgbufmap
,msgbuf
,MSGBUFPTECNT
)
SYSMAP(camap
,cabase
,16*CLSIZE
)
SYSMAP(ecamap
,calimit
,0 )
SYSMAP(Mbmap
,mbutl
,NMBCLUSTERS
*CLSIZE
)
.set _Syssize
,(eSysmap
-_Sysmap
)/4
* ipl 0x1f; mapen 0; scbb, pcbb, sbr, slr, isp, ksp not set
/* set system control block base and system page table params */
mtpr $_scb
-0x80000000,$SCBB
mtpr $_Sysmap
-0x80000000,$SBR
/* double map the kernel into the virtual user addresses of phys mem */
/* set ISP and get cpu type */
movl $_intstack
+NISP
*NBPG
,sp
movl r0
,(r0
)+ # rp_selfref
movl r1
,(r0
)+ # rp_dumprout
1: addl2 (r1
)+,r3
; sobgtr r2
,1b
movl r3
,(r0
)+ # rp_chksum
1: pushl $
4; pushl r7
; calls $
2,_badaddr
; tstl r0
; bneq
9f
acbl $
8192*1024-1,$
64*1024,r7
,1b
/* clear memory from kernel bss and pages for proc 0 u. and page table */
addl2 $
(UPAGES
*NBPG
)+NBPG
+NBPG
,r5
1: clrq (r6
); acbl r5
,$
8,r6
,1b
/* trap() and syscall() save r0-r11 in the entry mask (per ../h/reg.h) */
/* initialize system page table: scb and int stack writeable */
movab eintstack
,r1
; bbcc $
31,r1
,0f
; 0: ashl $
-PGSHIFT
,r1
,r1
1: bisl3 $PG_V
|PG_KW
,r2
,_Sysmap
[r2
]; aoblss r1
,r2
,1b
/* make rpb read-only as red zone for interrupt stack */
/* make kernel text space read-only */
movab _etext
+NBPG
-1,r1
; bbcc $
31,r1
,0f
; 0: ashl $
-PGSHIFT
,r1
,r1
1: bisl3 $PG_V
|PG_KR
,r2
,_Sysmap
[r2
]; aoblss r1
,r2
,1b
/* make kernel data, bss, read-write */
movab _end
+NBPG
-1,r1
; bbcc $
31,r1
,0f
; 0:; ashl $
-PGSHIFT
,r1
,r1
1: bisl3 $PG_V
|PG_KW
,r2
,_Sysmap
[r2
]; aoblss r1
,r2
,1b
/* now go to mapped mode */
mtpr $
1,$TBIA
; mtpr $
1,$MAPEN
; jmp
*$
0f
; 0:
ashl $
-PGSHIFT
,r7
,_maxmem
/* setup context for proc[0] == Scheduler */
bicl2 $NBPG
-1,r6
# make page boundary
/* setup page table for proc[0] */
ashl $
-PGSHIFT
,r6
,r3
# r3 = btoc(r6)
bisl3 $PG_V
|PG_KW
,r3
,_Usrptmap
# init first upt entry
moval
-4*UPAGES(r0
)[r1
],r2
/* setup mapping for UPAGES of _u */
movl $UPAGES
,r2
; movab _u
+NBPG
*UPAGES
,r1
; addl2 $UPAGES
,r3
; jbr
2f
bisl3 $PG_V
|PG_URKW
,r3
,-(r0
)
/* initialize (slightly) the pcb */
movab UPAGES
*NBPG(r1
),PCB_KSP(r1
)
movb $
4,PCB_P0LR
+3(r1
) # disable ast
movl $CLSIZE
,PCB_SZPT(r1
) # init u.u_pcb.pcb_szpt
movab
1f
,PCB_PC(r1
) # initial pc
clrl
PCB_PSL(r1
) # mode(k,k), ipl=0
mtpr r3
,$PCBB
# first pcbb
/* set regs, p0br, p0lr, p1br, p1lr, astlvl, ksp and change to kernel mode */
/* put signal trampoline code in u. area */
movc3 $
16,sigcode
,PCB_SIGC(r0
)
/* save reboot flags in global _boothowto */
/* calculate firstaddr, and call main() */
movab _end
+NBPG
-1,r0
; bbcc $
31,r0
,0f
; 0:; ashl $
-PGSHIFT
,r0
,-(sp
)
addl2 $UPAGES
+1,(sp
); calls $
1,_main
/* proc[1] == /etc/init now running here; run icode */
pushl $PSL_CURMOD
|PSL_PRVMOD
; pushl $
0; rei
/* signal trampoline code: it is known that this code takes exactly 16 bytes */
/* in ../vax/pcb.h and in the movc3 above */
calls $
4,5(pc
) # params pushed by sendsig
chmk $
139 # cleanup mask and onsigstack
.word
0x7f # registers 0-6 (6==sp/compat)
* see if access addr with a len type instruction causes a machine check
* len is length of access (1=byte, 2=short, 4=long)
movab
9f
+INTSTK
,_scb
+MCKVEC
1: bbc $
1,r4
,1f
; tstw (r3
)
1: bbc $
2,r4
,1f
; tstl (r3
)
1: clrl r0
# made it w/o machine checks
#if defined(VAX750) || defined(VAX730)
addl2 (sp
)+,sp
# discard mchchk trash
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
_Copyin
: .globl _Copyin
# <<<massaged for jsb by asm.sed>>>
movl
12(sp
),r0
# copy length
movl
4(sp
),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 ?
_Copyout
: .globl _Copyout
# <<<massaged for jsb by asm.sed >>>
movl
12(sp
),r0
# get count
movl
8(sp
),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?
cmpl r1
,sp
# must be a pop
* 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
* 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">>>
tstl
P_RLINK(r0
) ## firewall: p->p_rlink must be 0
movzbl
P_PRI(r0
),r1
# put on queue which is p->p_pri / 4
insque (r0
),*4(r2
) # at end of queue
bbss r1
,_whichqs
,set2
# mark queue non-empty
* Remrq(p), using fancy VAX instructions
* Call should be made at spl6().
.globl _Remrq
# <<<massaged to jsb by "asm.sed">>>
pushab rem3
# it wasn't recorded to be on its q
clrl P_RLINK(r0) ## for firewall checking
* 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.
* Swtch(), using fancy VAX instructions
_Swtch
: # <<<massaged to jsb by "asm.sed">>>
sw1
: ffs $
0,$
32,_whichqs
,r0
# look for non-empty queue
mtpr $
0,$IPL
# must allow interrupts here
jbr 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
remque
*(r1
),r2
# r2 = p = highest pri process
bvc sw2
# make sure something was there
insv $
1,r0
,$
1,_whichqs
# still more procs in this queue
tstl
P_WCHAN(r2
) ## firewalls
ashl $PGSHIFT
,r0
,r0
# r0 = pcbb(p)
/* mfpr $PCBB,r1 # resume of current proc is easy
.globl _Resume
# <<<massaged to jsb by "asm.sed">>>
mtpr $
0x18,$IPL
# no interrupts, please
movl _CMAP2
,_u
+PCB_CMAP2
# yech
movl _u
+PCB_CMAP2
,_CMAP2
# yech
movl $PSL_PRVMOD
,4(sp
) # ``cheating'' (jfr)
* {fu,su},{byte,word}, all massaged by asm.sed to jsb's
* Copy 1 relocation unit (NBPG bytes)
* from user virtual address to physical address
_copyseg
: .globl _copyseg
bisl3 $PG_V
|PG_KW
,8(ap
),_CMAP2
mtpr $_CADDR2
,$TBIS
# invalidate entry for copy
movc3 $NBPG
,*4(ap
),_CADDR2
* zero out physical memory
* specified in relocation units (NBPG bytes)
_clearseg
: .globl _clearseg
bisl3 $PG_V
|PG_KW
,4(ap
),_CMAP1
movc5 $
0,(sp
),$
0,$NBPG
,_CADDR1
* 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
blss kacerr
# address too low
cmpl r1
,r3
# compare last page to P0LR or SLR
bgtr 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
aoblss r1
,r0
,kacc4
# next page
* Extracted and unrolled most common case of pagein (hopefully):
* resident and not on free list (reclaim of page is purely
* for the purpose of simulating a reference bit)
* CLSIZE of 2, USRSTACK of 0x7ffff000, any bit fields
* in pte's or the core map
extzv $
9,$
23,28(sp
),r3
# virtual address
bicl2 $
1,r3
# v = clbase(btop(virtaddr));
movl _u
+U_PROCP
,r5
# p = u.u_procp
jgequ
2f
# if (isatsv(p, v)) {
addl2
P_P0BR(r5
),r4
# tptopte(p, vtotp(p, v));
movl $
1,r2
# type = CTEXT;
subl3
P_SSIZE(r5
),$
0x3ffff8,r0
jgequ
2f
# } else if (isadsv(p, v)) {
addl2
P_P0BR(r5
),r4
# dptopte(p, vtodp(p, v));
cvtwl
P_SZPT(r5
),r4
# } else (isassv(p, v)) {
subl2 $
(0x3ffff8+UPAGES
),r4
addl2
P_P0BR(r5
),r4
# sptopte(p, vtosp(p, v));
beql
2f
# if (pte->pg_v || pte->pg_fod)
POPR
; rsb
# let pagein handle it
bicl3 $
0xffe00000,(r4
),r0
jneq
2f
# if (pte->pg_pfnum == 0)
POPR
; rsb
# let pagein handle it
incl r0
# pgtocm(pte->pg_pfnum)
addl2 _cmap
,r0
# &cmap[pgtocm(pte->pg_pfnum)]
jeql
2f
# if (type == CTEXT &&
jbc $
29,4(r0
),2f
# c_intrans)
POPR
; rsb
# let pagein handle it
jbc $
30,4(r0
),2f
# if (c_free)
POPR
; rsb
# let pagein handle it
bisb2 $
0x80,3(r4
) # pte->pg_v = 1;
jbc $
26,4(r4
),2f
# if (anycl(pte, pg_m)
bisb2 $
0x04,3(r4
) # pte->pg_m = 1;
bisw3 r0
,r1
,6(r4
) # distcl(pte);
mtpr r0
,$TBIS
# tbiscl(v);
jeql
2f
# if (type == CTEXT)
movl
X_CADDR(r0
),r5
# for (p = p->p_textp->x_caddr; p; ) {
addl3
P_P0BR(r5
),r3
,r0
# tpte = tptopte(p, tp);
bisb2 $
1,P_FLAG
+3(r5
) # p->p_flag |= SPTECHG;
movl (r4
),(r0
)+ # for (i = 0; i < CLSIZE; i++)
movl
4(r4
),(r0
) # tpte[i] = pte[i];
movl
P_XLINK(r5
),r5
# p = p->p_xlink;
2: # collect a few statistics...
incl _u
+U_RU
+RU_MINFLT
# u.u_ru.ru_minflt++;
incl
V_FAULTS(r0
) # cnt.v_faults++;
incl
V_PGREC(r0
) # cnt.v_pgrec++;
incl
V_FASTPGREC(r0
) # cnt.v_fastpgrec++;
incl
V_TRAP(r0
) # cnt.v_trap++;
addl2 $
8,sp
# pop pc, code
mtpr $HIGH
,$IPL
## dont go to a higher IPL (GROT)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)
#if defined(VAX750) || defined(VAX730)