📄 locore.s
字号:
*/ mtc0 zero, MACH_COP_0_TLB_INDEX # set the index register mtc0 v0, MACH_COP_0_TLB_HI # init high entry mtc0 t0, MACH_COP_0_TLB_LOW # init low entry li t0, 1 << VMMACH_TLB_INDEX_SHIFT tlbwi # Write the TLB entry. addu v0, v0, NBPG # 2nd HI entry mtc0 t0, MACH_COP_0_TLB_INDEX # set the index register mtc0 v0, MACH_COP_0_TLB_HI # init high entry mtc0 t1, MACH_COP_0_TLB_LOW # init low entry nop tlbwi # Write the TLB entry./* * Now running on new u struct. * Restore registers and return. */ lw v0, UADDR+U_PCB_CONTEXT+44 # restore kernel context lw ra, UADDR+U_PCB_CONTEXT+40 lw s0, UADDR+U_PCB_CONTEXT+0 lw s1, UADDR+U_PCB_CONTEXT+4 lw s2, UADDR+U_PCB_CONTEXT+8 lw s3, UADDR+U_PCB_CONTEXT+12 lw s4, UADDR+U_PCB_CONTEXT+16 lw s5, UADDR+U_PCB_CONTEXT+20 lw s6, UADDR+U_PCB_CONTEXT+24 lw s7, UADDR+U_PCB_CONTEXT+28 lw sp, UADDR+U_PCB_CONTEXT+32 lw s8, UADDR+U_PCB_CONTEXT+36 mtc0 v0, MACH_COP_0_STATUS_REG j ra li v0, 1 # possible return to 'savectx()' .set reorderEND(cpu_switch)/* * {fu,su},{ibyte,isword,iword}, fetch or store a byte, short or word to * user text space. * {fu,su},{byte,sword,word}, fetch or store a byte, short or word to * user data space. */LEAF(fuword)ALEAF(fuiword) li v0, FSWBERR blt a0, zero, fswberr # make sure address is in user space sw v0, UADDR+U_PCB_ONFAULT lw v0, 0(a0) # fetch word sw zero, UADDR+U_PCB_ONFAULT j raEND(fuword)LEAF(fusword)ALEAF(fuisword) li v0, FSWBERR blt a0, zero, fswberr # make sure address is in user space sw v0, UADDR+U_PCB_ONFAULT lhu v0, 0(a0) # fetch short sw zero, UADDR+U_PCB_ONFAULT j raEND(fusword)LEAF(fubyte)ALEAF(fuibyte) li v0, FSWBERR blt a0, zero, fswberr # make sure address is in user space sw v0, UADDR+U_PCB_ONFAULT lbu v0, 0(a0) # fetch byte sw zero, UADDR+U_PCB_ONFAULT j raEND(fubyte)LEAF(suword) li v0, FSWBERR blt a0, zero, fswberr # make sure address is in user space sw v0, UADDR+U_PCB_ONFAULT sw a1, 0(a0) # store word sw zero, UADDR+U_PCB_ONFAULT move v0, zero j raEND(suword)/* * Have to flush instruction cache afterwards. */LEAF(suiword) li v0, FSWBERR blt a0, zero, fswberr # make sure address is in user space sw v0, UADDR+U_PCB_ONFAULT sw a1, 0(a0) # store word sw zero, UADDR+U_PCB_ONFAULT move v0, zero li a1, 4 # size of word b MachFlushICache # NOTE: this should not clobber v0!END(suiword)/* * Will have to flush the instruction cache if byte merging is done in hardware. */LEAF(susword)ALEAF(suisword) li v0, FSWBERR blt a0, zero, fswberr # make sure address is in user space sw v0, UADDR+U_PCB_ONFAULT sh a1, 0(a0) # store short sw zero, UADDR+U_PCB_ONFAULT move v0, zero j raEND(susword)LEAF(subyte)ALEAF(suibyte) li v0, FSWBERR blt a0, zero, fswberr # make sure address is in user space sw v0, UADDR+U_PCB_ONFAULT sb a1, 0(a0) # store byte sw zero, UADDR+U_PCB_ONFAULT move v0, zero j raEND(subyte)LEAF(fswberr) li v0, -1 j raEND(fswberr)/* * fuswintr and suswintr are just like fusword and susword except that if * the page is not in memory or would cause a trap, then we return an error. * The important thing is to prevent sleep() and switching. */LEAF(fuswintr) li v0, FSWINTRBERR blt a0, zero, fswintrberr # make sure address is in user space sw v0, UADDR+U_PCB_ONFAULT lhu v0, 0(a0) # fetch short sw zero, UADDR+U_PCB_ONFAULT j raEND(fuswintr)LEAF(suswintr) li v0, FSWINTRBERR blt a0, zero, fswintrberr # make sure address is in user space sw v0, UADDR+U_PCB_ONFAULT sh a1, 0(a0) # store short sw zero, UADDR+U_PCB_ONFAULT move v0, zero j raEND(suswintr)LEAF(fswintrberr) li v0, -1 j raEND(fswintrberr)/* * Insert 'p' after 'q'. * _insque(p, q) * caddr_t p, q; */LEAF(_insque) lw v0, 0(a1) # v0 = q->next sw a1, 4(a0) # p->prev = q sw v0, 0(a0) # p->next = q->next sw a0, 4(v0) # q->next->prev = p sw a0, 0(a1) # q->next = p j raEND(_insque)/* * Remove item 'p' from queue. * _remque(p) * caddr_t p; */LEAF(_remque) lw v0, 0(a0) # v0 = p->next lw v1, 4(a0) # v1 = p->prev sw v0, 0(v1) # p->prev->next = p->next sw v1, 4(v0) # p->next->prev = p->prev j raEND(_remque)/* * This code is copied to the UTLB exception vector address to * handle user level TLB translation misses. * NOTE: This code must be relocatable!!! */ .globl MachUTLBMissMachUTLBMiss: .set noat .set noreorder mfc0 k0, MACH_COP_0_BAD_VADDR # get the virtual address lw k1, UADDR+U_PCB_SEGTAB # get the current segment table bltz k0, 1f # R3000 chip bug srl k0, k0, SEGSHIFT # compute segment table index sll k0, k0, 2 addu k1, k1, k0 mfc0 k0, MACH_COP_0_BAD_VADDR # get the virtual address lw k1, 0(k1) # get pointer to segment map srl k0, k0, PGSHIFT - 2 # compute segment map index andi k0, k0, (NPTEPG - 1) << 2 beq k1, zero, 2f # invalid segment map addu k1, k1, k0 # index into segment map lw k0, 0(k1) # get page PTE nop beq k0, zero, 2f # dont load invalid entries mtc0 k0, MACH_COP_0_TLB_LOW mfc0 k1, MACH_COP_0_EXC_PC # get return address tlbwr # update TLB j k1 rfe1: mfc0 k1, MACH_COP_0_EXC_PC # get return address nop j k1 rfe2: j SlowFault # handle the rest nop .set reorder .set at .globl MachUTLBMissEndMachUTLBMissEnd:/* * This code is copied to the general exception vector address to * handle all execptions except RESET and UTLBMiss. * NOTE: This code must be relocatable!!! */ .globl MachExceptionMachException:/* * Find out what mode we came from and jump to the proper handler. */ .set noat .set noreorder mfc0 k0, MACH_COP_0_STATUS_REG # Get the status register mfc0 k1, MACH_COP_0_CAUSE_REG # Get the cause register value. and k0, k0, MACH_SR_KU_PREV # test for user mode sll k0, k0, 3 # shift user bit for cause index and k1, k1, MACH_CR_EXC_CODE # Mask out the cause bits. or k1, k1, k0 # change index to user table1: la k0, machExceptionTable # get base of the jump table addu k0, k0, k1 # Get the address of the # function entry. Note that # the cause is already # shifted left by 2 bits so # we don't have to shift. lw k0, 0(k0) # Get the function address nop j k0 # Jump to the function. nop .set reorder .set at .globl MachExceptionEndMachExceptionEnd:/* * We couldn't find a TLB entry. * Find out what mode we came from and call the appropriate handler. */SlowFault: .set noat .set noreorder mfc0 k0, MACH_COP_0_STATUS_REG nop and k0, k0, MACH_SR_KU_PREV bne k0, zero, MachUserGenException nop .set reorder .set at/* * Fall though ... *//*---------------------------------------------------------------------------- * * MachKernGenException -- * * Handle an exception from kernel mode. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------------- *//* * The kernel exception stack contains 18 saved general registers, * the status register and the multiply lo and high registers. * In addition, we set this up for linkage conventions. */#define KERN_REG_SIZE (18 * 4)#define KERN_REG_OFFSET (STAND_FRAME_SIZE)#define KERN_SR_OFFSET (STAND_FRAME_SIZE + KERN_REG_SIZE)#define KERN_MULT_LO_OFFSET (STAND_FRAME_SIZE + KERN_REG_SIZE + 4)#define KERN_MULT_HI_OFFSET (STAND_FRAME_SIZE + KERN_REG_SIZE + 8)#define KERN_EXC_FRAME_SIZE (STAND_FRAME_SIZE + KERN_REG_SIZE + 12)NNON_LEAF(MachKernGenException, KERN_EXC_FRAME_SIZE, ra) .set noreorder .set noat#ifdef KADB la k0, kdbpcb # save registers for kadb sw s0, (S0 * 4)(k0) sw s1, (S1 * 4)(k0) sw s2, (S2 * 4)(k0) sw s3, (S3 * 4)(k0) sw s4, (S4 * 4)(k0) sw s5, (S5 * 4)(k0) sw s6, (S6 * 4)(k0) sw s7, (S7 * 4)(k0) sw s8, (S8 * 4)(k0) sw gp, (GP * 4)(k0) sw sp, (SP * 4)(k0)#endif subu sp, sp, KERN_EXC_FRAME_SIZE .mask 0x80000000, (STAND_RA_OFFSET - KERN_EXC_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, KERN_REG_OFFSET + 0(sp) sw v0, KERN_REG_OFFSET + 4(sp) sw v1, KERN_REG_OFFSET + 8(sp) sw a0, KERN_REG_OFFSET + 12(sp) mflo v0 mfhi v1 sw a1, KERN_REG_OFFSET + 16(sp) sw a2, KERN_REG_OFFSET + 20(sp) sw a3, KERN_REG_OFFSET + 24(sp) sw t0, KERN_REG_OFFSET + 28(sp) mfc0 a0, MACH_COP_0_STATUS_REG # First arg is the status reg. sw t1, KERN_REG_OFFSET + 32(sp) sw t2, KERN_REG_OFFSET + 36(sp) sw t3, KERN_REG_OFFSET + 40(sp) sw t4, KERN_REG_OFFSET + 44(sp) mfc0 a1, MACH_COP_0_CAUSE_REG # Second arg is the cause reg. sw t5, KERN_REG_OFFSET + 48(sp) sw t6, KERN_REG_OFFSET + 52(sp) sw t7, KERN_REG_OFFSET + 56(sp) sw t8, KERN_REG_OFFSET + 60(sp) mfc0 a2, MACH_COP_0_BAD_VADDR # Third arg is the fault addr. sw t9, KERN_REG_OFFSET + 64(sp) sw ra, KERN_REG_OFFSET + 68(sp) sw v0, KERN_MULT_LO_OFFSET(sp) sw v1, KERN_MULT_HI_OFFSET(sp) mfc0 a3, MACH_COP_0_EXC_PC # Fourth arg is the pc. sw a0, KERN_SR_OFFSET(sp)/* * Call the exception handler. */ jal trap sw a3, STAND_RA_OFFSET(sp) # for debugging/* * Restore registers and return from the exception. * v0 contains the return address. */ lw a0, KERN_SR_OFFSET(sp) lw t0, KERN_MULT_LO_OFFSET(sp) lw t1, KERN_MULT_HI_OFFSET(sp) mtc0 a0, MACH_COP_0_STATUS_REG # Restore the SR, disable intrs mtlo t0 mthi t1 move k0, v0 lw AT, KERN_REG_OFFSET + 0(sp) lw v0, KERN_REG_OFFSET + 4(sp) lw v1, KERN_REG_OFFSET + 8(sp) lw a0, KERN_REG_OFFSET + 12(sp) lw a1, KERN_REG_OFFSET + 16(sp) lw a2, KERN_REG_OFFSET + 20(sp) lw a3, KERN_REG_OFFSET + 24(sp) lw t0, KERN_REG_OFFSET + 28(sp) lw t1, KERN_REG_OFFSET + 32(sp) lw t2, KERN_REG_OFFSET + 36(sp) lw t3, KERN_REG_OFFSET + 40(sp) lw t4, KERN_REG_OFFSET + 44(sp) lw t5, KERN_REG_OFFSET + 48(sp) lw t6, KERN_REG_OFFSET + 52(sp) lw t7, KERN_REG_OFFSET + 56(sp) lw t8, KERN_REG_OFFSET + 60(sp) lw t9, KERN_REG_OFFSET + 64(sp) lw ra, KERN_REG_OFFSET + 68(sp) addu sp, sp, KERN_EXC_FRAME_SIZE j k0 # Now return from the rfe # exception. .set at .set reorderEND(MachKernGenException) .globl MachKernGenExceptionEndMachKernGenExceptionEnd:/*---------------------------------------------------------------------------- * * MachUserGenException -- * * Handle an exception from user mode. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------------- */NNON_LEAF(MachUserGenException, STAND_FRAME_SIZE, ra) .set noreorder .set noat .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)/* * Save all of the registers except for the kernel temporaries in u.u_pcb. */ 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 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) mfhi v1 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 a0, MACH_COP_0_STATUS_REG # First arg is the status 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 s0, UADDR+U_PCB_REGS+(S0 * 4) mfc0 a1, MACH_COP_0_CAUSE_REG # Second arg is the cause reg. 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) mfc0 a2, MACH_COP_0_BAD_VADDR # Third arg is the fault addr 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 t8, UADDR+U_PCB_REGS+(T8 * 4) mfc0 a3, MACH_COP_0_EXC_PC # Fourth 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 s8, UADDR+U_PCB_REGS+(S8 * 4) li sp, KERNELSTACK - STAND_FRAME_SIZE # switch to kernel SP sw ra, UADDR+U_PCB_REGS+(RA * 4) sw v0, UADDR+U_PCB_REGS+(MULLO * 4) sw v1, UADDR+U_PCB_REGS+(MULHI * 4) sw a0, UADDR+U_PCB_REGS+(SR * 4) la gp, _gp # switch to kernel GP sw a3, UADDR+U_PCB_REGS+(PC * 4) sw a3, STAND_RA_OFFSET(sp) # for debugging and t0, a0, ~MACH_SR_COP_1_BIT # Turn off the FPU./* * Call the exception handler. */ jal trap mtc0 t0, MACH_COP_0_STATUS_REG/* * 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -