📄 locore.s
字号:
aoblss r1,r2,strtlp1 # fill text entries movab _end+511,r1 # end of kernal data segment bbcc $31,r1,strt2 # turn off high order bitstrt2: ashl $-9,r1,r1 # last page of kernal datastrtlp2: 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 entrystrtlp3: 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 # limitstrtlp4: bisl3 $PG_V|PG_KW,r1,(r2)+ aobleq r3,r1,strtlp4 movl $PHYSMBA0/512,r1 movab _Sysmap+mba0_offset,r2 movab 15(r1),r3strtlp5: bisl3 $PG_V|PG_KW,r1,(r2)+ aobleq r3,r1,strtlp5 movl $PHYSMBA1/512,r1 movab _Sysmap+mba1_offset,r2 movab 15(r1),r3strtlp6: 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 pcstartmap:# set maxmem = btoc(r7) ashl $-9,r7,_maxmem movl _maxmem,_physmem movl _maxmem,_freemem## 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,strt3strt3: 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+1)*512-0x800000,PCB_P1BR(r1) # p1 page table pointer movl $0x200000,PCB_P1LR(r1) # invalid p1 p t length movl $1,PCB_SZPT(r1) # init number pages usr page table addl3 $usize,r3,PCB_SZPT+4(r1) # store into u.u_ptable[0] movl $1,r2strt5: incl r3 bisl3 $PG_V|PG_KW,r3,_Sysmap+u_ptoffset[r2] addl2 $512,r1 mtpr r1,$TBIS aoblss $usize,r2,strt5 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,strt4strt4: 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: retadderr: 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 reteret: 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 # yesciloop: prober $3,$512,(r1) # bytes accessible ? beql eret # no addl2 $512,r1 # incr user address ptr acbl $513,$-512,r0,ciloop # reduce count and loopcishort: 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 # yescoloop: probew $3,$512,(r1) # bytes accessible? beql eret # no addl2 $512,r1 # increment user address acbl $513,$-512,r0,coloop # reduce count and loopcoshort: 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 interruptswaitloc: blbc idleflag,waitloc # loop until interruptewaitloc: bbcci $0,idleflag,idle1 # clear idle escape flagidle1: ret .data .globl _waitloc .globl _ewaitloc .align 2_waitloc: .long waitloc_ewaitloc: .long ewaitlocidleflag: .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 movl 8(ap),retloc# map u-area clrl r0 movab _u,r1 movl 4(ap),r2res1: cvtwl (r2)[r0],r3 # get u click number from proc bisl3 $PG_V|PG_KW,r3,_Umap[r0] mtpr r1,$TBIS addl2 $512,r1 aoblss $usize,r0,res1# map user page tables clrl r0 movl _u+PCB_SZPT,r3 jeql res3 # no user page tablesres2: bisl3 $PG_V|PG_KW,_u+PCB_SZPT+4[r0],_Umap+4*usize[r0] mtpr r1,$TBIS addl2 $512,r1 aoblss r3,r0,res2res3: movl _u,sp # KSP from u-area ashl $9,_Umap,r5 # pcb address 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 2retloc: .space 1*4 .text# 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 # yesuaw1: probew $3,$512,(r0) beql uaerr # no access addl2 $512,r0 acbl $513,$-512,r1,uaw1uaw2: probew $3,r1,(r0) beql uaerr movl $1,r0 retuserar: cmpl $512,r1 bgeq uar2uar1: prober $3,$512,(r0) beql uaerr addl2 $512,r0 acbl $513,$-512,r1,uar1uar2: prober $3,r1,(r0) beql uaerr movl $1,r0 retuaerr: clrl r0 ret# kernacc# check for kernal access privileges# Quiz: Why doesn't probe[rw] work?# .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 kacc2kacc1: bbsc $30,r0,kacc3 mfpr $P0BR,r2 # user P0 mfpr $P0LR,r3 brb kacc2kacc3: mfpr $P1BR,r2 # user P1 (stack) mfpr $P1LR,r3kacc2: 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 kacc4kacc6: cmpl r1,r3 # compare last page to P0LR or SLR bgeq kacerr # address too highkacc4: 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 accesskacc5: aobleq r1,r0,kacc4 # next page movl $1,r0 # no errors retkacerr: clrl r0 # error 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 .globl _mbautl .set _mbautl,_u+128*512 .globl _swaputl .set _swaputl,_mbautl+16*512 .globl _swap2utl .set _swap2utl,_swaputl+16*512 .globl _forkutl .set _forkutl,_swap2utl+16*512 .globl _xswaputl .set _xswaputl,_forkutl+16*512 .globl _xallutl .set _xallutl,_xswaputl+16*512 .globl _xccdutl .set _xccdutl,_xallutl+16*512 .globl _xswap2utl .set _xswap2utl,_xccdutl+16*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,u_ptoffset+32*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## Error messages# .dataemsg1: .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,0x0emsg2: .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,0x0SBImsg : .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.# additional 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).# used for phys & swap I/O## .align 2 .globl _Sysmap .globl _Umap .globl _Tempmap .globl _Mbamap .globl _Swapmap .globl _Swap2map .globl _Forkmap .globl _Xswapmap .globl _Xallmap .globl _Xccdmap .globl _Xswap2map_Sysmap: .space 2*128*4 # 2 pages of page table entries for kernal_Umap: .space 16*4 # u-area_Tempmap: .space 16*4*7 # utility area & others_Mbamap: .space 16*4 # map for phys & swap I/O_Swapmap: .space 16*4 # swap utility area_Swap2map: .space 16*4 # second swap area_Forkmap: .space 16*4 # fork area_Xswapmap: .space 16*4 # xswap area_Xallmap: .space 16*4 # xalloc area_Xccdmap: .space 16*4 # xccdec area_Xswap2map: .space 16*4 # xswap2 area .set Syssize,4*128 # number pt entries in sys page table .globl _mmap .set _mmap,_Sysmap+CMAP2+4 .globl _vmmap .set _vmmap,CADDR2+512
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -