From ec13cb0142b357c557d529e8d146684b5e71a3ac Mon Sep 17 00:00:00 2001 From: Bill Joy Date: Sat, 14 Apr 1990 01:25:57 -0800 Subject: [PATCH] baseline version, warts and all! SCCS-vsn: sys/i386/i386/locore.s 1.2 --- usr/src/sys/i386/i386/locore.s | 1516 +++++++++++++------------------- 1 file changed, 632 insertions(+), 884 deletions(-) diff --git a/usr/src/sys/i386/i386/locore.s b/usr/src/sys/i386/i386/locore.s index 2a54aaf7c9..d8c9e4df40 100644 --- a/usr/src/sys/i386/i386/locore.s +++ b/usr/src/sys/i386/i386/locore.s @@ -3,7 +3,7 @@ * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * - * @(#)locore.s 1.1 (Berkeley) %G% + * @(#)locore.s 1.2 (Berkeley) %G% */ #include "psl.h" @@ -32,6 +32,10 @@ .set UPDROFF,0x3F7 .set UPTEOFF,0x3FE +#define ENTRY(name) \ + .globl _##name; _##name: +#define ALTENTRY(name) \ + .globl _##name; _##name: #ifdef badidea /* * I/O Memory Map is 0xfffa000-0xffffffff (virtual == real) @@ -89,8 +93,9 @@ _##mname: .globl _##mname; \ .set atmemsz,0x100000-0xa0000 .set atpgs,(atmemsz>>PGSHIFT) SYSMAP(ATDevmem,atdevbase,atpgs) +#define USRIOSIZE 30 + SYSMAP(Usriomap,usrio,USRIOSIZE+CLSIZE) /* for PHYSIO */ ZSYSMAP(ekmempt,kmemlimit,0) - SYSMAP(Usrptmap,usrpt,USRPTSIZE+CLSIZE) eSysmap: @@ -105,12 +110,14 @@ eSysmap: # .set rptes,(ptes)%1024 # .set rptes,1024-rptes # .set ptes,ptes+rptes - .set Npdes,1 + .set Npdes,3 .space (NBPG - sz) + .globl _tMap # SYSMAP(Tmap,tmap,1024) _tMap: .space NBPG + .globl _PDR _PDR: # SYSMAP(PDR,pdr,1024) .space NBPG @@ -124,6 +131,18 @@ _cpu: .long 0 # are we 386, 386sx, or 486 .text .globl start start: + movw $0x1234,%ax + movw %ax,0x472 # warm boot + jmp 1f + .space 0x500 # skip over warm boot shit +1: +#ifdef notdef + inb $0x61,%al + orb $3,%al + outb %al,$0x61 + movl $0xffff,%ecx +fooy: loop fooy +#endif #ifdef notyet # XXX pass parameters on stack /* count up memory */ @@ -148,8 +167,8 @@ start: addl $NBPG,%eax loop 1b 2: movl %eax,_abovemem-SYSTEM - #endif notyet + /* clear memory. is this redundant ? */ movl $_edata-SYSTEM,%edi movl $_end-SYSTEM,%ecx @@ -228,7 +247,7 @@ start: /*# map proc 0's _u*/ movl $UPAGES,%ecx # for this many pte s, - lea (1*NBPG)(%esi),%eax # physical address of _u in proc 0 + lea (2*NBPG)(%esi),%eax # physical address of _u in proc 0 orl $PG_V|PG_URKW,%eax # having these bits set, lea (0*NBPG)(%esi),%ebx # physical address of stack pt in proc 0 addl $(UPTEOFF*4),%ebx @@ -238,6 +257,15 @@ start: addl $4,%ebx # next pte loop 1b + /*# map proc 0's page directory*/ + lea (1*NBPG)(%esi),%eax # physical address of ptd in proc 0 + movl %eax,%edi # remember ptd physical address + orl $PG_V|PG_URKW,%eax # having these bits set, + lea (0*NBPG)(%esi),%ebx # physical address of stack pt in proc 0 + addl $(UPTEOFF*4),%ebx + addl $(UPAGES*4),%ebx + movl %eax,0(%ebx) + /* * Construct a page table directory * (of page directory elements - pde's) @@ -246,8 +274,8 @@ start: movl $_Sysmap-SYSTEM,%eax # physical address of kernel page table orl $PG_V,%eax # pde entry is valid movl $Npdes,%ecx # for this many pde s, - movl $_PDR-SYSTEM,%ebx # address of start of ptd - # lea (2*NBPG)(%esi),%ebx # address of ptd in proc 0 pt + # movl $_PDR-SYSTEM,%ebx # address of start of ptd + movl %edi,%ebx # phys address of ptd in proc 0 addl $(SYSPDROFF*4), %ebx # offset of pde for kernel 1: movl %eax,0(%ebx) addl $NBPG,%eax # increment physical address @@ -256,8 +284,8 @@ start: # install a pde for temporary double map movl $_tMap-SYSTEM,%eax # physical address of temp page table orl $PG_V,%eax # pde entry is valid - movl $_PDR-SYSTEM,%ebx # address of start of ptd - # lea (2*NBPG)(%esi),%ebx # address of ptd in proc 0 pt + # movl $_PDR-SYSTEM,%ebx # address of start of ptd + movl %edi,%ebx # phys address of ptd in proc 0 movl %eax,0(%ebx) # which is where temp maps! #ifdef badidea # install a pde for IO memory @@ -271,8 +299,8 @@ start: # install a pde to map _u for proc 0 lea (0*NBPG)(%esi),%eax # physical address of pt in proc 0 orl $PG_V,%eax # pde entry is valid - movl $_PDR-SYSTEM,%ebx # address of start of ptd - # lea (2*NBPG)(%esi),%ebx # address of ptd in proc 0 pt + # movl $_PDR-SYSTEM,%ebx # address of start of ptd + movl %edi,%ebx # phys address of ptd in proc 0 addl $(UPDROFF*4), %ebx # offset of pde for kernel movl %eax,0(%ebx) # which is where _u maps! @@ -283,8 +311,8 @@ start: # addl $_PDR-SYSTEM,%eax # orl $PG_V,%eax - movl $_PDR-SYSTEM,%eax # address of start of ptd - # lea (2*NBPG)(%esi),%eax # address o ptd in proc 0 pt + # movl $_PDR-SYSTEM,%eax # address of start of ptd + movl %edi,%eax # phys address of ptd in proc 0 movl %eax,%cr3 # load ptd addr into mmu movl $0x80000001,%eax # and let s page! movl %eax,%cr0 # NOW! @@ -292,21 +320,113 @@ start: pushl $begin # jump to high mem! ret begin: - movl $_u+UPAGES*NBPG-4,%eax + # movl $_u+UPAGES*NBPG-4,%eax + # movl $0xfdfffffc,%eax + movl $_Sysbase,%eax movl %eax,%esp movl %eax,%ebp movl _Crtat,%eax subl $IOPHYSmem,%eax addl $_atdevbase,%eax movl %eax,_Crtat - # call _init386 + call _init386 +/* initialize (slightly) the pcb */ + movl $_u,%eax # proc0 u-area + movl $_usrpt,%ecx + movl %ecx,PCB_P0BR(%eax) # p0br: SVA of text/data user PT + xorl %ecx,%ecx + movl %ecx,PCB_P0LR(%eax) # p0lr: 0 (doesn t really exist) + movl $_usrpt+NBPG,%ecx # addr of end of PT + subl $P1PAGES*4,%ecx # backwards size of P1 region + movl %ecx,PCB_P1BR(%eax) # p1br: P1PAGES from end of PT + movl $P1PAGES-UPAGES,PCB_P1LR(%eax) # p1lr: vax style + movl $CLSIZE,PCB_SZPT(%eax) # page table size + #clrw a1@(PCB_FLAGS) # clear flags +#ifdef FPUNOTYET +#endif + pushl %edi # cr3 + movl %esi,%eax + # addl $(UPAGES*NBPG)+NBPG+NBPG+NBPG,%esi + addl $(UPAGES*NBPG)+NBPG+NBPG+NBPG,%eax + shrl $PGSHIFT,%eax + pushl %eax # firstaddr + + pushl $20 # install sigtrampoline code + pushl $_u+PCB_SIGC + pushl $sigcode + call _bcopy + addl $12,%esp + call _main - movw $0x1234,%ax - movw %ax,0x472 # warm boot + + .globl __ucodesel,__udatasel + movzwl __ucodesel,%eax + movzwl __udatasel,%ecx + # build outer stack frame + pushl %ecx # user ss + # pushl $0xfdffcffc # user esp + pushl $0xfdffd000 # user esp + pushl %eax # user cs + pushl $0 # user ip + movw %cx,%ds + movw %cx,%es + lret # goto user! +# pushal; pushl %edx; pushl $lr; call _pg; popl %eax ; popl %eax; popal ; .data ; lr: .asciz "lret %x" ; .text + + .globl __exit +__exit: lidt xaxa movl $0,%esp # segment violation ret xaxa: .long 0,0 + .set exec,11 + .set exit,1 + .globl _icode + .globl _initflags + .globl _szicode +/* gas fucks up offset -- */ +#define LCALL(x,y) .byte 0x9a ; .long y; .word x +/* + * Icode is copied out to process 1 to exec /etc/init. + * If the exec fails, process 1 exits. + */ +_icode: + # pushl $argv-_icode + movl $argv,%eax + subl $_icode,%eax + pushl %eax + + # pushl $init-_icode + movl $init,%eax + subl $_icode,%eax + pushl %eax + pushl %eax # dummy out rta + + movl %esp,%ebp + movl $exec,%eax + LCALL(0x7,0x0) + pushl %eax + movl $exit,%eax + pushl %eax # dummy out rta + LCALL(0x7,0x0) + +# init: .asciz "/sbin/init" +init: .asciz "/etc/init" + .align 2 +_initflags: + .long 0 +argv: .long init-_icode + .long _initflags-_icode + .long 0 +_szicode: + .long _szicode-_icode +sigcode: + movl 12(%esp),%eax # unsure if call will dec stack 1st + call %eax + xorl %eax,%eax # smaller movl $103,%eax + movb $103,%al # sigreturn() + LCALL(0x7,0) # enter kernel with args on stack + hlt # never gets here #ifdef newway @@ -359,550 +479,321 @@ xaxa: .long 0,0 9: /* clear memory from kernel bss and pages for proc 0 u. and page table */ - lea _edata-SYSTEM,r6 - lea _end-SYSTEM,r5 - bisl3 $SYSTEM,r5,r9 # convert to virtual address - addl2 $NBPG-1,r9 # roundup to next page - addl2 $(UPAGES*NBPG)+NBPG+NBPG,r5 -1: clrq (r6); acbl r5,$8,r6,1b -/* initialize system page table: uba vectors and int stack writeable */ - clrl r2 - movab eintstack,r1; bbcc $31,r1,1f; -1: bisl3 $PG_V|PG_KW,r2,_Sysmap[r2]; aoblss r1,r2,1b -/* make kernel text space read-only */ - movab _etext+NBPG-1,r1; bbcc $31,r1,1f; -1: bisl3 $PG_V|PG_URKR,r2,_Sysmap[r2]; aoblss r1,r2,1b -/* make kernel data, bss, read-write */ - bicl3 $SYSTEM,r9,r1; ashl $-PGSHIFT,r1,r1 -1: bisl3 $PG_V|PG_KW,r2,_Sysmap[r2]; aoblss r1,r2,1b -/* now go to mapped mode */ - mtpr $0,$TBIA; mtpr $1,$MAPEN; jmp *$0f; 0: -/* init mem sizes */ - ashl $-PGSHIFT,r7,_maxmem - movl _maxmem,_physmem - movl _maxmem,_freemem -/* setup context for proc[0] == Scheduler */ - bicl3 $SYSTEM|(NBPG-1),r9,r6 # make phys, 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 - incl r3 - movab _usrpt,r0 - mtpr r0,$TBIS -/* init p0br, p0lr */ - mtpr r0,$P0BR - mtpr $0,$P0LR -/* double map the kernel into the virtual user addresses of phys mem */ - mtpr $_Sysmap,$P0BR - mtpr $_Syssize,$P0LR -/* init p1br, p1lr */ - movab NBPG(r0),r0 - movl $0x200000-UPAGES,r1 - mtpr r1,$P1LR - mnegl r1,r1 - moval -4*UPAGES(r0)[r1],r2 - mtpr r2,$P1BR -/* setup mapping for UPAGES of _u */ - movl $UPAGES,r2; movab _u+NBPG*UPAGES,r1; addl2 $UPAGES,r3; jbr 2f -1: decl r3 - moval -NBPG(r1),r1; - bisl3 $PG_V|PG_URKW,r3,-(r0) - mtpr r1,$TBIS -2: sobgeq r2,1b -/* initialize (slightly) the pcb */ - movab UPAGES*NBPG(r1),PCB_KSP(r1) - mnegl $1,PCB_ESP(r1) - mnegl $1,PCB_SSP(r1) - movl r1,PCB_USP(r1) - mfpr $P0BR,PCB_P0BR(r1) - mfpr $P0LR,PCB_P0LR(r1) - movb $4,PCB_P0LR+3(r1) # disable ast - mfpr $P1BR,PCB_P1BR(r1) - mfpr $P1LR,PCB_P1LR(r1) - movl $CLSIZE,PCB_SZPT(r1) # init u.u_pcb.pcb_szpt - movl r9,PCB_R9(r1) - movl r10,PCB_R10(r1) - movl r11,PCB_R11(r1) - movab 1f,PCB_PC(r1) # initial pc - clrl PCB_PSL(r1) # mode(k,k), ipl=0 - ashl $PGSHIFT,r3,r3 - mtpr r3,$PCBB # first pcbb -/* set regs, p0br, p0lr, p1br, p1lr, astlvl, ksp and change to kernel mode */ - ldpctx - rei -/* put signal trampoline code in u. area */ -1: movab _u,r0 - movc3 $19,sigcode,PCB_SIGC(r0) -/* save boot device in global _bootdev */ - movl r10,_bootdev -/* save reboot flags in global _boothowto */ - movl r11,_boothowto -#ifdef KADB -/* save end of symbol & string table in global _bootesym */ - subl3 $NBPG-1,r9,_bootesym -#endif -/* calculate firstaddr, and call main() */ - bicl3 $SYSTEM,r9,r0; 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 19 bytes */ -/* in ../vax/pcb.h and in the movc3 above */ -sigcode: - calls $4,8(pc) # params pushed by sendsig - movl sp,ap # calls frame built by sendsig - chmk $103 # cleanup mask and onsigstack - halt # sigreturn() does not return! - .word 0x3f # registers 0-5 - callg (ap),*16(ap) # call the signal handler - ret # return to code above +#endif newway - .set exec,11 - .set exit,1 - .globl _icode - .globl _initflags - .globl _szicode -/* - * Icode is copied out to process 1 to exec /etc/init. - * If the exec fails, process 1 exits. - */ -_icode: - pushab b`argv-l0(pc) -l0: pushab b`init-l1(pc) -l1: pushl $2 - movl sp,ap - chmk $exec - pushl r0 - chmk $exit - -init: .asciz "/sbin/init" - .align 2 -_initflags: - .long 0 -argv: .long init+6-_icode - .long _initflags-_icode - .long 0 -_szicode: - .long _szicode-_icode + .globl ___udivsi3 +___udivsi3: + movl 4(%esp),%eax + xorl %edx,%edx + divl 8(%esp) + ret -/* - * Primitives - */ + .globl ___divsi3 +___divsi3: + movl 4(%esp),%eax + xorl %edx,%edx + cltd + idivl 8(%esp) + ret -#ifdef GPROF -#define ENTRY(name, regs) \ - .globl _##name; .align 1; _##name: .word regs; jsb mcount -#else -#define ENTRY(name, regs) \ - .globl _##name; .align 1; _##name: .word regs -#endif GPROF -#define R0 0x01 -#define R1 0x02 -#define R2 0x04 -#define R3 0x08 -#define R4 0x10 -#define R5 0x20 -#define R6 0x40 + .globl _inb +_inb: movl 4(%esp),%edx + subl %eax,%eax # clr eax + nop + inb %dx,%al + nop + ret -/* - * badaddr(addr, len) - * see if access addr with a len type instruction causes a machine check - * len is length of access (1=byte, 2=short, 4=long) - */ - .globl _badaddr -_badaddr: - .word 0 - movl $1,r0 - mfpr $IPL,r1 - mtpr $HIGH,$IPL - movl 4(ap),r3 - movl 8(ap),r4 - movab 2f,nofault # jump to 2f on machcheck - bbc $0,r4,1f; tstb (r3) -1: bbc $1,r4,1f; tstw (r3) -1: bbc $2,r4,1f; tstl (r3) -1: clrl r0 # made it w/o machine checks -2: clrl nofault - mtpr r1,$IPL + .globl _outb +_outb: movl 4(%esp),%edx + movl 8(%esp),%eax + nop + outb %al,%dx + nop ret -/* - * update profiling information for the user - * addupc(pc, &u.u_prof, ticks) - */ -ENTRY(addupc, 0) - movl 8(ap),r2 # &u.u_prof - subl3 8(r2),4(ap),r0 # corrected pc - blss 9f - extzv $1,$31,r0,r0 # logical right shift - extzv $1,$31,12(r2),r1 # ditto for scale - emul r1,r0,$0,r0 - ashq $-14,r0,r0 - tstl r1 - bneq 9f - bicl2 $1,r0 - cmpl r0,4(r2) # length - bgequ 9f - addl2 (r2),r0 # base - probew $3,$2,(r0) - beql 8f - addw2 12(ap),(r0) -9: + # + # bzero (base,cnt) + # + + .globl _bzero + .globl _blkclr +_bzero: +_blkclr: + pushl %edi + movl 8(%esp),%edi + movl 12(%esp),%ecx + movb $0x00,%al + cld + rep + stosb + popl %edi ret -8: - clrl 12(r2) + + # + # bcopy (src,dst,cnt) + # NOTE: does not (yet) handle overlapped copies + # + + .globl _bcopy + .globl _copyout + .globl _copyin +_bcopy: +_copyout: +_copyin: + pushl %esi + pushl %edi + movl 12(%esp),%esi + movl 16(%esp),%edi + movl 20(%esp),%ecx + cld + rep + movsb + popl %edi + popl %esi + movl %ecx,%eax ret -/* - * Copy a null terminated string from the user address space into - * the kernel address space. - * - * copyinstr(fromaddr, toaddr, maxlength, &lencopied) - */ -ENTRY(copyinstr, R6) - movl 12(ap),r6 # r6 = max length - jlss 8f - movl 4(ap),r1 # r1 = user address - bicl3 $~(NBPG*CLSIZE-1),r1,r2 # r2 = bytes on first page - subl3 r2,$NBPG*CLSIZE,r2 - movl 8(ap),r3 # r3 = kernel address -1: - cmpl r6,r2 # r2 = min(bytes on page, length left); - jgeq 2f - movl r6,r2 -2: - prober $3,r2,(r1) # bytes accessible? - jeql 8f - subl2 r2,r6 # update bytes left count -#ifdef NOSUBSINST - # fake the locc instr. for processors that don t have it - movl r2,r0 -6: - tstb (r1)+ - jeql 5f - sobgtr r0,6b - jbr 7f -5: - decl r1 - jbr 3f -7: -#else - locc $0,r2,(r1) # null byte found? - jneq 3f -#endif - subl2 r2,r1 # back up pointer updated by `locc - movc3 r2,(r1),(r3) # copy in next piece - movl $(NBPG*CLSIZE),r2 # check next page - tstl r6 # run out of space? - jneq 1b - movl $ENOENT,r0 # set error code and return - jbr 9f -3: - tstl 16(ap) # return length? - beql 4f - subl3 r6,12(ap),r6 # actual len = maxlen - unused pages - subl2 r0,r6 # - unused on this page - addl3 $1,r6,*16(ap) # + the null byte -4: - subl2 r0,r2 # r2 = number of bytes to move - subl2 r2,r1 # back up pointer updated by `locc - incl r2 # copy null byte as well - movc3 r2,(r1),(r3) # copy in last piece - clrl r0 # redundant + # insw(port,addr,cnt) + .globl _insw +_insw: + pushl %edi + movw 8(%esp),%dx + movl 12(%esp),%edi + movl 16(%esp),%ecx + cld + nop + .byte 0x66,0xf2,0x6d # rep insw + nop + movl %edi,%eax + popl %edi ret -8: - movl $EFAULT,r0 -9: - tstl 16(ap) - beql 1f - subl3 r6,12(ap),*16(ap) -1: + + # outsw(port,addr,cnt) + .globl _outsw +_outsw: + pushl %esi + movw 8(%esp),%dx + movl 12(%esp),%esi + movl 16(%esp),%ecx + cld + nop + .byte 0x66,0xf2,0x6f # rep outsw + nop + movl %esi,%eax + popl %esi ret -/* - * Copy a null terminated string from the kernel - * address space to the user address space. - * - * copyoutstr(fromaddr, toaddr, maxlength, &lencopied) - */ -ENTRY(copyoutstr, R6) - movl 12(ap),r6 # r6 = max length - jlss 8b - movl 4(ap),r1 # r1 = kernel address - movl 8(ap),r3 # r3 = user address - bicl3 $~(NBPG*CLSIZE-1),r3,r2 # r2 = bytes on first page - subl3 r2,$NBPG*CLSIZE,r2 -1: - cmpl r6,r2 # r2 = min(bytes on page, length left); - jgeq 2f - movl r6,r2 -2: - probew $3,r2,(r3) # bytes accessible? - jeql 8b - subl2 r2,r6 # update bytes left count -#ifdef NOSUBSINST - # fake the locc instr. for processors that don t have it - movl r2,r0 -6: - tstb (r1)+ - jeql 5f - sobgtr r0,6b - jbr 7f -5: - decl r1 - jbr 3b -7: -#else - locc $0,r2,(r1) # null byte found? - jneq 3b -#endif - subl2 r2,r1 # back up pointer updated by `locc - movc3 r2,(r1),(r3) # copy in next piece - movl $(NBPG*CLSIZE),r2 # check next page - tstl r6 # run out of space? - jneq 1b - movl $ENOENT,r0 # set error code and return - jbr 9b + # lgdt(*gdt, ngdt) + .globl _lgdt + # .globl _gdt +xxx: .word 31 + .long 0 +_lgdt: + movl 4(%esp),%eax + movl %eax,xxx+2 + movl 8(%esp),%eax + movw %ax,xxx + lgdt xxx + jmp 1f + nop +1: movw $0x10,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%ss + movl 0(%esp),%eax + pushl %eax + movl $8,4(%esp) + lret + + # lidt(*idt, nidt) + .globl _lidt + # .globl _idt +yyy: .word 255 + .long 0 # _idt +_lidt: + movl 4(%esp),%eax + movl %eax,yyy+2 + movl 8(%esp),%eax + movw %ax,yyy + lidt yyy + ret -/* - * Copy a null terminated string from one point to another in - * the kernel address space. - * - * copystr(fromaddr, toaddr, maxlength, &lencopied) - */ -ENTRY(copystr, R6) - movl 12(ap),r6 # r6 = max length - jlss 8b - movl 4(ap),r1 # r1 = src address - movl 8(ap),r3 # r3 = dest address -1: - movzwl $65535,r2 # r2 = bytes in first chunk - cmpl r6,r2 # r2 = min(bytes in chunk, length left); - jgeq 2f - movl r6,r2 -2: - subl2 r2,r6 # update bytes left count -#ifdef NOSUBSINST - # fake the locc instr. for processors that don t have it - movl r2,r0 -6: - tstb (r1)+ - jeql 5f - sobgtr r0,6b - jbr 7f -5: - decl r1 - jbr 3b -7: -#else - locc $0,r2,(r1) # null byte found? - jneq 3b -#endif - subl2 r2,r1 # back up pointer updated by `locc - movc3 r2,(r1),(r3) # copy in next piece - tstl r6 # run out of space? - jneq 1b - movl $ENOENT,r0 # set error code and return - jbr 9b - -/* - * Copy specified amount of data from user space into the kernel - * Copyin(from, to, len) - * r1 == from (user source address) - * r3 == to (kernel destination address) - * r5 == length - */ - .align 1 -JSBENTRY(Copyin, R1|R3|R5) - cmpl r5,$(NBPG*CLSIZE) # probing one page or less ? - bgtru 1f # no - prober $3,r5,(r1) # bytes accessible ? - beql ersb # no - movc3 r5,(r1),(r3) -/* clrl r0 # redundant */ - rsb -1: - blss ersb # negative length? - pushl r6 # r6 = length - movl r5,r6 - bicl3 $~(NBPG*CLSIZE-1),r1,r0 # r0 = bytes on first page - subl3 r0,$(NBPG*CLSIZE),r0 - addl2 $(NBPG*CLSIZE),r0 # plus one additional full page - jbr 2f - -ciloop: - movc3 r0,(r1),(r3) - movl $(2*NBPG*CLSIZE),r0 # next amount to move -2: - cmpl r0,r6 - bleq 3f - movl r6,r0 -3: - prober $3,r0,(r1) # bytes accessible ? - beql ersb1 # no - subl2 r0,r6 # last move? - bneq ciloop # no - - movc3 r0,(r1),(r3) -/* clrl r0 # redundant */ - movl (sp)+,r6 # restore r6 - rsb - -ersb1: - movl (sp)+,r6 # restore r6 -ersb: - movl $EFAULT,r0 - rsb - -/* - * Copy specified amount of data from kernel to the user space - * Copyout(from, to, len) - * r1 == from (kernel source address) - * r3 == to (user destination address) - * r5 == length - */ - .align 1 -JSBENTRY(Copyout, R1|R3|R5) - cmpl r5,$(NBPG*CLSIZE) # moving one page or less ? - bgtru 1f # no - probew $3,r5,(r3) # bytes writeable? - beql ersb # no - movc3 r5,(r1),(r3) -/* clrl r0 # redundant */ - rsb -1: - blss ersb # negative length? - pushl r6 # r6 = length - movl r5,r6 - bicl3 $~(NBPG*CLSIZE-1),r3,r0 # r0 = bytes on first page - subl3 r0,$(NBPG*CLSIZE),r0 - addl2 $(NBPG*CLSIZE),r0 # plus one additional full page - jbr 2f - -coloop: - movc3 r0,(r1),(r3) - movl $(2*NBPG*CLSIZE),r0 # next amount to move -2: - cmpl r0,r6 - bleq 3f - movl r6,r0 -3: - probew $3,r0,(r3) # bytes writeable? - beql ersb1 # no - subl2 r0,r6 # last move? - bneq coloop # no - - movc3 r0,(r1),(r3) -/* clrl r0 # redundant */ - movl (sp)+,r6 # restore r6 - rsb + # lldt(sel) + .globl _lldt +_lldt: + movl 4(%esp),%eax + lldt %eax + ret -/* - * non-local goto s - */ -#ifdef notdef /* this is now expanded completely inline */ - .align 1 -JSBENTRY(Setjmp, R0) - movl fp,(r0)+ # current stack frame - movl (sp),(r0) # resuming pc - clrl r0 - rsb -#endif + # ltr(sel) + .globl _ltr +_ltr: + movl 4(%esp),%eax + ltr %eax + ret -#define PCLOC 16 /* location of pc in calls frame */ -#define APLOC 8 /* location of ap,fp in calls frame */ - .align 1 -JSBENTRY(Longjmp, R0) - movl (r0)+,newfp # must save parameters in memory as all - movl (r0),newpc # registers may be clobbered. -1: - cmpl fp,newfp # are we there yet? - bgequ 2f # yes - moval 1b,PCLOC(fp) # redirect return pc to us! - ret # pop next frame -2: - beql 3f # did we miss our frame? - pushab 4f # yep ?!? - calls $1,_panic -3: - movl newpc,r0 # all done, just return to the `setjmp - jmp (r0) # rsb + # lcr3(cr3) + .globl _lcr3 + .globl _load_cr3 +_load_cr3: +_lcr3: + movl 4(%esp),%eax + movl %eax,%cr3 + movl %cr3,%eax + ret - .data -newpc: .space 4 -newfp: .space 4 -4: .asciz "longjmp" - .text -/* - * setjmp that saves all registers as the call frame may not - * be available to recover them in the usual mannor by longjmp. - * Called before swapping out the u. area, restored by resume() - * below. - */ -ENTRY(savectx, 0) - movl 4(ap),r0 - movq r6,(r0)+ - movq r8,(r0)+ - movq r10,(r0)+ - movq APLOC(fp),(r0)+ # save ap, fp - addl3 $8,ap,(r0)+ # save sp - movl PCLOC(fp),(r0) # save pc - clrl r0 + # lcr0(cr0) + .globl _lcr0 +_lcr0: + movl 4(%esp),%eax + movl %eax,%cr0 + ret + + # rcr0() + .globl _rcr0 +_rcr0: + movl %cr0,%eax + ret + + # rcr2() + .globl _rcr2 +_rcr2: + movl %cr2,%eax + ret + + # rcr3() + .globl _rcr3 + .globl __cr3 +__cr3: +_rcr3: + movl %cr3,%eax + ret + + # ssdtosd(*ssdp,*sdp) + .globl _ssdtosd +_ssdtosd: + pushl %ebx + movl 8(%esp),%ecx + movl 8(%ecx),%ebx + shll $16,%ebx + movl (%ecx),%edx + roll $16,%edx + movb %dh,%bl + movb %dl,%bh + rorl $8,%ebx + movl 4(%ecx),%eax + movw %ax,%dx + andl $0xf0000,%eax + orl %eax,%ebx + movl 12(%esp),%ecx + movl %edx,(%ecx) + movl %ebx,4(%ecx) + popl %ebx ret -#ifdef KADB /* - * C library -- reset, setexit - * - * reset(x) - * will generate a "return" from - * the last call to - * setexit() - * by restoring r6 - r12, ap, fp - * and doing a return. - * The returned value is x; on the original - * call the returned value is 0. + * {fu,su},{byte,sword,word} */ -ENTRY(setexit, 0) - movab setsav,r0 - movq r6,(r0)+ - movq r8,(r0)+ - movq r10,(r0)+ - movq 8(fp),(r0)+ # ap, fp - movab 4(ap),(r0)+ # sp - movl 16(fp),(r0) # pc - clrl r0 +ALTENTRY(fuiword) +ENTRY(fuword) + movl $fusufault,_nofault # in case we page/protection violate + movl 4(%esp),%edx + movl 0(%edx),%eax + xorl %edx,%edx + movl %edx,_nofault + ret + +ENTRY(fusword) + movl $fusufault,_nofault # in case we page/protection violate + movl 4(%esp),%edx + movzwl 0(%edx),%eax + xorl %edx,%edx + movl %edx,_nofault + ret + +ALTENTRY(fuibyte) +ENTRY(fubyte) + movl $fusufault,_nofault # in case we page/protection violate + movl 4(%esp),%edx + movzbl 0(%edx),%eax + xorl %edx,%edx + movl %edx,_nofault + ret + +fusufault: + xorl %eax,%eax + movl %eax,_nofault + decl %eax ret -ENTRY(reset, 0) - movl 4(ap),r0 # returned value - movab setsav,r1 - movq (r1)+,r6 - movq (r1)+,r8 - movq (r1)+,r10 - movq (r1)+,r12 - movl (r1)+,sp - jmp *(r1) +ALTENTRY(suiword) +ENTRY(suword) + movl $fusufault,_nofault # in case we page/protection violate + movl 4(%esp),%edx + movl 8(%esp),%eax + movl %eax,0(%edx) + xorl %eax,%eax + movl %eax,_nofault + ret + +ENTRY(susword) + movl $fusufault,_nofault # in case we page/protection violate + movl 4(%esp),%edx + movl 8(%esp),%eax + movl %eax,0(%edx) + xorl %eax,%eax + movl %eax,_nofault + ret - .data - .align 2 -setsav: .space 10*4 - .text -#endif +ALTENTRY(suibyte) +ENTRY(subyte) + movl $fusufault,_nofault # in case we page/protection violate + movl 4(%esp),%edx + movl 8(%esp),%eax + movl %eax,0(%edx) + xorl %eax,%eax + movl %eax,_nofault + ret - .globl _whichqs - .globl _qs - .globl _cnt + ALTENTRY(savectx) + ENTRY(setjmp) + movl 4(%esp),%eax + movl %ebx, 0(%eax) # save ebx + movl %esp, 4(%eax) # save esp + movl %ebp, 8(%eax) # save ebp + movl %esi,12(%eax) # save esi + movl %edi,16(%eax) # save edi + movl (%esp),%edx # get rta + movl %edx,20(%eax) # save eip + movl $0,%edx # return (0); + movl $0,%eax # return (0); + ret - .globl _noproc - .comm _noproc,4 - .globl _runrun - .comm _runrun,4 + ENTRY(qsetjmp) + movl 4(%esp),%eax + movl %esp, 4(%eax) # save esp + movl %ebp, 8(%eax) # save ebp + movl (%esp),%edx # get rta + movl %edx,20(%eax) # save eip + xorl %eax,%eax # return (0); + ret + ENTRY(longjmp) + movl 4(%esp),%eax + movl 0(%eax),%ebx # restore ebx + movl 4(%eax),%esp # restore esp + movl 8(%eax),%ebp # restore ebp + movl 12(%eax),%esi # restore esi + movl 16(%eax),%edi # restore edi + movl 20(%eax),%edx # get rta + movl %edx,(%esp) # put in return frame + xorl %eax,%eax # return (1); + incl %eax + ret /* - * The following primitives use the fancy VAX instructions - * much like VMS does. _whichqs tells which of the 32 queues _qs + * The following primitives manipulate the run queues. + * _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 @@ -910,395 +801,252 @@ setsav: .space 10*4 * queues. */ + .globl _whichqs,_qs,_cnt,_panic,_ctasksel + .comm _noproc,4 + .comm _runrun,4 + .comm _ctasksel,4 + /* - * Setrq(p), using fancy VAX instructions. + * Setrq(p) * - * Call should be made at splclock(), and p->p_stat should be SRUN + * Call should be made at spl6(), and p->p_stat should be SRUN */ - .align 1 -JSBENTRY(Setrq, R0) - tstl P_RLINK(r0) ## firewall: p->p_rlink must be 0 - beql set1 ## - pushab set3 ## - calls $1,_panic ## +ENTRY(setrq) + movl 4(%esp),%eax + cmpl $0,P_RLINK(%eax) # should not be on q already + je set1 + pushl $set2 + call _panic set1: - 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 + movzbl P_PRI(%eax),%edx + shrl $2,%edx + btsl %edx,_whichqs # set q full bit + shll $3,%edx + addl $_qs,%edx # locate q hdr + movl %edx,P_LINK(%eax) # link process on tail of q + movl P_RLINK(%edx),%ecx + movl %ecx,P_RLINK(%eax) + movl %eax,P_RLINK(%edx) + movl %eax,P_LINK(%ecx) + ret -set3: .asciz "setrq" +set2: .asciz "setrq" /* - * Remrq(p), using fancy VAX instructions + * Remrq(p) * - * Call should be made at splclock(). + * Call should be made at spl6(). */ - .align 1 -JSBENTRY(Remrq, R0) - 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 +ENTRY(remrq) + movl 4(%esp),%eax + movzbl P_PRI(%eax),%edx + shrl $2,%edx + btrl %edx,_whichqs # clear full bit, panic if clear already + jb rem1 + pushl $rem3 + call _panic rem1: - remque (r0),r2 - beql rem2 - bbss r1,_whichqs,rem2 + pushl %edx + movl P_LINK(%eax),%ecx # unlink process + movl P_RLINK(%eax),%edx + movl %edx,P_RLINK(%ecx) + movl P_RLINK(%eax),%ecx + movl P_LINK(%eax),%edx + movl %edx,P_LINK(%ecx) + popl %edx + movl $_qs,%ecx + shll $3,%edx + addl %edx,%ecx + cmpl P_LINK(%ecx),%ecx # q still has something? + je rem2 + shrl $3,%edx # yes, set bit as still full + btsl %edx,_whichqs rem2: - clrl P_RLINK(r0) ## for firewall checking - rsb + movl $0,P_RLINK(%eax) # zap reverse link to indicate off list + ret 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" +sw01: .asciz "swtch1" +sw02: .asciz "swtch2" /* * When no processes are on the runq, Swtch branches to idle * to wait for something to come ready. */ .globl Idle -Idle: idle: - movl $1,_noproc - mtpr $0,$IPL # must allow interrupts here -1: - tstl _whichqs # look for non-empty queue - bneq sw1 - brb 1b - -badsw: pushab sw0 - calls $1,_panic +Idle: +idle: + call _spl0 + cmpl $0,_whichqs + jne sw1 + hlt # wait for interrupt + jmp idle + +badsw: + pushl $sw0 + call _panic /*NOTREACHED*/ /* - * Swtch(), using fancy VAX instructions + * Swtch() */ - .align 1 -JSBENTRY(Swtch, 0) +ENTRY(swtch) + movl $1,%eax + movl %eax,_noproc incl _cnt+V_SWTCH -sw1: ffs $0,$32,_whichqs,r0 # look for non-empty queue - beql idle # if none, idle - mtpr $0x18,$IPL # lock out all so _whichqs==_qs - bbcc r0,_whichqs,sw1 # proc moved via interrupt - movaq _qs[r0],r1 - remque *(r1),r2 # r2 = p = highest pri process - bvs badsw # make sure something was there - beql sw2 - insv $1,r0,$1,_whichqs # still more procs in this queue +sw1: + bsfl _whichqs,%eax # find a full q + jz idle # if none, idle +swfnd: + cli + btrl %eax,_whichqs # clear q full status + jnb sw1 # if it was clear, look for another + pushl %eax # save which one we are using + shll $3,%eax + addl $_qs,%eax # select q + pushl %eax + + cmpl P_LINK(%eax),%eax # linked to self? (e.g. not on list) + je badsw # not possible + movl P_LINK(%eax),%ecx # unlink from front of process q + movl P_LINK(%ecx),%edx + movl %edx,P_LINK(%eax) + movl P_RLINK(%ecx),%eax + movl %eax,P_RLINK(%edx) + + popl %eax + popl %edx + cmpl P_LINK(%ecx),%eax # q empty + je sw2 + btsl %edx,_whichqs # nope, indicate full sw2: - clrl _noproc - clrl _runrun -#ifdef notdef - tstl P_WCHAN(r2) ## firewalls - bneq badsw ## - cmpb P_STAT(r2),$SRUN ## - bneq badsw ## -#endif - clrl P_RLINK(r2) ## - movl *P_ADDR(r2),r0 -#ifdef notdef - cmpl r0,_masterpaddr # resume of current proc is easy - beql res0 + movl $0,%eax + movl %eax,_noproc + movl %eax,_runrun + cmpl $0,P_WCHAN(%ecx) + jne badsw + cmpb $SRUN,P_STAT(%ecx) + jne badsw + movl %eax,P_RLINK(%ecx) + # movl P_ADDR(%ecx),%edx + movl P_CR3(%ecx),%edx +/*pushal; pushl %edx; pushl $lc; call _printf; popl %eax ; popl %eax; popal ; .data ; lc: .asciz "swtch %x" ; .text*/ + +/* switch to new process. first, save context as needed */ + movl $_u,%ecx + + movl (%esp),%eax # Hardware registers + movl %eax, PCB_EIP(%ecx) + movl %ebx, PCB_EBX(%ecx) + movl %esp, PCB_ESP(%ecx) + movl %ebp, PCB_EBP(%ecx) + movl %esi, PCB_ESI(%ecx) + movl %edi, PCB_EDI(%ecx) + +#ifdef FPUNOTYET #endif - movl r0,_masterpaddr - ashl $PGSHIFT,r0,r0 # r0 = pcbb(p) -/* fall into... */ -/* - * Resume(pf) - */ -JSBENTRY(Resume, R0) - mtpr $HIGH,$IPL # no interrupts, please - movl _CMAP2,_u+PCB_CMAP2 # yech - svpctx - mtpr r0,$PCBB - ldpctx - movl _u+PCB_CMAP2,_CMAP2 # yech - mtpr $_CADDR2,$TBIS -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 # restore r6, r7 - movq (r0)+,r8 # restore r8, r9 - movq (r0)+,r10 # restore r10, r11 - movq (r0)+,r12 # restore ap, fp - movl (r0)+,r1 # saved sp - cmpl r1,sp # must be a pop - bgequ 1f - pushab 2f - calls $1,_panic - /* NOTREACHED */ -1: - movl r1,sp # restore sp - pushl $PSL_PRVMOD # return psl - pushl (r0) # address to return to - rei + movl _CMAP2,%eax # save temporary map PTE + movl %eax,PCB_CMAP2(%ecx) # in our context -2: .asciz "ldctx" -/* - * {fu,su},{byte,word}, all massaged by asm.sed to jsb s - */ - .align 1 -JSBENTRY(Fuword, R0) - prober $3,$4,(r0) - beql fserr - movl (r0),r0 - rsb -fserr: - mnegl $1,r0 - rsb - - .align 1 -JSBENTRY(Fubyte, R0) - prober $3,$1,(r0) - beql fserr - movzbl (r0),r0 - rsb - - .align 1 -JSBENTRY(Suword, R0|R1) - probew $3,$4,(r0) - beql fserr - movl r1,(r0) - clrl r0 - rsb - - .align 1 -JSBENTRY(Subyte, R0|R1) - probew $3,$1,(r0) - beql fserr - movb r1,(r0) - clrl r0 - rsb + movl %edx,%cr3 # context switch -/* - * Copy 1 relocation unit (NBPG bytes) - * from user virtual address to physical address - */ -ENTRY(copyseg, 0) - bisl3 $PG_V|PG_KW,8(ap),_CMAP2 - mtpr $_CADDR2,$TBIS # invalidate entry for copy - movc3 $NBPG,*4(ap),_CADDR2 - ret + movl $_u,%edx -/* - * zero out physical memory - * specified in relocation units (NBPG bytes) - */ -ENTRY(clearseg, 0) - bisl3 $PG_V|PG_KW,4(ap),_CMAP1 - mtpr $_CADDR1,$TBIS - movc5 $0,(sp),$0,$NBPG,_CADDR1 +/* restore context */ + movl PCB_EBX(%ecx), %ebx + movl PCB_ESP(%ecx), %esp + movl PCB_EBP(%ecx), %ebp + movl PCB_ESI(%ecx), %esi + movl PCB_EDI(%ecx), %edi + movl PCB_EIP(%ecx), %eax + movl %eax, (%esp) + +#ifdef FPUNOTYET +#endif + + movl PCB_CMAP2(%edx),%eax # get temporary map + movl %eax,_CMAP2 # reload temporary map PTE +#ifdef FPUNOTYET +#endif + cmpl $0,PCB_SSWAP(%edx) # do an alternate return? + jne res3 # yes, go reload regs + # call _spl0 + cli + ret +res3: + xorl %eax,%eax # inline restore context + xchgl PCB_SSWAP(%edx),%eax # addr of saved context, clear it + movl 0(%eax),%ebx # restore ebx + movl 4(%eax),%esp # restore esp + movl 8(%eax),%ebp # restore ebp + movl 12(%eax),%esi # restore esi + movl 16(%eax),%edi # restore edi + movl 20(%eax),%edx # get rta + movl %edx,(%esp) # put in return frame + xorl %eax,%eax # return (1); + incl %eax + sti ret /* - * Check address. - * Given virtual address, byte count, and rw flag - * returns 0 on no access. + * Resume(p_addr) + * current just used to fillout u. tss so fork can fake a return to swtch + * [ all thats really needed is esp and eip ] */ -ENTRY(useracc, 0) - movl 4(ap),r0 # get va - movl 8(ap),r1 # count - tstl 12(ap) # test for read access ? - bneq userar # yes - cmpl $NBPG,r1 # can we do it in one probe ? - bgeq uaw2 # yes -uaw1: - probew $3,$NBPG,(r0) - beql uaerr # no access - addl2 $NBPG,r0 - acbl $NBPG+1,$-NBPG,r1,uaw1 -uaw2: - probew $3,r1,(r0) - beql uaerr - movl $1,r0 +ENTRY(resume) + movl 4(%esp),%ecx + movl (%esp),%eax + movl %eax, PCB_EIP(%ecx) + movl %ebx, PCB_EBX(%ecx) + movl %esp, PCB_ESP(%ecx) + movl %ebp, PCB_EBP(%ecx) + movl %esi, PCB_ESI(%ecx) + movl %edi, PCB_EDI(%ecx) +#ifdef FPUNOTYET +#endif + movl $0,%eax ret -userar: - cmpl $NBPG,r1 - bgeq uar2 -uar1: - prober $3,$NBPG,(r0) - beql uaerr - addl2 $NBPG,r0 - acbl $NBPG+1,$-NBPG,r1,uar1 -uar2: - prober $3,r1,(r0) - beql uaerr - movl $1,r0 +.data + .globl _cyloffset +_cyloffset: .long 0 + .globl _nofault +_nofault: .long 0 +.text + # To be done: + .globl _addupc + .globl _astoff + .globl _doadump + .globl _inittodr + .globl _ovbcopy + .globl _physaddr +_addupc: + .byte 0xcc +_astoff: ret -uaerr: - clrl r0 +_doadump: + .byte 0xcc +_ovbcopy: + .byte 0xcc +_physaddr: + .byte 0xcc + .globl _svfpsp,_rsfpsp +_svfpsp: + popl %eax + movl %esp,svesp + movl %ebp,svebp + pushl %eax ret -/* - * kernacc - check for kernel access privileges - * - * We can t use the probe instruction directly because - * it ors together current and previous mode. - */ - ENTRY(kernacc, 0) - movl 4(ap),r0 # virtual address - bbcc $31,r0,kacc1 - bbs $30,r0,kacerr - mfpr $SBR,r2 # address and length of page table (system) - bbss $31,r2,0f; 0: - 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 - addl2 $NBPG-1,r1 - ashl $-PGSHIFT,r0,r0 - ashl $-PGSHIFT,r1,r1 - bbs $31,4(ap),kacc6 - 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 - bgtr kacerr # address too high -kacc4: - movl (r2)[r0],r3 - bbc $31,4(ap),kacc4a - bbc $31,r3,kacerr # valid bit is off -kacc4a: - cmpzv $27,$4,r3,$1 # check protection code - bleq kacerr # no access allowed - tstb 12(ap) - bneq kacc5 # only check read access - cmpzv $27,$2,r3,$3 # check low 2 bits of prot code - beql kacerr # no write access -kacc5: - aoblss r1,r0,kacc4 # next page - movl $1,r0 # no errors +_rsfpsp: + popl %eax + movl svesp,%esp + movl svebp,%ebp + pushl %eax ret -kacerr: - clrl r0 # error - ret -/* - * 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) - * - * Built in constants: - * CLSIZE of 2, any bit fields in pte s - */ - .text - .globl Fastreclaim -Fastreclaim: - PUSHR -#ifdef GPROF - movl fp,-(sp) - movab 12(sp),fp - jsb mcount - movl (sp)+,fp -#endif GPROF - extzv $9,$23,28(sp),r3 # virtual address - bicl2 $1,r3 # v = clbase(btop(virtaddr)); - movl _u+U_PROCP,r5 # p = u.u_procp - # from vtopte(p, v) ... - movl $1,r2 # type = CTEXT; - cmpl r3,P_TSIZE(r5) - jlssu 1f # if (isatsv(p, v)) { - addl3 P_TSIZE(r5),P_DSIZE(r5),r0 - cmpl r3,r0 - jgequ 2f - clrl r2 # type = !CTEXT; -1: - ashl $2,r3,r4 - addl2 P_P0BR(r5),r4 # tptopte(p, vtotp(p, v)); - jbr 3f -2: - cvtwl P_SZPT(r5),r4 # } else (isassv(p, v)) { - ashl $7,r4,r4 - subl2 $0x400000,r4 - addl2 r3,r4 - ashl $2,r4,r4 - addl2 P_P0BR(r5),r4 # sptopte(p, vtosp(p, v)); - clrl r2 # type = !CTEXT; -3: # } - bitb $0x82,3(r4) - beql 2f # if (pte->pg_v || pte->pg_fod) - POPR; rsb # let pagein handle it -2: - bicl3 $0xffe00000,(r4),r0 - jneq 2f # if (pte->pg_pfnum == 0) - POPR; rsb # let pagein handle it -2: - subl2 _firstfree,r0 - ashl $-1,r0,r0 - incl r0 # pgtocm(pte->pg_pfnum) - mull2 $SZ_CMAP,r0 - addl2 _cmap,r0 # &cmap[pgtocm(pte->pg_pfnum)] - tstl r2 - jeql 2f # if (type == CTEXT && - jbc $C_INTRANS,(r0),2f # c_intrans) - POPR; rsb # let pagein handle it -2: - jbc $C_FREE,(r0),2f # if (c_free) - POPR; rsb # let pagein handle it -2: - 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; -2: - bicw3 $0x7f,2(r4),r0 - bicw3 $0xff80,6(r4),r1 - bisw3 r0,r1,6(r4) # distcl(pte); - ashl $PGSHIFT,r3,r0 - mtpr r0,$TBIS - addl2 $NBPG,r0 - mtpr r0,$TBIS # tbiscl(v); - tstl r2 - jeql 2f # if (type == CTEXT) - movl P_TEXTP(r5),r0 - movl X_CADDR(r0),r5 # for (p = p->p_textp->x_caddr; p; ) { - jeql 2f - ashl $2,r3,r3 -3: - 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; - jneq 3b # } -2: # collect a few statistics... - incl _u+U_RU+RU_MINFLT # u.u_ru.ru_minflt++; - moval _cnt,r0 - 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++; - POPR - addl2 $8,sp # pop pc, code - mtpr $HIGH,$IPL ## dont go to a higher IPL (GROT) - rei -#endif newway + +svesp: .long 0 +svebp: .long 0 -- 2.20.1