📄 locore.s
字号:
* do a dump and then perform power-up sequence * called on warm starts */EXPORT(doadump) li sp,STARTUP_STACK # setup temporary dumpstack la gp,_gp # load the gp .set noreorder nop mtc0 zero,C0_TLBHI nop li v0,KPTEBASE nop mtc0 v0,C0_CTXT nop .set reorder jal dumpsetupvectors # load exception vector code jal dumpsys # do the dump lw a0,rex_magicid li a1,0x30464354 bne a0,a1,1f li a0,0x62 j rex_rex1: j prom_reboot/* * Deal with tlbmisses in KUSEG */NESTED(utlbmiss, 0, k1) # Copied down to 0x80000000 .set noreorder .set noat mfc0 k0,C0_CTXT mfc0 k1,C0_EPC lw k0,0(k0) nop#if NOMEMCACHE==1 or k0,PG_N#endif sll k0,8 # abstract format to R2000/R3000#if CNT_TLBMISS_HACK==1 mtc0 k0,C0_TLBLO lw k0,CNT_UTLBMISS c0 C0_WRITER addu k0,1 sw k0,CNT_UTLBMISS#else mtc0 k0,C0_TLBLO nop c0 C0_WRITER#endif CNT_TLBMISS_HACK j k1 c0 C0_RFEEXPORT(eutlbmiss) .set at .set reorder END(utlbmiss)/* * General exception entry point. */#ifdef ASM_FIXED#define M_EXCEPT +(M_SP|M_GP|M_AT|M_K1|M_A0|M_A1|M_A2|M_A3|M_S0|M_RA)#define M_TFISAVE +(M_V0|M_V1|M_T0|M_T1|M_T2|M_T3|M_T4|M_T5|M_T6|\ M_T7|M_T8|M_T9)#else#define M_EXCEPT 0xb80100f3#define M_TFISAVE 0x4300ff0d#define M_EXCSAVE 0xfb01ffff#define M_TRAPSAVE 0xfbffffff#define M_SYSCALLSAVE 0xf80100ff#endifVECTOR(exception, M_EXCEPT) # Copied down to 0x80000080#ifdef notdef .set noreorder .set noat /* * Inline implementation of a fast kernel tlbmiss * WARNING: this is half-baked and incomplete */ mfc0 k0,C0_CAUSE sw AT,K2_ATSAVE(zero) # put AT in u area and fill load delay and k0,CAUSE_EXCMASK # isolate exception cause beq k0,EXC_RMISS,1f # we can only handle TLB r/w misses nop bne k0,EXC_WMISS,longway1: mfc0 k0,C0_CTXT # pick up pte address and fill BDSLOT lw AT,Sysptsize # should be a literal but for mas /* * The expression in the next instruction requires unsigned * arithmetic (I'll bet it won't work!) */ subu k0,KPTEBASE+(K2BASE/PGSIZE*4) # make Sys pte offset (LDSLOT) bgeu k0,AT,longway # outside Sysmap addu k0,Sysmap # offset into Sysmap and fill BDSLOT lw k0,0(k0) # load desired pte mfc0 k1,C0_EPC # get ready for rfe and fill load delay sll k0,8 # abstract format to R2000/R3000 mtc0 k0,C0_TLBLO # drop pte in tlb and k0,TLBLO_V # check valid bit and fill load delay c0 C0_WRITER # random drop in into tlb beq k0,zero,2f # panic if not valid lw AT,K2_ATSAVE(zero) # reload AT j k1 c0 C0_RFE nop2: PANIC("invalid kernel pte")longway: lw AT,K2_ATSAVE(zero) # reload AT move k0,AT .set at .set reorder#endif#ifdef ROWEN_LEDS li k0,0xbe0800c0 sb k0,-189(k0)#endif lw k0,u+PCB_CPUPTR # get cpudata pointer lw k0,CPU_KSTACK(k0) # get kstack flag beq k0,zero,1f sw sp,EF_SP*4-EF_SIZE(sp) subu sp,EF_SIZE b 2f /* * Came from user mode or utlbmiss, initialize kernel stack */1: sw sp,KERNELSTACK-EF_SIZE+EF_SP*4 la sp,KERNELSTACK-EF_SIZE sw gp,EF_GP*4(sp) la gp,_gp lw k0,u+PCB_CPUPTR # get cpudata pointer sw gp,CPU_KSTACK(k0) # now on kernel stack (gp always != 0) /* * This instruction stream can be cleaned up somewhat for write stalls, * but for now, left as is so its readable when debugging */ .set noat2: sw AT,EF_AT*4(sp) .set at sw k1,EF_K1*4(sp) # in case we came from utlbmiss .set noreorder sw a0,EF_A0*4(sp) sw a1,EF_A1*4(sp) sw a2,EF_A2*4(sp) sw a3,EF_A3*4(sp)#ifdef DS5000_100#ifdef MIPS_ARCH_SPL_ORIG lw a0,mips_spl_arch_type nop beq a0,zero,1f nop#endif lw a1,ipllevel nop sw a1,EF_SYS1*4(sp)#endif1: mfc0 a3,C0_CAUSE mfc0 a0,C0_EPC sw a3,EF_CAUSE*4(sp) sw s0,EF_S0*4(sp) sw ra,EF_RA*4(sp) mfc0 s0,C0_SR sw a0,EF_EPC*4(sp) .set reorder#ifdef notdef#ifdef XPRBUG lw a2,xpr_flags and a2,XPR_INTR beq a2,zero,1f jal tfi_save subu sp,10*4 la a0,9f lw a1,EF_CAUSE*4(sp) la a2,cause_desc move a3,s0 la v0,sr_desc sw v0,4*4(sp) jal xprintf MSG("exception cause=%r sr=%r") la a0,9f move a1,sp lw a2,EF_EPC*4(sp) jal xprintf MSG("exception sp=0x%x pc=0x%x") addu sp,10*4 jal tfi_restore lw a3,EF_CAUSE*4(sp)1:#endif XPRBUG#endif notdef /* * Dispatch to appropriate exception handler * Register setup: * s0 -- SR register at time of exception * a0 -- exception frame pointer * a1 -- cause code * a3 -- cause register */ and a1,a3,CAUSE_EXCMASK lw a2,causevec(a1) move a0,sp .set noreorder j a2 sw s0,EF_SR*4(sp) # should clear PE in s0 after here .set reorderEXPORT(eexception) END(exception)/* * VEC_int -- interrupt handler */#ifdef ASM_FIXEDVECTOR(VEC_int, M_EXCEPT|M_TFISAVE)#elseVECTOR(VEC_int, M_EXCSAVE)#endif .set noreorder li k0,SR_IEC|SR_IMASK8 # enable, but mask all interrupts mtc0 k0,C0_SR .set reorder jal tfi_save /* For ISIS halt interrupt we want to go directly to the boot rom. */ lw v0, cpu # get cpu bne v0, DS_5800, 1f # see if 5800 andi a2,a3,CAUSE_IP7 # check cause for halt intr beq a2,zero,1f # no halt, skip to check for FP intr lw v0,EF_V0*4(sp) # restore v0 for isis halt path jal prom_halt # Call rom halt routine .set noreorder nop b 2f # Let's get outta here. nop .set reorder /* * If this is a floating-point interrupt then we may need "all" the * user's register values in case we need to emulate an branch * instruction if we are in a branch delay slot. * * For pmax, if IP5 of the cause register is set, then it must * be a FPU interrupt. For mipsfair, and isis, if IP4 of the * cause interrupt is set, then it may be a FPU interrupt, it may * also be other hard error interrupts. We save s1-s8 if IP5 or * IP4 is set just in case that the interrupt is a FPU interrupt. */1: andi a2,a3,CAUSE_IP8 # check cause for possible fp intr beq a2,zero,1f sw s1,EF_S1*4(sp) sw s2,EF_S2*4(sp) sw s3,EF_S3*4(sp) sw s4,EF_S4*4(sp) sw s5,EF_S5*4(sp) sw s6,EF_S6*4(sp) sw s7,EF_S7*4(sp) sw s8,EF_S8*4(sp)1:#if defined(DS5000_100) && defined(MIPS_ARCH_SPL_ORIG) lw a2,mips_spl_arch_type beq a2,zero,1f move a2,s0 # sr is arg3 jal kn02ba_intr b 2f1: move a2,s0 # sr is arg3 jal kn01_intr#else#if defined(DS5000_100) move a2,s0 # sr is arg3 jal kn02ba_intr#else move a2,s0 # sr is arg3 jal kn01_intr#endif#endif2: jal tfi_restore .set noreorder mtc0 s0,C0_SR # disable interrupts .set reorder b exception_exit END(VEC_int)/* * TLB mod. * Could enable interrupts here if we were so inclined.... */#ifdef ASM_FIXEDVECTOR(VEC_tlbmod, M_EXCEPT|M_TFISAVE)#elseVECTOR(VEC_tlbmod, M_EXCSAVE)#endif .set noreorder mfc0 a2,C0_BADVADDR # arg3 is bad vaddr nop .set reorder sw a2,EF_BADVADDR*4(sp) # save in case of trap (ugh!) jal tfi_save jal tlbmod # tlbmod(ef_ptr, code, vaddr, cause)#ifdef DS5000_100 .set noreorder mtc0 s0, C0_SR # restore status register .set reorder#endif la ra,exception_exit # fake jal with less nops # if we had reloc-reloc, 1 cycle beq v0,zero,tfi_restore # zero if legal to modify or a0,s0,SR_IEC # enable interrupts .set noreorder mtc0 a0,C0_SR .set reorder move a0,sp # restore ep since tlbmod can trash move a1,v0 # move software exception code lw a3,EF_CAUSE*4(sp) # restore cause since tlbmod can trash b soft_trap # and handle as trap END(VEC_tlbmod)/* * TLB miss. * Handles TLBMiss Read and TLBMiss Write * Could enable interrupts here if we were so inclined.... */#ifdef ASM_FIXEDVECTOR(VEC_tlbmiss, M_EXCEPT|M_TFISAVE)#elseVECTOR(VEC_tlbmiss, M_EXCSAVE)#endif .set noreorder mfc0 a2,C0_BADVADDR # arg3 is bad vaddr nop .set reorder sw a2,EF_BADVADDR*4(sp) # save in case of trap (ugh!) jal tfi_save jal tlbmiss # tlbmiss(ef_ptr, code, vaddr, cause) lw s0,EF_SR*4(sp) # tlbmiss can alter return SR#ifdef DS5000_100 .set noreorder nop mtc0 s0, C0_SR # restore status register .set reorder#endif beq v0,zero,1f # zero if accessable or a0,s0,SR_IEC # enable interrupts .set noreorder mtc0 a0,C0_SR .set reorder move a0,sp # restore ep since tlbmiss can trash move a1,v0 # software exception code lw a3,EF_CAUSE*4(sp) # restore cause since tlbmiss can trash b soft_trap # handle as trap1: la ra,exception_exit # 2 cycles, but 1 fills delay slot b tfi_restore END(VEC_tlbmiss)/* * VEC_addrerr * Handles AdrErrRead, AdrErrWrite */VECTOR(VEC_addrerr, M_EXCEPT) .set noreorder nop mfc0 a2,C0_BADVADDR nop .set reorder sw a2,EF_BADVADDR*4(sp) b VEC_trap END(VEC_addrerr)#define KN02ERR_ADDR 0xbfd80000 /* KSEG1 addr of kn02 Error register */#define KN02CHKSYN_ADDR 0xbfd00000 /* KSEG1 addr of kn02 check/syn reg *//* * VEC_ibe * Handles Instruction Bus Errors */VECTOR(VEC_ibe, M_EXCEPT) .set noreorder nop mfc0 a2,C0_EPC nop mfc0 ra,C0_CAUSE nop .set reorder bgez ra,1f # BD bit not set addu a2,4 # point at BD slot1: sw a2,EF_BADVADDR*4(sp) # ibe's occur at pc /* * Work around for DS5000 (3max). We must get a soft copy of * the "erradr" reg, then clear the "erradr" reg to dismiss the * pending interrupt. We "know" that "a2" and "ra" are safe to * use here as temp registers. */ lw a2, cpu # get system type bne a2, DS_5000, VEC_trap # see if 5000 la a2, KN02ERR_ADDR # get addr of hardware erradr reg lw ra, (a2) # get contents of hardware erradr reg sw ra, kn02erradr # and save a software copy sw zero, (a2) # clear hardware erradr to clear intr la a2, KN02CHKSYN_ADDR # get addr of hardware chksyn reg lw ra, (a2) # get contents of hardware chksyn reg sw ra, kn02chksyn # and save a software copy # latency absorbed in 3 prior instructs jal kn01wbflush # wait for erradr write b VEC_trap END(VEC_ibe)/* * VEC_dbe * Handles Data Bus Errors * * Trap will calculate appropriate badvaddr */VECTOR(VEC_dbe, M_EXCEPT) /* * Work around for DS5000 (3max). We must get a soft copy of * the "erradr" reg, then clear the "erradr" reg to dismiss the * pending interrupt. We "know" that "a2" and "ra" are safe to * use here as temp registers. */ lw a2, cpu # get system type bne a2, DS_5000, VEC_trap # see if 5000 (3max) la a2, KN02ERR_ADDR # get addr of hardware erradr reg lw ra, (a2) # get contents of hardware erradr reg sw ra, kn02erradr # and save a software copy sw zero, (a2) # clear hardware erradr to clear intr la a2, KN02CHKSYN_ADDR # get addr of hardware chksyn reg lw ra, (a2) # get contents of hardware chksyn reg sw ra, kn02chksyn # and save a software copy # latency absorbed in 3 prior instructs jal kn01wbflush # wait for erradr write b VEC_trap END(VEC_dbe)/* * TRAP * Illegal Instruction, and Overflow. * Also handles software exceptions raised by tlbmod and tlbmiss, * NOTE: tlbmod and tlbmiss replace the original exception code with * an appropriate software exception code. */#define M_TRAP +(M_S1|M_S2|M_S3|M_S4|M_S5|M_S6|M_S7)#ifdef ASM_FIXEDVECTOR(VEC_trap, M_EXCEPT|M_TFISAVE|M_TRAP)#elseVECTOR(VEC_trap, M_TRAPSAVE)#endif .set noreorder or a2,s0,SR_IEC # enable interrupts mtc0 a2,C0_SR .set reorder jal tfi_savesoft_trap: # (from tlbmod / tlbmiss) /* * Save rest of state for debuggers * ENTRY CONDITIONS: interrupts enabled, a1 contains software * exception code */ sw s1,EF_S1*4(sp) sw s2,EF_S2*4(sp) sw s3,EF_S3*4(sp) move a2,s0 sw s4,EF_S4*4(sp) sw s5,EF_S5*4(sp) sw s6,EF_S6*4(sp) sw s7,EF_S7*4(sp) sw s8,EF_S8*4(sp) jal trap # trap(ef_ptr, code, sr, cause)full_restore: lw s1,EF_S1*4(sp) lw s2,EF_S2*4(sp) lw s3,EF_S3*4(sp) lw s4,EF_S4*4(sp) lw s5,EF_S5*4(sp) lw s6,EF_S6*4(sp) lw s7,EF_S7*4(sp) lw s8,EF_S8*4(sp) jal tfi_restore .set noreorder mtc0 s0,C0_SR # disable interrupts .set reorder b exception_exit END(VEC_trap)/* * VEC_nofault -- handles nofault exceptions early on in system initialization * before VEC_trap is usable. */#ifdef ASM_FIXEDVECTOR(VEC_nofault, M_EXCEPT|M_TFISAVE)#elseVECTOR(VEC_nofault, M_EXCSAVE)#endif jal tfi_save move a2,s0 jal trap_nofault # trap_nofault(ef_ptr, code, sr, cause) jal tfi_restore#ifdef DS5000_100 .set noreorder mtc0 s0, C0_SR # restore status register .set reorder#endif b exception_exit END(VEC_nofault)/* * Syscall * NOTE: v0, and, v1 must get restored on exit from syscall!! */#define M_SYSCALL +(M_V0|M_V1)#ifdef ASM_FIXEDVECTOR(VEC_syscall, M_EXCEPT|M_SYSCALL)#elseVECTOR(VEC_syscall, M_SYSCALLSAVE)#endif .set noreorder or a1,s0,SR_IEC # enable interrupts mtc0 a1,C0_SR .set reorder sw v0,EF_V0*4(sp) # u_rval1 sw v1,EF_V1*4(sp) # u_rval2 move a1,v0 # arg2 -- syscall number move a2,s0 # arg3 -- sr jal syscall # syscall(ef_ptr, sysnum, sr, cause) bne v0,zero,full_restore # doing a sigreturn lw v0,EF_V0*4(sp) # u_rval1 lw v1,EF_V1*4(sp) # u_rval2 .set noreorder mtc0 s0,C0_SR # disable interrupts .set reorder b exception_exit END(VEC_syscall)/* * Breakpoint -- determine if breakpoint is for prom monitor, else * call trap. */VECTOR(VEC_breakpoint, M_EXCEPT) .set noreorder nop mfc0 k1,C0_CAUSE nop .set reorder lw k0,EF_EPC*4(sp) and k1,CAUSE_BD beq k1,zero,1f addu k0,4 # advance pc to bdslot1: lw k0,0(k0) # read faulting instruction and k1,s0,SR_KUP # if from use mode bne k1,zero,2f # kernel break not allowed lw k1,kernelbp # what a kernel bp looks like bne k0,k1,2f # not a kernel bp inst lw k0,+RB_BPADDR # address of breakpoint handler bne k0,zero,4f2: /* * Check to see if there is a branch delay slot emulation taking place * which is indicated by a non-zero value in PCB_BD_RA (left there by * emulate_instr() ). If this is the case go on to check for the two
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -