📄 locore.s
字号:
lw s8, UADDR+U_PCB_REGS+(S8 * 4) lw ra, UADDR+U_PCB_REGS+(RA * 4) j k0 rfe .set at .set reorderEND(MachUserGenException)/*---------------------------------------------------------------------------- * * MachKernIntr -- * * Handle an interrupt from kernel mode. * Interrupts use the standard kernel stack. * switch_exit sets up a kernel stack after exit so interrupts won't fail. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------------- */#define KINTR_REG_OFFSET (STAND_FRAME_SIZE)#define KINTR_SR_OFFSET (STAND_FRAME_SIZE + KERN_REG_SIZE)#define KINTR_MULT_LO_OFFSET (STAND_FRAME_SIZE + KERN_REG_SIZE + 4)#define KINTR_MULT_HI_OFFSET (STAND_FRAME_SIZE + KERN_REG_SIZE + 8)#define KINTR_FRAME_SIZE (STAND_FRAME_SIZE + KERN_REG_SIZE + 12)NNON_LEAF(MachKernIntr, KINTR_FRAME_SIZE, ra) .set noreorder .set noat subu sp, sp, KINTR_FRAME_SIZE # allocate stack frame .mask 0x80000000, (STAND_RA_OFFSET - KINTR_FRAME_SIZE)/* * Save the relevant kernel registers onto the stack. * We don't need to save s0 - s8, sp and gp because * the compiler does it for us. */ sw AT, KINTR_REG_OFFSET + 0(sp) sw v0, KINTR_REG_OFFSET + 4(sp) sw v1, KINTR_REG_OFFSET + 8(sp) sw a0, KINTR_REG_OFFSET + 12(sp) mflo v0 mfhi v1 sw a1, KINTR_REG_OFFSET + 16(sp) sw a2, KINTR_REG_OFFSET + 20(sp) sw a3, KINTR_REG_OFFSET + 24(sp) sw t0, KINTR_REG_OFFSET + 28(sp) mfc0 a0, MACH_COP_0_STATUS_REG # First arg is the status reg. sw t1, KINTR_REG_OFFSET + 32(sp) sw t2, KINTR_REG_OFFSET + 36(sp) sw t3, KINTR_REG_OFFSET + 40(sp) sw t4, KINTR_REG_OFFSET + 44(sp) mfc0 a1, MACH_COP_0_CAUSE_REG # Second arg is the cause reg. sw t5, KINTR_REG_OFFSET + 48(sp) sw t6, KINTR_REG_OFFSET + 52(sp) sw t7, KINTR_REG_OFFSET + 56(sp) sw t8, KINTR_REG_OFFSET + 60(sp) mfc0 a2, MACH_COP_0_EXC_PC # Third arg is the pc. sw t9, KINTR_REG_OFFSET + 64(sp) sw ra, KINTR_REG_OFFSET + 68(sp) sw v0, KINTR_MULT_LO_OFFSET(sp) sw v1, KINTR_MULT_HI_OFFSET(sp) sw a0, KINTR_SR_OFFSET(sp)/* * Call the interrupt handler. */ jal interrupt sw a2, STAND_RA_OFFSET(sp) # for debugging/* * Restore registers and return from the interrupt. */ lw a0, KINTR_SR_OFFSET(sp) lw t0, KINTR_MULT_LO_OFFSET(sp) lw t1, KINTR_MULT_HI_OFFSET(sp) mtc0 a0, MACH_COP_0_STATUS_REG # Restore the SR, disable intrs mtlo t0 mthi t1 lw k0, STAND_RA_OFFSET(sp) lw AT, KINTR_REG_OFFSET + 0(sp) lw v0, KINTR_REG_OFFSET + 4(sp) lw v1, KINTR_REG_OFFSET + 8(sp) lw a0, KINTR_REG_OFFSET + 12(sp) lw a1, KINTR_REG_OFFSET + 16(sp) lw a2, KINTR_REG_OFFSET + 20(sp) lw a3, KINTR_REG_OFFSET + 24(sp) lw t0, KINTR_REG_OFFSET + 28(sp) lw t1, KINTR_REG_OFFSET + 32(sp) lw t2, KINTR_REG_OFFSET + 36(sp) lw t3, KINTR_REG_OFFSET + 40(sp) lw t4, KINTR_REG_OFFSET + 44(sp) lw t5, KINTR_REG_OFFSET + 48(sp) lw t6, KINTR_REG_OFFSET + 52(sp) lw t7, KINTR_REG_OFFSET + 56(sp) lw t8, KINTR_REG_OFFSET + 60(sp) lw t9, KINTR_REG_OFFSET + 64(sp) lw ra, KINTR_REG_OFFSET + 68(sp) addu sp, sp, KINTR_FRAME_SIZE j k0 # Now return from the rfe # interrupt. .set at .set reorderEND(MachKernIntr)/*---------------------------------------------------------------------------- * * MachUserIntr -- * * Handle an interrupt from user mode. * Note: we save minimal state in the u.u_pcb struct and use the standard * kernel stack since there has to be a u page if we came from user mode. * If there is a pending software interrupt, then save the remaining state * and call softintr(). This is all because if we call mi_switch() inside * interrupt(), not all the user registers have been saved in u.u_pcb. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------------- */NNON_LEAF(MachUserIntr, STAND_FRAME_SIZE, ra) .set noreorder .set noat .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)/* * Save the relevant user registers into the u.u_pcb struct. * We don't need to save s0 - s8 because * the compiler does it for us. */ sw AT, UADDR+U_PCB_REGS+(AST * 4) sw v0, UADDR+U_PCB_REGS+(V0 * 4) sw v1, UADDR+U_PCB_REGS+(V1 * 4) sw a0, UADDR+U_PCB_REGS+(A0 * 4) mflo v0 mfhi v1 sw a1, UADDR+U_PCB_REGS+(A1 * 4) sw a2, UADDR+U_PCB_REGS+(A2 * 4) sw a3, UADDR+U_PCB_REGS+(A3 * 4) sw t0, UADDR+U_PCB_REGS+(T0 * 4) mfc0 a0, MACH_COP_0_STATUS_REG # First arg is the status reg. sw t1, UADDR+U_PCB_REGS+(T1 * 4) sw t2, UADDR+U_PCB_REGS+(T2 * 4) sw t3, UADDR+U_PCB_REGS+(T3 * 4) sw t4, UADDR+U_PCB_REGS+(T4 * 4) mfc0 a1, MACH_COP_0_CAUSE_REG # Second arg is the cause reg. sw t5, UADDR+U_PCB_REGS+(T5 * 4) sw t6, UADDR+U_PCB_REGS+(T6 * 4) sw t7, UADDR+U_PCB_REGS+(T7 * 4) sw t8, UADDR+U_PCB_REGS+(T8 * 4) mfc0 a2, MACH_COP_0_EXC_PC # Third arg is the pc. sw t9, UADDR+U_PCB_REGS+(T9 * 4) sw gp, UADDR+U_PCB_REGS+(GP * 4) sw sp, UADDR+U_PCB_REGS+(SP * 4) sw ra, UADDR+U_PCB_REGS+(RA * 4) li sp, KERNELSTACK - STAND_FRAME_SIZE # switch to kernel SP sw v0, UADDR+U_PCB_REGS+(MULLO * 4) sw v1, UADDR+U_PCB_REGS+(MULHI * 4) sw a0, UADDR+U_PCB_REGS+(SR * 4) sw a2, UADDR+U_PCB_REGS+(PC * 4) la gp, _gp # switch to kernel GP and t0, a0, ~MACH_SR_COP_1_BIT # Turn off the FPU. mtc0 t0, MACH_COP_0_STATUS_REG/* * Call the interrupt handler. */ jal interrupt sw a2, STAND_RA_OFFSET(sp) # for debugging/* * Restore registers and return from the interrupt. */ lw a0, UADDR+U_PCB_REGS+(SR * 4) lw v0, astpending # any pending interrupts? mtc0 a0, MACH_COP_0_STATUS_REG # Restore the SR, disable intrs bne v0, zero, 1f # don't restore, call softintr lw t0, UADDR+U_PCB_REGS+(MULLO * 4) lw t1, UADDR+U_PCB_REGS+(MULHI * 4) lw k0, UADDR+U_PCB_REGS+(PC * 4) lw AT, UADDR+U_PCB_REGS+(AST * 4) lw v0, UADDR+U_PCB_REGS+(V0 * 4) lw v1, UADDR+U_PCB_REGS+(V1 * 4) lw a0, UADDR+U_PCB_REGS+(A0 * 4) lw a1, UADDR+U_PCB_REGS+(A1 * 4) lw a2, UADDR+U_PCB_REGS+(A2 * 4) lw a3, UADDR+U_PCB_REGS+(A3 * 4) mtlo t0 mthi t1 lw t0, UADDR+U_PCB_REGS+(T0 * 4) lw t1, UADDR+U_PCB_REGS+(T1 * 4) lw t2, UADDR+U_PCB_REGS+(T2 * 4) lw t3, UADDR+U_PCB_REGS+(T3 * 4) lw t4, UADDR+U_PCB_REGS+(T4 * 4) lw t5, UADDR+U_PCB_REGS+(T5 * 4) lw t6, UADDR+U_PCB_REGS+(T6 * 4) lw t7, UADDR+U_PCB_REGS+(T7 * 4) lw t8, UADDR+U_PCB_REGS+(T8 * 4) lw t9, UADDR+U_PCB_REGS+(T9 * 4) lw gp, UADDR+U_PCB_REGS+(GP * 4) lw sp, UADDR+U_PCB_REGS+(SP * 4) lw ra, UADDR+U_PCB_REGS+(RA * 4) j k0 # Now return from the rfe # interrupt.1:/* * We have pending software interrupts; save remaining user state in u.u_pcb. */ sw s0, UADDR+U_PCB_REGS+(S0 * 4) sw s1, UADDR+U_PCB_REGS+(S1 * 4) sw s2, UADDR+U_PCB_REGS+(S2 * 4) sw s3, UADDR+U_PCB_REGS+(S3 * 4) sw s4, UADDR+U_PCB_REGS+(S4 * 4) sw s5, UADDR+U_PCB_REGS+(S5 * 4) sw s6, UADDR+U_PCB_REGS+(S6 * 4) sw s7, UADDR+U_PCB_REGS+(S7 * 4) sw s8, UADDR+U_PCB_REGS+(S8 * 4) li t0, MACH_HARD_INT_MASK | MACH_SR_INT_ENA_CUR/* * Call the software interrupt handler. */ jal softintr mtc0 t0, MACH_COP_0_STATUS_REG # enable interrupts (spl0)/* * Restore user registers and return. NOTE: interrupts are enabled. */ lw a0, UADDR+U_PCB_REGS+(SR * 4) lw t0, UADDR+U_PCB_REGS+(MULLO * 4) lw t1, UADDR+U_PCB_REGS+(MULHI * 4) mtc0 a0, MACH_COP_0_STATUS_REG # this should disable interrupts mtlo t0 mthi t1 lw k0, UADDR+U_PCB_REGS+(PC * 4) lw AT, UADDR+U_PCB_REGS+(AST * 4) lw v0, UADDR+U_PCB_REGS+(V0 * 4) lw v1, UADDR+U_PCB_REGS+(V1 * 4) lw a0, UADDR+U_PCB_REGS+(A0 * 4) lw a1, UADDR+U_PCB_REGS+(A1 * 4) lw a2, UADDR+U_PCB_REGS+(A2 * 4) lw a3, UADDR+U_PCB_REGS+(A3 * 4) lw t0, UADDR+U_PCB_REGS+(T0 * 4) lw t1, UADDR+U_PCB_REGS+(T1 * 4) lw t2, UADDR+U_PCB_REGS+(T2 * 4) lw t3, UADDR+U_PCB_REGS+(T3 * 4) lw t4, UADDR+U_PCB_REGS+(T4 * 4) lw t5, UADDR+U_PCB_REGS+(T5 * 4) lw t6, UADDR+U_PCB_REGS+(T6 * 4) lw t7, UADDR+U_PCB_REGS+(T7 * 4) lw s0, UADDR+U_PCB_REGS+(S0 * 4) lw s1, UADDR+U_PCB_REGS+(S1 * 4) lw s2, UADDR+U_PCB_REGS+(S2 * 4) lw s3, UADDR+U_PCB_REGS+(S3 * 4) lw s4, UADDR+U_PCB_REGS+(S4 * 4) lw s5, UADDR+U_PCB_REGS+(S5 * 4) lw s6, UADDR+U_PCB_REGS+(S6 * 4) lw s7, UADDR+U_PCB_REGS+(S7 * 4) lw t8, UADDR+U_PCB_REGS+(T8 * 4) lw t9, UADDR+U_PCB_REGS+(T9 * 4) lw gp, UADDR+U_PCB_REGS+(GP * 4) lw sp, UADDR+U_PCB_REGS+(SP * 4) lw s8, UADDR+U_PCB_REGS+(S8 * 4) lw ra, UADDR+U_PCB_REGS+(RA * 4) j k0 rfe .set at .set reorderEND(MachUserIntr)#if 0/*---------------------------------------------------------------------------- * * MachTLBModException -- * * Handle a TLB modified exception. * The BaddVAddr, Context, and EntryHi registers contain the failed * virtual address. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------------- */#ifdef NOTDEFNLEAF(MachTLBModException) .set noreorder .set noat tlbp # find the TLB entry mfc0 k0, MACH_COP_0_TLB_LOW # get the physical address mfc0 k1, MACH_COP_0_TLB_INDEX # check to be sure its valid or k0, k0, VMMACH_TLB_MOD_BIT # update TLB blt k1, zero, 4f # not found!!! mtc0 k0, MACH_COP_0_TLB_LOW li k1, MACH_CACHED_MEMORY_ADDR subu k0, k0, k1 srl k0, k0, VMMACH_TLB_PHYS_PAGE_SHIFT la k1, pmap_attributes add k0, k0, k1 lbu k1, 0(k0) # fetch old value nop or k1, k1, 1 # set modified bit sb k1, 0(k0) # save new value mfc0 k0, MACH_COP_0_EXC_PC # get return address nop j k0 rfe4: break 0 # panic .set reorder .set atEND(MachTLBModException)#endif /* NOTDEF */#endif/*---------------------------------------------------------------------------- * * MachTLBMissException -- * * Handle a TLB miss exception from kernel mode. * The BaddVAddr, Context, and EntryHi registers contain the failed * virtual address. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------------- */NLEAF(MachTLBMissException) .set noreorder .set noat mfc0 k0, MACH_COP_0_BAD_VADDR # get the fault address li k1, VM_MIN_KERNEL_ADDRESS # compute index subu k0, k0, k1 lw k1, Sysmapsize # index within range? srl k0, k0, PGSHIFT sltu k1, k0, k1 beq k1, zero, 1f # No. check for valid stack nop lw k1, Sysmap sll k0, k0, 2 # compute offset from index addu k1, k1, k0 lw k0, 0(k1) # get PTE entry mfc0 k1, MACH_COP_0_EXC_PC # get return address mtc0 k0, MACH_COP_0_TLB_LOW # save PTE entry and k0, k0, PG_V # check for valid entry beq k0, zero, MachKernGenException # PTE invalid nop tlbwr # update TLB j k1 rfe1: subu k0, sp, UADDR + 0x200 # check to see if we have a sltiu k0, UPAGES*NBPG - 0x200 # valid kernel stack bne k0, zero, MachKernGenException # Go panic nop la a0, start - START_FRAME - 8 # set sp to a valid place sw sp, 24(a0) move sp, a0 la a0, 1f mfc0 a2, MACH_COP_0_STATUS_REG mfc0 a3, MACH_COP_0_CAUSE_REG mfc0 a1, MACH_COP_0_EXC_PC sw a2, 16(sp) sw a3, 20(sp) sw sp, 24(sp) move a2, ra jal printf mfc0 a3, MACH_COP_0_BAD_VADDR .data1: .asciiz "ktlbmiss: PC %x RA %x ADR %x\nSR %x CR %x SP %x\n" .text la sp, start - START_FRAME # set sp to a valid place PANIC("kernel stack overflow") .set reorder .set atEND(MachTLBMissException)/* * Set/clear software interrupt routines. */LEAF(setsoftclock) .set noreorder mfc0 v0, MACH_COP_0_CAUSE_REG # read cause register nop or v0, v0, MACH_SOFT_INT_MASK_0 # set soft clock interrupt mtc0 v0, MACH_COP_0_CAUSE_REG # save it j ra nop .set reorderEND(setsoftclock)LEAF(clearsoftclock) .set noreorder mfc0 v0, MACH_COP_0_CAUSE_REG # read cause register nop and v0, v0, ~MACH_SOFT_INT_MASK_0 # clear soft clock interrupt mtc0 v0, MACH_COP_0_CAUSE_REG # save it j ra nop .set reorderEND(clearsoftclock)LEAF(setsoftnet) .set noreorder mfc0 v0, MACH_COP_0_CAUSE_REG # read cause register nop or v0, v0, MACH_SOFT_INT_MASK_1 # set soft net interrupt mtc0 v0, MACH_COP_0_CAUSE_REG # save it j ra nop .set reorderEND(setsoftnet)LEAF(clearsoftnet) .set noreorder mfc0 v0, MACH_COP_0_CAUSE_REG # read cause register nop and v0, v0, ~MACH_SOFT_INT_MASK_1 # clear soft net interrupt mtc0 v0, MACH_COP_0_CAUSE_REG # save it j ra nop .set reorderEND(clearsoftnet)/* * Set/change interrupt priority routines. */#ifdef NOTDEFLEAF(MachEnableIntr) .set noreorder mfc0 v0, MACH_COP_0_STATUS_REG # read status register nop or v0, v0, MACH_SR_INT_ENA_CUR mtc0 v0, MACH_COP_0_STATUS_REG # enable all interrupts j ra nop .set reorderEND(MachEnableIntr)#endif /* NOTDEF */#include <sys/cdefs.h>#define SPL(level) \LEAF(__CONCAT(spl,level)); \ .set noreorder; \ mfc0 v0, MACH_COP_0_STATUS_REG; \ li t0, __CONCAT(MACH_SPL_MASK_,level) | MACH_SR_INT_ENA_CUR; \ and t0, t0, v0; \ j ra; \ mtc0 t0, MACH_COP_0_STATUS_REG; \ .set reorder; \END(__CONCAT(spl,level)) \LEAF(spl0) .set noreorder mfc0 v0, MACH_COP_0_STATUS_REG li t0, MACH_SPL_MASK_0 | MACH_SR_INT_ENA_CUR j ra mtc0 t0, MACH_COP_0_STATUS_REG .set reorderEND(spl0)SPL(1); SPL(2); SPL(3); SPL(4); SPL(5); SPL(6); SPL(7)LEAF(spl8)ALEAF(splhigh)ALEAF(_splhigh) .set noreorder mfc0 v0, MACH_COP_0_STATUS_REG li t0, MACH_SPL_MASK_8 | MACH_SR_INT_ENA_CUR j ra mtc0 t0, MACH_COP_0_STATUS_REG .set reorderEND(spl8)/* * Restore saved interrupt mask. */LEAF(splx)ALEAF(_splx) .set noreorder mfc0 v0, MACH_COP_0_STATUS_REG j ra mtc0 a0, MACH_COP_0_STATUS_REG .set reorderEND(splx)/*----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -