📄 locore.s
字号:
* that when the MMU is turned on, all prefetched addresses (including * the PC) are valid. In order guarentee that, we use the last physical * page (which is conveniently mapped == VA) and load it up with enough * code to defeat the prefetch, then we execute the jump back to here. * * Is this all really necessary, or am I paranoid?? */ RELOC(_Sysseg, a0) | system segment table addr movl a0@,d1 | read value (a KVA) addl a5,d1 | convert to PA RELOC(_mmutype, a0) tstl a0@ | HP MMU? jeq Lhpmmu2 | yes, skip cmpl #-2,a0@ | 68040? jne Lmotommu1 | no, skip .long 0x4e7b1807 | movc d1,srp jra LstploaddoneLmotommu1: RELOC(_protorp, a0) movl #0x80000202,a0@ | nolimit + share global + 4 byte PTEs movl d1,a0@(4) | + segtable address pmove a0@,srp | load the supervisor root pointer movl #0x80000002,a0@ | reinit upper half for CRP loads jra Lstploaddone | doneLhpmmu2: moveq #PGSHIFT,d2 lsrl d2,d1 | convert to page frame movl d1,INTIOBASE+MMUBASE+MMUSSTP | load in sysseg table registerLstploaddone: lea MAXADDR,a2 | PA of last RAM page RELOC(Lhighcode, a1) | addr of high code RELOC(Lehighcode, a3) | end addrLcodecopy: movw a1@+,a2@+ | copy a word cmpl a3,a1 | done yet? jcs Lcodecopy | no, keep going jmp MAXADDR | go for it!Lhighcode: RELOC(_mmutype, a0) tstl a0@ | HP MMU? jeq Lhpmmu3 | yes, skip cmpl #-2,a0@ | 68040? jne Lmotommu2 | no, skip movw #0,INTIOBASE+MMUBASE+MMUCMD+2 movw #MMU_IEN+MMU_CEN+MMU_FPE,INTIOBASE+MMUBASE+MMUCMD+2 | enable FPU and caches moveq #0,d0 | ensure TT regs are disabled .long 0x4e7b0004 | movc d0,itt0 .long 0x4e7b0005 | movc d0,itt1 .long 0x4e7b0006 | movc d0,dtt0 .long 0x4e7b0007 | movc d0,dtt1 .word 0xf4d8 | cinva bc .word 0xf518 | pflusha movl #0x8000,d0 .long 0x4e7b0003 | movc d0,tc movl #0x80008000,d0 movc d0,cacr | turn on both caches jmp Lenab1Lmotommu2: movl #MMU_IEN+MMU_FPE,INTIOBASE+MMUBASE+MMUCMD | enable 68881 and i-cache movl #0x82c0aa00,a2@ | value to load TC with pmove a2@,tc | load it jmp Lenab1Lhpmmu3: movl #0,INTIOBASE+MMUBASE+MMUCMD | clear external cache movl #MMU_ENAB,INTIOBASE+MMUBASE+MMUCMD | turn on MMU jmp Lenab1 | jmp to mapped codeLehighcode:/* * Should be running mapped from this point on */Lenab1:/* check for internal HP-IB in SYSFLAG */ btst #5,0xfffffed2 | internal HP-IB? jeq Lfinish | yes, have HP-IB just continue clrl _internalhpib | no, clear associated addressLfinish:/* select the software page size now */ lea tmpstk,sp | temporary stack jbsr _vm_set_page_size | select software page size/* set kernel stack, user SP, and initial pcb */ lea _kstack,a1 | proc0 kernel stack lea a1@(UPAGES*NBPG-4),sp | set kernel stack to end of area movl #USRSTACK-4,a2 movl a2,usp | init user SP movl _proc0paddr,a1 | get proc0 pcb addr movl a1,_curpcb | proc0 is running#ifdef FPCOPROC clrl a1@(PCB_FPCTX) | ensure null FP context movl a1,sp@- jbsr _m68881_restore | restore it (does not kill a1) addql #4,sp#endif/* flush TLB and turn on caches */ jbsr _TBIA | invalidate TLB cmpl #-2,_mmutype | 68040? jeq Lnocache0 | yes, cache already on movl #CACHE_ON,d0 movc d0,cacr | clear cache(s) tstl _ectype jeq Lnocache0 MMUADDR(a0) orl #MMU_CEN,a0@(MMUCMD) | turn on external cacheLnocache0:/* final setup for C code */ jbsr _isrinit | be ready for stray ints movw #PSL_LOWIPL,sr | lower SPL movl d7,_boothowto | save reboot flags movl d6,_bootdev | and boot device/* * Create a fake exception frame that returns to user mode, * make space for the rest of a fake saved register set, and * pass the first available RAM and a pointer to the register * set to "main()". "main()" will call "icode()", which fakes * an "execve()" system call, which is why we need to do that * ("main()" sets "u.u_ar0" to point to the register set). * When "main()" returns, we're running in process 1 and have * successfully faked the "execve()". We load up the registers from * that set; the "rte" loads the PC and PSR, which jumps to "init". */ clrw sp@- | vector offset/frame type clrl sp@- | PC - filled in by "execve" movw #PSL_USER,sp@- | in user mode clrw sp@- | pad SR to longword lea sp@(-64),sp | construct space for D0-D7/A0-A7 pea sp@ | addr of space for D0 jbsr _main | main(firstaddr, r0) addql #4,sp | pop args cmpl #-2,_mmutype | 68040? jne Lnoflush | no, skip .word 0xf478 | cpusha dc .word 0xf498 | cinva icLnoflush: movl sp@(60),a0 | grab and load movl a0,usp | user SP moveml sp@+,#0x7FFF | load most registers (all but SSP) addql #6,sp | pop SSP and align word rte/* * Signal "trampoline" code (18 bytes). Invoked from RTE setup by sendsig(). * * Stack looks like: * * sp+0 -> signal number * sp+4 signal specific code * sp+8 pointer to signal context frame (scp) * sp+12 address of handler * sp+16 saved hardware state * . * . * scp+0-> beginning of signal context frame */ .globl _sigcode, _esigcode, _sigcodetrap .data_sigcode: movl sp@(12),a0 | signal handler addr (4 bytes) jsr a0@ | call signal handler (2 bytes) addql #4,sp | pop signo (2 bytes)_sigcodetrap: trap #1 | special syscall entry (2 bytes) movl d0,sp@(4) | save errno (4 bytes) moveq #1,d0 | syscall == exit (2 bytes) trap #0 | exit(errno) (2 bytes) .align 2_esigcode:/* * Primitives */ #ifdef __STDC__#define EXPORT(name) .globl _ ## name; _ ## name:#else#define EXPORT(name) .globl _/**/name; _/**/name:#endif#ifdef GPROF#if __GNUC__ >= 2#define ENTRY(name) EXPORT(name) link a6,\#0; jbsr mcount; unlk a6#else#define ENTRY(name) EXPORT(name) link a6,#0; jbsr mcount; unlk a6#endif#define ALTENTRY(name, rname) ENTRY(name); jra rname+12#else#define ENTRY(name) EXPORT(name)#define ALTENTRY(name, rname) ENTRY(name)#endif/* * For gcc2 */ENTRY(__main) rts/* * copypage(fromaddr, toaddr) * * Optimized version of bcopy for a single page-aligned NBPG byte copy. */ENTRY(copypage) movl sp@(4),a0 | source address movl sp@(8),a1 | destination address movl #NBPG/32,d0 | number of 32 byte chunks#if defined(HP380) cmpl #-2,_mmutype | 68040? jne Lmlloop | no, use movlLm16loop: .long 0xf6209000 | move16 a0@+,a1@+ .long 0xf6209000 | move16 a0@+,a1@+ subql #1,d0 jne Lm16loop rts#endifLmlloop: movl a0@+,a1@+ movl a0@+,a1@+ movl a0@+,a1@+ movl a0@+,a1@+ movl a0@+,a1@+ movl a0@+,a1@+ movl a0@+,a1@+ movl a0@+,a1@+ subql #1,d0 jne Lmlloop rts/* * copyinstr(fromaddr, toaddr, maxlength, &lencopied) * * Copy a null terminated string from the user address space into * the kernel address space. * * NOTE: maxlength must be < 64K (due to use of DBcc) */ENTRY(copyinstr) movl _curpcb,a0 | current pcb movl #Lcisflt1,a0@(PCB_ONFAULT) | set up to catch faults movl sp@(4),a0 | a0 = fromaddr movl sp@(8),a1 | a1 = toaddr moveq #0,d0 movw sp@(14),d0 | d0 = maxlength jlt Lcisflt1 | negative count, error jeq Lcisdone | zero count, all done subql #1,d0 | set up for dbeqLcisloop: movsb a0@+,d1 | grab a byte nop movb d1,a1@+ | copy it dbeq d0,Lcisloop | if !null and more, continue jne Lcisflt2 | ran out of room, error moveq #0,d0 | got a null, all doneLcisdone: tstl sp@(16) | return length desired? jeq Lcisret | no, just return subl sp@(4),a0 | determine how much was copied movl sp@(16),a1 | return location movl a0,a1@ | stash itLcisret: movl _curpcb,a0 | current pcb clrl a0@(PCB_ONFAULT) | clear fault addr rtsLcisflt1: moveq #EFAULT,d0 | copy fault jra LcisdoneLcisflt2: moveq #ENAMETOOLONG,d0 | ran out of space jra Lcisdone /* * copyoutstr(fromaddr, toaddr, maxlength, &lencopied) * * Copy a null terminated string from the kernel * address space to the user address space. * * NOTE: maxlength must be < 64K (due to use of DBcc) */ENTRY(copyoutstr) movl _curpcb,a0 | current pcb movl #Lcosflt1,a0@(PCB_ONFAULT) | set up to catch faults movl sp@(4),a0 | a0 = fromaddr movl sp@(8),a1 | a1 = toaddr moveq #0,d0 movw sp@(14),d0 | d0 = maxlength jlt Lcosflt1 | negative count, error jeq Lcosdone | zero count, all done subql #1,d0 | set up for dbeqLcosloop: movb a0@+,d1 | grab a byte movsb d1,a1@+ | copy it nop dbeq d0,Lcosloop | if !null and more, continue jne Lcosflt2 | ran out of room, error moveq #0,d0 | got a null, all doneLcosdone: tstl sp@(16) | return length desired? jeq Lcosret | no, just return subl sp@(4),a0 | determine how much was copied movl sp@(16),a1 | return location movl a0,a1@ | stash itLcosret: movl _curpcb,a0 | current pcb clrl a0@(PCB_ONFAULT) | clear fault addr rtsLcosflt1: moveq #EFAULT,d0 | copy fault jra LcosdoneLcosflt2: moveq #ENAMETOOLONG,d0 | ran out of space jra Lcosdone /* * copystr(fromaddr, toaddr, maxlength, &lencopied) * * Copy a null terminated string from one point to another in * the kernel address space. * * NOTE: maxlength must be < 64K (due to use of DBcc) */ENTRY(copystr) movl sp@(4),a0 | a0 = fromaddr movl sp@(8),a1 | a1 = toaddr moveq #0,d0 movw sp@(14),d0 | d0 = maxlength jlt Lcsflt1 | negative count, error jeq Lcsdone | zero count, all done subql #1,d0 | set up for dbeqLcsloop: movb a0@+,a1@+ | copy a byte dbeq d0,Lcsloop | if !null and more, continue jne Lcsflt2 | ran out of room, error moveq #0,d0 | got a null, all doneLcsdone: tstl sp@(16) | return length desired? jeq Lcsret | no, just return subl sp@(4),a0 | determine how much was copied movl sp@(16),a1 | return location movl a0,a1@ | stash itLcsret: rtsLcsflt1: moveq #EFAULT,d0 | copy fault jra LcsdoneLcsflt2: moveq #ENAMETOOLONG,d0 | ran out of space jra Lcsdone /* * Copyin(from_user, to_kernel, len) * Copyout(from_kernel, to_user, len) * * Copy specified amount of data between kernel and user space. * * XXX both use the DBcc instruction which has 16-bit limitation so only * 64k units can be copied, where "unit" is either a byte or a longword * depending on alignment. To be safe, assume it can copy at most * 64k bytes. Don't make MAXBSIZE or MAXPHYS larger than 64k without * fixing this code! */ENTRY(copyin) movl sp@(12),d0 | get size#ifdef MAPPEDCOPY .globl _mappedcopysize,_mappedcopyin cmpl _mappedcopysize,d0 | size >= mappedcopysize jcc _mappedcopyin | yes, go do it the new way#endif movl d2,sp@- | scratch register movl _curpcb,a0 | current pcb movl #Lciflt,a0@(PCB_ONFAULT) | set up to catch faults tstl d0 | check count jlt Lciflt | negative, error jeq Lcidone | zero, done movl sp@(8),a0 | src address movl sp@(12),a1 | dest address movl a0,d2 btst #0,d2 | src address odd? jeq Lcieven | no, go check dest movsb a0@+,d1 | yes, get a byte nop movb d1,a1@+ | put a byte subql #1,d0 | adjust count jeq Lcidone | exit if doneLcieven: movl a1,d2 btst #0,d2 | dest address odd? jne Lcibloop | yes, must copy by bytes movl d0,d2 | no, get count lsrl #2,d2 | convert to longwords jeq Lcibloop | no longwords, copy bytesLcilloop: movsl a0@+,d1 | get a long nop movl d1,a1@+ | put a long subql #1,d2 jne Lcilloop | til done andl #3,d0 | what remains jeq Lcidone | all doneLcibloop: movsb a0@+,d1 | get a byte nop movb d1,a1@+ | put a byte subql #1,d0 jne Lcibloop | til doneLcidone: movl _curpcb,a0 | current pcb clrl a0@(PCB_ONFAULT) | clear fault catcher movl sp@+,d2 | restore scratch reg rtsLciflt: moveq #EFAULT,d0 | got a fault jra LcidoneENTRY(copyout) movl sp@(12),d0 | get size#ifdef MAPPEDCOPY .globl _mappedcopysize,_mappedcopyout cmpl _mappedcopysize,d0 | size >= mappedcopysize jcc _mappedcopyout | yes, go do it the new way#endif movl d2,sp@- | scratch register movl _curpcb,a0 | current pcb movl #Lcoflt,a0@(PCB_ONFAULT) | catch faults tstl d0 | check count jlt Lcoflt | negative, error jeq Lcodone | zero, done movl sp@(8),a0 | src address movl sp@(12),a1 | dest address movl a0,d2 btst #0,d2 | src address odd? jeq Lcoeven | no, go check dest movb a0@+,d1 | yes, get a byte movsb d1,a1@+ | put a byte nop subql #1,d0 | adjust count jeq Lcodone | exit if doneLcoeven: movl a1,d2 btst #0,d2 | dest address odd? jne Lcobloop | yes, must copy by bytes movl d0,d2 | no, get count lsrl #2,d2 | convert to longwords jeq Lcobloop | no longwords, copy bytesLcolloop: movl a0@+,d1 | get a long movsl d1,a1@+ | put a long nop subql #1,d2 jne Lcolloop | til done andl #3,d0 | what remains jeq Lcodone | all doneLcobloop: movb a0@+,d1 | get a byte movsb d1,a1@+ | put a byte nop subql #1,d0 jne Lcobloop | til doneLcodone: movl _curpcb,a0 | current pcb clrl a0@(PCB_ONFAULT) | clear fault catcher movl sp@+,d2 | restore scratch reg rtsLcoflt: moveq #EFAULT,d0 | got a fault jra Lcodone/* * non-local gotos */ENTRY(setjmp) movl sp@(4),a0 | savearea pointer moveml #0xFCFC,a0@ | save d2-d7/a2-a7 movl sp@,a0@(48) | and return address moveq #0,d0 | return 0 rtsENTRY(longjmp) movl sp@(4),a0 moveml a0@+,#0xFCFC movl a0@,sp@ moveq #1,d0 rts/* * The following primitives manipulate the run queues. _whichqs tells which * of the 32 queues _qs have processes in them. Setrunqueue 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_priority, divided * by 4 actually to shrink the 0-127 range of priorities into the 32 available * queues. */ .globl _whichqs,_qs,_cnt,_panic .globl _curproc,_want_resched/* * Setrunqueue(p) *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -