diff --git a/sys/arch/mips/mips/locore_r2000.S b/sys/arch/mips/mips/locore_r2000.S deleted file mode 100644 index 963c344d6f9c..000000000000 --- a/sys/arch/mips/mips/locore_r2000.S +++ /dev/null @@ -1,1786 +0,0 @@ -/* $NetBSD: locore_r2000.S,v 1.46 1998/12/25 16:52:10 msaitoh Exp $ */ - -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Digital Equipment Corporation and Ralph Campbell. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Copyright (C) 1989 Digital Equipment Corporation. - * Permission to use, copy, modify, and distribute this software and - * its documentation for any purpose and without fee is hereby granted, - * provided that the above copyright notice appears in all copies. - * Digital Equipment Corporation makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s, - * v 1.1 89/07/11 17:55:04 nelson Exp SPRITE (DECWRL) - * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s, - * v 9.2 90/01/29 18:00:39 shirriff Exp SPRITE (DECWRL) - * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s, - * v 1.1 89/07/10 14:27:41 nelson Exp SPRITE (DECWRL) - * - * @(#)locore.s 8.5 (Berkeley) 1/4/94 - */ - - -#define TRAP_FRAME_SIZE (4 * 38 + 4 * 4 + 4 + 4) -#define TRAP_RA_OFFSET (TRAP_FRAME_SIZE - 4) -#define TRAP_FRAME_OFFSET (4 * 4) -#define INTR_FRAME_SIZE (4 * 38 + 4 * 4 + 4 + 4) -#define INTR_RA_OFFSET STAND_RA_OFFSET -#define INTR_FRAME_OFFSET STAND_FRAME_SIZE - -/* - * Mark where code entered from exception hander jumptable - * starts, for stack traceback code. - */ - - .globl _C_LABEL(mips1_exceptionentry_start) -_C_LABEL(mips1_exceptionentry_start): - -/* - *---------------------------------------------------------------------------- - * - * mips1_UTLBmiss -- - * - * Vector code for a MIPS-I user-space TLB miss from user-space. - * - * - * This code is copied to the UTLB exception vector address to - * handle user level TLB translation misses. - * NOTE: This code must be relocatable!!! - */ - .globl _C_LABEL(mips1_UTLBMiss) -_C_LABEL(mips1_UTLBMiss): - .set noat - mfc0 k0, MIPS_COP_0_BAD_VADDR # get the virtual address - lw k1, _C_LABEL(curpcb) - bltz k0, 1f # R3000 chip bug - lw k1, U_PCB_SEGTAB(k1) # get the current segment table - srl k0, k0, SEGSHIFT # compute segment table index - sll k0, k0, 2 - addu k1, k1, k0 - mfc0 k0, MIPS_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, MIPS_COP_0_TLB_LOW - mfc0 k1, MIPS_COP_0_EXC_PC # get return address - tlbwr # update TLB - j k1 - rfe -1: - mfc0 k1, MIPS_COP_0_EXC_PC # get return address - nop - j k1 - rfe -2: - j mips1_SlowFault # handle the rest - nop - .set at - .globl _C_LABEL(mips1_UTLBMissEnd) -_C_LABEL(mips1_UTLBMissEnd): - - -/* - *---------------------------------------------------------------------------- - * - * mips1_execption -- - * - * Vector code for the general exception vector 0x80000080 - * on an r2000 or r3000. - * - * 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 _C_LABEL(mips1_exception) -_C_LABEL(mips1_exception): -/* - * Find out what mode we came from and jump to the proper handler. - */ - .set noat - mfc0 k0, MIPS_COP_0_STATUS_REG # Get the status register - mfc0 k1, MIPS_COP_0_CAUSE_REG # Get the cause register value. - and k0, k0, MIPS1_SR_KU_PREV # test for user mode - sll k0, k0, 4 # shift user bit for cause index - and k1, k1, MIPS1_CR_EXC_CODE # Mask out the cause bits. - or k1, k1, k0 # change index to user table -1: - la k0, _C_LABEL(mips1_ExceptionTable) # 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 dont have to shift. - lw k0, 0(k0) # Get the function address - nop - j k0 # Jump to the function. - nop - .set at - .globl _C_LABEL(mips1_exceptionEnd) -_C_LABEL(mips1_exceptionEnd): - - - - -/*---------------------------------------------------------------------------- - * - * mips1_SlowFault -- - * - * Alternate entry point into the mips1_UserGenException or - * or mips1_user_Kern_exception, when the ULTB miss handler couldn't - * find a TLB entry. - * - * Find out what mode we came from and call the appropriate handler. - */ -mips1_SlowFault: - .set noat - mfc0 k0, MIPS_COP_0_STATUS_REG - nop - and k0, k0, MIPS1_SR_KU_PREV - bne k0, zero, _C_LABEL(mips1_UserGenException) - nop - .set at -/* - * Fall though ... - */ - -/*---------------------------------------------------------------------------- - * - * mips1_KernGenException -- - * - * Handle an exception from kernel mode. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -NNON_LEAF(mips1_KernGenException, TRAP_FRAME_SIZE, ra) - .set noat - .mask 0x80000000, (TRAP_RA_OFFSET - TRAP_FRAME_SIZE) - subu sp, sp, TRAP_FRAME_SIZE - sw AT, TRAP_FRAME_OFFSET+(AST * 4)(sp) - sw v0, TRAP_FRAME_OFFSET+(V0 * 4)(sp) - sw v1, TRAP_FRAME_OFFSET+(V1 * 4)(sp) - sw a0, TRAP_FRAME_OFFSET+(A0 * 4)(sp) - mflo v0 - mfhi v1 - sw a1, TRAP_FRAME_OFFSET+(A1 * 4)(sp) - sw a2, TRAP_FRAME_OFFSET+(A2 * 4)(sp) - sw a3, TRAP_FRAME_OFFSET+(A3 * 4)(sp) - sw t0, TRAP_FRAME_OFFSET+(T0 * 4)(sp) - mfc0 a0, MIPS_COP_0_STATUS_REG # 1st arg is STATUS - sw t1, TRAP_FRAME_OFFSET+(T1 * 4)(sp) - sw t2, TRAP_FRAME_OFFSET+(T2 * 4)(sp) - sw t3, TRAP_FRAME_OFFSET+(T3 * 4)(sp) - sw t4, TRAP_FRAME_OFFSET+(T4 * 4)(sp) - mfc0 a1, MIPS_COP_0_CAUSE_REG # 2nd arg is CAUSE - sw t5, TRAP_FRAME_OFFSET+(T5 * 4)(sp) - sw t6, TRAP_FRAME_OFFSET+(T6 * 4)(sp) - sw t7, TRAP_FRAME_OFFSET+(T7 * 4)(sp) - sw t8, TRAP_FRAME_OFFSET+(T8 * 4)(sp) - mfc0 a2, MIPS_COP_0_BAD_VADDR # 3rd arg is fault address - sw t9, TRAP_FRAME_OFFSET+(T9 * 4)(sp) - sw ra, TRAP_FRAME_OFFSET+(RA * 4)(sp) - sw a0, TRAP_FRAME_OFFSET+(SR * 4)(sp) - sw v0, TRAP_FRAME_OFFSET+(MULLO * 4)(sp) - mfc0 a3, MIPS_COP_0_EXC_PC # 4th arg is PC - sw v1, TRAP_FRAME_OFFSET+(MULHI * 4)(sp) - sw a3, TRAP_FRAME_OFFSET+(PC * 4)(sp) -#ifdef DDB - addu v0, sp, TRAP_FRAME_SIZE # SP at trap for debugging - sw v0, TRAP_FRAME_OFFSET+(SP * 4)(sp) -#endif DDB - jal _C_LABEL(trap) - sw a3, TRAP_RA_OFFSET(sp) # for debugging - - lw a0, TRAP_FRAME_OFFSET+(SR * 4)(sp) - lw t0, TRAP_FRAME_OFFSET+(MULLO * 4)(sp) - lw t1, TRAP_FRAME_OFFSET+(MULHI * 4)(sp) - mtc0 a0, MIPS_COP_0_STATUS_REG - mtlo t0 - mthi t1 - lw k0, TRAP_FRAME_OFFSET+(PC * 4)(sp) # might be changed inside trap - lw AT, TRAP_FRAME_OFFSET+(AST * 4)(sp) - lw v0, TRAP_FRAME_OFFSET+(V0 * 4)(sp) - lw v1, TRAP_FRAME_OFFSET+(V1 * 4)(sp) - lw a0, TRAP_FRAME_OFFSET+(A0 * 4)(sp) - lw a1, TRAP_FRAME_OFFSET+(A1 * 4)(sp) - lw a2, TRAP_FRAME_OFFSET+(A2 * 4)(sp) - lw a3, TRAP_FRAME_OFFSET+(A3 * 4)(sp) - lw t0, TRAP_FRAME_OFFSET+(T0 * 4)(sp) - lw t1, TRAP_FRAME_OFFSET+(T1 * 4)(sp) - lw t2, TRAP_FRAME_OFFSET+(T2 * 4)(sp) - lw t3, TRAP_FRAME_OFFSET+(T3 * 4)(sp) - lw t4, TRAP_FRAME_OFFSET+(T4 * 4)(sp) - lw t5, TRAP_FRAME_OFFSET+(T5 * 4)(sp) - lw t6, TRAP_FRAME_OFFSET+(T6 * 4)(sp) - lw t7, TRAP_FRAME_OFFSET+(T7 * 4)(sp) - lw t8, TRAP_FRAME_OFFSET+(T8 * 4)(sp) - lw t9, TRAP_FRAME_OFFSET+(T9 * 4)(sp) - lw ra, TRAP_FRAME_OFFSET+(RA * 4)(sp) - addu sp, sp, TRAP_FRAME_SIZE # restore kernel SP - j k0 - rfe - .set at - .global _C_LABEL(mips1_KernGenExceptionEnd) -_C_LABEL(mips1_KernGenExceptionEnd): -END(mips1_KernGenException) - -/*---------------------------------------------------------------------------- - * - * mips1_UserGenException -- - * - * Handle an exception from user mode. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -NNON_LEAF(mips1_UserGenException, STAND_FRAME_SIZE, ra) - .set noat - .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE) - lw k1, _C_LABEL(curpcb) - nop - sw AT, U_PCB_REGS+(AST * 4)(k1) - sw v0, U_PCB_REGS+(V0 * 4)(k1) - sw v1, U_PCB_REGS+(V1 * 4)(k1) - sw a0, U_PCB_REGS+(A0 * 4)(k1) - mflo v0 - sw a1, U_PCB_REGS+(A1 * 4)(k1) - sw a2, U_PCB_REGS+(A2 * 4)(k1) - sw a3, U_PCB_REGS+(A3 * 4)(k1) - sw t0, U_PCB_REGS+(T0 * 4)(k1) - mfhi v1 - sw t1, U_PCB_REGS+(T1 * 4)(k1) - sw t2, U_PCB_REGS+(T2 * 4)(k1) - sw t3, U_PCB_REGS+(T3 * 4)(k1) - sw t4, U_PCB_REGS+(T4 * 4)(k1) - mfc0 a0, MIPS_COP_0_STATUS_REG # 1st arg is STATUS - sw t5, U_PCB_REGS+(T5 * 4)(k1) - sw t6, U_PCB_REGS+(T6 * 4)(k1) - sw t7, U_PCB_REGS+(T7 * 4)(k1) - sw s0, U_PCB_REGS+(S0 * 4)(k1) - mfc0 a1, MIPS_COP_0_CAUSE_REG # 2nd arg is CAUSE - sw s1, U_PCB_REGS+(S1 * 4)(k1) - sw s2, U_PCB_REGS+(S2 * 4)(k1) - sw s3, U_PCB_REGS+(S3 * 4)(k1) - sw s4, U_PCB_REGS+(S4 * 4)(k1) - mfc0 a2, MIPS_COP_0_BAD_VADDR # 3rd arg is fault address - sw s5, U_PCB_REGS+(S5 * 4)(k1) - sw s6, U_PCB_REGS+(S6 * 4)(k1) - sw s7, U_PCB_REGS+(S7 * 4)(k1) - sw t8, U_PCB_REGS+(T8 * 4)(k1) - mfc0 a3, MIPS_COP_0_EXC_PC # 4th arg is PC - sw t9, U_PCB_REGS+(T9 * 4)(k1) - sw gp, U_PCB_REGS+(GP * 4)(k1) - sw sp, U_PCB_REGS+(SP * 4)(k1) - sw s8, U_PCB_REGS+(S8 * 4)(k1) - li sp, KERNELSTACK - STAND_FRAME_SIZE # switch to kernel SP - sw ra, U_PCB_REGS+(RA * 4)(k1) - sw a0, U_PCB_REGS+(SR * 4)(k1) - sw v0, U_PCB_REGS+(MULLO * 4)(k1) - sw v1, U_PCB_REGS+(MULHI * 4)(k1) - sw a3, U_PCB_REGS+(PC * 4)(k1) - sw a3, STAND_RA_OFFSET(sp) # for debugging -#ifdef __GP_SUPPORT__ - la gp, _C_LABEL(_gp) # switch to kernel GP -#endif - .set at - and t0, a0, ~MIPS_SR_COP_1_BIT # Turn off the FPU. - .set noat - jal _C_LABEL(trap) - mtc0 t0, MIPS_COP_0_STATUS_REG -/* - * Restore user registers and return. NOTE: interrupts are enabled. - */ - lw a1, _C_LABEL(curpcb) - nop - lw a0, U_PCB_REGS+(SR * 4)(a1) - lw t0, U_PCB_REGS+(MULLO * 4)(a1) - lw t1, U_PCB_REGS+(MULHI * 4)(a1) - mtc0 a0, MIPS_COP_0_STATUS_REG # this should disable interrupts - mtlo t0 - mthi t1 - move k1, a1 - lw k0, U_PCB_REGS+(PC * 4)(k1) - lw AT, U_PCB_REGS+(AST * 4)(k1) - lw v0, U_PCB_REGS+(V0 * 4)(k1) - lw v1, U_PCB_REGS+(V1 * 4)(k1) - lw a0, U_PCB_REGS+(A0 * 4)(k1) - lw a1, U_PCB_REGS+(A1 * 4)(k1) - lw a2, U_PCB_REGS+(A2 * 4)(k1) - lw a3, U_PCB_REGS+(A3 * 4)(k1) - lw t0, U_PCB_REGS+(T0 * 4)(k1) - lw t1, U_PCB_REGS+(T1 * 4)(k1) - lw t2, U_PCB_REGS+(T2 * 4)(k1) - lw t3, U_PCB_REGS+(T3 * 4)(k1) - lw t4, U_PCB_REGS+(T4 * 4)(k1) - lw t5, U_PCB_REGS+(T5 * 4)(k1) - lw t6, U_PCB_REGS+(T6 * 4)(k1) - lw t7, U_PCB_REGS+(T7 * 4)(k1) - lw s0, U_PCB_REGS+(S0 * 4)(k1) - lw s1, U_PCB_REGS+(S1 * 4)(k1) - lw s2, U_PCB_REGS+(S2 * 4)(k1) - lw s3, U_PCB_REGS+(S3 * 4)(k1) - lw s4, U_PCB_REGS+(S4 * 4)(k1) - lw s5, U_PCB_REGS+(S5 * 4)(k1) - lw s6, U_PCB_REGS+(S6 * 4)(k1) - lw s7, U_PCB_REGS+(S7 * 4)(k1) - lw t8, U_PCB_REGS+(T8 * 4)(k1) - lw t9, U_PCB_REGS+(T9 * 4)(k1) - lw gp, U_PCB_REGS+(GP * 4)(k1) - lw sp, U_PCB_REGS+(SP * 4)(k1) - lw s8, U_PCB_REGS+(S8 * 4)(k1) - lw ra, U_PCB_REGS+(RA * 4)(k1) - j k0 - rfe - .set at - .globl _C_LABEL(mips1_UserGenExceptionEnd) -_C_LABEL(mips1_UserGenExceptionEnd): -END(mips1_UserGenException) - -/* - * System call handler - */ -NNON_LEAF(mips1_SystemCall, STAND_FRAME_SIZE, ra) - .set noat - .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE) - lw k1, _C_LABEL(curpcb) - nop - sw AT, U_PCB_REGS+(AST * 4)(k1) - sw v0, U_PCB_REGS+(V0 * 4)(k1) - sw v1, U_PCB_REGS+(V1 * 4)(k1) - mflo v0 - mfhi v1 - sw a0, U_PCB_REGS+(A0 * 4)(k1) - sw a1, U_PCB_REGS+(A1 * 4)(k1) - sw a2, U_PCB_REGS+(A2 * 4)(k1) - sw a3, U_PCB_REGS+(A3 * 4)(k1) - sw t0, U_PCB_REGS+(T0 * 4)(k1) - sw t1, U_PCB_REGS+(T1 * 4)(k1) - sw t2, U_PCB_REGS+(T2 * 4)(k1) - sw t3, U_PCB_REGS+(T3 * 4)(k1) - sw t4, U_PCB_REGS+(T4 * 4)(k1) - mfc0 a0, MIPS_COP_0_STATUS_REG # 1st arg is STATUS - sw t5, U_PCB_REGS+(T5 * 4)(k1) - sw t6, U_PCB_REGS+(T6 * 4)(k1) - sw t7, U_PCB_REGS+(T7 * 4)(k1) - sw s0, U_PCB_REGS+(S0 * 4)(k1) - mfc0 a1, MIPS_COP_0_CAUSE_REG # 2nd arg is CAUSE - sw s1, U_PCB_REGS+(S1 * 4)(k1) - sw s2, U_PCB_REGS+(S2 * 4)(k1) - sw s3, U_PCB_REGS+(S3 * 4)(k1) - sw s4, U_PCB_REGS+(S4 * 4)(k1) - sw s5, U_PCB_REGS+(S5 * 4)(k1) - sw s6, U_PCB_REGS+(S6 * 4)(k1) - sw s7, U_PCB_REGS+(S7 * 4)(k1) - sw t8, U_PCB_REGS+(T8 * 4)(k1) - mfc0 a2, MIPS_COP_0_EXC_PC # 3rd arg is PC - sw t9, U_PCB_REGS+(T9 * 4)(k1) - sw gp, U_PCB_REGS+(GP * 4)(k1) - sw sp, U_PCB_REGS+(SP * 4)(k1) - sw s8, U_PCB_REGS+(S8 * 4)(k1) - sw ra, U_PCB_REGS+(RA * 4)(k1) - la a3, U_PCB_REGS(k1) # 4th arg is p. to trapframe - sw a0, U_PCB_REGS+(SR * 4)(k1) - sw v0, U_PCB_REGS+(MULLO * 4)(k1) - sw v1, U_PCB_REGS+(MULHI * 4)(k1) - sw a2, U_PCB_REGS+(PC * 4)(k1) - li sp, KERNELSTACK - STAND_FRAME_SIZE # switch to kernel SP - sw a2, STAND_RA_OFFSET(sp) # for debugging -#ifdef __GP_SUPPORT__ - la gp, _C_LABEL(_gp) # switch to kernel GP -#endif - .set at - and t0, a0, ~MIPS_SR_COP_1_BIT # Turn off the FPU. - .set noat - jal _C_LABEL(syscall) - mtc0 t0, MIPS_COP_0_STATUS_REG -/* - * Restore user registers and return. NOTE: interrupts are enabled. - */ - lw a1, _C_LABEL(curpcb) - nop - lw a0, U_PCB_REGS+(SR * 4)(a1) - lw t0, U_PCB_REGS+(MULLO * 4)(a1) - lw t1, U_PCB_REGS+(MULHI * 4)(a1) - mtc0 a0, MIPS_COP_0_STATUS_REG # this should disable interrupts - mtlo t0 - mthi t1 - move k1, a1 - lw k0, U_PCB_REGS+(PC * 4)(k1) # might be changed in syscall - lw AT, U_PCB_REGS+(AST * 4)(k1) - lw v0, U_PCB_REGS+(V0 * 4)(k1) - lw v1, U_PCB_REGS+(V1 * 4)(k1) - lw a0, U_PCB_REGS+(A0 * 4)(k1) - lw a1, U_PCB_REGS+(A1 * 4)(k1) - lw a2, U_PCB_REGS+(A2 * 4)(k1) - lw a3, U_PCB_REGS+(A3 * 4)(k1) - lw t0, U_PCB_REGS+(T0 * 4)(k1) - lw t1, U_PCB_REGS+(T1 * 4)(k1) - lw t2, U_PCB_REGS+(T2 * 4)(k1) - lw t3, U_PCB_REGS+(T3 * 4)(k1) - lw t4, U_PCB_REGS+(T4 * 4)(k1) - lw t5, U_PCB_REGS+(T5 * 4)(k1) - lw t6, U_PCB_REGS+(T6 * 4)(k1) - lw t7, U_PCB_REGS+(T7 * 4)(k1) - lw s0, U_PCB_REGS+(S0 * 4)(k1) - lw s1, U_PCB_REGS+(S1 * 4)(k1) - lw s2, U_PCB_REGS+(S2 * 4)(k1) - lw s3, U_PCB_REGS+(S3 * 4)(k1) - lw s4, U_PCB_REGS+(S4 * 4)(k1) - lw s5, U_PCB_REGS+(S5 * 4)(k1) - lw s6, U_PCB_REGS+(S6 * 4)(k1) - lw s7, U_PCB_REGS+(S7 * 4)(k1) - lw t8, U_PCB_REGS+(T8 * 4)(k1) - lw t9, U_PCB_REGS+(T9 * 4)(k1) - lw gp, U_PCB_REGS+(GP * 4)(k1) - lw sp, U_PCB_REGS+(SP * 4)(k1) - lw s8, U_PCB_REGS+(S8 * 4)(k1) - lw ra, U_PCB_REGS+(RA * 4)(k1) - j k0 - rfe - .set at - .globl _C_LABEL(mips1_SystemCallEnd) -_C_LABEL(mips1_SystemCallEnd): -END(mips1_SystemCall) - -/*---------------------------------------------------------------------------- - * - * mips1_KernIntr -- - * - * 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: - * OBNone. - * - *---------------------------------------------------------------------------- - */ -NNON_LEAF(mips1_KernIntr, INTR_FRAME_SIZE, ra) - .set noat - subu sp, sp, INTR_FRAME_SIZE - .mask 0x80000000, (STAND_RA_OFFSET - INTR_FRAME_SIZE) -/* - * Save the relevant kernel registers onto the stack. - * We don't need to save s0 - s8 and sp because - * the compiler does it for us. - */ - sw AT, INTR_FRAME_OFFSET+(AST * 4)(sp) - sw v0, INTR_FRAME_OFFSET+(V0 * 4)(sp) - sw v1, INTR_FRAME_OFFSET+(V1 * 4)(sp) - sw a0, INTR_FRAME_OFFSET+(A0 * 4)(sp) - mflo v0 - mfhi v1 - sw a1, INTR_FRAME_OFFSET+(A1 * 4)(sp) - sw a2, INTR_FRAME_OFFSET+(A2 * 4)(sp) - sw a3, INTR_FRAME_OFFSET+(A3 * 4)(sp) - sw t0, INTR_FRAME_OFFSET+(T0 * 4)(sp) - mfc0 a0, MIPS_COP_0_STATUS_REG # 1st arg is STATUS - sw t1, INTR_FRAME_OFFSET+(T1 * 4)(sp) - sw t2, INTR_FRAME_OFFSET+(T2 * 4)(sp) - sw t3, INTR_FRAME_OFFSET+(T3 * 4)(sp) - sw t4, INTR_FRAME_OFFSET+(T4 * 4)(sp) - mfc0 a1, MIPS_COP_0_CAUSE_REG # Second arg is the cause reg. - sw t5, INTR_FRAME_OFFSET+(T5 * 4)(sp) - sw t6, INTR_FRAME_OFFSET+(T6 * 4)(sp) - sw t7, INTR_FRAME_OFFSET+(T7 * 4)(sp) - sw t8, INTR_FRAME_OFFSET+(T8 * 4)(sp) - mfc0 a2, MIPS_COP_0_EXC_PC # 3rd arg is PC - sw t9, INTR_FRAME_OFFSET+(T9 * 4)(sp) - sw ra, INTR_FRAME_OFFSET+(RA * 4)(sp) - la a3, INTR_FRAME_OFFSET(sp) # 4th arg is p. to trapframe - sw a0, INTR_FRAME_OFFSET+(SR * 4)(sp) - sw v0, INTR_FRAME_OFFSET+(MULLO * 4)(sp) - sw v1, INTR_FRAME_OFFSET+(MULHI * 4)(sp) - sw gp, INTR_FRAME_OFFSET+(GP * 4)(sp) -#ifdef __GP_SUPPORT__ - la gp, _C_LABEL(_gp) # switch to kernel GP -#endif - jal _C_LABEL(interrupt) - sw a2, STAND_RA_OFFSET(sp) # for debugging - - lw a0, INTR_FRAME_OFFSET+(SR * 4)(sp) - lw t0, INTR_FRAME_OFFSET+(MULLO * 4)(sp) - lw t1, INTR_FRAME_OFFSET+(MULHI * 4)(sp) - mtc0 a0, MIPS_COP_0_STATUS_REG # Restore the SR, disable intrs - mtlo t0 - mthi t1 - lw k0, STAND_RA_OFFSET(sp) # restore original PC - lw AT, INTR_FRAME_OFFSET+(AST * 4)(sp) - lw v0, INTR_FRAME_OFFSET+(V0 * 4)(sp) - lw v1, INTR_FRAME_OFFSET+(V1 * 4)(sp) - lw a0, INTR_FRAME_OFFSET+(A0 * 4)(sp) - lw a1, INTR_FRAME_OFFSET+(A1 * 4)(sp) - lw a2, INTR_FRAME_OFFSET+(A2 * 4)(sp) - lw a3, INTR_FRAME_OFFSET+(A3 * 4)(sp) - lw t0, INTR_FRAME_OFFSET+(T0 * 4)(sp) - lw t1, INTR_FRAME_OFFSET+(T1 * 4)(sp) - lw t2, INTR_FRAME_OFFSET+(T2 * 4)(sp) - lw t3, INTR_FRAME_OFFSET+(T3 * 4)(sp) - lw t4, INTR_FRAME_OFFSET+(T4 * 4)(sp) - lw t5, INTR_FRAME_OFFSET+(T5 * 4)(sp) - lw t6, INTR_FRAME_OFFSET+(T6 * 4)(sp) - lw t7, INTR_FRAME_OFFSET+(T7 * 4)(sp) - lw t8, INTR_FRAME_OFFSET+(T8 * 4)(sp) - lw t9, INTR_FRAME_OFFSET+(T9 * 4)(sp) - lw gp, INTR_FRAME_OFFSET+(GP * 4)(sp) - lw ra, INTR_FRAME_OFFSET+(RA * 4)(sp) - addu sp, sp, INTR_FRAME_SIZE # restore kernel SP - j k0 # Now return from interrupt - rfe # - .globl _C_LABEL(mips1_KernIntrEnd) -_C_LABEL(mips1_KernIntrEnd): -END(mips1_KernIntr) - -/*---------------------------------------------------------------------------- - * - * mips1_UserIntr -- - * - * 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 switch() inside - * interrupt(), not all the user registers have been saved in u.u_pcb. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -NNON_LEAF(mips1_UserIntr, STAND_FRAME_SIZE, ra) - .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. - */ - lw k1, _C_LABEL(curpcb) - nop - sw AT, U_PCB_REGS+(AST * 4)(k1) - sw v0, U_PCB_REGS+(V0 * 4)(k1) - sw v1, U_PCB_REGS+(V1 * 4)(k1) - sw a0, U_PCB_REGS+(A0 * 4)(k1) - mflo v0 - mfhi v1 - sw a1, U_PCB_REGS+(A1 * 4)(k1) - sw a2, U_PCB_REGS+(A2 * 4)(k1) - sw a3, U_PCB_REGS+(A3 * 4)(k1) - sw t0, U_PCB_REGS+(T0 * 4)(k1) - mfc0 a0, MIPS_COP_0_STATUS_REG # 1st arg is STATUS - sw t1, U_PCB_REGS+(T1 * 4)(k1) - sw t2, U_PCB_REGS+(T2 * 4)(k1) - sw t3, U_PCB_REGS+(T3 * 4)(k1) - sw t4, U_PCB_REGS+(T4 * 4)(k1) - mfc0 a1, MIPS_COP_0_CAUSE_REG # 2nd arg is CAUSE - sw t5, U_PCB_REGS+(T5 * 4)(k1) - sw t6, U_PCB_REGS+(T6 * 4)(k1) - sw t7, U_PCB_REGS+(T7 * 4)(k1) - sw t8, U_PCB_REGS+(T8 * 4)(k1) - mfc0 a2, MIPS_COP_0_EXC_PC # 3rd arg is PC - sw t9, U_PCB_REGS+(T9 * 4)(k1) - sw gp, U_PCB_REGS+(GP * 4)(k1) - sw sp, U_PCB_REGS+(SP * 4)(k1) - sw ra, U_PCB_REGS+(RA * 4)(k1) - la a3, U_PCB_REGS(k1) # 4th arg is p. to trapframe - sw a0, U_PCB_REGS+(SR * 4)(k1) - sw v0, U_PCB_REGS+(MULLO * 4)(k1) - sw v1, U_PCB_REGS+(MULHI * 4)(k1) - li sp, KERNELSTACK - STAND_FRAME_SIZE # switch to kernel SP - sw a2, U_PCB_REGS+(PC * 4)(k1) - sw a2, STAND_RA_OFFSET(sp) # for debugging -#ifdef __GP_SUPPORT__ - la gp, _C_LABEL(_gp) # switch to kernel GP -#endif -/* - * Call the interrupt handler. - */ - .set at - and t0, a0, ~MIPS_SR_COP_1_BIT # Turn off the FPU. - .set noat - jal _C_LABEL(interrupt) - mtc0 t0, MIPS_COP_0_STATUS_REG -/* - * Check pending asynchoronous traps. - */ - lw a1, _C_LABEL(curpcb) - nop - lw a0, U_PCB_REGS+(SR * 4)(a1) - lw v0, _C_LABEL(astpending) # any pending ast? - mtc0 a0, MIPS_COP_0_STATUS_REG # restore SR disabling intrs - beq v0, zero, 1f # if no, skip ast processing -/* - * We have pending asynchronous traps; save remaining user state in u.u_pcb. - */ - sw s0, U_PCB_REGS+(S0 * 4)(a1) - sw s1, U_PCB_REGS+(S1 * 4)(a1) - sw s2, U_PCB_REGS+(S2 * 4)(a1) - sw s3, U_PCB_REGS+(S3 * 4)(a1) - sw s4, U_PCB_REGS+(S4 * 4)(a1) - sw s5, U_PCB_REGS+(S5 * 4)(a1) - sw s6, U_PCB_REGS+(S6 * 4)(a1) - sw s7, U_PCB_REGS+(S7 * 4)(a1) - sw s8, U_PCB_REGS+(S8 * 4)(a1) - - lw a0, U_PCB_REGS+(PC * 4)(a1) # argument is interrupted PC - li t0, MIPS_HARD_INT_MASK | MIPS_SR_INT_IE - jal _C_LABEL(ast) - mtc0 t0, MIPS_COP_0_STATUS_REG # enable interrupts (spl0) - - lw a1, _C_LABEL(curpcb) - nop - lw a0, U_PCB_REGS+(SR * 4)(a1) - lw s0, U_PCB_REGS+(S0 * 4)(a1) - mtc0 a0, MIPS_COP_0_STATUS_REG # this should disable interrupts - lw s1, U_PCB_REGS+(S1 * 4)(a1) - lw s2, U_PCB_REGS+(S2 * 4)(a1) - lw s3, U_PCB_REGS+(S3 * 4)(a1) - lw s4, U_PCB_REGS+(S4 * 4)(a1) - lw s5, U_PCB_REGS+(S5 * 4)(a1) - lw s6, U_PCB_REGS+(S6 * 4)(a1) - lw s7, U_PCB_REGS+(S7 * 4)(a1) - lw s8, U_PCB_REGS+(S8 * 4)(a1) -1: - move k1, a1 - lw v0, U_PCB_REGS+(MULLO * 4)(k1) - lw v1, U_PCB_REGS+(MULHI * 4)(k1) - mtlo v0 - mthi v1 - lw k0, U_PCB_REGS+(PC * 4)(k1) # interrupted PC - move k1, a1 - lw AT, U_PCB_REGS+(AST * 4)(k1) - lw v0, U_PCB_REGS+(V0 * 4)(k1) - lw v1, U_PCB_REGS+(V1 * 4)(k1) - lw a0, U_PCB_REGS+(A0 * 4)(k1) - lw a1, U_PCB_REGS+(A1 * 4)(k1) - lw a2, U_PCB_REGS+(A2 * 4)(k1) - lw a3, U_PCB_REGS+(A3 * 4)(k1) - lw t0, U_PCB_REGS+(T0 * 4)(k1) - lw t1, U_PCB_REGS+(T1 * 4)(k1) - lw t2, U_PCB_REGS+(T2 * 4)(k1) - lw t3, U_PCB_REGS+(T3 * 4)(k1) - lw t4, U_PCB_REGS+(T4 * 4)(k1) - lw t5, U_PCB_REGS+(T5 * 4)(k1) - lw t6, U_PCB_REGS+(T6 * 4)(k1) - lw t7, U_PCB_REGS+(T7 * 4)(k1) - lw t8, U_PCB_REGS+(T8 * 4)(k1) - lw t9, U_PCB_REGS+(T9 * 4)(k1) - lw gp, U_PCB_REGS+(GP * 4)(k1) - lw sp, U_PCB_REGS+(SP * 4)(k1) - lw ra, U_PCB_REGS+(RA * 4)(k1) - j k0 - rfe - .set at - .globl _C_LABEL(mips1_UserIntrEnd) -_C_LABEL(mips1_UserIntrEnd): -END(mips1_UserIntr) - - -/*---------------------------------------------------------------------------- - * - * XXX START of r3000-specific code XXX - * - *---------------------------------------------------------------------------- - */ - - -#if 0 -/*---------------------------------------------------------------------------- - * - * mips1_TLBModException -- - * - * Handle a TLB modified exception. - * The BaddVAddr, Context, and EntryHi registers contain the failed - * virtual address. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -NLEAF(mips1_TLBModException) - .set noat - tlbp # find the TLB entry - mfc0 k0, MIPS_COP_0_TLB_LOW # get the physical address - mfc0 k1, MIPS_COP_0_TLB_INDEX # check to be sure its valid - or k0, k0, MIPS1_TLB_MOD_BIT # update TLB - blt k1, zero, 4f # not found!!! - mtc0 k0, MIPS_COP_0_TLB_LOW - li k1, MIPS_KSEG0_START - subu k0, k0, k1 - srl k0, k0, MIPS1_TLB_PHYS_PAGE_SHIFT - la k1, pmap_attributes - addu 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, MIPS_COP_0_EXC_PC # get return address - nop - j k0 - rfe -4: - break 0 # panic - .set at -END(mips1_TLBModException) -#endif - -/*---------------------------------------------------------------------------- - * - * mips1_TLBMissException -- - * - * 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(mips1_TLBMissException) - .set noat - mfc0 k0, MIPS_COP_0_BAD_VADDR # get the fault address - li k1, VM_MIN_KERNEL_ADDRESS # compute index - subu k0, k0, k1 - lw k1, _C_LABEL(Sysmapsize) # index within range? - srl k0, k0, PGSHIFT - sltu k1, k0, k1 - beq k1, zero, 1f # No. check for valid stack - nop - lw k1, _C_LABEL(Sysmap) - sll k0, k0, 2 # compute offset from index - addu k1, k1, k0 - lw k0, 0(k1) # get PTE entry - mfc0 k1, MIPS_COP_0_EXC_PC # get return address - mtc0 k0, MIPS_COP_0_TLB_LOW # save PTE entry - and k0, k0, MIPS1_PG_V # check for valid entry - beq k0, zero, _C_LABEL(mips1_KernGenException) # PTE invalid - nop - tlbwr # update TLB - j k1 - rfe - -1: - subu k0, sp, UADDR + 0x200 # check to see if we have a - sltiu k0, UPAGES*NBPG - 0x200 # valid kernel stack - bne k0, zero, _C_LABEL(mips1_KernGenException) # 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, MIPS_COP_0_STATUS_REG - mfc0 a3, MIPS_COP_0_CAUSE_REG - mfc0 a1, MIPS_COP_0_EXC_PC - sw a2, 16(sp) - sw a3, 20(sp) - move a2, ra - jal _C_LABEL(printf) - mfc0 a3, MIPS_COP_0_BAD_VADDR - .data -1: - .asciiz "ktlbmiss: PC %x RA %x ADR %x\nSR %x CR %x SP %x\n" - .text - - /* Call mips1_dump_tlb(0, 2, printf) to show the bad kstack TLB */ - la a2, _C_LABEL(printf) - li a0,0 - jal _C_LABEL(mips1_dump_tlb) - li a1,3 # BDslot - - la sp, start - START_FRAME # set sp to a valid place - PANIC("kernel stack overflow") - .set at -END(mips1_TLBMissException) - -/* - * Mark where code entered from exception hander jumptable - * ends, for stack traceback code. - */ - - .globl _C_LABEL(mips1_exceptionentry_end) -_C_LABEL(mips1_exceptionentry_end): - - -/*-------------------------------------------------------------------------- - * - * mips1_TLBWriteIndexed -- - * - * Write the given entry into the TLB at the given index. - * - * mips1_TLBWriteIndexed(index, highEntry, lowEntry) - * int index; - * int highEntry; - * int lowEntry; - * - * Results: - * None. - * - * Side effects: - * TLB entry set. - * - *-------------------------------------------------------------------------- - */ -LEAF(mips1_TLBWriteIndexed) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - mfc0 t0, MIPS_COP_0_TLB_HI # Save the current PID. - - sll a0, a0, MIPS1_TLB_INDEX_SHIFT - mtc0 a0, MIPS_COP_0_TLB_INDEX # Set the index. - mtc0 a1, MIPS_COP_0_TLB_HI # Set up entry high. - mtc0 a2, MIPS_COP_0_TLB_LOW # Set up entry low. - nop - tlbwi # Write the TLB - - mtc0 t0, MIPS_COP_0_TLB_HI # Restore the PID. - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(mips1_TLBWriteIndexed) - -#if 0 -/*-------------------------------------------------------------------------- - * - * mips1_TLBWriteRandom -- - * - * Write the given entry into the TLB at a random location. - * - * mips1_TLBWriteRandom(highEntry, lowEntry) - * unsigned highEntry; - * unsigned lowEntry; - * - * Results: - * None. - * - * Side effects: - * TLB entry set. - * - *-------------------------------------------------------------------------- - */ -LEAF(mips1_TLBWriteRandom) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - mfc0 v0, MIPS_COP_0_TLB_HI # Save the current PID. - nop - - mtc0 a0, MIPS_COP_0_TLB_HI # Set up entry high. - mtc0 a1, MIPS_COP_0_TLB_LOW # Set up entry low. - nop - tlbwr # Write the TLB - - mtc0 v0, MIPS_COP_0_TLB_HI # Restore the PID. - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(mips1_TLBWriteRandom) -#endif - -/*-------------------------------------------------------------------------- - * - * mips1_SetPID -- - * - * Write the given pid into the TLB pid reg. - * - * mips1_SetPID(pid) - * int pid; - * - * Results: - * None. - * - * Side effects: - * PID set in the entry hi register. - * - *-------------------------------------------------------------------------- - */ -LEAF(mips1_SetPID) - sll a0, a0, MIPS1_TLB_PID_SHIFT # put PID in right spot - mtc0 a0, MIPS_COP_0_TLB_HI # Write the hi reg value - j ra - nop -END(mips1_SetPID) - -/*-------------------------------------------------------------------------- - * - * mips1_TLBFlush -- - * - * Flush the "random" entries from the TLB. - * Arg "tlbsize" is the number of entries to flush. - * - * mips1_TLBFlush(tlbsize) - * - * Results: - * None. - * - * Side effects: - * The TLB is flushed. - * - *-------------------------------------------------------------------------- - */ -LEAF(mips1_TLBFlush) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - mfc0 t0, MIPS_COP_0_TLB_HI # Save the PID - li t1, MIPS_KSEG0_START # invalid address - mtc0 t1, MIPS_COP_0_TLB_HI # Mark entry high as invalid - mtc0 zero, MIPS_COP_0_TLB_LOW # Zero out low entry. -/* - * Align the starting value (t1) and the upper bound (t2). - */ - li t1, MIPS1_TLB_FIRST_RAND_ENTRY << MIPS1_TLB_INDEX_SHIFT - sll t2, a0, MIPS1_TLB_INDEX_SHIFT -1: - mtc0 t1, MIPS_COP_0_TLB_INDEX # Set the index register. - addu t1, t1, 1 << MIPS1_TLB_INDEX_SHIFT # Increment index. - bne t1, t2, 1b - tlbwi # Write the TLB entry. - - mtc0 t0, MIPS_COP_0_TLB_HI # Restore the PID - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(mips1_TLBFlush) - -#if 0 -/*-------------------------------------------------------------------------- - * - * mips1_TLBFlushPID -- - * - * Flush all entries with the given PID from the TLB. - * - * mips1_TLBFlushPID(pid) - * int pid; - * - * Results: - * None. - * - * Side effects: - * All entries corresponding to this PID are flushed. - * - *-------------------------------------------------------------------------- - */ -LEAF(mips1_TLBFlushPID) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - mfc0 t0, MIPS_COP_0_TLB_HI # Save the current PID - sll a0, a0, MIPS1_TLB_PID_SHIFT # Align the pid to flush. -/* - * Align the starting value (t1) and the upper bound (t2). - */ - li t1, MIPS1_TLB_FIRST_RAND_ENTRY << MIPS1_TLB_INDEX_SHIFT - li t2, MIPS1_TLB_NUM_TLB_ENTRIES << MIPS1_TLB_INDEX_SHIFT - mtc0 t1, MIPS_COP_0_TLB_INDEX # Set the index register -1: - addu t1, t1, 1 << MIPS1_TLB_INDEX_SHIFT # Increment index. - tlbr # Read from the TLB - mfc0 t4, MIPS_COP_0_TLB_HI # Fetch the hi register. - nop - and t4, t4, MIPS1_TLB_PID # compare PIDs - bne t4, a0, 2f - li v0, MIPS_KSEG0_START # invalid address - mtc0 v0, MIPS_COP_0_TLB_HI # Mark entry high as invalid - mtc0 zero, MIPS_COP_0_TLB_LOW # Zero out low entry. - nop - tlbwi # Write the entry. -2: - bne t1, t2, 1b - mtc0 t1, MIPS_COP_0_TLB_INDEX # Set the index register - - mtc0 t0, MIPS_COP_0_TLB_HI # restore PID - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(mips1_TLBFlushPID) -#endif - -/*-------------------------------------------------------------------------- - * - * mips1_TLBFlushAddr -- - * - * Flush any TLB entries for the given address and TLB PID. - * - * mips1_TLBFlushAddr(highreg) - * unsigned highreg; - * - * Results: - * None. - * - * Side effects: - * The process's page is flushed from the TLB. - * - *-------------------------------------------------------------------------- - */ -LEAF(mips1_TLBFlushAddr) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - mfc0 t0, MIPS_COP_0_TLB_HI # Get current PID - nop - - mtc0 a0, MIPS_COP_0_TLB_HI # look for addr & PID - nop - tlbp # Probe for the entry. - mfc0 v0, MIPS_COP_0_TLB_INDEX # See what we got - li t1, MIPS_KSEG0_START # Load invalid entry. - bltz v0, 1f # index < 0 => !found - mtc0 t1, MIPS_COP_0_TLB_HI # Mark entry high as invalid - mtc0 zero, MIPS_COP_0_TLB_LOW # Zero out low entry. - nop - tlbwi -1: - mtc0 t0, MIPS_COP_0_TLB_HI # restore PID - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(mips1_TLBFlushAddr) - -/*-------------------------------------------------------------------------- - * - * mips1_TLBUpdate -- - * - * Update the TLB if highreg is found; otherwise, enter the data. - * - * mips1_TLBUpdate(highreg, lowreg) - * unsigned highreg, lowreg; - * - * Results: - * None. - * - * Side effects: - * None. - * - *-------------------------------------------------------------------------- - */ -LEAF(mips1_TLBUpdate) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - mfc0 t0, MIPS_COP_0_TLB_HI # Save current PID - nop # 2 cycles before intr disabled - mtc0 a0, MIPS_COP_0_TLB_HI # init high reg. - nop - tlbp # Probe for the entry. - mfc0 v0, MIPS_COP_0_TLB_INDEX # See what we got - mtc0 a1, MIPS_COP_0_TLB_LOW # init low reg. - bltz v0, 1f # index < 0 => !found - sra v0, v0, MIPS1_TLB_INDEX_SHIFT # convert index to regular num - b 2f - tlbwi # update slot found -1: - mtc0 a0, MIPS_COP_0_TLB_HI # init high reg. - nop - tlbwr # enter into a random slot -2: - mtc0 t0, MIPS_COP_0_TLB_HI # restore PID - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(mips1_TLBUpdate) - -/*-------------------------------------------------------------------------- - * - * mips1_TLBFind -- - * - * Search the TLB for the given entry. - * - * mips1_TLBFind(hi) - * unsigned hi; - * - * Results: - * Returns a value >= 0 if the entry was found (the index). - * Returns a value < 0 if the entry was not found. - * - * Side effects: - * tlbhi and tlblo will contain the TLB entry found. - * - *-------------------------------------------------------------------------- - */ - .comm tlbhi, 4 - .comm tlblo, 4 -LEAF(mips1_TLBFind) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - mfc0 t0, MIPS_COP_0_TLB_HI # Get current PID - nop - mtc0 a0, MIPS_COP_0_TLB_HI # Set up entry high. - nop - tlbp # Probe for the entry. - mfc0 v0, MIPS_COP_0_TLB_INDEX # See what we got - nop - bltz v0, 1f # not found - nop - tlbr # read TLB - mfc0 t1, MIPS_COP_0_TLB_HI # See what we got - mfc0 t2, MIPS_COP_0_TLB_LOW # See what we got - sw t1, tlbhi - sw t2, tlblo - srl v0, v0, MIPS1_TLB_INDEX_SHIFT # convert index to regular num -1: - mtc0 t0, MIPS_COP_0_TLB_HI # Restore current PID - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(mips1_TLBFind) - -/*-------------------------------------------------------------------------- - * - * mips1_TLBRead -- - * - * Read the TLB entry. - * - * mips1_TLBRead(entry) - * unsigned entry; - * - * Results: - * None. - * - * Side effects: - * tlbhi and tlblo will contain the TLB entry found. - * - *-------------------------------------------------------------------------- - */ -LEAF(mips1_TLBRead) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - mfc0 t0, MIPS_COP_0_TLB_HI # Get current PID - - sll a0, a0, MIPS1_TLB_INDEX_SHIFT - mtc0 a0, MIPS_COP_0_TLB_INDEX # Set the index register - nop - tlbr # Read from the TLB - mfc0 t3, MIPS_COP_0_TLB_HI # fetch the hi entry - mfc0 t4, MIPS_COP_0_TLB_LOW # fetch the low entry - sw t3, tlbhi - sw t4, tlblo - - mtc0 t0, MIPS_COP_0_TLB_HI # restore PID - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(mips1_TLBRead) - -/*-------------------------------------------------------------------------- - * - * mips1_TLBGetPID -- - * - * mips1_TLBGetPID() - * - * Results: - * Returns the current TLB pid reg. - * - * Side effects: - * None. - * - *-------------------------------------------------------------------------- - */ -LEAF(mips1_TLBGetPID) - mfc0 v0, MIPS_COP_0_TLB_HI # get PID - nop - and v0, v0, MIPS1_TLB_PID # mask off PID - j ra - srl v0, v0, MIPS1_TLB_PID_SHIFT # put PID in right spot -END(mips1_TLBGetPID) - - -/*---------------------------------------------------------------------------- - * - * R3000 cache sizing and flushing code. - * - *---------------------------------------------------------------------------- - */ - - -/*---------------------------------------------------------------------------- - * - * mips1_ConfigCache -- - * - * Size the caches. - * NOTE: should only be called from mach_init(). - * - * Results: - * None. - * - * Side effects: - * The size of the data cache is stored into mips_L1DCacheSize and the - * size of instruction cache is stored into mips_L1ICacheSize. - * - *---------------------------------------------------------------------------- - */ -NON_LEAF(mips1_ConfigCache, STAND_FRAME_SIZE, ra) - subu sp, sp, STAND_FRAME_SIZE - sw ra, STAND_RA_OFFSET(sp) # Save return address. - .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE) - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts. - la v0, 1f - or v0, MIPS_KSEG1_START # Run uncached. - j v0 - nop -1: -/* - * This works because jal doesn't change pc[31..28] and the - * linker still thinks SizeCache is in the cached region so it computes - * the correct address without complaining. - */ - jal _C_LABEL(mips1_SizeCache) # Get the size of the d-cache. - nop - sw v0, _C_LABEL(mips_L1DCacheSize) - nop # Make sure sw out of pipe - nop - nop - nop - li v0, MIPS_SR_SWAP_CACHES # Swap caches - mtc0 v0, MIPS_COP_0_STATUS_REG - nop # Insure caches stable - nop - nop - nop - jal _C_LABEL(mips1_SizeCache) # Get the size of the i-cache. - nop - mtc0 zero, MIPS_COP_0_STATUS_REG # Swap back caches and enable. - nop - nop - nop - nop - sw v0, _C_LABEL(mips_L1ICacheSize) - la t0, 1f - j t0 # Back to cached mode - nop -1: - lw ra, STAND_RA_OFFSET(sp) # Restore return addr - addu sp, sp, STAND_FRAME_SIZE # Restore sp. - j ra - nop -END(mips1_ConfigCache) - -/*---------------------------------------------------------------------------- - * - * mips1_SizeCache -- - * - * Get the size of the cache. - * - * Results: - * The size of the cache. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -LEAF(mips1_SizeCache) - mfc0 t0, MIPS_COP_0_STATUS_REG # Save the current status reg. - nop - or v0, t0, MIPS_SR_ISOL_CACHES # Isolate the caches. - nop # Make sure no stores in pipe - mtc0 v0, MIPS_COP_0_STATUS_REG - nop # Make sure isolated - nop - nop -/* - * Clear cache size boundaries. - */ - li v0, MIPS_MIN_CACHE_SIZE - li v1, MIPS_KSEG0_START - li t2, MIPS_MAX_CACHE_SIZE -1: - addu t1, v0, v1 # Compute address to clear - sw zero, 0(t1) # Clear cache memory - bne v0, t2, 1b - sll v0, v0, 1 - - li v0, -1 - sw v0, 0(v1) # Store marker in cache - li v0, MIPS_MIN_CACHE_SIZE -2: - addu t1, v0, v1 # Compute address - lw t3, 0(t1) # Look for marker - nop - bne t3, zero, 3f # Found marker. - nop - bne v0, t2, 2b # keep looking - sll v0, v0, 1 # cache size * 2 - - move v0, zero # must be no cache -3: - mtc0 t0, MIPS_COP_0_STATUS_REG - nop # Make sure unisolated - nop - nop - nop - j ra - nop -END(mips1_SizeCache) - -/*---------------------------------------------------------------------------- - * - * mips1_FlushCache -- - * - * Flush the caches. - * - * Results: - * None. - * - * Side effects: - * The contents of the caches is flushed. - * - *---------------------------------------------------------------------------- - */ -LEAF(mips1_FlushCache) - lw t1, _C_LABEL(mips_L1ICacheSize) # Must load before isolating - lw t2, _C_LABEL(mips_L1DCacheSize) # Must load before isolating - mfc0 t3, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts. - la v0, 1f - or v0, MIPS_KSEG1_START # Run uncached. - j v0 - nop -/* - * Flush the instruction cache. - */ -1: - li v0, MIPS_SR_ISOL_CACHES | MIPS_SR_SWAP_CACHES - mtc0 v0, MIPS_COP_0_STATUS_REG # Isolate and swap caches. - li t0, MIPS_KSEG1_START - subu t0, t0, t1 - li t1, MIPS_KSEG1_START - la v0, 1f # Run cached - j v0 - nop -1: - addu t0, t0, 4 - bne t0, t1, 1b - sb zero, -4(t0) - - la v0, 1f - or v0, MIPS_KSEG1_START - j v0 # Run uncached - nop -/* - * Flush the data cache. - */ -1: - li v0, MIPS_SR_ISOL_CACHES - mtc0 v0, MIPS_COP_0_STATUS_REG # Isolate and swap back caches - li t0, MIPS_KSEG1_START - subu t0, t0, t2 - la v0, 1f - j v0 # Back to cached mode - nop -1: - addu t0, t0, 4 - bne t0, t1, 1b - sb zero, -4(t0) - - nop # Insure isolated stores - nop # out of pipe. - nop - nop - mtc0 t3, MIPS_COP_0_STATUS_REG # Restore status reg. - nop # Insure cache unisolated. - nop - nop - nop - j ra - nop -END(mips1_FlushCache) - -/*---------------------------------------------------------------------------- - * - * mips1_FlushICache -- - * - * void mips1_FlushICache(addr, len) - * vm_offset_t addr, len; - * - * Flush instruction cache for range of addr to addr + len - 1. - * The address can be any valid address so long as no TLB misses occur. - * - * Results: - * None. - * - * Side effects: - * The contents of the cache is flushed. - * - *---------------------------------------------------------------------------- - */ -LEAF(mips1_FlushICache) - mfc0 t0, MIPS_COP_0_STATUS_REG # Save SR - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts. - - la v1, 1f - or v1, MIPS_KSEG1_START # Run uncached. - j v1 - nop -1: -#ifdef pmax - /* - * The insn below attempts to wait for the writebuffer to drain. - * It does not work on all MIPS hosts or maybe even all DEC machines. - * It assumes that the COP0 usability bit is wired to external - * writebuffer logic. This is not true on some DECstations or on - * the SONY news3400. - * Why we are even doing this for an I-cache flush is beyond me. - */ - bc0f 1b # make sure stores are complete -#endif /* pmax */ - li v1, MIPS_SR_ISOL_CACHES | MIPS_SR_SWAP_CACHES # DELAYSLOT - - mtc0 v1, MIPS_COP_0_STATUS_REG - nop - addu a1, a1, a0 # compute ending address -1: - addu a0, a0, 4 - bne a0, a1, 1b - sb zero, -4(a0) - - mtc0 t0, MIPS_COP_0_STATUS_REG # enable interrupts - j ra # return and run cached - nop -END(mips1_FlushICache) - -/*---------------------------------------------------------------------------- - * - * mips1_FlushDCache -- - * - * void mips1_FlushDCache(addr, len) - * vm_offset_t addr, len; - * - * Flush data cache for range of addr to addr + len - 1. - * The address can be any valid address so long as no TLB misses occur. - * (Be sure to use cached K0SEG kernel addresses) - * Results: - * None. - * - * Side effects: - * The contents of the cache is flushed. - * - *---------------------------------------------------------------------------- - */ -LEAF(mips1_FlushDCache) - mfc0 t0, MIPS_COP_0_STATUS_REG # Save SR - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts. - nop - -#ifdef pmax - /* - * The insn below attempts to wait for the writebuffer to drain. - * It does not work on all MIPS hosts or maybe even all DEC machines. - * It assumes that the COP0 usability bit is wired to external - * writebuffer logic. This is not true on some DECstations or on - * the SONY news3400. (note the following ld is in our delayslot.) - */ -1: - bc0f 1b # make sure stores are complete -#endif - - li v1, MIPS_SR_ISOL_CACHES # DELAYSLOT - mtc0 v1, MIPS_COP_0_STATUS_REG - nop - addu t1, a1, a0 # compute ending address -1: - sb zero, 0(a0) - sb zero, 4(a0) - sb zero, 8(a0) - sb zero, 12(a0) - sb zero, 16(a0) - sb zero, 20(a0) - sb zero, 24(a0) - addu a0, 32 - bltu a0, t1, 1b - sb zero, -4(a0) - - nop # drain pipeline - nop - mtc0 t0, MIPS_COP_0_STATUS_REG # enable interrupts - nop - j ra # return and run cached - nop -END(mips1_FlushDCache) - -/*---------------------------------------------------------------------------- - * - * mips1_wbflush -- - * - * Return when the write buffer is empty. - * - * mips1_wbflush() - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -LEAF(mips1_wbflush) - nop - nop - nop - nop -1: bc0f 1b - nop - j ra - nop -END(mips1_wbflush) - -/* - * mips1_proc_trampoline() - * - * Arrange for a function to be invoked neatly, after a cpu_switch(). - * Invoke the service function with one argument, specified by the s0 - * and s1 respectively. There is no need register save operation. - */ -LEAF(mips1_proc_trampoline) - jal ra, s0 - move a0, s1 - .set noat - lw a1, _C_LABEL(curpcb) - nop - lw a0, U_PCB_REGS + (SR * 4)(a1) - lw t0, U_PCB_REGS + (MULLO * 4)(a1) - lw t1, U_PCB_REGS + (MULHI * 4)(a1) - mtc0 a0, MIPS_COP_0_STATUS_REG # this should disable interrupts - mtlo t0 - mthi t1 - nop - move k1, a1 - lw AT, U_PCB_REGS + (AST * 4)(k1) - lw k0, U_PCB_REGS + (PC * 4)(k1) - lw v0, U_PCB_REGS + (V0 * 4)(k1) - lw v1, U_PCB_REGS + (V1 * 4)(k1) - lw a0, U_PCB_REGS + (A0 * 4)(k1) - lw a1, U_PCB_REGS + (A1 * 4)(k1) - lw a2, U_PCB_REGS + (A2 * 4)(k1) - lw a3, U_PCB_REGS + (A3 * 4)(k1) - lw t0, U_PCB_REGS + (T0 * 4)(k1) - lw t1, U_PCB_REGS + (T1 * 4)(k1) - lw t2, U_PCB_REGS + (T2 * 4)(k1) - lw t3, U_PCB_REGS + (T3 * 4)(k1) - lw t4, U_PCB_REGS + (T4 * 4)(k1) - lw t5, U_PCB_REGS + (T5 * 4)(k1) - lw t6, U_PCB_REGS + (T6 * 4)(k1) - lw t7, U_PCB_REGS + (T7 * 4)(k1) - lw s0, U_PCB_REGS + (S0 * 4)(k1) - lw s1, U_PCB_REGS + (S1 * 4)(k1) - lw s2, U_PCB_REGS + (S2 * 4)(k1) - lw s3, U_PCB_REGS + (S3 * 4)(k1) - lw s4, U_PCB_REGS + (S4 * 4)(k1) - lw s5, U_PCB_REGS + (S5 * 4)(k1) - lw s6, U_PCB_REGS + (S6 * 4)(k1) - lw s7, U_PCB_REGS + (S7 * 4)(k1) - lw t8, U_PCB_REGS + (T8 * 4)(k1) - lw t9, U_PCB_REGS + (T9 * 4)(k1) - lw gp, U_PCB_REGS + (GP * 4)(k1) - lw s8, U_PCB_REGS + (S8 * 4)(k1) - lw ra, U_PCB_REGS + (RA * 4)(k1) - lw sp, U_PCB_REGS + (SP * 4)(k1) - nop - j k0 - rfe - .set at -END(mips1_proc_trampoline) - -/* - * switch_exit(struct proc *) - * Make the named process exit. Switch SP to nullproc stack, schedule - * the exiting proc's vmspace and stack to be freed, then jump into the - * middle of cpu_switch(). MUST BE CALLED AT SPLHIGH. - */ -LEAF(mips1_switch_exit) - la v1, _C_LABEL(nullproc) # !! SP runs on p->p_addr !! - lw t0, P_MD_UPTE+0(v1) # t0 = first u. pte - lw t1, P_MD_UPTE+4(v1) # t1 = 2nd u. pte - li v0, MIPS_KSEG0_START # clear wired entries for pcb - mtc0 v0, MIPS_COP_0_TLB_HI - mtc0 zero, MIPS_COP_0_TLB_LOW - li v0, 2 << MIPS1_TLB_INDEX_SHIFT - mtc0 v0, MIPS_COP_0_TLB_INDEX # clear wired entry 2 - nop - tlbwi - li v0, 3 << MIPS1_TLB_INDEX_SHIFT - mtc0 v0, MIPS_COP_0_TLB_INDEX # clear wired entry 3 - nop - tlbwi - li v0, UADDR # still using UADDR for kstack - nop - mtc0 zero, MIPS_COP_0_TLB_INDEX # set the index register - mtc0 v0, MIPS_COP_0_TLB_HI # init high entry - mtc0 t0, MIPS_COP_0_TLB_LOW # init low entry - li t0, 1 << MIPS1_TLB_INDEX_SHIFT - tlbwi # Write the TLB entry. - addu v0, v0, NBPG # 2nd HI entry - mtc0 t0, MIPS_COP_0_TLB_INDEX # set the index register - mtc0 v0, MIPS_COP_0_TLB_HI # init high entry - mtc0 t1, MIPS_COP_0_TLB_LOW # init low entry - subu v0, v0, NBPG # back to start of u-area - tlbwi # Write the TLB entry. - - addu sp, v0, USPACE - START_FRAME - la ra, sw1 # goto cpu_switch() - j exit2 # proc already in a0 -END(mips1_switch_exit) - -/* - * Resume process indicated by the pte's for its u struct - * NOTE: This is hard coded to UPAGES == 2. - * Also, there should be no TLB faults at this point. - * - * Entered from CPU-common cpu_switch() - * a0 = p_addr [curpcb] - * a1 = First u.pte - * a2 = Second u.pte - * a3 = TLB Process ID for this process - */ -/* - * XXXX - almost done with the UADDR mapping; only the kernel stack should - * now be using UADDR. The first TLB entries are used to map - * UADDR to the u-area. Then the following TLB entries are used to - * map the current u-area. Also, any current mapping for the u-area - * address space needs to be flushed as well. - * - * Both the UADDR and u-area are now mapped global. - * - * NB: cannot be profiled due to weird argument-assing convention. - * mcount would trash v0, t0, t1. - */ -NLEAF(mips1_cpu_switch_resume) - sll a3, a3, MIPS1_TLB_PID_SHIFT # a3 = aligned PID - li v0, UADDR # HI entry; PID = 0 - ori a1, MIPS1_PG_G # Global - ori a2, MIPS1_PG_G # Global - mtc0 zero, MIPS_COP_0_TLB_INDEX # set the index register - mtc0 v0, MIPS_COP_0_TLB_HI # init high entry - mtc0 a1, MIPS_COP_0_TLB_LOW # init low entry - li s1, 1 << MIPS1_TLB_INDEX_SHIFT - tlbwi # Write the TLB entry. - addu v0, v0, NBPG # 2nd HI entry - mtc0 s1, MIPS_COP_0_TLB_INDEX # set the index register - mtc0 v0, MIPS_COP_0_TLB_HI # init high entry - mtc0 a2, MIPS_COP_0_TLB_LOW # init low entry - nop - tlbwi # Write the TLB entry. - # now map p_addr; may need to flush random TLB entries - mtc0 a0, MIPS_COP_0_TLB_HI # PID = 0 - nop - tlbp # probe for entry - mfc0 s1, MIPS_COP_0_TLB_INDEX # see if we found it - nop - bltz s1, 1f # not found - li s1, MIPS_KSEG0_START - mtc0 s1, MIPS_COP_0_TLB_HI - mtc0 zero, MIPS_COP_0_TLB_LOW - nop - tlbwi - nop - mtc0 a0, MIPS_COP_0_TLB_HI # restore High -1: - li s1, 2 << MIPS1_TLB_INDEX_SHIFT - mtc0 s1, MIPS_COP_0_TLB_INDEX - mtc0 a1, MIPS_COP_0_TLB_LOW - nop - tlbwi - addu a0, a0, NBPG - mtc0 a0, MIPS_COP_0_TLB_HI # second page of p_addr - nop - tlbp # probe for entry - mfc0 s1, MIPS_COP_0_TLB_INDEX # see if we found it - nop - bltz s1, 1f # not found - li s1, MIPS_KSEG0_START - mtc0 s1, MIPS_COP_0_TLB_HI - mtc0 zero, MIPS_COP_0_TLB_LOW - nop - tlbwi - nop - mtc0 a0, MIPS_COP_0_TLB_HI # restore High -1: - li s1, 3 << MIPS1_TLB_INDEX_SHIFT - mtc0 s1, MIPS_COP_0_TLB_INDEX - mtc0 a2, MIPS_COP_0_TLB_LOW - nop - tlbwi - mtc0 a3, MIPS_COP_0_TLB_HI # set PID [UADDR/pcb GLOBAL] -/* - * Now running on new u struct. - * Restore registers and return. - */ - lw t0, _C_LABEL(curpcb) - nop - lw v0, U_PCB_CONTEXT+44(t0) # restore kernel context - lw ra, U_PCB_CONTEXT+40(t0) - lw s0, U_PCB_CONTEXT+0(t0) - lw s1, U_PCB_CONTEXT+4(t0) - lw s2, U_PCB_CONTEXT+8(t0) - lw s3, U_PCB_CONTEXT+12(t0) - lw s4, U_PCB_CONTEXT+16(t0) - lw s5, U_PCB_CONTEXT+20(t0) - lw s6, U_PCB_CONTEXT+24(t0) - lw s7, U_PCB_CONTEXT+28(t0) - lw sp, U_PCB_CONTEXT+32(t0) - lw s8, U_PCB_CONTEXT+36(t0) - nop - mtc0 v0, MIPS_COP_0_STATUS_REG - j ra - li v0, 1 # possible return to 'savectx()' -END(mips1_cpu_switch_resume) - -/*---------------------------------------------------------------------------- - * - * XXX END of r3000-specific code XXX - * - *---------------------------------------------------------------------------- - */ - diff --git a/sys/arch/mips/mips/locore_r4000.S b/sys/arch/mips/mips/locore_r4000.S deleted file mode 100644 index 096ef1254c02..000000000000 --- a/sys/arch/mips/mips/locore_r4000.S +++ /dev/null @@ -1,2311 +0,0 @@ -/* $NetBSD: locore_r4000.S,v 1.46 1998/12/28 00:31:03 nisimura Exp $ */ - -/* - * Copyright (c) 1997 Jonathan Stone (hereinafter referred to as the author) - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Jonathan R. Stone for - * the NetBSD Project. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Digital Equipment Corporation and Ralph Campbell. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Copyright (C) 1989 Digital Equipment Corporation. - * Permission to use, copy, modify, and distribute this software and - * its documentation for any purpose and without fee is hereby granted, - * provided that the above copyright notice appears in all copies. - * Digital Equipment Corporation makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s, - * v 1.1 89/07/11 17:55:04 nelson Exp SPRITE (DECWRL) - * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s, - * v 9.2 90/01/29 18:00:39 shirriff Exp SPRITE (DECWRL) - * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s, - * v 1.1 89/07/10 14:27:41 nelson Exp SPRITE (DECWRL) - * - * @(#)locore.s 8.5 (Berkeley) 1/4/94 - */ - -/* - *============================================================================ - * - * Mips-III ISA support, part 1: locore exception vectors. - * The following code is copied to the vector locations to which - * the CPU jumps in response to an exception or a TLB miss. - * - *============================================================================ - -/* - * Mark where code entered from exception hander jumptable - * starts, for stack traceback code. - */ - - .globl _C_LABEL(mips3_exceptionentry_start) -_C_LABEL(mips3_exceptionentry_start): - -/* - *---------------------------------------------------------------------------- - * - * mips3_TLBMiss -- - * - * Vector code for the TLB-miss exception vector 0x80000180 - * on an r4000. - * - * This code is copied to the TLB exception vector address to - * handle TLB translation misses. - * NOTE: This code must be relocatable and max 32 instructions!!! - * Don't check for invalid pte's here. We load them as well and - * let the processor trap to load the correct value after service. - * - *---------------------------------------------------------------------------- - */ - .globl _C_LABEL(mips3_TLBMiss) -_C_LABEL(mips3_TLBMiss): - .set noat - .set mips3 - dmfc0 k0, MIPS_COP_0_BAD_VADDR # get the virtual address - lw k1, _C_LABEL(curpcb) - bltz k0, 1f # kernel address space - nop - lw k1, U_PCB_SEGTAB(k1) # get the current segment table - srl k0, k0, SEGSHIFT - 2 # compute segment table index - andi k0, k0, 0x7fc # PMAP_SEGTABSIZ-1 - addu k1, k1, k0 - dmfc0 k0, MIPS_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/2) - 1) << 3 - beq k1, zero, 2f # invalid segment map - addu k1, k1, k0 # index into segment map - lw k0, 0(k1) # get page PTE - lw k1, 4(k1) - dsll k0, k0, 34 - dsrl k0, k0, 34 - dmtc0 k0, MIPS_COP_0_TLB_LO0 - dsll k1, k1, 34 - dsrl k1, k1, 34 - dmtc0 k1, MIPS_COP_0_TLB_LO1 - nop - tlbwr # update TLB - nop - nop - nop - nop - nop - eret -1: - j _C_LABEL(mips3_TLBMissException) - nop -2: - j mips3_SlowFault - nop - - .globl _C_LABEL(mips3_TLBMissEnd) -_C_LABEL(mips3_TLBMissEnd): - .set at - -/* - *---------------------------------------------------------------------------- - * - * mips3_execption -- - * - * Vector code for the general exception vector 0x80000180 - * on an r4000 or r4400. - * - * This code is copied to the general exception vector address to - * handle all execptions except RESET and TLBMiss. - * NOTE: This code must be relocatable!!! - *---------------------------------------------------------------------------- - */ - .globl _C_LABEL(mips3_exception) -_C_LABEL(mips3_exception): -/* - * Find out what mode we came from and jump to the proper handler. - */ - .set noat - mfc0 k0, MIPS_COP_0_STATUS_REG # Get the status register - mfc0 k1, MIPS_COP_0_CAUSE_REG # Get the cause register value. - and k0, k0, MIPS3_SR_KSU_USER # test for user mode - # sneaky but the bits are - # with us........ - sll k0, k0, 3 # shift user bit for cause index - and k1, k1, MIPS3_CR_EXC_CODE # Mask out the cause bits. - or k1, k1, k0 # change index to user table -1: - la k0, _C_LABEL(mips3_ExceptionTable) # 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 dont have to shift. - lw k0, 0(k0) # Get the function address - nop - j k0 # Jump to the function. - nop - .set at - .globl _C_LABEL(mips3_exceptionEnd) -_C_LABEL(mips3_exceptionEnd): - - -/*---------------------------------------------------------------------------- - * - * mips3_SlowFault -- - * - * Alternate entry point into the mips3_UserGenException or - * or mips3_user_Kern_exception, when the ULTB miss handler couldn't - * find a TLB entry. - * - * Find out what mode we came from and call the appropriate handler. - * - *---------------------------------------------------------------------------- - */ - -/* - * We couldn't find a TLB entry. - * Find out what mode we came from and call the appropriate handler. - */ -mips3_SlowFault: - .set noat - mfc0 k0, MIPS_COP_0_STATUS_REG - nop - and k0, k0, MIPS3_SR_KSU_USER - bne k0, zero, _C_LABEL(mips3_UserGenException) - nop - .set at -/* - * Fall though ... - */ - -/*---------------------------------------------------------------------------- - * - * mips3_KernGenException -- - * - * Handle an exception from kernel mode. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ - -/* - * XXX - incorrect now. - * 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 TRAP_FRAME_SIZE (4 * 38 + 4 * 4 + 4 + 4) -#define TRAP_RA_OFFSET (TRAP_FRAME_SIZE - 4) -#define TRAP_FRAME_OFFSET (4 * 4) - -/* - * Similar definition for interrupt-exception frames. - */ -#define KINTR_FRAME_SIZE (4 * 38 + 4 * 4 + 4 + 4) -#define KINTR_RA_OFFSET STAND_RA_OFFSET -#define KINTR_FRAME_OFFSET STAND_FRAME_SIZE - -NNON_LEAF(mips3_KernGenException, TRAP_FRAME_SIZE, ra) - .set noat - subu sp, sp, TRAP_FRAME_SIZE - .mask 0x80000000, (TRAP_RA_OFFSET - TRAP_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, TRAP_FRAME_OFFSET + (AST * 4)(sp) - sw v0, TRAP_FRAME_OFFSET + (V0 * 4)(sp) - sw v1, TRAP_FRAME_OFFSET + (V1 * 4)(sp) - sw a0, TRAP_FRAME_OFFSET + (A0 * 4)(sp) - mflo v0 - mfhi v1 - sw a1, TRAP_FRAME_OFFSET + (A1 * 4)(sp) - sw a2, TRAP_FRAME_OFFSET + (A2 * 4)(sp) - sw a3, TRAP_FRAME_OFFSET + (A3 * 4)(sp) - sw t0, TRAP_FRAME_OFFSET + (T0 * 4)(sp) - mfc0 a0, MIPS_COP_0_STATUS_REG # First arg is the status reg. - sw t1, TRAP_FRAME_OFFSET + (T1 * 4)(sp) - sw t2, TRAP_FRAME_OFFSET + (T2 * 4)(sp) - sw t3, TRAP_FRAME_OFFSET + (T3 * 4)(sp) - sw t4, TRAP_FRAME_OFFSET + (T4 * 4)(sp) - mfc0 a1, MIPS_COP_0_CAUSE_REG # Second arg is the cause reg. - sw t5, TRAP_FRAME_OFFSET + (T5 * 4)(sp) - sw t6, TRAP_FRAME_OFFSET + (T6 * 4)(sp) - sw t7, TRAP_FRAME_OFFSET + (T7 * 4)(sp) - sw t8, TRAP_FRAME_OFFSET + (T8 * 4)(sp) - mfc0 a2, MIPS_COP_0_BAD_VADDR # Third arg is the fault addr. - sw t9, TRAP_FRAME_OFFSET + (T9 * 4)(sp) - sw ra, TRAP_FRAME_OFFSET + (RA * 4)(sp) - sw v0, TRAP_FRAME_OFFSET + (MULLO * 4)(sp) - sw v1, TRAP_FRAME_OFFSET + (MULHI * 4)(sp) - mfc0 a3, MIPS_COP_0_EXC_PC # Fourth arg is the pc. - sw a0, TRAP_FRAME_OFFSET + (SR * 4)(sp) - -#ifdef DDB - addu v0, sp, TRAP_FRAME_SIZE # SP at trap for debugging - sw v0, TRAP_FRAME_OFFSET+(SP * 4)(sp) -#else - nop -#endif DDB - sw a3, TRAP_FRAME_OFFSET + (PC * 4)(sp) - mtc0 zero,MIPS_COP_0_STATUS_REG # Set kernel no error level -/* - * Call the exception handler. - */ - jal _C_LABEL(trap) - sw a3, TRAP_RA_OFFSET(sp) # for debugging -/* - * Restore registers and return from the exception. - */ - mtc0 zero,MIPS_COP_0_STATUS_REG # Make sure int disabled - nop - lw a0, TRAP_FRAME_OFFSET + (SR * 4)(sp) - lw v0, TRAP_FRAME_OFFSET + (PC * 4)(sp) # might be changed inside trap - lw t0, TRAP_FRAME_OFFSET + (MULLO * 4)(sp) - lw t1, TRAP_FRAME_OFFSET + (MULHI * 4)(sp) - nop - mtc0 a0, MIPS_COP_0_STATUS_REG # Restore the SR, disable intrs - mtlo t0 - mthi t1 - dmtc0 v0, MIPS_COP_0_EXC_PC # set return address - nop - - lw AT, TRAP_FRAME_OFFSET + (AST * 4)(sp) - lw v0, TRAP_FRAME_OFFSET + (V0 * 4)(sp) - lw v1, TRAP_FRAME_OFFSET + (V1 * 4)(sp) - lw a0, TRAP_FRAME_OFFSET + (A0 * 4)(sp) - lw a1, TRAP_FRAME_OFFSET + (A1 * 4)(sp) - lw a2, TRAP_FRAME_OFFSET + (A2 * 4)(sp) - lw a3, TRAP_FRAME_OFFSET + (A3 * 4)(sp) - lw t0, TRAP_FRAME_OFFSET + (T0 * 4)(sp) - lw t1, TRAP_FRAME_OFFSET + (T1 * 4)(sp) - lw t2, TRAP_FRAME_OFFSET + (T2 * 4)(sp) - lw t3, TRAP_FRAME_OFFSET + (T3 * 4)(sp) - lw t4, TRAP_FRAME_OFFSET + (T4 * 4)(sp) - lw t5, TRAP_FRAME_OFFSET + (T5 * 4)(sp) - lw t6, TRAP_FRAME_OFFSET + (T6 * 4)(sp) - lw t7, TRAP_FRAME_OFFSET + (T7 * 4)(sp) - lw t8, TRAP_FRAME_OFFSET + (T8 * 4)(sp) - lw t9, TRAP_FRAME_OFFSET + (T9 * 4)(sp) - lw ra, TRAP_FRAME_OFFSET + (RA * 4)(sp) - - addu sp, sp, TRAP_FRAME_SIZE - eret # exception. - .set at - .globl _C_LABEL(mips3_KernGenExceptionEnd) -_C_LABEL(mips3_KernGenExceptionEnd): -END(mips3_KernGenException) - -/*---------------------------------------------------------------------------- - * - * mips3_UserGenException -- - * - * Handle an exception from user mode. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -NNON_LEAF(mips3_UserGenException, STAND_FRAME_SIZE, ra) - .set noat - .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE) -/* - * Save all of the registers except for the kernel temporaries in u.u_pcb. - */ - lw k1, _C_LABEL(curpcb) - sw AT, U_PCB_REGS+(AST * 4)(k1) - sw v0, U_PCB_REGS+(V0 * 4)(k1) - sw v1, U_PCB_REGS+(V1 * 4)(k1) - sw a0, U_PCB_REGS+(A0 * 4)(k1) - mflo v0 - sw a1, U_PCB_REGS+(A1 * 4)(k1) - sw a2, U_PCB_REGS+(A2 * 4)(k1) - sw a3, U_PCB_REGS+(A3 * 4)(k1) - sw t0, U_PCB_REGS+(T0 * 4)(k1) - mfhi v1 - sw t1, U_PCB_REGS+(T1 * 4)(k1) - sw t2, U_PCB_REGS+(T2 * 4)(k1) - sw t3, U_PCB_REGS+(T3 * 4)(k1) - sw t4, U_PCB_REGS+(T4 * 4)(k1) - mfc0 a0, MIPS_COP_0_STATUS_REG # First arg is the status reg. - sw t5, U_PCB_REGS+(T5 * 4)(k1) - sw t6, U_PCB_REGS+(T6 * 4)(k1) - sw t7, U_PCB_REGS+(T7 * 4)(k1) - sw s0, U_PCB_REGS+(S0 * 4)(k1) - mfc0 a1, MIPS_COP_0_CAUSE_REG # Second arg is the cause reg. - sw s1, U_PCB_REGS+(S1 * 4)(k1) - sw s2, U_PCB_REGS+(S2 * 4)(k1) - sw s3, U_PCB_REGS+(S3 * 4)(k1) - sw s4, U_PCB_REGS+(S4 * 4)(k1) - mfc0 a2, MIPS_COP_0_BAD_VADDR # Third arg is the fault addr - sw s5, U_PCB_REGS+(S5 * 4)(k1) - sw s6, U_PCB_REGS+(S6 * 4)(k1) - sw s7, U_PCB_REGS+(S7 * 4)(k1) - sw t8, U_PCB_REGS+(T8 * 4)(k1) - mfc0 a3, MIPS_COP_0_EXC_PC # Fourth arg is the pc. - sw t9, U_PCB_REGS+(T9 * 4)(k1) - sw gp, U_PCB_REGS+(GP * 4)(k1) - sw sp, U_PCB_REGS+(SP * 4)(k1) - sw s8, U_PCB_REGS+(S8 * 4)(k1) - li sp, KERNELSTACK - STAND_FRAME_SIZE # switch to kernel SP - sw ra, U_PCB_REGS+(RA * 4)(k1) - sw v0, U_PCB_REGS+(MULLO * 4)(k1) - sw v1, U_PCB_REGS+(MULHI * 4)(k1) - sw a0, U_PCB_REGS+(SR * 4)(k1) -#ifdef __GP_SUPPORT__ - la gp, _C_LABEL(_gp) # switch to kernel GP -#endif - sw a3, U_PCB_REGS+(PC * 4)(k1) - sw a3, STAND_RA_OFFSET(sp) # for debugging - .set at -# Turn off fpu and enter kernel mode - and t0, a0, ~(MIPS_SR_COP_1_BIT | MIPS_SR_EXL | MIPS_SR_KSU_MASK | MIPS_SR_INT_IE) - .set noat -/* - * Call the exception handler. - */ - jal _C_LABEL(trap) - mtc0 t0, MIPS_COP_0_STATUS_REG -/* - * Restore user registers and return. - * First disable interrupts and set exeption level. - */ - mtc0 zero, MIPS_COP_0_STATUS_REG # disable int - nop - nop - nop - - li v0, MIPS_SR_EXL - mtc0 v0, MIPS_COP_0_STATUS_REG # set exception level - nop - nop - nop - - lw k1, _C_LABEL(curpcb) - # lw a0, U_PCB_REGS+(SR * 4)(k1) - lw t0, U_PCB_REGS+(MULLO * 4)(k1) - lw t1, U_PCB_REGS+(MULHI * 4)(k1) - nop - nop - # mtc0 a0, MIPS_COP_0_STATUS_REG # still exeption level - mtlo t0 - mthi t1 - lw a0, U_PCB_REGS+(PC * 4)(k1) - lw AT, U_PCB_REGS+(AST * 4)(k1) - lw v0, U_PCB_REGS+(V0 * 4)(k1) - nop - nop - dmtc0 a0, MIPS_COP_0_EXC_PC # set return address - nop - nop - - lw v1, U_PCB_REGS+(V1 * 4)(k1) - lw a0, U_PCB_REGS+(A0 * 4)(k1) - lw a1, U_PCB_REGS+(A1 * 4)(k1) - lw a2, U_PCB_REGS+(A2 * 4)(k1) - lw a3, U_PCB_REGS+(A3 * 4)(k1) - lw t0, U_PCB_REGS+(T0 * 4)(k1) - lw t1, U_PCB_REGS+(T1 * 4)(k1) - lw t2, U_PCB_REGS+(T2 * 4)(k1) - lw t3, U_PCB_REGS+(T3 * 4)(k1) - lw t4, U_PCB_REGS+(T4 * 4)(k1) - lw t5, U_PCB_REGS+(T5 * 4)(k1) - lw t6, U_PCB_REGS+(T6 * 4)(k1) - lw t7, U_PCB_REGS+(T7 * 4)(k1) - lw s0, U_PCB_REGS+(S0 * 4)(k1) - lw s1, U_PCB_REGS+(S1 * 4)(k1) - lw s2, U_PCB_REGS+(S2 * 4)(k1) - lw s3, U_PCB_REGS+(S3 * 4)(k1) - lw s4, U_PCB_REGS+(S4 * 4)(k1) - lw s5, U_PCB_REGS+(S5 * 4)(k1) - lw s6, U_PCB_REGS+(S6 * 4)(k1) - lw s7, U_PCB_REGS+(S7 * 4)(k1) - lw t8, U_PCB_REGS+(T8 * 4)(k1) - lw t9, U_PCB_REGS+(T9 * 4)(k1) - lw gp, U_PCB_REGS+(GP * 4)(k1) - lw sp, U_PCB_REGS+(SP * 4)(k1) - lw s8, U_PCB_REGS+(S8 * 4)(k1) - lw ra, U_PCB_REGS+(RA * 4)(k1) - lw k0, U_PCB_REGS+(SR * 4)(k1) - nop - mtc0 k0, MIPS_COP_0_STATUS_REG # still exeption level - - eret - .set at - .globl _C_LABEL(mips3_UserGenExceptionEnd) -_C_LABEL(mips3_UserGenExceptionEnd): -END(mips3_UserGenException) - -/* - * System call handler - */ -NNON_LEAF(mips3_SystemCall, STAND_FRAME_SIZE, ra) - .set noat - .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE) - lw k1, _C_LABEL(curpcb) - sw AT, U_PCB_REGS+(AST * 4)(k1) - sw v0, U_PCB_REGS+(V0 * 4)(k1) - sw v1, U_PCB_REGS+(V1 * 4)(k1) - mflo v0 - mfhi v1 - sw a0, U_PCB_REGS+(A0 * 4)(k1) - sw a1, U_PCB_REGS+(A1 * 4)(k1) - sw a2, U_PCB_REGS+(A2 * 4)(k1) - sw a3, U_PCB_REGS+(A3 * 4)(k1) - sw t0, U_PCB_REGS+(T0 * 4)(k1) - sw t1, U_PCB_REGS+(T1 * 4)(k1) - sw t2, U_PCB_REGS+(T2 * 4)(k1) - sw t3, U_PCB_REGS+(T3 * 4)(k1) - sw t4, U_PCB_REGS+(T4 * 4)(k1) - sw t5, U_PCB_REGS+(T5 * 4)(k1) - sw t6, U_PCB_REGS+(T6 * 4)(k1) - sw t7, U_PCB_REGS+(T7 * 4)(k1) - sw s0, U_PCB_REGS+(S0 * 4)(k1) - sw s1, U_PCB_REGS+(S1 * 4)(k1) - sw s2, U_PCB_REGS+(S2 * 4)(k1) - sw s3, U_PCB_REGS+(S3 * 4)(k1) - sw s4, U_PCB_REGS+(S4 * 4)(k1) - sw s5, U_PCB_REGS+(S5 * 4)(k1) - mfc0 a0, MIPS_COP_0_STATUS_REG # 1st arg is STATUS - sw s6, U_PCB_REGS+(S6 * 4)(k1) - sw s7, U_PCB_REGS+(S7 * 4)(k1) - sw t8, U_PCB_REGS+(T8 * 4)(k1) - sw t9, U_PCB_REGS+(T9 * 4)(k1) - mfc0 a1, MIPS_COP_0_CAUSE_REG # 2nd arg is CAUSE - sw gp, U_PCB_REGS+(GP * 4)(k1) - sw sp, U_PCB_REGS+(SP * 4)(k1) - sw s8, U_PCB_REGS+(S8 * 4)(k1) - sw ra, U_PCB_REGS+(RA * 4)(k1) - mfc0 a2, MIPS_COP_0_EXC_PC # 3rd arg is PC - la a3, U_PCB_REGS(k1) # 4th arg is p. to trapframe - sw a0, U_PCB_REGS+(SR * 4)(k1) - sw v0, U_PCB_REGS+(MULLO * 4)(k1) - sw v1, U_PCB_REGS+(MULHI * 4)(k1) - sw a2, U_PCB_REGS+(PC * 4)(k1) - li sp, KERNELSTACK - STAND_FRAME_SIZE # switch to kernel SP - sw a2, STAND_RA_OFFSET(sp) # for debugging -#ifdef __GP_SUPPORT__ - la gp, _C_LABEL(_gp) # switch to kernel GP -#endif - .set at -# Turn off fpu and enter kernel mode - and t0, a0, ~(MIPS_SR_COP_1_BIT | MIPS_SR_EXL | MIPS_SR_KSU_MASK | MIPS_SR_INT_IE) - .set noat - jal _C_LABEL(syscall) - mtc0 t0, MIPS_COP_0_STATUS_REG -/* - * Restore user registers and return. - * First disable interrupts and set exeption level. - */ - mtc0 zero, MIPS_COP_0_STATUS_REG # disable int - nop - nop - nop - - li v0, MIPS_SR_EXL - mtc0 v0, MIPS_COP_0_STATUS_REG # set exception level - nop - nop - nop - -/* - * Restore user registers and return. - */ - lw k1, _C_LABEL(curpcb) - # lw a0, U_PCB_REGS+(SR * 4)(k1) - lw t0, U_PCB_REGS+(MULLO * 4)(k1) - lw t1, U_PCB_REGS+(MULHI * 4)(k1) - # mtc0 a0, MIPS_COP_0_STATUS_REG # this should disable interrupts - mtlo t0 - mthi t1 - lw k0, U_PCB_REGS+(PC * 4)(k1) # might be changed in syscall - dmtc0 k0, MIPS_COP_0_EXC_PC # set return address - nop - nop - lw AT, U_PCB_REGS+(AST * 4)(k1) - lw v0, U_PCB_REGS+(V0 * 4)(k1) - lw v1, U_PCB_REGS+(V1 * 4)(k1) - lw a0, U_PCB_REGS+(A0 * 4)(k1) - lw a1, U_PCB_REGS+(A1 * 4)(k1) - lw a2, U_PCB_REGS+(A2 * 4)(k1) - lw a3, U_PCB_REGS+(A3 * 4)(k1) - lw t0, U_PCB_REGS+(T0 * 4)(k1) - lw t1, U_PCB_REGS+(T1 * 4)(k1) - lw t2, U_PCB_REGS+(T2 * 4)(k1) - lw t3, U_PCB_REGS+(T3 * 4)(k1) - lw t4, U_PCB_REGS+(T4 * 4)(k1) - lw t5, U_PCB_REGS+(T5 * 4)(k1) - lw t6, U_PCB_REGS+(T6 * 4)(k1) - lw t7, U_PCB_REGS+(T7 * 4)(k1) - lw s0, U_PCB_REGS+(S0 * 4)(k1) - lw s1, U_PCB_REGS+(S1 * 4)(k1) - lw s2, U_PCB_REGS+(S2 * 4)(k1) - lw s3, U_PCB_REGS+(S3 * 4)(k1) - lw s4, U_PCB_REGS+(S4 * 4)(k1) - lw s5, U_PCB_REGS+(S5 * 4)(k1) - lw s6, U_PCB_REGS+(S6 * 4)(k1) - lw s7, U_PCB_REGS+(S7 * 4)(k1) - lw t8, U_PCB_REGS+(T8 * 4)(k1) - lw t9, U_PCB_REGS+(T9 * 4)(k1) - lw gp, U_PCB_REGS+(GP * 4)(k1) - lw sp, U_PCB_REGS+(SP * 4)(k1) - lw s8, U_PCB_REGS+(S8 * 4)(k1) - lw ra, U_PCB_REGS+(RA * 4)(k1) - lw k0, U_PCB_REGS+(SR * 4)(k1) - nop - mtc0 k0, MIPS_COP_0_STATUS_REG - nop - eret - .set at - .globl _C_LABEL(mips3_SystemCallEnd) -_C_LABEL(mips3_SystemCallEnd): -END(mips3_SystemCall) - -/*---------------------------------------------------------------------------- - * - * mips3_KernIntr -- - * - * 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. - * - *---------------------------------------------------------------------------- - */ -NNON_LEAF(mips3_KernIntr, KINTR_FRAME_SIZE, ra) - .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_FRAME_OFFSET + (AST * 4)(sp) - sw v0, KINTR_FRAME_OFFSET + (V0 * 4)(sp) - sw v1, KINTR_FRAME_OFFSET + (V1 * 4)(sp) - sw a0, KINTR_FRAME_OFFSET + (A0 * 4)(sp) - mflo v0 - mfhi v1 - sw a1, KINTR_FRAME_OFFSET + (A1 * 4)(sp) - sw a2, KINTR_FRAME_OFFSET + (A2 * 4)(sp) - sw a3, KINTR_FRAME_OFFSET + (A3 * 4)(sp) - sw t0, KINTR_FRAME_OFFSET + (T0 * 4)(sp) - mfc0 a0, MIPS_COP_0_STATUS_REG # First arg is the status reg. - sw t1, KINTR_FRAME_OFFSET + (T1 * 4)(sp) - sw t2, KINTR_FRAME_OFFSET + (T2 * 4)(sp) - sw t3, KINTR_FRAME_OFFSET + (T3 * 4)(sp) - sw t4, KINTR_FRAME_OFFSET + (T4 * 4)(sp) - mfc0 a1, MIPS_COP_0_CAUSE_REG # Second arg is the cause reg. - sw t5, KINTR_FRAME_OFFSET + (T5 * 4)(sp) - sw t6, KINTR_FRAME_OFFSET + (T6 * 4)(sp) - sw t7, KINTR_FRAME_OFFSET + (T7 * 4)(sp) - sw t8, KINTR_FRAME_OFFSET + (T8 * 4)(sp) - mfc0 a2, MIPS_COP_0_EXC_PC # Third arg is the pc. - sw t9, KINTR_FRAME_OFFSET + (T9 * 4)(sp) - sw ra, KINTR_FRAME_OFFSET + (RA * 4)(sp) - sw v0, KINTR_FRAME_OFFSET + (MULLO * 4)(sp) - sw v1, KINTR_FRAME_OFFSET + (MULHI * 4)(sp) - sw a0, KINTR_FRAME_OFFSET + (SR * 4)(sp) - la a3, KINTR_FRAME_OFFSET(sp) # Fourth arg is address of frame - - nop - mtc0 zero, MIPS_COP_0_STATUS_REG # Reset exl, trap possible. -/* - * Call the interrupt handler. - */ - jal _C_LABEL(interrupt) - sw a2, KINTR_RA_OFFSET(sp) # for debugging -/* - * Restore registers and return from the interrupt. - */ - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupt - nop - lw a0, KINTR_FRAME_OFFSET + (SR * 4)(sp) - lw t0, KINTR_FRAME_OFFSET + (MULLO * 4)(sp) - lw t1, KINTR_FRAME_OFFSET + (MULHI * 4)(sp) - nop - mtc0 a0, MIPS_COP_0_STATUS_REG # Restore the SR, disable intrs - mtlo t0 - mthi t1 - lw a0, KINTR_RA_OFFSET(sp) - lw AT, KINTR_FRAME_OFFSET + (AST * 4)(sp) - lw v0, KINTR_FRAME_OFFSET + (V0 * 4)(sp) - nop - dmtc0 a0, MIPS_COP_0_EXC_PC # set return address - nop - - lw v1, KINTR_FRAME_OFFSET+(V1 * 4)(sp) - lw a0, KINTR_FRAME_OFFSET+(A0 * 4)(sp) - lw a1, KINTR_FRAME_OFFSET+(A1 * 4)(sp) - lw a2, KINTR_FRAME_OFFSET+(A2 * 4)(sp) - lw a3, KINTR_FRAME_OFFSET+(A3 * 4)(sp) - lw t0, KINTR_FRAME_OFFSET+(T0 * 4)(sp) - lw t1, KINTR_FRAME_OFFSET+(T1 * 4)(sp) - lw t2, KINTR_FRAME_OFFSET+(T2 * 4)(sp) - lw t3, KINTR_FRAME_OFFSET+(T3 * 4)(sp) - lw t4, KINTR_FRAME_OFFSET+(T4 * 4)(sp) - lw t5, KINTR_FRAME_OFFSET+(T5 * 4)(sp) - lw t6, KINTR_FRAME_OFFSET+(T6 * 4)(sp) - lw t7, KINTR_FRAME_OFFSET+(T7 * 4)(sp) - lw t8, KINTR_FRAME_OFFSET+(T8 * 4)(sp) - lw t9, KINTR_FRAME_OFFSET+(T9 * 4)(sp) - # lw gp, KINTR_FRAME_OFFSET+(GP * 4)(sp) - lw ra, KINTR_FRAME_OFFSET+(RA * 4)(sp) - - addu sp, sp, KINTR_FRAME_SIZE - eret # interrupt. - .set at - .globl _C_LABEL(mips3_KernIntrEnd) -_C_LABEL(mips3_KernIntrEnd): -END(mips3_KernIntr) - -/*---------------------------------------------------------------------------- - * - * mips3_UserIntr -- - * - * 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 switch() inside - * interrupt(), not all the user registers have been saved in u.u_pcb. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -NNON_LEAF(mips3_UserIntr, STAND_FRAME_SIZE, ra) - .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. - */ - lw k1, _C_LABEL(curpcb) - sw AT, U_PCB_REGS+(AST * 4)(k1) - sw v0, U_PCB_REGS+(V0 * 4)(k1) - sw v1, U_PCB_REGS+(V1 * 4)(k1) - sw a0, U_PCB_REGS+(A0 * 4)(k1) - mflo v0 - mfhi v1 - sw a1, U_PCB_REGS+(A1 * 4)(k1) - sw a2, U_PCB_REGS+(A2 * 4)(k1) - sw a3, U_PCB_REGS+(A3 * 4)(k1) - sw t0, U_PCB_REGS+(T0 * 4)(k1) - mfc0 a0, MIPS_COP_0_STATUS_REG # First arg is the status reg. - sw t1, U_PCB_REGS+(T1 * 4)(k1) - sw t2, U_PCB_REGS+(T2 * 4)(k1) - sw t3, U_PCB_REGS+(T3 * 4)(k1) - sw t4, U_PCB_REGS+(T4 * 4)(k1) - mfc0 a1, MIPS_COP_0_CAUSE_REG # Second arg is the cause reg. - sw t5, U_PCB_REGS+(T5 * 4)(k1) - sw t6, U_PCB_REGS+(T6 * 4)(k1) - sw t7, U_PCB_REGS+(T7 * 4)(k1) - sw t8, U_PCB_REGS+(T8 * 4)(k1) - mfc0 a2, MIPS_COP_0_EXC_PC # Third arg is the pc. - sw t9, U_PCB_REGS+(T9 * 4)(k1) - sw gp, U_PCB_REGS+(GP * 4)(k1) - sw sp, U_PCB_REGS+(SP * 4)(k1) - sw ra, U_PCB_REGS+(RA * 4)(k1) - la a3, U_PCB_REGS(k1) - li sp, KERNELSTACK - STAND_FRAME_SIZE # switch to kernel SP - sw v0, U_PCB_REGS+(MULLO * 4)(k1) - sw v1, U_PCB_REGS+(MULHI * 4)(k1) - sw a0, U_PCB_REGS+(SR * 4)(k1) - sw a2, U_PCB_REGS+(PC * 4)(k1) -#ifdef __GP_SUPPORT__ - la gp, _C_LABEL(_gp) # switch to kernel GP -#endif -# Turn off fpu and enter kernel mode - .set at - and t0, a0, ~(MIPS_SR_COP_1_BIT | MIPS_SR_EXL | MIPS_SR_INT_IE | MIPS_SR_KSU_MASK) - .set noat - mtc0 t0, MIPS_COP_0_STATUS_REG -/* - * Call the interrupt handler. - */ - jal _C_LABEL(interrupt) - sw a2, STAND_RA_OFFSET(sp) # for debugging -/* - * Restore registers and return from the interrupt. - */ - nop - mtc0 zero, MIPS_COP_0_STATUS_REG - nop - nop - nop - li v0, MIPS_SR_EXL - mtc0 v0, MIPS_COP_0_STATUS_REG # set exception level bit. - nop - - lw k1, _C_LABEL(curpcb) - # lw a0, U_PCB_REGS+(SR * 4)(k1) - lw v0, _C_LABEL(astpending) # any pending interrupts? - nop - # mtc0 a0, MIPS_COP_0_STATUS_REG # Restore the SR, disable intrs - bne v0, zero, 1f # dont restore, call softintr - lw t0, U_PCB_REGS+(MULLO * 4)(k1) - lw t1, U_PCB_REGS+(MULHI * 4)(k1) - lw a0, U_PCB_REGS+(PC * 4)(k1) - lw AT, U_PCB_REGS+(AST * 4)(k1) - lw v0, U_PCB_REGS+(V0 * 4)(k1) - nop - dmtc0 a0, MIPS_COP_0_EXC_PC # set return address - nop - lw v1, U_PCB_REGS+(V1 * 4)(k1) - lw a0, U_PCB_REGS+(A0 * 4)(k1) - lw a1, U_PCB_REGS+(A1 * 4)(k1) - lw a2, U_PCB_REGS+(A2 * 4)(k1) - lw a3, U_PCB_REGS+(A3 * 4)(k1) - mtlo t0 - mthi t1 - lw t0, U_PCB_REGS+(T0 * 4)(k1) - lw t1, U_PCB_REGS+(T1 * 4)(k1) - lw t2, U_PCB_REGS+(T2 * 4)(k1) - lw t3, U_PCB_REGS+(T3 * 4)(k1) - lw t4, U_PCB_REGS+(T4 * 4)(k1) - lw t5, U_PCB_REGS+(T5 * 4)(k1) - lw t6, U_PCB_REGS+(T6 * 4)(k1) - lw t7, U_PCB_REGS+(T7 * 4)(k1) - lw t8, U_PCB_REGS+(T8 * 4)(k1) - lw t9, U_PCB_REGS+(T9 * 4)(k1) - lw gp, U_PCB_REGS+(GP * 4)(k1) - lw sp, U_PCB_REGS+(SP * 4)(k1) - lw ra, U_PCB_REGS+(RA * 4)(k1) - lw k0, U_PCB_REGS+(SR * 4)(k1) - nop - mtc0 k0, MIPS_COP_0_STATUS_REG # Restore the SR - nop - eret # interrupt. - -1: -/* - * We have pending software interrupts; save remaining user state in u.u_pcb. - */ - sw s0, U_PCB_REGS+(S0 * 4)(k1) - sw s1, U_PCB_REGS+(S1 * 4)(k1) - sw s2, U_PCB_REGS+(S2 * 4)(k1) - sw s3, U_PCB_REGS+(S3 * 4)(k1) - sw s4, U_PCB_REGS+(S4 * 4)(k1) - sw s5, U_PCB_REGS+(S5 * 4)(k1) - sw s6, U_PCB_REGS+(S6 * 4)(k1) - sw s7, U_PCB_REGS+(S7 * 4)(k1) - sw s8, U_PCB_REGS+(S8 * 4)(k1) - li t0, MIPS_HARD_INT_MASK | MIPS_SR_INT_IE -/* - * Call the software interrupt handler. - */ - jal _C_LABEL(ast) - mtc0 t0, MIPS_COP_0_STATUS_REG # enable interrupts (spl0) -/* - * Restore user registers and return. NOTE: interrupts are enabled. - */ - mtc0 zero, MIPS_COP_0_STATUS_REG - nop - nop - nop - li v0, MIPS_SR_EXL - mtc0 v0, MIPS_COP_0_STATUS_REG # set exeption level bit. - nop - - lw k1, _C_LABEL(curpcb) - # lw a0, U_PCB_REGS+(SR * 4)(k1) - lw t0, U_PCB_REGS+(MULLO * 4)(k1) - lw t1, U_PCB_REGS+(MULHI * 4)(k1) - nop - # mtc0 a0, MIPS_COP_0_STATUS_REG # this should disable interrupts - mtlo t0 - mthi t1 - lw a0, U_PCB_REGS+(PC * 4)(k1) - lw AT, U_PCB_REGS+(AST * 4)(k1) - lw v0, U_PCB_REGS+(V0 * 4)(k1) - nop - dmtc0 a0, MIPS_COP_0_EXC_PC # set return address - nop - - lw v1, U_PCB_REGS+(V1 * 4)(k1) - lw a0, U_PCB_REGS+(A0 * 4)(k1) - lw a1, U_PCB_REGS+(A1 * 4)(k1) - lw a2, U_PCB_REGS+(A2 * 4)(k1) - lw a3, U_PCB_REGS+(A3 * 4)(k1) - lw t0, U_PCB_REGS+(T0 * 4)(k1) - lw t1, U_PCB_REGS+(T1 * 4)(k1) - lw t2, U_PCB_REGS+(T2 * 4)(k1) - lw t3, U_PCB_REGS+(T3 * 4)(k1) - lw t4, U_PCB_REGS+(T4 * 4)(k1) - lw t5, U_PCB_REGS+(T5 * 4)(k1) - lw t6, U_PCB_REGS+(T6 * 4)(k1) - lw t7, U_PCB_REGS+(T7 * 4)(k1) - lw t8, U_PCB_REGS+(T8 * 4)(k1) - lw t9, U_PCB_REGS+(T9 * 4)(k1) - lw gp, U_PCB_REGS+(GP * 4)(k1) - lw sp, U_PCB_REGS+(SP * 4)(k1) - lw ra, U_PCB_REGS+(RA * 4)(k1) - lw k0, U_PCB_REGS+(SR * 4)(k1) - nop - mtc0 k0, MIPS_COP_0_STATUS_REG # Restore the SR - nop - - eret - .set at - .globl _C_LABEL(mips3_UserIntrEnd) -_C_LABEL(mips3_UserIntrEnd): -END(mips3_UserIntr) - - -/*---------------------------------------------------------------------------- - * - * XXX START of r4000-specific code XXX - * - *---------------------------------------------------------------------------- - */ - - -/*---------------------------------------------------------------------------- - * - * R4000 TLB exception handlers - * - *---------------------------------------------------------------------------- - */ - - -/*---------------------------------------------------------------------------- - * - * mips3_TLBMInvalidException -- - * - * Handle a TLB invalid exception from kernel mode in kernel space. - * The BaddVAddr, Context, and EntryHi registers contain the failed - * virtual address. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -NLEAF(mips3_TLBInvalidException) - .set noat - dmfc0 k0, MIPS_COP_0_BAD_VADDR # get the fault address - li k1, VM_MIN_KERNEL_ADDRESS # compute index - subu k0, k0, k1 - lw k1, _C_LABEL(Sysmapsize) # index within range? - srl k0, k0, PGSHIFT - sltu k1, k0, k1 - beq k1, zero, sys_stk_chk # No. check for valid stack - lw k1, _C_LABEL(Sysmap) - - sll k0, k0, 2 # compute offset from index - tlbp # Probe the invalid entry - addu k1, k1, k0 - and k0, k0, 4 # check even/odd page - bne k0, zero, KernTLBIOdd - nop - - mfc0 k0, MIPS_COP_0_TLB_INDEX - nop - bltz k0, sys_stk_chk - # sltiu k0, k0, 8 - - # bne k0, zero, sys_stk_chk - beqz k0, sys_stk_chk - lw k0, 0(k1) # get PTE entry - - dsll k0, k0, 34 # get rid of "wired" bit - dsrl k0, k0, 34 - dmtc0 k0, MIPS_COP_0_TLB_LO0 # load PTE entry - and k0, k0, MIPS3_PG_V # check for valid entry - beq k0, zero, _C_LABEL(mips3_KernGenException) # PTE invalid - lw k0, 4(k1) # get odd PTE entry - dsll k0, k0, 34 - dsrl k0, k0, 34 - dmtc0 k0, MIPS_COP_0_TLB_LO1 # load PTE entry - nop - tlbwi # write TLB - nop - nop - nop - nop - nop - eret - -KernTLBIOdd: - mfc0 k0, MIPS_COP_0_TLB_INDEX - nop - bltz k0, sys_stk_chk - # sltiu k0, k0, 8 - - # bne k0, zero, sys_stk_chk - beqz k0, sys_stk_chk - lw k0, 0(k1) # get PTE entry - - dsll k0, k0, 34 # get rid of wired bit - dsrl k0, k0, 34 - dmtc0 k0, MIPS_COP_0_TLB_LO1 # save PTE entry - and k0, k0, MIPS3_PG_V # check for valid entry - beq k0, zero, _C_LABEL(mips3_KernGenException) # PTE invalid - lw k0, -4(k1) # get even PTE entry - dsll k0, k0, 34 - dsrl k0, k0, 34 - dmtc0 k0, MIPS_COP_0_TLB_LO0 # save PTE entry - nop - tlbwi # update TLB - nop - nop - nop - nop - nop - eret -END(mips3_TLBInvalidException) - -/*---------------------------------------------------------------------------- - * - * mips3_TLBMissException -- - * - * Handle a TLB miss exception from kernel mode in kernel space. - * The BaddVAddr, Context, and EntryHi registers contain the failed - * virtual address. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -NLEAF(mips3_TLBMissException) - .set noat - dmfc0 k0, MIPS_COP_0_BAD_VADDR # get the fault address - li k1, VM_MIN_KERNEL_ADDRESS # compute index - subu k0, k0, k1 - lw k1, _C_LABEL(Sysmapsize) # index within range? - srl k0, k0, PGSHIFT - sltu k1, k0, k1 - beq k1, zero, sys_stk_chk # No. check for valid stack - lw k1, _C_LABEL(Sysmap) - srl k0, k0, 1 - sll k0, k0, 3 # compute offset from index - addu k1, k1, k0 - lw k0, 0(k1) # get PTE entry - lw k1, 4(k1) # get odd PTE entry - dsll k0, k0, 34 # get rid of "wired" bit - dsrl k0, k0, 34 - dmtc0 k0, MIPS_COP_0_TLB_LO0 # load PTE entry - dsll k1, k1, 34 - dsrl k1, k1, 34 - dmtc0 k1, MIPS_COP_0_TLB_LO1 # load PTE entry - nop - tlbwr # write TLB - nop - nop - nop - nop - nop - eret - -sys_stk_chk: - subu k0, sp, UADDR + 0x200 # check to see if we have a - sltiu k0, UPAGES*NBPG - 0x200 # valid kernel stack - bne k0, zero, _C_LABEL(mips3_KernGenException) # 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, MIPS_COP_0_STATUS_REG - mfc0 a3, MIPS_COP_0_CAUSE_REG - dmfc0 a1, MIPS_COP_0_EXC_PC - sw a2, 16(sp) - sw a3, 20(sp) - move a2, ra - jal _C_LABEL(printf) - dmfc0 a3, MIPS_COP_0_BAD_VADDR - .data -1: - .asciiz "ktlbmiss: PC %x RA %x ADR %x\nSR %x CR %x SP %x\n" - .text - - /* Call mips3_dump_tlb(0, 2, printf) to show the bad kstack TLB */ - la a2, _C_LABEL(printf) - li a0, 0 - jal _C_LABEL(mips3_dump_tlb) - li a1, 2 # BDslot - - la sp, start - START_FRAME # set sp to a valid place -#ifdef DEBUG - # break MIPS_BREAK_SOVER_VAL -#endif - PANIC("kernel stack overflow") - .set at -END(mips3_TLBMissException) - -/* - * Mark where code entered from exception hander jumptable - * ends, for stack traceback code. - */ - - .globl _C_LABEL(mips3_exceptionentry_end) -_C_LABEL(mips3_exceptionentry_end): - - -/*-------------------------------------------------------------------------- - * - * mips3_TLBWriteIndexedVPS -- - * - * Write the given entry into the TLB at the given index. - * Pass full r4000 tlb info icnluding variable page size mask. - * - * mips3_TLBWriteIndexed(index, tlb) - * unsigned index; - * tlb *tlb; - * - * Results: - * None. - * - * Side effects: - * TLB entry set. - * - *-------------------------------------------------------------------------- - */ -LEAF(mips3_TLBWriteIndexedVPS) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - nop - lw a2, 8(a1) - lw a3, 12(a1) - dmfc0 t0, MIPS_COP_0_TLB_HI # Save the current PID. - - dmtc0 a2, MIPS_COP_0_TLB_LO0 # Set up entry low0. - dmtc0 a3, MIPS_COP_0_TLB_LO1 # Set up entry low1. - nop - lw a2, 0(a1) - lw a3, 4(a1) - nop - mtc0 a0, MIPS_COP_0_TLB_INDEX # Set the index. - dmtc0 a2, MIPS_COP_0_TLB_PG_MASK # Set up entry mask. - dmtc0 a3, MIPS_COP_0_TLB_HI # Set up entry high. - nop - tlbwi # Write the TLB - nop - nop - nop # Delay for effect - nop - - dmtc0 t0, MIPS_COP_0_TLB_HI # Restore the PID. - nop - dmtc0 zero, MIPS_COP_0_TLB_PG_MASK # Default mask value. - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(mips3_TLBWriteIndexedVPS) - -/*-------------------------------------------------------------------------- - * - * mips3_TLBWriteIndexed -- - * - * Write the given entry into the TLB at the given index. - * - * mips3_TLBWriteIndexed(index, highentry, lowentry0, lowentry1) - * unsigned index; - * int highEntry; - * int lowEntry0; - * int lowEntry1; - * - * Results: - * None. - * - * Side effects: - * TLB entry set. - * - *-------------------------------------------------------------------------- - */ -LEAF(mips3_TLBWriteIndexed) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - nop - lw a2, 8(a1) - lw a3, 12(a1) - dmfc0 t0, MIPS_COP_0_TLB_HI # Save the current PID. - - dmtc0 a2, MIPS_COP_0_TLB_LO0 # Set up entry low0. - dmtc0 a3, MIPS_COP_0_TLB_LO1 # Set up entry low1. - nop - lw a2, 0(a1) - lw a3, 4(a1) - nop - mtc0 a0, MIPS_COP_0_TLB_INDEX # Set the index. - dmtc0 a2, MIPS_COP_0_TLB_PG_MASK # Set up entry mask. - dmtc0 a3, MIPS_COP_0_TLB_HI # Set up entry high. - nop - tlbwi # Write the TLB - nop - nop - nop # Delay for effect - nop - - dmtc0 t0, MIPS_COP_0_TLB_HI # Restore the PID. - nop - dmtc0 zero, MIPS_COP_0_TLB_PG_MASK # Default mask value. - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(mips3_TLBWriteIndexed) - -/*-------------------------------------------------------------------------- - * - * mips3_SetPID -- - * - * Write the given pid into the TLB pid reg. - * - * mips3_SetPID(pid) - * int pid; - * - * Results: - * None. - * - * Side effects: - * PID set in the entry hi register. - * - *-------------------------------------------------------------------------- - */ -LEAF(mips3_SetPID) - dmtc0 a0, MIPS_COP_0_TLB_HI # Write the hi reg value - j ra - nop -END(mips3_SetPID) - -/*-------------------------------------------------------------------------- - * - * mips3_SetWIRED -- - * - * Write the given value into the TLB wired reg. - * - * mips3_SetPID(wired) - * int wired; - * - * Results: - * None. - * - * Side effects: - * WIRED set in the wired register. - * - *-------------------------------------------------------------------------- - */ -LEAF(mips3_SetWIRED) - mtc0 a0, MIPS_COP_0_TLB_WIRED - j ra - nop -END(mips3_SetWIRED) - -/*-------------------------------------------------------------------------- - * - * mips3_GetWIRED -- - * - * Get the value from the TLB wired reg. - * - * mips3_GetWIRED(void) - * - * Results: - * Value of wired reg. - * - * Side effects: - * None. - * - *-------------------------------------------------------------------------- - */ -LEAF(mips3_GetWIRED) - mfc0 v0, MIPS_COP_0_TLB_WIRED - j ra - nop -END(mips3_GetWIRED) - -/*-------------------------------------------------------------------------- - * - * mips3_TLBFlush -- - * - * Flush the "random" entries from the TLB. - * Uses "wired" register to determine what register to start with. - * Arg "tlbsize" is the number of entries to flush. - * - * mips3_TLBFlush(tlbsize) - * - * Results: - * None. - * - * Side effects: - * The TLB is flushed. - * - *-------------------------------------------------------------------------- - */ -LEAF(mips3_TLBFlush) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - mfc0 t1, MIPS_COP_0_TLB_WIRED - li v0, MIPS_KSEG0_START # invalid address - dmfc0 t0, MIPS_COP_0_TLB_HI # Save the PID - - dmtc0 v0, MIPS_COP_0_TLB_HI # Mark entry high as invalid - dmtc0 zero, MIPS_COP_0_TLB_LO0 # Zero out low entry0. - dmtc0 zero, MIPS_COP_0_TLB_LO1 # Zero out low entry1. - mtc0 zero, MIPS_COP_0_TLB_PG_MASK # Zero out mask entry. -/* - * Align the starting value (t1) and the upper bound (a0). - */ -1: - mtc0 t1, MIPS_COP_0_TLB_INDEX # Set the index register. - addu t1, t1, 1 # Increment index. - tlbwi # Write the TLB entry. - nop - nop - bne t1, a0, 1b - nop - - dmtc0 t0, MIPS_COP_0_TLB_HI # Restore the PID - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(mips3_TLBFlush) - - -/*-------------------------------------------------------------------------- - * - * mips3_TLBFlushAddr -- - * - * Flush any TLB entries for the given address and TLB PID. - * - * mips3_TLBFlushAddr(TLBhi) - * unsigned TLBhi; - * - * Results: - * None. - * - * Side effects: - * The process's page is flushed from the TLB. - * - *-------------------------------------------------------------------------- - */ -LEAF(mips3_TLBFlushAddr) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - nop - li v0, (MIPS3_PG_HVPN | MIPS3_PG_ASID) - and a0, a0, v0 # Make shure valid hi value. - dmfc0 t0, MIPS_COP_0_TLB_HI # Get current PID - dmtc0 a0, MIPS_COP_0_TLB_HI # look for addr & PID - nop - nop - nop - tlbp # Probe for the entry. - nop - nop # Delay for effect - nop - mfc0 v0, MIPS_COP_0_TLB_INDEX # See what we got - li t1, MIPS_KSEG0_START # Load invalid entry. - bltz v0, 1f # index < 0 => !found - nop - dmtc0 t1, MIPS_COP_0_TLB_HI # Mark entry high as invalid - - dmtc0 zero, MIPS_COP_0_TLB_LO0 # Zero out low entry. - dmtc0 zero, MIPS_COP_0_TLB_LO1 # Zero out low entry. - nop - tlbwi - nop - nop - nop - nop -1: - dmtc0 t0, MIPS_COP_0_TLB_HI # restore PID - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(mips3_TLBFlushAddr) - -/*-------------------------------------------------------------------------- - * - * mips3_TLBUpdate -- - * - * Update the TLB if highreg is found; otherwise, enter the data. - * - * mips3_TLBUpdate(virpageadr, lowregx) - * unsigned virpageadr, lowregx; - * - * Results: - * < 0 if loaded >= 0 if updated. - * - * Side effects: - * None. - * - *-------------------------------------------------------------------------- - */ -LEAF(mips3_TLBUpdate) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - and t1, a0, 0x1000 # t1 = Even/Odd flag - li v0, (MIPS3_PG_HVPN | MIPS3_PG_ASID) - and a0, a0, v0 - dmfc0 t0, MIPS_COP_0_TLB_HI # Save current PID - dmtc0 a0, MIPS_COP_0_TLB_HI # Init high reg - and a2, a1, MIPS3_PG_G # Copy global bit - nop - nop - tlbp # Probe for the entry. - dsll a1, a1, 34 - dsrl a1, a1, 34 - bne t1, zero, 2f # Decide even odd - mfc0 v0, MIPS_COP_0_TLB_INDEX # See what we got -# EVEN - nop - bltz v0, 1f # index < 0 => !found - nop - - tlbr # update, read entry first - nop - nop - nop - dmtc0 a1, MIPS_COP_0_TLB_LO0 # init low reg0. - nop - tlbwi # update slot found - b 4f - nop -1: - mtc0 zero, MIPS_COP_0_TLB_PG_MASK # init mask. - dmtc0 a0, MIPS_COP_0_TLB_HI # init high reg. - dmtc0 a1, MIPS_COP_0_TLB_LO0 # init low reg0. - dmtc0 a2, MIPS_COP_0_TLB_LO1 # init low reg1. - nop - tlbwr # enter into a random slot - b 4f - nop -# ODD -2: - nop - bltz v0, 3f # index < 0 => !found - nop - - tlbr # read the entry first - nop - nop - nop - dmtc0 a1, MIPS_COP_0_TLB_LO1 # init low reg1. - nop - tlbwi # update slot found - b 4f - nop -3: - mtc0 zero, MIPS_COP_0_TLB_PG_MASK # init mask. - dmtc0 a0, MIPS_COP_0_TLB_HI # init high reg. - dmtc0 a2, MIPS_COP_0_TLB_LO0 # init low reg0. - dmtc0 a1, MIPS_COP_0_TLB_LO1 # init low reg1. - nop - tlbwr # enter into a random slot - -4: # Make shure pipeline - nop # advances before we - nop # uses the tlb. - nop - nop - dmtc0 t0, MIPS_COP_0_TLB_HI # restore PID - j ra - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register -END(mips3_TLBUpdate) - -/*-------------------------------------------------------------------------- - * - * mips3_TLBReadVPS -- - * - * Read the TLB entry, including variable-page-size mask. - * - * mips3_TLBReadVPS(entry, tlb) - * unsigned entry; - * struct tlb *tlb; - * - * Results: - * None. - * - * Side effects: - * tlb will contain the TLB entry found. - * - *-------------------------------------------------------------------------- - */ -LEAF(mips3_TLBReadVPS) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - nop - nop - nop - dmfc0 t0, MIPS_COP_0_TLB_HI # Get current PID - - mtc0 a0, MIPS_COP_0_TLB_INDEX # Set the index register - nop - tlbr # Read from the TLB - nop - nop - nop - mfc0 t2, MIPS_COP_0_TLB_PG_MASK # fetch the hi entry - dmfc0 t3, MIPS_COP_0_TLB_HI # fetch the hi entry - dmfc0 t4, MIPS_COP_0_TLB_LO0 # See what we got - dmfc0 t5, MIPS_COP_0_TLB_LO1 # See what we got - dmtc0 t0, MIPS_COP_0_TLB_HI # restore PID - nop - nop - nop # wait for PID active - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register - nop - sw t2, 0(a1) - sw t3, 4(a1) - sw t4, 8(a1) - j ra - sw t5, 12(a1) -END(mips3_TLBReadVPS) - -/*-------------------------------------------------------------------------- - * - * mips3_TLBRead -- - * - * Read the TLB entry. - * - * mips3_TLBRead(entry, tlb) - * unsigned entry; - * struct tlb *tlb; - * - * Results: - * None. - * - * Side effects: - * tlb will contain the TLB entry found. - * - *-------------------------------------------------------------------------- - */ -LEAF(mips3_TLBRead) - mfc0 v1, MIPS_COP_0_STATUS_REG # Save the status register. - mtc0 zero, MIPS_COP_0_STATUS_REG # Disable interrupts - nop - nop - nop - dmfc0 t0, MIPS_COP_0_TLB_HI # Get current PID - - mtc0 a0, MIPS_COP_0_TLB_INDEX # Set the index register - nop - tlbr # Read from the TLB - nop - nop - nop - mfc0 t2, MIPS_COP_0_TLB_PG_MASK # fetch the hi entry - dmfc0 t3, MIPS_COP_0_TLB_HI # fetch the hi entry - dmfc0 t4, MIPS_COP_0_TLB_LO0 # See what we got - dmfc0 t5, MIPS_COP_0_TLB_LO1 # See what we got - dmtc0 t0, MIPS_COP_0_TLB_HI # restore PID - nop - nop - nop # wait for PID active - mtc0 v1, MIPS_COP_0_STATUS_REG # Restore the status register - nop - sw t2, 0(a1) - sw t3, 4(a1) - sw t4, 8(a1) - j ra - sw t5, 12(a1) -END(mips3_TLBRead) - -/*-------------------------------------------------------------------------- - * - * mips3_TLBGetPID -- - * - * mips3_TLBGetPID() - * - * Results: - * Returns the current TLB pid reg. - * - * Side effects: - * None. - * - *-------------------------------------------------------------------------- - */ -LEAF(mips3_TLBGetPID) - dmfc0 v0, MIPS_COP_0_TLB_HI # get PID - j ra - and v0, v0, MIPS3_TLB_PID # mask off PID -END(mips3_TLBGetPID) - - - -/*---------------------------------------------------------------------------- - * - * R4000 cache flushing code. - * - *---------------------------------------------------------------------------- - */ - -/* - * XXX need to handle two-way caches for r4600 and mips ISA-IV. - */ - -/*---------------------------------------------------------------------------- - * - * mips3_FlushCache -- - * - * Flush the caches. Assumes a line size of 16 bytes for speed. - * - * Results: - * None. - * - * Side effects: - * The contents of the caches is flushed. - * - *---------------------------------------------------------------------------- - */ -LEAF(mips3_FlushCache) - lw t1, mips_L1ICacheSize - lw t2, mips_L1DCacheSize - # lw t3, mips_L1ICacheLSize - # lw t4, mips_L1DCacheLSize -/* - * Flush the instruction cache. - */ - li t0, MIPS_KSEG0_START - addu t1, t0, t1 # End address - subu t1, t1, 128 -1: - cache 0, 0(t0) - cache 0, 16(t0) - cache 0, 32(t0) - cache 0, 48(t0) - cache 0, 64(t0) - cache 0, 80(t0) - cache 0, 96(t0) - cache 0, 112(t0) - bne t0, t1, 1b - addu t0, t0, 128 - -/* - * Flush the data cache. - */ - li t0, MIPS_KSEG0_START - addu t1, t0, t2 # End address - subu t1, t1, 128 -1: - cache 1, 0(t0) - cache 1, 16(t0) - cache 1, 32(t0) - cache 1, 48(t0) - cache 1, 64(t0) - cache 1, 80(t0) - cache 1, 96(t0) - cache 1, 112(t0) - bne t0, t1, 1b - addu t0, t0, 128 - -#if 1 - lw t2, mips_L2CacheSize - beq t2, zero, 2f - nop - li t0, MIPS_KSEG0_START - addu t1, t0, t2 - subu t1, t1, 128 -1: - cache 3, 0(t0) - cache 3, 32(t0) - cache 3, 64(t0) - cache 3, 96(t0) - bne t0, t1, 1b - addu t0, t0, 128 -2: -#endif - - j ra - nop -END(mips3_FlushCache) - -/*---------------------------------------------------------------------------- - * - * mips3_FlushICache -- - * - * void mips3_FlushICache(addr, len) - * vm_offset_t addr, len; - * - * Flush instruction cache for range of addr to addr + len - 1. - * The address can be any valid address so long as no TLB misses occur. - * Assumes a cache line size of 16 bytes for speed. - * - * Results: - * None. - * - * Side effects: - * The contents of the cache is flushed. - * Must not touch v0. - * - *---------------------------------------------------------------------------- - */ -LEAF(mips3_FlushICache) - addu a1, 127 # Align - srl a1, a1, 7 # Number of unrolled loops -1: - cache 0, 0(a0) - cache 0, 16(a0) - cache 0, 32(a0) - cache 0, 48(a0) - cache 0, 64(a0) - cache 0, 80(a0) - cache 0, 96(a0) - cache 0, 112(a0) - addu a1, -1 - bne a1, zero, 1b - addu a0, 128 - - j ra - nop -END(mips3_FlushICache) - -/*---------------------------------------------------------------------------- - * - * mips3_FlushDCache -- - * - * void mips3_FlushDCache(addr, len) - * vm_offset_t addr, len; - * - * Flush data cache for index range of addr to addr + len - 1. - * The address is reduced to a kseg0 index. - * - * Results: - * None. - * - * Side effects: - * The contents of the cache is written back to primary memory. - * The cache line is invalidated. - * - *---------------------------------------------------------------------------- - */ -LEAF(mips3_FlushDCache) - lw a2, mips_L1DCacheSize - addiu a2, -1 - move t0, a0 # copy start address - and a0, a0, a2 # get index into primary cache - addu a1, 127 # Align - li a2, 0x80000000 - addu a0, a0, a2 - addu a1, a1, a0 - and a0, a0, -128 - subu a1, a1, a0 - srl a1, a1, 7 # Compute number of cache lines - move t1, a1 # copy length -1: - cache 1, 0(a0) - cache 1, 16(a0) - cache 1, 32(a0) - cache 1, 48(a0) - cache 1, 64(a0) - cache 1, 80(a0) - cache 1, 96(a0) - cache 1, 112(a0) - addu a1, -1 - bne a1, zero, 1b - addu a0, 128 - -#if 1 - lw a2, mips_L2CacheSize - beq a2, zero, 2f # no secondary cache - addiu a2, -1 - and t0,t0,a2 # secondary cache index - li a0, 0x80000000 - addu a0, a0, t0 # reduce to kseg0 address -1: - cache 3, 0(a0) - cache 3, 32(a0) - cache 3, 64(a0) - cache 3, 96(a0) - addu t1, -1 - bne t1, zero, 1b - addu a0, 128 -2: -#endif - - j ra - nop -END(mips3_FlushDCache) - -/*---------------------------------------------------------------------------- - * - * mips3_HitFlushDCache -- - * - * void mips3_HitFlushDCache(addr, len) - * vm_offset_t addr, len; - * - * Flush data cache for range of addr to addr + len - 1. - * The address can be any valid viritual address as long - * as no TLB invalid traps occur. Only lines with matching - * addr is flushed. - * - * Results: - * None. - * - * Side effects: - * The contents of the cache is written back to primary memory. - * The cache line is invalidated. - * - *---------------------------------------------------------------------------- - */ -LEAF(mips3_HitFlushDCache) - beq a1, zero, 2f - addu a1, 127 # Align - addu a1, a1, a0 - and a0, a0, -128 - subu a1, a1, a0 - srl a1, a1, 7 # Compute number of cache lines -1: - cache 0x15, 0(a0) - cache 0x15, 16(a0) - cache 0x15, 32(a0) - cache 0x15, 48(a0) - cache 0x15, 64(a0) - cache 0x15, 80(a0) - cache 0x15, 96(a0) - cache 0x15, 112(a0) -#if 1 - cache 0x17, 0(a0) - cache 0x17, 32(a0) - cache 0x17, 64(a0) - cache 0x17, 96(a0) -#endif - addu a1, -1 - bne a1, zero, 1b - addu a0, 128 - -2: - j ra - nop -END(mips3_HitFlushDCache) -/*---------------------------------------------------------------------------- - * - * mips3_InvalidateDCache -- - * - * void mips3_FlushDCache(addr, len) - * vm_offset_t addr, len; - * - * Flush data cache for range of addr to addr + len - 1. - * The address can be any valid address as long as no TLB misses occur. - * (Be sure to use cached K0SEG kernel addresses or mapped addresses) - * Results: - * None. - * - * Side effects: - * The cache line is invalidated. - * - *---------------------------------------------------------------------------- - */ -LEAF(mips3_InvalidateDCache) - addu a1, a1, a0 # compute ending address -1: - cache 0x13, 0(a0) - addu a0, a0, 4 - bne a0, a1, 1b - cache 0x11,-4(a0) - - j ra - nop -END(mips3_InvalidateDCache) - -/*---------------------------------------------------------------------------- - * - * mips3_VCED -- - * - * Handle virtual coherency exceptions. - * Called directly from the mips3 execption-table code. - * only k0, k1 are avaiable on entry - * - * Results: - * None. - * - * Side effects: - * Remaps the conflicting address as uncached and returns - * from the execption. - * - * NB: cannot be profiled, all registers are user registers on entry. - * - *---------------------------------------------------------------------------- - */ -NLEAF(mips3_VCED) -ALEAF(mips3_VCEI) /* XXXX */ - .set noat - move k0, AT - .set at - sw k0, vce_saveat - mfc0 k0, MIPS_COP_0_BAD_VADDR # fault addr. - nop - nop - and k0, -16 - sw k0, vce_savek0 # save virtual address - cache 1, 0(k0) # writeback primary line - lw k1, _C_LABEL(mips_L1DCacheSize) - addiu k1, -1 - and k0, k0, k1 # mask to cache index - or k0, 0x80000000 # physical K0SEG address - xor k0, 0x1000 # other page of cache - cache 1, 0(k0) - xor k0, 0x10 # other half of cache line - cache 1, 0(k0) - xor k0, 0x1000 # other half in same page - cache 1, 0(k0) - sltiu k1, k1, 0x3fff - bnez k1, 1f # not R4400 - xor k0, 0x2000 # clear out same cache lines - cache 1, 0(k0) # in the other half of the - xor k0, 0x1000 # R4400 primary cache - cache 1, 0(k0) - xor k0, 0x10 - cache 1, 0(k0) - xor k0, 0x1000 - cache 1, 0(k0) - # end R4400 -1: - lw k0, vce_savek0 # get original address - cache 31, 0(k0) - nop -#ifdef DEBUG - mfc0 k1, MIPS_COP_0_EXC_PC - sw k0, VCE_vaddr - sw k1, VCE_epc - la k1, VCE_count # count number of exceptions - srl k0, k0, 26 # position upper 4 bits of VA - andi k0, k0, 0x3c # mask it off - add k1, k0 # get address of count table - lw k0, 0(k1) - addu k0, 1 - sw k0, 0(k1) -#endif - lw k0, vce_saveat - .set noat - move AT, k0 - .set at - eret - .align 3 # needs to be aligned? -vce_saveat: - .word 0 - .word 0 -vce_savek0: - .word 0 - .word 0 - .globl _C_LABEL(VCE_count) -_C_LABEL(VCE_count): - .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - .globl _C_LABEL(VCE_epc) -_C_LABEL(VCE_epc): - .word 0 - .globl _C_LABEL(VCE_vaddr) -_C_LABEL(VCE_vaddr): - .word 0 -END(mips3_VCED) - -/*---------------------------------------------------------------------------- - * - * mips3_wbflush -- - * - * Return when the write buffer is empty. - * - * mips3_wbflush() - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------------- - */ -LEAF(mips3_wbflush) - nop - sync - j ra - nop -END(mips3_wbflush) - -/* - * mips3_proc_trampoline() - * - * Arrange for a function to be invoked neatly, after a cpu_switch(). - * Invoke the service function with one argument, specified by the s0 - * and s1 respectively. There is no need register save operation. - */ -LEAF(mips3_proc_trampoline) - jal ra, s0 - move a0, s1 - .set noat - li a0, MIPS_SR_EXL # set exception level - mtc0 a0, MIPS_COP_0_STATUS_REG - nop - nop - lw a1, _C_LABEL(curpcb) - nop - lw a0, U_PCB_REGS + (SR * 4)(a1) - lw t0, U_PCB_REGS + (MULLO * 4)(a1) - lw t1, U_PCB_REGS + (MULHI * 4)(a1) - mtlo t0 - mthi t1 - nop - move k1, a1 - lw AT, U_PCB_REGS + (AST * 4)(k1) - lw a0, U_PCB_REGS + (PC * 4)(k1) - nop - dmtc0 a0, MIPS_COP_0_EXC_PC - nop - lw v0, U_PCB_REGS + (V0 * 4)(k1) - lw v1, U_PCB_REGS + (V1 * 4)(k1) - lw a0, U_PCB_REGS + (A0 * 4)(k1) - lw a1, U_PCB_REGS + (A1 * 4)(k1) - lw a2, U_PCB_REGS + (A2 * 4)(k1) - lw a3, U_PCB_REGS + (A3 * 4)(k1) - lw t0, U_PCB_REGS + (T0 * 4)(k1) - lw t1, U_PCB_REGS + (T1 * 4)(k1) - lw t2, U_PCB_REGS + (T2 * 4)(k1) - lw t3, U_PCB_REGS + (T3 * 4)(k1) - lw t4, U_PCB_REGS + (T4 * 4)(k1) - lw t5, U_PCB_REGS + (T5 * 4)(k1) - lw t6, U_PCB_REGS + (T6 * 4)(k1) - lw t7, U_PCB_REGS + (T7 * 4)(k1) - lw s0, U_PCB_REGS + (S0 * 4)(k1) - lw s1, U_PCB_REGS + (S1 * 4)(k1) - lw s2, U_PCB_REGS + (S2 * 4)(k1) - lw s3, U_PCB_REGS + (S3 * 4)(k1) - lw s4, U_PCB_REGS + (S4 * 4)(k1) - lw s5, U_PCB_REGS + (S5 * 4)(k1) - lw s6, U_PCB_REGS + (S6 * 4)(k1) - lw s7, U_PCB_REGS + (S7 * 4)(k1) - lw t8, U_PCB_REGS + (T8 * 4)(k1) - lw t9, U_PCB_REGS + (T9 * 4)(k1) - lw gp, U_PCB_REGS + (GP * 4)(k1) - lw s8, U_PCB_REGS + (S8 * 4)(k1) - lw ra, U_PCB_REGS + (RA * 4)(k1) - lw sp, U_PCB_REGS + (SP * 4)(k1) - lw k0, U_PCB_REGS + (SR * 4)(k1) - nop - mtc0 k0, MIPS_COP_0_STATUS_REG - nop - nop - eret - .set at -END(mips3_proc_trampoline) - -/* - * mips3_switch_exit(struct proc *) - * Make the named process exit. Switch SP to nullproc stack, schedule - * the exiting proc's vmspace and stack to be freed, then jump into the - * middle of cpu_switch(). MUST BE CALLED AT SPLHIGH. - */ -LEAF(mips3_switch_exit) - la v1, _C_LABEL(nullproc) # !! SP runs on p->p_addr !! - lw t0, P_MD_UPTE+0(v1) # t0 = first u. pte - lw t1, P_MD_UPTE+4(v1) # t1 = 2nd u. pte - li v0, MIPS_KSEG0_START # clear wired entries for pcb - mtc0 v0, MIPS_COP_0_TLB_HI - mtc0 zero, MIPS_COP_0_TLB_LO0 - mtc0 zero, MIPS_COP_0_TLB_LO1 - li v0, 1 # clear wired entry 1 - mtc0 v0, MIPS_COP_0_TLB_INDEX - tlbwi - li v0, 2 # clear wired entry 2 - mtc0 v0, MIPS_COP_0_TLB_INDEX - tlbwi - li v0, UADDR # still using UADDR for kstack - nop - mtc0 zero, MIPS_COP_0_TLB_INDEX # set the index register - mtc0 v0, MIPS_COP_0_TLB_HI # init high entry - mtc0 t0, MIPS_COP_0_TLB_LO0 # init low entry 0 - mtc0 t1, MIPS_COP_0_TLB_LO1 # init low entry 1 - nop - tlbwi # Write the TLB entry. - - addu sp, v0, USPACE - START_FRAME - la ra, sw1 # goto cpu_switch() - j exit2 # proc already in a0 - nop # XXX schedule better -END(mips3_switch_exit) - -/* - * Resume process indicated by the pte's for its u struct - * NOTE: This is hard coded to UPAGES == 2. - * Also, there should be no TLB faults at this point. - * - * Entered from CPU-common cpu_switch() - * a0 = p_addr [curpcb] - * a1 = First u.pte - * a2 = Second u.pte - * a3 = Address Space Identifier (TLB PID) for this process - */ -/* - * XXXX - almost done with the UADDR mapping; only the kernel stack should - * now be using UADDR. The first TLB entry is used to map UADDR to the - * u-area. Then the following TLB entries are used to map the current u-area. - * This gets a bit messy on the R4000: it can take one or two TLB - * entries to map the u-area, depending upon whether the u-area - * begins on an even or odd page. Also, any current mapping for the u-area - * address space needs to be flushed as well. - * - * Both UADDR and p_addr are mapped global. - * - * NB: cannot be profiled due to weird argument-assing convention. - * mcount would trash v0, t0, t1. - */ -NLEAF(mips3_cpu_switch_resume) - li v0, UADDR # Hi entry = UADD, ASID = 0 - ori a1, MIPS3_PG_G # set PG_G - ori a2, MIPS3_PG_G # set PG_G - mtc0 zero, MIPS_COP_0_TLB_INDEX # set the index register - mtc0 v0, MIPS_COP_0_TLB_HI # init high entry - mtc0 a1, MIPS_COP_0_TLB_LO0 # init low entry 0 - mtc0 a2, MIPS_COP_0_TLB_LO1 # init low entry 1 - nop - nop - tlbwi # Write the TLB entry. - nop - nop - nop - nop -# now map the p_addr pages - li s1, MIPS3_PG_ODDPG - and s1, a0 # does p_addr start on odd page - beq s1, zero, 1f # no, only one TLB entry needed -# p_addr starts on an odd page, need to set up 2 TLB entries - addu a0, a0, MIPS3_PG_ODDPG # map second page -# see if this address currently exists in TLB - mtc0 a0, MIPS_COP_0_TLB_HI - nop - tlbp # probe for existing entry - nop - nop - mfc0 s1, MIPS_COP_0_TLB_INDEX - nop - slti s1, s1, 8 # if found in random entry - bnez s1, 2f - mtc0 zero, MIPS_COP_0_TLB_LO0 # flush it - mtc0 zero, MIPS_COP_0_TLB_LO1 - li s1, MIPS_KSEG0_START - mtc0 s1, MIPS_COP_0_TLB_HI - nop - tlbwi - nop - mtc0 a0, MIPS_COP_0_TLB_HI # restore high entry -2: - mtc0 a2, MIPS_COP_0_TLB_LO0 # even page to LO0 - li s1, MIPS3_PG_G # invalid page set PG_G - mtc0 s1, MIPS_COP_0_TLB_LO1 # invalid page to LO1 - li s1, 2 # use TLB entry 2 for even page - mtc0 s1, MIPS_COP_0_TLB_INDEX - nop - tlbwi # write odd page TLB entry - move a2, a1 # odd page to LO1 - li a1, MIPS3_PG_G # LO0 - addi a0, a0, -NBPG * 2 # backup to odd page mapping -# set up TLB entry 1 -1: -# see if this address currently exists in TLB - mtc0 a0, MIPS_COP_0_TLB_HI - nop - tlbp # probe for existing entry - nop - nop - mfc0 s1, MIPS_COP_0_TLB_INDEX - nop - slti s1, s1, 8 # if found in random entry - bnez s1, 2f - mtc0 zero, MIPS_COP_0_TLB_LO0 # flush it - mtc0 zero, MIPS_COP_0_TLB_LO1 - li s1, MIPS_KSEG0_START - mtc0 s1, MIPS_COP_0_TLB_HI - nop - tlbwi - nop - mtc0 a0, MIPS_COP_0_TLB_HI # restore high entry -2: - mtc0 a1, MIPS_COP_0_TLB_LO0 # first page - mtc0 a2, MIPS_COP_0_TLB_LO1 # second page - li s1, 1 # use TLB entry 1 - mtc0 s1, MIPS_COP_0_TLB_INDEX - nop - tlbwi # write TLB entry - nop - - mtc0 a3, MIPS_COP_0_TLB_HI # set current ASID -/* - * Now running on new u struct. - * Restore registers and return. - */ - lw t0, _C_LABEL(curpcb) - nop - lw v0, U_PCB_CONTEXT+44(t0) # restore kernel context - lw ra, U_PCB_CONTEXT+40(t0) - lw s0, U_PCB_CONTEXT+0(t0) - lw s1, U_PCB_CONTEXT+4(t0) - lw s2, U_PCB_CONTEXT+8(t0) - lw s3, U_PCB_CONTEXT+12(t0) - lw s4, U_PCB_CONTEXT+16(t0) - lw s5, U_PCB_CONTEXT+20(t0) - lw s6, U_PCB_CONTEXT+24(t0) - lw s7, U_PCB_CONTEXT+28(t0) - lw sp, U_PCB_CONTEXT+32(t0) - lw s8, U_PCB_CONTEXT+36(t0) - nop - mtc0 v0, MIPS_COP_0_STATUS_REG - j ra - li v0, 1 # possible return to 'savectx()' -END(mips3_cpu_switch_resume) - - -/*---------------------------------------------------------------------------- - * - * mips3_cycle_count -- - * - * u_int32_t mips3_cycle_count(void) - * - * read 32-bit cycle-counter clock in coprocessor 0. - * - * Results: - * returns 32-bit clock value, incremented automatically by CPU - * at nominal cycle rate (i.e., half the maximum issue rate.) - * - * Side effects: - * none. - * - *---------------------------------------------------------------------------- - */ -LEAF(mips3_cycle_count) - mfc0 v0, MIPS_COP_0_COUNT - nop - nop - j ra - nop -END(mips3_cycle_count) - -/* - * Read compare register. - * - * On mips3, generates a hardint 5 interrupt request is generated - * each time the COUNT register increments past the COMPARE register. - * - * (The mips interrupt mask defintions currently leaves this interrupt - * unconditionally masked out on mips3 CPUs.) - */ -LEAF(mips3_read_compare) - mfc0 v0, MIPS_COP_0_COMPARE - nop - j ra - nop -END(mips3_read_compare) - -LEAF(mips3_read_config) - mfc0 v0, MIPS_COP_0_CONFIG - nop - j ra - nop -END(mips3_read_config) - -/* - * Write value to compare register. - * - * Side Effects: - * Clears interrupt request from cycle-counter clock. - */ -LEAF(mips3_write_compare) - mtc0 a0, MIPS_COP_0_COMPARE - nop - j ra - nop -END(mips3_write_compare) - -/* - * The variables below are used to communicate the cache handling - * to higher-level software. - */ - .data - - .globl _C_LABEL(mips3_L1TwoWayCache) -_C_LABEL(mips3_L1TwoWayCache): - .word 0 - - .globl _C_LABEL(mips3_cacheflush_bug) -_C_LABEL(mips3_cacheflush_bug): - .word 0 - -/*---------------------------------------------------------------------------- - * - * XXX END of r4000-specific code XXX - * - *---------------------------------------------------------------------------- - */ - .text - .set mips2