📄 locore.s
字号:
movl #84,sp@- | default: adjust by 84 bytes moveml #0xFFFF,sp@- | save user registers movl usp,a0 | save the user SP movl a0,sp@(FR_SP) | in the savearea movl #SYS_sigreturn,sp@- | push syscall number jbsr _syscall | handle it addql #4,sp | pop syscall# movl sp@(FR_SP),a0 | grab and restore movl a0,usp | user SP lea sp@(FR_HW),a1 | pointer to HW frame movw sp@(FR_ADJ),d0 | do we need to adjust the stack? jeq Lsigr1 | no, just continue moveq #92,d1 | total size subw d0,d1 | - hole size = frame size lea a1@(92),a0 | destination addw d1,a1 | source lsrw #1,d1 | convert to word count subqw #1,d1 | minus 1 for dbfLsigrlp: movw a1@-,a0@- | copy a word dbf d1,Lsigrlp | continue movl a0,a1 | new HW frame baseLsigr1: movl a1,sp@(FR_SP) | new SP value moveml sp@+,#0x7FFF | restore user registers movl sp@,sp | and our SP jra rei | all done/* * Interrupt handlers. * All DIO device interrupts are auto-vectored. Most can be configured * to interrupt in the range IPL2 to IPL5. Here are our assignments: * * Level 0: Spurious: ignored. * Level 1: (low XP) * Level 2: SCSI * Level 3: LANCE * Level 4: [PC98] * Level 5: Clock * Level 6: RS232C * Level 7: Non-maskable: parity errors, Abort SW */ .globl _hardclock, _nmihand_spurintr: addql #1,_intrcnt+0 addql #1,_cnt+V_INTR jra rei_lev1intr: addql #1,_intrcnt+4 addql #1,_cnt+V_INTR jra rei | XP not surpported yet XXXX_lev2intr: addql #1,_intrcnt+8 moveml #0xC0C0,sp@- jbsr __scintr moveml sp@+,#0x0303 addql #1,_cnt+V_INTR jra rei_lev3intr: addql #1,_intrcnt+12 moveml #0xC0C0,sp@- jbsr __leintr moveml sp@+,#0x0303 addql #1,_cnt+V_INTR jra rei_lev4intr: addql #1,_intrcnt+16 addql #1,_cnt+V_INTR jra rei | EX-PC not surpported yet XXXX_lev6intr: addql #1,_intrcnt+24 moveml #0xC0C0,sp@- jbsr __siointr moveml sp@+,#0x0303 addql #1,_cnt+V_INTR jra rei_lev5intr:#ifdef STACKCHECK .globl _panicstr,_badkstack cmpl #_kstack+NBPG,sp | are we still in stack page? jcc Lstackok | yes, continue normally tstl _curproc | if !curproc could have switch_exited, jeq Lstackok | might be on tmpstk tstl _panicstr | have we paniced? jne Lstackok | yes, do not re-panic movl sp@(4),tmpstk-4 | no, copy common movl sp@,tmpstk-8 | frame info movl sp,tmpstk-16 | no, save original SP lea tmpstk-16,sp | switch to tmpstk moveml #0xFFFE,sp@- | push remaining registers movl #1,sp@- | is an overflow jbsr _badkstack | badkstack(1, frame) addql #4,sp moveml sp@+,#0x7FFF | restore most registers movl sp@,sp | and SPLstackok:#endif moveml #0xC0C0,sp@- lea sp@(16),a1 | a1 = &clockframe btst #CLK_INT,CLOCK_REG | system-clock intrrupt? jeq Lnottimer | no, skip hardclock movb #CLK_CLR,CLOCK_REG | clear system-clock interrupt tstl _clock_on | system-clock started? jeq Lnottimer | no, skip hardclock addql #1,_intrcnt+28 | count hardclock interrupt movl a1,sp@- jbsr _hardclock | hardclock(&frame) addql #4,spLnottimer: moveml sp@+,#0x0303 | restore scratch regs addql #1,_cnt+V_INTR | chalk up another interrupt jra rei | all done_lev7intr: addql #1,_intrcnt+36 clrl sp@- | pad SR to longword moveml #0xFFFF,sp@- | save registers movl usp,a0 | and save movl a0,sp@(FR_SP) | the user stack pointer jbsr _nmihand | call handler movl sp@(FR_SP),a0 | restore movl a0,usp | user SP moveml sp@+,#0x7FFF | and remaining registers addql #8,sp | pop SSP and align word jra rei | all done/* * Emulation of VAX REI instruction. * * This code deals with checking for and servicing ASTs * (profiling, scheduling) and software interrupts (network, softclock). * We check for ASTs first, just like the VAX. To avoid excess overhead * the T_ASTFLT handling code will also check for software interrupts so we * do not have to do it here. After identifing that we need an AST we * drop the IPL to allow device interrupts. * * This code is complicated by the fact that sendsig may have been called * necessitating a stack cleanup. */ .comm _ssir,1 .globl _astpendingrei:#ifdef STACKCHECK tstl _panicstr | have we paniced? jne Ldorte1 | yes, do not make matters worse#endif tstl _astpending | AST pending? jeq Lchksir | no, go check for SIRLrei1: btst #5,sp@ | yes, are we returning to user mode? jne Lchksir | no, go check for SIR movw #PSL_LOWIPL,sr | lower SPL clrl sp@- | stack adjust moveml #0xFFFF,sp@- | save all registers movl usp,a1 | including movl a1,sp@(FR_SP) | the users SP clrl sp@- | VA == none clrl sp@- | code == none movl #T_ASTFLT,sp@- | type == async system trap jbsr _trap | go handle it lea sp@(12),sp | pop value args movl sp@(FR_SP),a0 | restore user SP movl a0,usp | from save area movw sp@(FR_ADJ),d0 | need to adjust stack? jne Laststkadj | yes, go to it moveml sp@+,#0x7FFF | no, restore most user regs addql #8,sp | toss SP and stack adjust#ifdef STACKCHECK jra Ldorte#else rte | and do real RTE#endifLaststkadj: lea sp@(FR_HW),a1 | pointer to HW frame addql #8,a1 | source pointer movl a1,a0 | source addw d0,a0 | + hole size = dest pointer movl a1@-,a0@- | copy movl a1@-,a0@- | 8 bytes movl a0,sp@(FR_SP) | new SSP moveml sp@+,#0x7FFF | restore user registers movl sp@,sp | and our SP#ifdef STACKCHECK jra Ldorte#else rte | and do real RTE#endifLchksir: tstb _ssir | SIR pending? jeq Ldorte | no, all done movl d0,sp@- | need a scratch register movw sp@(4),d0 | get SR andw #PSL_IPL7,d0 | mask all but IPL jne Lnosir | came from interrupt, no can do movl sp@+,d0 | restore scratch registerLgotsir: movw #SPL1,sr | prevent others from servicing int tstb _ssir | too late? jeq Ldorte | yes, oh well... clrl sp@- | stack adjust moveml #0xFFFF,sp@- | save all registers movl usp,a1 | including movl a1,sp@(FR_SP) | the users SP clrl sp@- | VA == none clrl sp@- | code == none movl #T_SSIR,sp@- | type == software interrupt jbsr _trap | go handle it lea sp@(12),sp | pop value args movl sp@(FR_SP),a0 | restore movl a0,usp | user SP moveml sp@+,#0x7FFF | and all remaining registers addql #8,sp | pop SP and stack adjust#ifdef STACKCHECK jra Ldorte#else rte#endifLnosir: movl sp@+,d0 | restore scratch registerLdorte:#ifdef STACKCHECK movw #SPL6,sr | avoid trouble btst #5,sp@ | are we returning to user mode? jne Ldorte1 | no, skip it movl a6,tmpstk-20 movl d0,tmpstk-76 moveq #0,d0 movb sp@(6),d0 | get format/vector lsrl #3,d0 | convert to index lea _exframesize,a6 | into exframesize addl d0,a6 | to get pointer to correct entry movw a6@,d0 | get size for this frame addql #8,d0 | adjust for unaccounted for bytes lea _kstackatbase,a6 | desired stack base subl d0,a6 | - frame size == our stack cmpl a6,sp | are we where we think? jeq Ldorte2 | yes, skip it lea tmpstk,a6 | will be using tmpstk movl sp@(4),a6@- | copy common movl sp@,a6@- | frame info clrl a6@- movl sp,a6@- | save sp subql #4,a6 | skip over already saved a6 moveml #0x7FFC,a6@- | push remaining regs (d0/a6/a7 done) lea a6@(-4),sp | switch to tmpstk (skip saved d0) clrl sp@- | is an underflow jbsr _badkstack | badkstack(0, frame) addql #4,sp moveml sp@+,#0x7FFF | restore most registers movl sp@,sp | and SP rteLdorte2: movl tmpstk-76,d0 movl tmpstk-20,a6Ldorte1:#endif rte | real return/* * Kernel access to the current processes kernel stack is via a fixed * virtual address. It is at the same address as in the users VA space. * Umap contains the KVA of the first of UPAGES PTEs mapping VA _kstack. */ .data .set _kstack,KERNELSTACK | KERNELSTACK(0x3ff00000) != USRSTACK_Umap: .long 0 .globl _kstack, _Umap/* * Initialization * * Kernel is loaded at 0. * VBR contains zero from ROM. Exceptions will continue to vector * through ROM until MMU is turned on at which time they will vector * through our table (vectors.s). */ .comm _lowram,4 .text .globl _edata .globl _etext,_end .globl startstart: movw #PSL_HIGHIPL,sr | no interrupts lea tmpstk,sp | give ourselves a temporary stack clrl d0 | XXXX if loader set vbr = 0 movc d0,vbr | XXXX please remove these 2 lines/* * a5 contains parameters address from booter. * First, we copy whole parameters to Kernel InterFace Field */ movl #KIFF_SIZE,sp@- | KIFF size pea _KernInter | KIFF address pea a5@ | bootor's KIFF address jbsr _bcopy lea sp@(12),sp | pop value args movl a5@(KI_MAXADDR),d0 | maxaddr moveq #PGSHIFT,d1 lsrl d1,d0 | convert to page (click) number movl d0,_maxmem | argument saved in maxmem movl d0,_physmem | physmem = maxmem clrl _lowram | lowram = 0 movl #0,a5 | kernel is loaded at 0 movl #CACHE_OFF,d0 movc d0,cacr | clear and disable on-chip cache(s)#if defined(LUNA2)/* determine our CPU/MMU combo - check for all regardless of kernel config */ movl #0x200,d0 | data freeze bit movc d0,cacr | only exists on 68030 movc cacr,d0 | read it back tstl d0 | zero? jeq Lnot68030 | yes, we have 68040(LUNA2) movl #1,_machineid | no, must be a LUNA-I movl #-1,_mmutype | set to reflect 68030 PMMU jra Lstart1Lnot68030: movl #2,_machineid | must be a LUNA-II movl #-2,_mmutype | set to reflect 68040 MMU#ifdef HPFPLIB movl #3,_processor | HP-UX style processor id#endifLstart1:#endif/* set 60 to hz, when running LUNA-I */ .globl _modify_clock_param jbsr _modify_clock_param/* initialize source/destination control registers for movs */ moveq #FC_USERD,d0 | user space movc d0,sfc | as source movc d0,dfc | and destination of transfers /* * LUNA PIO initialization. */ movw PIO0_A,d0 | dipsw-1,2 (from port A&B) movw d0,_dipswitch/* configure kernel and proc0 VA space so we can get going */ .globl _Sysseg, _pmap_bootstrap, _avail_start movl #_end,d5 | end of static kernel text/data addl #NBPG-1,d5 andl #PG_FRAME,d5 | round to a page movl d5,a4 | PA=VA pea a5@ | firstpa pea a4@ | nextpa jbsr _pmap_bootstrap | bootstrap(firstpa, nextpa) addql #8,sp/* * Prepare to enable MMU. */ movl _Sysseg,d1 | system segment table addr read value (a KVA)#if defined(LUNA2) cmpl #-2,_mmutype | 68040? jne Lmotommu1 | no, skip .long 0x4e7b1807 | movc d1,srp/* we must set tt-registers here */ movl #0x403FA040,d0 | tt0 for LUNA2 0x40000000-0x7fffffff .long 0x4e7b0004 | movc d0,itt0 .long 0x4e7b0006 | movc d0,dtt0 movl #0x807FA040,d0 | tt1 for LUNA2 0x80000000-0xffffffff .long 0x4e7b0005 | movc d0,itt1 .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 Lenab1Lmotommu1:#endif lea _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/* we must set tt-registers here */ lea _protott0,a0 | tt0 for LUNA1 0x40000000-0x7fffffff .word 0xf010 | pmove a0@,mmutt0 .word 0x0800 lea _protott1,a0 | tt1 for LUNA1 0x80000000-0xffffffff .word 0xf010 | pmove a0@,mmutt1 .word 0x0c00 lea _mapping_tc,a2 movl #0x82c0aa00,a2@ | value to load TC with pmove a2@,tc | load it/* * Should be running mapped from this point on */Lenab1:#ifdef FPCOPROC/* fpp check */ movl a1,sp@- jbsr _checkfpp | check fpp frestore _fppnull | reset movl sp@+,a1#endif/* 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#if defined(LUNA2) cmpl #-2,_mmutype | 68040? jeq Lnocache0 | yes, cache already on#endif movl #CACHE_ON,d0 movc d0,cacr | clear cache(s)Lnocache0:/* final setup for C code */ 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#if defined(LUNA2) cmpl #-2,_mmutype | 68040? jne Lnoflush | no, skip .word 0xf478 | cpusha dc .word 0xf498 | cinva icLnoflush:#endif 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -