📄 locore.s
字号:
#ifdef KGDB moveq #T_TRACE,d0 movw sp@(FR_HW),d1 | get SSW andw #PSL_S,d1 | from user mode? jeq fault | no, regular fault movl d0,sp@- jbsr _kgdb_trap_glue | returns if no debugger addl #4,sp#endif moveq #T_TRACE,d0 jra fault/* * The sigreturn() syscall comes here. It requires special handling * because we must open a hole in the stack to fill in the (possibly much * larger) original stack frame. */sigreturn: lea sp@(-84),sp | leave enough space for largest frame movl sp@(84),sp@ | move up current 8 byte frame movl sp@(88),sp@(4) 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 IPL3 to IPL5. Here are our assignments: * * Level 0: Spurious: ignored. * Level 1: HIL * Level 2: * Level 3: Internal HP-IB, DCM * Level 4: "Fast" HP-IBs, SCSI * Level 5: DMA, Ethernet, Built-in RS232 (DCA) * Level 6: Clock * Level 7: Non-maskable: parity errors, RESET key */ .globl _hilint, _intrhand, _hardclock, _nmihand, _dmaintr .globl _dcafastservice_spurintr: addql #1,_intrcnt+0 addql #1,_cnt+V_INTR jra rei_lev1intr: moveml #0xC0C0,sp@- jbsr _hilint moveml sp@+,#0x0303 addql #1,_intrcnt+4 addql #1,_cnt+V_INTR jra rei/* * Check for unbuffered serial port (DCA) interrupts first in an attempt * to minimize received character lossage. Then we check for DMA activity * to reduce overhead there. */_lev5intr: moveml #0xC0C0,sp@- tstl _dcafastservice | unbuffered port active? jeq Ltrydma | no, check DMA clrl sp@- | yes, check DCA port 0 jbsr _dcaintr | first to avoid overflow addql #4,sp tstl d0 | did it belong to DCA? jeq Ltrydma | no, go try DMA moveml sp@+,#0x0303 addql #1,_intrcnt+20 addql #1,_cnt+V_INTR jra reiLtrydma: jbsr _dmaintr | check DMA channels tstl d0 | was it ours? jeq Lnotdma | no, go poll other devices moveml sp@+,#0x0303 addql #1,_intrcnt+24 addql #1,_cnt+V_INTR jra rei_lev2intr:_lev3intr:_lev4intr: moveml #0xC0C0,sp@-Lnotdma: lea _intrcnt,a0 movw sp@(22),d0 | use vector offset andw #0xfff,d0 | sans frame type addql #1,a0@(-0x60,d0:w) | to increment apropos counter movw sr,sp@- | push current SR value clrw sp@- | padded to longword jbsr _intrhand | handle interrupt addql #4,sp | pop SR moveml sp@+,#0x0303 addql #1,_cnt+V_INTR jra rei_lev6intr:#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@- | save scratch registers CLKADDR(a0) movb a0@(CLKSR),d0 | read clock statusLclkagain: btst #0,d0 | clear timer1 int immediately to jeq Lnotim1 | minimize chance of losing another movpw a0@(CLKMSB1),d1 | due to statintr processing delayLnotim1: btst #2,d0 | timer3 interrupt? jeq Lnotim3 | no, skip statclock movpw a0@(CLKMSB3),d1 | clear timer3 interrupt addql #1,_intrcnt+32 | count clock interrupts lea sp@(16),a1 | a1 = &clockframe movl d0,sp@- | save status movl a1,sp@- jbsr _statintr | statintr(&frame) addql #4,sp movl sp@+,d0 | restore pre-statintr status CLKADDR(a0)Lnotim3: btst #0,d0 | timer1 interrupt? jeq Lrecheck | no, skip hardclock addql #1,_intrcnt+28 | count hardclock interrupts lea sp@(16),a1 | a1 = &clockframe movl a1,sp@-#ifdef USELEDS .globl _ledaddr, _inledcontrol, _ledcontrol, _hz tstl _ledaddr | using LEDs? jeq Lnoled0 | no, skip this code movl heartbeat,d0 | get tick count addql #1,d0 | increment movl _hz,d1 lsrl #1,d1 | throb twice a second cmpl d0,d1 | are we there yet? jne Lnoled1 | no, nothing to do tstl _inledcontrol | already updating LEDs? jne Lnoled2 | yes, skip it movl #LED_PULSE,sp@- movl #LED_DISK+LED_LANRCV+LED_LANXMT,sp@- clrl sp@- jbsr _ledcontrol | toggle pulse, turn all others off lea sp@(12),spLnoled2: movql #0,d0Lnoled1: movl d0,heartbeatLnoled0:#endif jbsr _hardclock | hardclock(&frame) addql #4,sp CLKADDR(a0)Lrecheck: addql #1,_cnt+V_INTR | chalk up another interrupt movb a0@(CLKSR),d0 | see if anything happened jmi Lclkagain | while we were in hardclock/statintr moveml sp@+,#0x0303 | restore scratch registers jra rei | all done_lev7intr: addql #1,_intrcnt+36 clrl sp@- 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 SP and stack adjust 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,USRSTACK .set _kstackatbase,USRSTACK+UPAGES*NBPG-4 .globl _kstackatbase_Umap: .long 0 .globl _kstack, _Umap#define RELOC(var, ar) \ lea var,ar; \ addl a5,ar/* * Initialization * * A5 contains physical load point from boot * 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 RELOC(tmpstk, a0) movl a0,sp | give ourselves a temporary stack RELOC(_lowram, a0) movl a5,a0@ | store start of physical memory movl #CACHE_OFF,d0 movc d0,cacr | clear and disable on-chip cache(s)/* determine our CPU/MMU combo - check for all regardless of kernel config */ movl #INTIOBASE+MMUBASE,a1 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 68020/68040 RELOC(_mmutype, a0) | no, we have 68030 movl #-1,a0@ | set to reflect 68030 PMMU RELOC(_machineid, a0) movl #0x80,a1@(MMUCMD) | set magic cookie movl a1@(MMUCMD),d0 | read it back btst #7,d0 | cookie still on? jeq Lnot370 | no, 360 or 375 movl #0,a1@(MMUCMD) | clear magic cookie movl a1@(MMUCMD),d0 | read it back btst #7,d0 | still on? jeq Lisa370 | no, must be a 370 movl #5,a0@ | yes, must be a 340 jra Lstart1Lnot370: movl #3,a0@ | type is at least a 360 movl #0,a1@(MMUCMD) | clear magic cookie2 movl a1@(MMUCMD),d0 | read it back btst #16,d0 | still on? jeq Lstart1 | no, must be a 360 movl #6,a0@ | yes, must be a 345/375 jra LhaspacLisa370: movl #4,a0@ | set to 370Lhaspac: RELOC(_ectype, a0) movl #-1,a0@ | also has a physical address cache jra Lstart1Lnot68030: bset #31,d0 | data cache enable bit movc d0,cacr | only exists on 68040 movc cacr,d0 | read it back tstl d0 | zero? beq Lis68020 | yes, we have 68020 moveq #0,d0 | now turn it back off movec d0,cacr | before we access any data RELOC(_mmutype, a0) movl #-2,a0@ | with a 68040 MMU RELOC(_ectype, a0) movl #0,a0@ | and no cache (for now XXX)#ifdef HPFPLIB RELOC(_processor, a0) movl #3,a0@ | HP-UX style processor id#endif RELOC(_machineid, a0) movl a1@(MMUCMD),d0 | read MMU register lsrl #8,d0 | get apparent ID cmpb #6,d0 | id == 6? jeq Lis33mhz | yes, we have a 433s movl #7,a0@ | no, we have a 380/425t jra Lstart1Lis33mhz: movl #8,a0@ | 433s (XXX 425s returns same ID, ugh!) jra Lstart1Lis68020: movl #1,a1@(MMUCMD) | a 68020, write HP MMU location movl a1@(MMUCMD),d0 | read it back btst #0,d0 | non-zero? jne Lishpmmu | yes, we have HP MMU RELOC(_mmutype, a0) movl #1,a0@ | no, we have PMMU RELOC(_machineid, a0) movl #1,a0@ | and 330 CPU jra Lstart1Lishpmmu: RELOC(_ectype, a0) | 320 or 350 movl #1,a0@ | both have a virtual address cache movl #0x80,a1@(MMUCMD) | set magic cookie movl a1@(MMUCMD),d0 | read it back btst #7,d0 | cookie still on? jeq Lstart1 | no, just a 320 RELOC(_machineid, a0) movl #2,a0@ | yes, a 350Lstart1: movl #0,a1@(MMUCMD) | clear out MMU again/* 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/* initialize memory sizes (for pmap_bootstrap) */ movl #MAXADDR,d1 | last page moveq #PGSHIFT,d2 lsrl d2,d1 | convert to page (click) number RELOC(_maxmem, a0) movl d1,a0@ | save as maxmem movl a5,d0 | lowram value from ROM via boot lsrl d2,d0 | convert to page number subl d0,d1 | compute amount of RAM present RELOC(_physmem, a0) movl d1,a0@ | and physmem/* 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 addl a5,a4 | convert to PA pea a5@ | firstpa pea a4@ | nextpa RELOC(_pmap_bootstrap,a0) jbsr a0@ | pmap_bootstrap(firstpa, nextpa) addql #8,sp/* * Prepare to enable MMU. * Since the kernel is not mapped logical == physical we must insure
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -