#include <mips/asm.h>
RCSID("$NetBSD: mipsX_subr.S,v 1.118 2026/06/27 07:44:56 kbowling Exp $")
#include "opt_cputype.h"
#include "opt_ddb.h"
#include "opt_kgdb.h"
#include "opt_mips3_wired.h"
#include "opt_multiprocessor.h"
#include "opt_vmswap.h"
#include <sys/cdefs.h>
#include <sys/endian.h>
#include <mips/cpuregs.h>
#if defined(MIPS3)
#include <mips/cache_r4k.h>
#endif
#include <mips/trap.h>
#include "assym.h"
#if defined(MIPS64_OCTEON)
#include "cpunode.h"
#else
#define NWDOG 0
#endif
#if defined(MIPS1) || defined(MIPS2)
#error use locore_mips1.S
#endif
#if defined(__mips_o32)
#define RESET_EXCEPTION_LEVEL_DISABLE_INTERRUPTS(reg) \
mtc0 zero, MIPS_COP_0_STATUS
#define SET_EXCEPTION_LEVEL(reg) \
li reg, MIPS_SR_EXL; mtc0 reg, MIPS_COP_0_STATUS
#else
#define RESET_EXCEPTION_LEVEL_DISABLE_INTERRUPTS(reg) \
li reg, MIPS_SR_KX; mtc0 reg, MIPS_COP_0_STATUS
#define SET_EXCEPTION_LEVEL(reg) \
li reg, MIPS_SR_EXL | MIPS_SR_KX; mtc0 reg, MIPS_COP_0_STATUS
#endif
#ifdef MIPS3_LOONGSON2
#define KERN_ENTRY_ERRATA \
li k0, MIPS_DIAG_BTB_CLEAR|MIPS_DIAG_RAS_DISABLE; mtc0 k0, MIPS_COP_0_DIAG
#else
#define KERN_ENTRY_ERRATA
#endif
#if MIPS1
#error This file can not be compiled with MIPS1 defined
#endif
#if (MIPS3 + MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) != 1
# error Only one of MIPS{3,32,32R2,64,64R2} can be defined
#endif
#if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0
#define MIPSNN
#if (MIPS32R2 + MIPS64R2) > 0
#define MIPSNNR2
#endif
#endif
#if (MIPS3 + MIPS64 + MIPS64R2) > 0
#define USE_64BIT_INSTRUCTIONS
#define USE_64BIT_CP0_FUNCTIONS
#elif (MIPS32 + MIPS32R2) > 0
#ifdef _LP64
#error MIPS32 and MIPS32R2 can't run 64-bit kernels.
#endif
#undef USE_64BIT_INSTRUCTIONS
#undef USE_64BIT_CP0_FUNCTIONS
#else
#error One of MIPS{3,32,32R2,64,64R2} must be defined
#endif
#ifdef _LP64
#define _SLLV dsllv
#else
#define _SLLV sllv
#endif
#if defined(USE_64BIT_CP0_FUNCTIONS)
#define _SLL dsll
#define _SRL dsrl
#define _SRA dsra
#define _EXT dext
#define _INS dins
#define WIRED_SHIFT 34
#define WIRED_POS 30
#define PG_V_LSHIFT (63 - V_MIPS3_PG_V)
#define PG_V_RSHIFT 63
#else
#define _SLL sll
#define _SRL srl
#define _SRA sra
#define _EXT ext
#define _INS ins
#define WIRED_SHIFT 2
#define WIRED_POS 30
#define PG_V_LSHIFT (31 - V_MIPS3_PG_V)
#define PG_V_RSHIFT 31
#endif
#if defined(USE_64BIT_CP0_FUNCTIONS)
#define _MFC0 dmfc0
#define _MTC0 dmtc0
#else
#define _MFC0 mfc0
#define _MTC0 mtc0
#endif
#if defined(MIPS3)
.set mips3
#endif
#if defined(MIPS32)
.set mips32
#endif
#if defined(MIPS32R2)
.set mips32r2
#endif
#if defined(MIPS64)
.set mips64
#endif
#if defined(MIPS64R2)
.set mips64r2
#endif
#if defined(MIPS3_LOONGSON2)
#define MIPSX(name) __CONCAT(loongson2_,name)
#elif defined(MIPS3)
#define MIPSX(name) __CONCAT(mips3_,name)
#endif
#if defined(MIPS32)
#define MIPSX(name) __CONCAT(mips32_,name)
#endif
#if defined(MIPS32R2)
#define MIPSX(name) __CONCAT(mips32r2_,name)
#endif
#if defined(MIPS64)
#define MIPSX(name) __CONCAT(mips64_,name)
#endif
#if defined(MIPS64R2)
#define MIPSX(name) __CONCAT(mips64r2_,name)
#endif
#define _VECTOR_END(name) VECTOR_END(name)
.set noreorder
.text
.global mips_kseg0
.equiv mips_kseg0, MIPS_KSEG0_START
.global mips_kseg1
.equiv mips_kseg1, MIPS_KSEG1_START
.global mips_kseg2
.equiv mips_kseg2, MIPS_KSEG2_START
.global mips_xkphys
.equiv mips_xkphys, MIPS_XKPHYS_START
.global mips_xkphys_u
.equiv mips_xkphys_u, MIPS_XKPHYS_UNCACHED
.global mips_xkphys_cca3
.equiv mips_xkphys_cca3, MIPS_XKPHYS_CCA3
.global mips_xkphys_cca4
.equiv mips_xkphys_cca4, MIPS_XKPHYS_CCA4
.global mips_xkseg
.equiv mips_xkseg, MIPS_XKSEG_START
#ifdef MIPS3_LOONGSON2
VECTOR(MIPSX(tlb_miss), unknown)
.set noat
dmfc0 k0, MIPS_COP_0_BAD_VADDR #00: k0=bad address
#ifdef _LP64
nop #01: nop
PTR_SRL k1, k0, 31 #02: clear useg bits
beqz k1, 2f #03: k1==0 -> useg address
PTR_SLL k1, k0, 2 #0x: clear top bits
PTR_SRL k1, XSEGSHIFT+XSEGLENGTH+2 #04: clear valid bits
bnez k1, MIPSX(nopagetable) #05: not legal address
PTR_SRA k0, XSEGSHIFT - PTR_SCALESHIFT #06: k0=seg offset (almost)
bgez k0, 1f #07: k0<0 -> kernel fault
lui k1, %hi(CPUVAR(PMAP_SEGTAB)) #08: k1=hi of segtab
PTR_ADDI k1, 1 << PTR_SCALESHIFT #09: kernel segtab entry
1:
andi k0, (NSEGPG-1)<<PTR_SCALESHIFT #0a: k0=seg offset (mask 0x3)
PTR_L k1, %lo(CPUVAR(PMAP_SEGTAB))(k1)#0b: k1=segment tab
PTR_ADDU k1, k0 #0c: k1=seg entry address
dmfc0 k0, MIPS_COP_0_BAD_VADDR #0d: k0=bad address (again)
PTR_L k1, 0(k1) #0e: k1=seg entry
b MIPSX(tlb_miss_common) #0f
PTR_SRL k0, SEGSHIFT - PTR_SCALESHIFT #10: k0=seg offset (almost)
#endif
2:
lui k1, %hi(CPUVAR(PMAP_SEG0TAB)) #11: k1=hi of seg0tab
dsrl k0, 31 #12: clear low 31 bits
bnez k0, MIPSX(nopagetable) #13: not legal address
PTR_L k1, %lo(CPUVAR(PMAP_SEG0TAB))(k1)#14: k1=segment tab base
dmfc0 k0, MIPS_COP_0_BAD_VADDR #15: k0=bad address (again)
nop #16
b MIPSX(tlb_miss_common) #17
PTR_SRL k0, 1*(PGSHIFT-PTR_SCALESHIFT)+(PGSHIFT-2) #18: k0=seg offset (almost)
_VECTOR_END(MIPSX(tlb_miss))
VECTOR(MIPSX(xtlb_miss), unknown)
lui k0, %hi(_C_LABEL(panic)) #00
addiu k0, %lo(_C_LABEL(panic)) #01
lui a0, %hi(loongson2_xtlb_miss_str) #02
jr k0 #03
addiu a0, %lo(loongson2_xtlb_miss_str) #04
#else
VECTOR(MIPSX(tlb_miss), unknown)
.set noat
_MFC0 k0, MIPS_COP_0_BAD_VADDR #00: k0=bad address
lui k1, %hi(CPUVAR(PMAP_SEG0TAB)) #01: k1=hi of seg0tab
#ifdef _LP64
bltz k0, MIPSX(nopagetable) #02: k0<0 -> kernel access
#ifdef MIPSNNR2
_EXT k0, k0, SEGSHIFT, SEGLENGTH #03: k0=seg index
#else
PTR_SRA k0, SEGSHIFT - PTR_SCALESHIFT #03: k0=seg offset (almost)
#endif
#else
bgez k0, 1f #02: k0<0 -> kernel access
#ifdef MIPSNNR2
_EXT k0, k0, SEGSHIFT, SEGLENGTH #03: k0=seg index
#else
PTR_SRA k0, SEGSHIFT - PTR_SCALESHIFT #03: k0=seg offset (almost)
#endif
PTR_ADDU k1, 1 << PTR_SCALESHIFT #04: fetch kernel segtab
1:
#endif
PTR_L k1, %lo(CPUVAR(PMAP_SEG0TAB))(k1)#05: k1=seg0tab
#endif
MIPSX(tlb_miss_common):
#ifdef _LP64
beqz k1, MIPSX(nopagetable) #06: is there a pagetable?
#endif
#ifdef MIPSNNR2
_INS k1, k0, PTR_SCALESHIFT, SEGLENGTH #07: k1=seg entry address
#else
andi k0, (NSEGPG-1)<<PTR_SCALESHIFT #07: k0=seg offset (mask 0x3)
PTR_ADDU k1, k0 #08: k1=seg entry address
#endif
PTR_L k1, 0(k1) #09: k1=seg entry
_MFC0 k0, MIPS_COP_0_BAD_VADDR #0a: k0=bad address (again)
beqz k1, MIPSX(nopagetable) #0b: ==0 -- no page table
#if (PGSHIFT & 1)
#ifdef MIPSNNR2
_EXT k0, k0, PGSHIFT, PTPLENGTH #0c: delay slot: page index
_INS k1, k0, PTPSHIFT, PTPLENGTH #0d: k1=pte address
#else
PTR_SRL k0, PGSHIFT - PTPSHIFT #0c: k0=VPN (aka va>>10)
andi k0, (NPTEPG-1) << PTPSHIFT #0d: k0=page table offset
PTR_ADDU k1, k0 #0e: k1=pte address
#endif
INT_L k0, 0(k1) #0f: k0=lo0 pte
#ifdef MIPSNNR2
_EXT k0, k0, 0, WIRED_POS #10: chop top 2 bits
#else
_SLL k0, WIRED_SHIFT #10: chop top 2 bits (part 1a)
_SRL k0, WIRED_SHIFT #11: chop top 2 bits (part 1b)
#endif
INT_ADDU k1, k0, MIPS3_PG_NEXT #12: k1=lo1 pte
#else
PTR_SRL k0, PGSHIFT - PTPSHIFT #0c: k0=VPN (aka va>>10) --ds--
andi k0, (NPTEPG/2-1) << (PTPSHIFT+1)#0d: k0=page table offset
PTR_ADDU k1, k0 #0e: k1=pte address
#ifdef USE_64BIT_CP0_FUNCTIONS
ld k0, 0(k1) #0f: load both ptes
#ifdef MIPSNNR2
_EXT k1, k0, 32*_QUAD_HIGHWORD, WIRED_POS #10: get lo1 pte
_EXT k0, k0, 32*_QUAD_LOWWORD, WIRED_POS #11: get lo0 pte
#else
_SLL k1, k0, WIRED_SHIFT - 32*_QUAD_HIGHWORD #10: get lo1 pte (1a)
_SLL k0, k0, WIRED_SHIFT - 32*_QUAD_LOWWORD #11: get lo0 pte (2a)
_SRL k0, WIRED_SHIFT #12: chopped top 2 bits (1b)
_SRL k1, WIRED_SHIFT #13: chopped top 2 bits (2b)
#endif
#else
INT_L k0, 0(k1) #0f: k0=lo0 pte
INT_L k1, 4(k1) #10: k1=lo1 pte
_SLL k0, WIRED_SHIFT #11: chop top 2 bits (part 1a)
_SLL k1, WIRED_SHIFT #12: chop top 2 bits (part 2a)
_SRL k0, WIRED_SHIFT #13: chop top 2 bits (part 1b)
_SRL k1, WIRED_SHIFT #14: chop top 2 bits (part 2b)
#endif
#endif
_MTC0 k0, MIPS_COP_0_TLB_LO0 #15: lo0 is loaded
_MTC0 k1, MIPS_COP_0_TLB_LO1 #16: lo1 is loaded
sll $0, $0, 3 #17: standard nop (ehb)
#ifdef MIPS3
nop #18: extra nop for QED5230
#endif
tlbwr #19: write to tlb
sll $0, $0, 3 #1a: standard nop (ehb)
#if (MIPS3 + MIPS64 + MIPS64R2) > 0
lui k1, %hi(CPUVAR(EV_TLBMISSES)) #1b: k1=hi of tlbmisses
REG_L k0, %lo(CPUVAR(EV_TLBMISSES))(k1) #1c
REG_ADDU k0, 1 #1d
REG_S k0, %lo(CPUVAR(EV_TLBMISSES))(k1) #1e
#endif
eret #1f: return from exception
.set at
#ifdef MIPS3_LOONGSON2
_VECTOR_END(MIPSX(xtlb_miss))
#else
_VECTOR_END(MIPSX(tlb_miss))
#endif
#ifndef MIPS3_LOONGSON2
#if defined(USE_64BIT_CP0_FUNCTIONS)
VECTOR(MIPSX(xtlb_miss), unknown)
.set noat
dmfc0 k0, MIPS_COP_0_BAD_VADDR #00: k0=bad address
#ifdef _LP64
MFC0_HAZARD #01: nop
PTR_SLL k1, k0, 2 #02: clear top bits
PTR_SRL k1, XSEGSHIFT+XSEGLENGTH+2 #03: clear valid bits
bnez k1, MIPSX(nopagetable) #04: not legal address
PTR_SRA k0, XSEGSHIFT - PTR_SCALESHIFT #05: k0=seg offset (almost)
bgez k0, 1f #06: k0<0 -> kernel fault
lui k1, %hi(CPUVAR(PMAP_SEGTAB)) #07: k1=hi of segtab
PTR_ADDU k1, 1 << PTR_SCALESHIFT #08: advance to kernel segtab
1:
PTR_L k1, %lo(CPUVAR(PMAP_SEGTAB))(k1)#09: k1=segment tab
andi k0, (NSEGPG-1)<<PTR_SCALESHIFT #0a: k0=seg offset (mask 0x3)
PTR_ADDU k1, k0 #0b: k1=seg entry address
dmfc0 k0, MIPS_COP_0_BAD_VADDR #0c: k0=bad address (again)
PTR_L k1, 0(k1) #0d: k1=seg entry address
#else
lui k1, %hi(CPUVAR(PMAP_SEG0TAB)) #02: k1=hi of seg0tab
bgez k0, 1f #03: k0<0 -> kernel access
dsra k0, 31 #04: clear low 31 bits
PTR_ADDU k1, 1 << PTR_SCALESHIFT #05
1:
PTR_ADDU k0, 1 #06
sltiu k0, k0, 2 #07
beqz k0, MIPSX(nopagetable) #08: not legal address
nop #09
dmfc0 k0, MIPS_COP_0_BAD_VADDR #0a: k0=bad address (again)
PTR_L k1, %lo(CPUVAR(PMAP_SEG0TAB))(k1)#0b: k1=segment tab base
#endif
b MIPSX(tlb_miss_common) #0e/0c
#ifdef MIPSNNR2
_EXT k0, k0, SEGSHIFT, SEGLENGTH #0f/0d: k0=seg index
#else
PTR_SRL k0, SEGSHIFT - PTR_SCALESHIFT #0f/0d: k0=seg offset (almost)
#endif
.set at
_VECTOR_END(MIPSX(xtlb_miss))
#else
.space 128
#endif
#endif
VECTOR(MIPSX(cache), unknown)
PTR_LA k0, _C_LABEL(MIPSX(cache_exception)) #00
li k1, MIPS_PHYS_MASK #01
and k0, k1 #02
li k1, MIPS_KSEG1_START #03
or k0, k1 #04
lui k1, %hi(CPUVAR(CURLWP)) #05: k1=hi of curlwp
jr k0 #06
PTR_L k1, %lo(CPUVAR(CURLWP))(k1) #07: k1=lo of curlwp
_VECTOR_END(MIPSX(cache))
VECTOR(MIPSX(exception), unknown)
.set noat
mfc0 k0, MIPS_COP_0_STATUS #00: get the status register
mfc0 k1, MIPS_COP_0_CAUSE #01: get the cause register
and k0, MIPS3_SR_KSU_USER #02: test for user mode
sll k0, 3 #03: shift user bit for cause index
and k1, MIPS3_CR_EXC_CODE #04: mask out the cause bits.
or k1, k0 #05: change index to user table
#if PTR_SCALESHIFT > MIPS_CR_EXC_CODE_SHIFT
PTR_SLL k1, PTR_SCALESHIFT - MIPS_CR_EXC_CODE_SHIFT
#endif
PTR_LA k0, MIPSX(excpt_sw) #06: get base of the jump table
PTR_ADDU k0, k1 #08: get the address of the
PTR_L k0, 0(k0) #09: get the function address
lui k1, %hi(CPUVAR(CURLWP)) #0a: k1=hi of curlwp
jr k0 #0b: jump to the function
PTR_L k1, %lo(CPUVAR(CURLWP))(k1) #0c: k1=lo of curlwp
nop #0d
nop #0e
#ifndef _LP64
nop #0f
#endif
.p2align 4
MIPSX(nopagetable):
lui k1, %hi(CPUVAR(CURLWP)) #10: k1=hi of curlwp
j MIPSX(slowfault) #11: no page table present
PTR_L k1, %lo(CPUVAR(CURLWP))(k1) #12: k1=lo of curlwp
nop #13: branch delay slot
.set at
_VECTOR_END(MIPSX(exception))
VECTOR(MIPSX(intr), unknown)
.set noat
mfc0 k0, MIPS_COP_0_STATUS #00: get the status register
MFC0_HAZARD #01: stall
and k0, k0, MIPS3_SR_KSU_USER #02: test for user mode
bnez k0, 1f #03: yep, do it
nop #04: branch delay
j MIPSX(kern_intr) #05: nope, kernel intr
1:
lui k1, %hi(CPUVAR(CURLWP)) #06: k1=hi of curlwp
j MIPSX(user_intr) #07: user intr
PTR_L k1, %lo(CPUVAR(CURLWP))(k1) #08: k1=lo of curlwp
.set at
_VECTOR_END(MIPSX(intr))
.org ((. + 31) & ~31) + 12
MIPSX(slowfault):
.set noat
mfc0 k0, MIPS_COP_0_STATUS
MFC0_HAZARD
and k0, MIPS3_SR_KSU_USER
bnez k0, _C_LABEL(MIPSX(user_gen_exception))
nop
.set at
NESTED_NOPROFILE(MIPSX(kern_gen_exception), KERNFRAME_SIZ, ra)
.set noat
.mask 0x80000000, -4
#if defined(PARANOIA)
PTR_L k0, L_PCB(MIPS_CURLWP)
slt k0, k0, sp # k0 = L_PCB(MIPS_CURLWP) < sp
1: beqz k0, 1b # loop forever if false
nop
PTR_L k0, L_PCB(MIPS_CURLWP)
PTR_ADDU k0, USPACE
slt k0, sp, k0 # k0 = sp < L_PCB(MIPS_CURLWP) + USPACE
2: beqz k0, 2b # loop forever if false
nop
#endif
PTR_SUBU sp, KERNFRAME_SIZ
REG_S AT, TF_BASE+TF_REG_AST(sp)
REG_S v0, TF_BASE+TF_REG_V0(sp)
REG_S v1, TF_BASE+TF_REG_V1(sp)
mflo v0
mfhi v1
REG_S a0, TF_BASE+TF_REG_A0(sp)
REG_S a1, TF_BASE+TF_REG_A1(sp)
REG_S a2, TF_BASE+TF_REG_A2(sp)
REG_S a3, TF_BASE+TF_REG_A3(sp)
mfc0 a0, MIPS_COP_0_STATUS # 1st arg is STATUS
REG_S t0, TF_BASE+TF_REG_T0(sp)
REG_S t1, TF_BASE+TF_REG_T1(sp)
REG_S t2, TF_BASE+TF_REG_T2(sp)
REG_S t3, TF_BASE+TF_REG_T3(sp)
mfc0 a1, MIPS_COP_0_CAUSE # 2nd arg is CAUSE
REG_S ta0, TF_BASE+TF_REG_TA0(sp)
REG_S ta1, TF_BASE+TF_REG_TA1(sp)
REG_S ta2, TF_BASE+TF_REG_TA2(sp)
REG_S ta3, TF_BASE+TF_REG_TA3(sp)
_MFC0 a2, MIPS_COP_0_BAD_VADDR # 3rd arg is fault address
#ifdef DDB
REG_S t8, TF_BASE+TF_REG_T8(sp) # is MIPS_CURLWP
#endif
REG_S t9, TF_BASE+TF_REG_T9(sp)
REG_S ra, TF_BASE+TF_REG_RA(sp)
REG_S a0, TF_BASE+TF_REG_SR(sp)
_MFC0 a3, MIPS_COP_0_EXC_PC # 4th arg is exception PC
REG_S v0, TF_BASE+TF_REG_MULLO(sp)
REG_S v1, TF_BASE+TF_REG_MULHI(sp)
REG_S a3, TF_BASE+TF_REG_EPC(sp)
REG_S a1, TF_BASE+TF_REG_CAUSE(sp)
#if defined(DDB) || defined(KGDB)
REG_S s0, TF_BASE+TF_REG_S0(sp)
REG_S s1, TF_BASE+TF_REG_S1(sp)
REG_S s2, TF_BASE+TF_REG_S2(sp)
REG_S s3, TF_BASE+TF_REG_S3(sp)
REG_S s4, TF_BASE+TF_REG_S4(sp)
REG_S s5, TF_BASE+TF_REG_S5(sp)
REG_S s6, TF_BASE+TF_REG_S6(sp)
REG_S s7, TF_BASE+TF_REG_S7(sp)
PTR_ADDU v0, sp, KERNFRAME_SIZ
REG_S v0, TF_BASE+TF_REG_SP(sp)
REG_S s8, TF_BASE+TF_REG_S8(sp)
REG_S gp, TF_BASE+TF_REG_GP(sp)
#endif
#if defined(__mips_o32) || defined(__mips_o64)
PTR_ADDU v0, sp, TF_BASE
REG_S v0, KERNFRAME_ARG5(sp) # 5th arg is p. to trapframe
#endif
#if defined(__mips_n32) || defined(__mips_n64)
PTR_ADDU a4, sp, TF_BASE # 5th arg is p. to trapframe
#endif
#ifdef PARANOIA
PTR_L t0, L_CPU(MIPS_CURLWP)
INT_L t1, CPU_INFO_CPL(t0) # get current priority level
INT_S t1, TF_BASE+TF_PPL(sp) # save priority level
#endif
#if defined(__mips_o32) && (defined(DDB) || defined(DEBUG) || defined(KGDB))
PTR_ADDU v0, sp, KERNFRAME_SIZ
REG_S v0, KERNFRAME_SP(sp)
#endif
#ifdef PARANOIA
jal _C_LABEL(splcheck)
nop
#endif
li v1, MIPS_SR_INT_IE << T_BREAK # make a mask of T_BREAK
srl t0, a1, MIPS_CR_EXC_CODE_SHIFT # shift exc code to low 5 bits
srl v1, t0 # shift break mask using it
and v1, MIPS_SR_INT_IE # restrict to IE bit
or v1, MIPS_SR_EXL # or in EXL bit
and v1, a0 # extract bits from status
xor v0, a0, v1 # generate new status
mtc0 v0, MIPS_COP_0_STATUS # update.
COP0_SYNC
#ifdef MIPS3
nop
nop
nop
#endif
jal _C_LABEL(trap)
REG_S a3, KERNFRAME_RA(sp) # for debugging
RESET_EXCEPTION_LEVEL_DISABLE_INTERRUPTS(v0)
COP0_SYNC
#ifdef MIPS3
nop # 3 nop delay
nop
nop
#endif
REG_L a0, TF_BASE+TF_REG_SR(sp) # get SR with EXL set
mtc0 a0, MIPS_COP_0_STATUS # restore the SR, disable intrs
COP0_SYNC
MIPSX(kern_return):
REG_L t0, TF_BASE+TF_REG_MULLO(sp)
REG_L t1, TF_BASE+TF_REG_MULHI(sp)
REG_L k1, TF_BASE+TF_REG_EPC(sp) # might be changed inside trap
mtlo t0
mthi t1
#ifdef PARANOIA
INT_L t2, TF_BASE+TF_PPL(sp) # get saved priority level
PTR_L t0, L_CPU(MIPS_CURLWP)
INT_L t1, CPU_INFO_CPL(t0) # get current priority level
11: bne t2, t1, 11b # loop forever if unequal
nop
jal _C_LABEL(splcheck)
nop
#endif
PTR_LA t0, _C_LABEL(_lock_ras_start)
li t1, -MIPS_LOCK_RAS_SIZE
and t1, k1
bne t1, t0, 1f # exception PC in RAS area?
nop
jal _C_LABEL(_restart_lock_ras) # fix the pc (k1)
nop
1:
_MTC0 k1, MIPS_COP_0_EXC_PC # set return address
COP0_SYNC
REG_L AT, TF_BASE+TF_REG_AST(sp)
REG_L v0, TF_BASE+TF_REG_V0(sp)
REG_L v1, TF_BASE+TF_REG_V1(sp)
REG_L a0, TF_BASE+TF_REG_A0(sp)
REG_L a1, TF_BASE+TF_REG_A1(sp)
REG_L a2, TF_BASE+TF_REG_A2(sp)
REG_L a3, TF_BASE+TF_REG_A3(sp)
REG_L t0, TF_BASE+TF_REG_T0(sp)
REG_L t1, TF_BASE+TF_REG_T1(sp)
REG_L t2, TF_BASE+TF_REG_T2(sp)
REG_L t3, TF_BASE+TF_REG_T3(sp)
REG_L ta0, TF_BASE+TF_REG_TA0(sp)
REG_L ta1, TF_BASE+TF_REG_TA1(sp)
REG_L ta2, TF_BASE+TF_REG_TA2(sp)
REG_L ta3, TF_BASE+TF_REG_TA3(sp)
REG_L t9, TF_BASE+TF_REG_T9(sp)
REG_L ra, TF_BASE+TF_REG_RA(sp)
#ifdef DDBnotyet
REG_L s0, TF_BASE+TF_REG_S0(sp)
REG_L s1, TF_BASE+TF_REG_S1(sp)
REG_L s2, TF_BASE+TF_REG_S2(sp)
REG_L s3, TF_BASE+TF_REG_S3(sp)
REG_L s4, TF_BASE+TF_REG_S4(sp)
REG_L s5, TF_BASE+TF_REG_S5(sp)
REG_L s6, TF_BASE+TF_REG_S6(sp)
REG_L s7, TF_BASE+TF_REG_S7(sp)
REG_L s8, TF_BASE+TF_REG_S8(sp)
#endif
PTR_ADDU sp, KERNFRAME_SIZ
eret # return to interrupted point
.set at
END(MIPSX(kern_gen_exception))
#if NWDOG > 0 || defined(DDB)
NESTED_NOPROFILE(MIPSX(kern_nonmaskable_intr), KERNFRAME_SIZ, ra)
.set noat
.mask 0x80000000, -4
#if defined(PARANOIA)
PTR_L k0, L_PCB(MIPS_CURLWP)
slt k0, k0, sp # k0 = L_PCB(MIPS_CURLWP) < sp
1: beqz k0, 1b # loop forever if false
nop
PTR_L k0, L_PCB(MIPS_CURLWP)
PTR_ADDU k0, USPACE
slt k0, sp, k0 # k0 = sp < L_PCB(MIPS_CURLWP) + USPACE
2: beqz k0, 2b # loop forever if false
nop
#endif
move k1, sp # save for later
PTR_L sp, CPU_INFO_NMI_STACK(k0) # get NMI stack
REG_S k1, TF_BASE+TF_REG_SP(sp)
REG_S AT, TF_BASE+TF_REG_AST(sp)
REG_S v0, TF_BASE+TF_REG_V0(sp)
REG_S v1, TF_BASE+TF_REG_V1(sp)
mflo v0
mfhi v1
REG_S a0, TF_BASE+TF_REG_A0(sp)
REG_S a1, TF_BASE+TF_REG_A1(sp)
REG_S a2, TF_BASE+TF_REG_A2(sp)
REG_S a3, TF_BASE+TF_REG_A3(sp)
mfc0 a0, MIPS_COP_0_STATUS # 1st arg is STATUS
REG_S t0, TF_BASE+TF_REG_T0(sp)
REG_S t1, TF_BASE+TF_REG_T1(sp)
REG_S t2, TF_BASE+TF_REG_T2(sp)
REG_S t3, TF_BASE+TF_REG_T3(sp)
mfc0 a1, MIPS_COP_0_CAUSE # 2nd arg is CAUSE
REG_S ta0, TF_BASE+TF_REG_TA0(sp)
REG_S ta1, TF_BASE+TF_REG_TA1(sp)
REG_S ta2, TF_BASE+TF_REG_TA2(sp)
REG_S ta3, TF_BASE+TF_REG_TA3(sp)
_MFC0 a2, MIPS_COP_0_BAD_VADDR # 3rd arg is fault address
REG_S t8, TF_BASE+TF_REG_T8(sp) # is MIPS_CURLWP
REG_S t9, TF_BASE+TF_REG_T9(sp)
REG_S ra, TF_BASE+TF_REG_RA(sp)
REG_S a0, TF_BASE+TF_REG_SR(sp)
_MFC0 a3, MIPS_COP_0_ERROR_PC # 4th arg is exception PC
REG_S v0, TF_BASE+TF_REG_MULLO(sp)
REG_S v1, TF_BASE+TF_REG_MULHI(sp)
REG_S a3, TF_BASE+TF_REG_EPC(sp)
REG_S a1, TF_BASE+TF_REG_CAUSE(sp)
REG_S s0, TF_BASE+TF_REG_S0(sp)
REG_S s1, TF_BASE+TF_REG_S1(sp)
REG_S s2, TF_BASE+TF_REG_S2(sp)
REG_S s3, TF_BASE+TF_REG_S3(sp)
REG_S s4, TF_BASE+TF_REG_S4(sp)
REG_S s5, TF_BASE+TF_REG_S5(sp)
REG_S s6, TF_BASE+TF_REG_S6(sp)
REG_S s7, TF_BASE+TF_REG_S7(sp)
REG_S s8, TF_BASE+TF_REG_S8(sp)
REG_S gp, TF_BASE+TF_REG_GP(sp)
PTR_L t8, CPU_INFO_CURLWP(k0)
#if defined(__mips_o32) || defined(__mips_o64)
PTR_ADDU v0, sp, TF_BASE
REG_S v0, KERNFRAME_ARG5(sp) # 5th arg is p. to trapframe
#endif
#if defined(__mips_n32) || defined(__mips_n64)
PTR_ADDU a4, sp, TF_BASE # 5th arg is p. to trapframe
#endif
PTR_L t0, L_CPU(MIPS_CURLWP)
INT_L t1, CPU_INFO_CPL(t0) # get current priority level
INT_S t1, TF_BASE+TF_PPL(sp) # save priority level
#if defined(__mips_o32) && (defined(DDB) || defined(DEBUG) || defined(KGDB))
PTR_ADDU v0, sp, KERNFRAME_SIZ
REG_S v0, KERNFRAME_SP(sp)
#endif
#if defined(PARANOIA_SPL)
jal _C_LABEL(splcheck)
nop
#endif
li v0, ~(MIPS_SR_EXL|MIPS3_SR_ERL|MIPS3_SR_NMI)
and v0, a0 # zero EXL/ERL/NMI bits
mtc0 v0, MIPS_COP_0_STATUS # update.
COP0_SYNC
#ifdef MIPS3
nop
nop
nop
#endif
jal _C_LABEL(trap)
REG_S a3, KERNFRAME_RA(sp) # for debugging
1: wait
b 1b
nop
.set at
END(MIPSX(kern_nonmaskable_intr))
#endif
.p2align 5
NESTED_NOPROFILE(MIPSX(kern_intr), KERNFRAME_SIZ, ra)
.set noat
.mask 0x80000000, -4
#ifdef PARANOIA
PTR_L k0, L_PCB(MIPS_CURLWP)
slt k0, k0, sp # k0 = L_PCB(MIPS_CURLWP) < sp
1: beqz k0, 1b # loop forever if false
nop
PTR_L k0, L_PCB(MIPS_CURLWP)
PTR_ADDU k0, USPACE
slt k0, sp, k0 # k0 = sp < L_PCB(MIPS_CURLWP) + USPACE
2: beqz k0, 2b # loop forever if false
nop
PTR_L k0, L_CPU(MIPS_CURLWP)
INT_L k0, CPU_INFO_IDEPTH(k0) # grab interrupt depth
sltu k0, k0, 3 # must be < 3
3: beqz k0, 3b # loop forever if false
nop
#endif
PTR_SUBU sp, KERNFRAME_SIZ
REG_S AT, TF_BASE+TF_REG_AST(sp)
REG_S v0, TF_BASE+TF_REG_V0(sp)
REG_S v1, TF_BASE+TF_REG_V1(sp)
mflo v0
mfhi v1
REG_S a0, TF_BASE+TF_REG_A0(sp)
REG_S a1, TF_BASE+TF_REG_A1(sp)
REG_S a2, TF_BASE+TF_REG_A2(sp)
REG_S a3, TF_BASE+TF_REG_A3(sp)
REG_S t0, TF_BASE+TF_REG_T0(sp)
REG_S t1, TF_BASE+TF_REG_T1(sp)
REG_S t2, TF_BASE+TF_REG_T2(sp)
REG_S t3, TF_BASE+TF_REG_T3(sp)
REG_S ta0, TF_BASE+TF_REG_TA0(sp)
REG_S ta1, TF_BASE+TF_REG_TA1(sp)
REG_S ta2, TF_BASE+TF_REG_TA2(sp)
REG_S ta3, TF_BASE+TF_REG_TA3(sp)
REG_S s0, TF_BASE+TF_REG_S0(sp) # used for saved ipl/idepth
REG_S s1, TF_BASE+TF_REG_S1(sp) # used for initial status
mfc0 s1, MIPS_COP_0_STATUS
REG_S s2, TF_BASE+TF_REG_S2(sp) # used for cpu_info
#ifdef DDB
REG_S t8, TF_BASE+TF_REG_T8(sp) # already contains MIPS_CURLWP
#endif
REG_S t9, TF_BASE+TF_REG_T9(sp)
REG_S ra, TF_BASE+TF_REG_RA(sp)
REG_S s1, TF_BASE+TF_REG_SR(sp)
REG_S v0, TF_BASE+TF_REG_MULLO(sp)
REG_S v1, TF_BASE+TF_REG_MULHI(sp)
_MFC0 ta0, MIPS_COP_0_EXC_PC # grab exception PC
PTR_L s2, L_CPU(MIPS_CURLWP) # delay slot
REG_S ta0, TF_BASE+TF_REG_EPC(sp) # and save it
#if defined(DDB) || defined(DEBUG) || defined(KGDB)
REG_S ta0, KERNFRAME_RA(sp) # for debugging
#endif
#ifdef PARANOIA
INT_L s0, CPU_INFO_CPL(s2)
INT_S s0, TF_BASE+TF_PPL(sp) # save priority level
jal _C_LABEL(splcheck)
nop
#endif
jal _C_LABEL(splhigh_noprof)
nop
#ifdef PARANOIA
1: bne s0, v0, 1b
nop
#endif
sll s0, v0, 8 # remember previous priority
#ifdef PARANOIA
li v1, IPL_HIGH
sltu t0, v0, v1
2: beqz t0, 2b
nop
#endif
INT_L t1, CPU_INFO_IDEPTH(s2) # we need to inc. intr depth
or s0, t1 # save old interrupt depth
INT_ADDU t1, 1
INT_S t1, CPU_INFO_IDEPTH(s2) # store new interrupt depth
mfc0 v1, MIPS_COP_0_STATUS
MFC0_HAZARD
and v0, v1, MIPS_SR_EXL # grab exception level bit
xor v0, v1 # clear it
mtc0 v0, MIPS_COP_0_STATUS # write new status
COP0_SYNC
move a1, ta0 # 2nd arg is exception PC
move a2, s1 # 3rd arg is status
jal _C_LABEL(cpu_intr) # cpu_intr(ppl, pc, status)
srl a0, s0, 8 # 1st arg is previous pri level
and t1, s0, 0xff # get previous interrupt depth
INT_S t1, CPU_INFO_IDEPTH(s2) # to it previous value
#if defined(PARANOIA)
mfc0 t0, MIPS_COP_0_STATUS # verify INT_IE is still set
MFC0_HAZARD
and t0, MIPS_SR_INT_IE
#if defined(MIPSNN)
teqi t0, 0
#else
3: beqz t0, 3b
nop
#endif
#endif
#ifdef __HAVE_FAST_SOFTINTS
and a0, s1, MIPS_SOFT_INT_MASK # were softints enabled?
beqz a0, 4f # nope
nop
mfc0 v0, MIPS_COP_0_CAUSE # grab the pending softints
MFC0_HAZARD
and a0, v0 # are softints pending
beqz a0, 4f # nope
nop
jal _C_LABEL(softint_process) # softint_process(pending)
nop
#ifdef __HAVE_PREEMPTION
srl v1, s0, 8 # get saved priority level
bnez v1, 4f # branch if not at IPL_NONE
nop
INT_L t0, CPU_INFO_SOFTINTS(s2) # get pending softints
and v0, t0, 1 << SOFTINT_KPREEMPT # do we need a kernel preempt?
beqz v0, 4f # nope
nop
xor t0, v0 # clear preempt bit
INT_S t0, CPU_INFO_SOFTINTS(s2) # and save it.
jal _C_LABEL(splx_noprof) # drop to IPL_SCHED
li a0, IPL_SCHED
jal _C_LABEL(kpreempt) # kpreempt(pc)
li a0, -2
#endif
4:
#endif
#ifdef MIPSNNR2
di v0 # disable interrupts
#else
mfc0 v0, MIPS_COP_0_STATUS # read it
MFC0_HAZARD
xor v0, MIPS_SR_INT_IE # disable interrupts
mtc0 v0, MIPS_COP_0_STATUS # write it
#endif
COP0_SYNC
or v0, MIPS_SR_EXL # set exception mode
mtc0 v0, MIPS_COP_0_STATUS # write it
COP0_SYNC
srl a0, s0, 8 # get previous priority level
#ifdef PARANOIA
INT_L t0, TF_BASE+TF_PPL(sp) # get saved priority level
9: bne t0, a0, 9b # should still match
nop
li t0, IPL_HIGH
sltu v0, a0, t0
8: beqz v0, 8b
nop
#endif
jal _C_LABEL(splx_noprof) # splx(ppl)
nop
#ifdef PARANOIA
mfc0 v0, MIPS_COP_0_STATUS
MFC0_HAZARD
or v0, MIPS_SR_INT_IE
5: bne v0, s1, 5b
nop
#endif
mtc0 s1, MIPS_COP_0_STATUS
COP0_SYNC
REG_L s0, TF_BASE+TF_REG_S0(sp)
REG_L s1, TF_BASE+TF_REG_S1(sp)
b MIPSX(kern_return)
REG_L s2, TF_BASE+TF_REG_S2(sp)
.set at
END(MIPSX(kern_intr))
.p2align 5
NESTED_NOPROFILE(MIPSX(user_reserved_insn), CALLFRAME_SIZ, ra)
.set noat
.mask 0x80000000, -4
KERN_ENTRY_ERRATA
PTR_L k0, L_PCB(k1) # XXXuvm_lwp_getuarea
PTR_ADDU k0, USPACE - TF_SIZ - CALLFRAME_SIZ
REG_S AT, CALLFRAME_SIZ+TF_REG_AST(k0)
REG_S v0, CALLFRAME_SIZ+TF_REG_V0(k0)
mfc0 v0, MIPS_COP_0_CAUSE
MFC0_HAZARD
bltz v0, MIPSX(user_gen_exception_common)
nop
_MFC0 v0, MIPS_COP_0_EXC_PC
MFC0_HAZARD
INT_L AT, 0(v0)
lui v0, %hi(0x7c03e83b) # 0x7c03e83b => rdhwr $3,$29
addiu v0, %lo(0x7c03e83b) # or ... rdhwr v1,ulr
bne AT, v0, MIPSX(user_gen_exception_common)
nop
_MFC0 v0, MIPS_COP_0_EXC_PC
MFC0_HAZARD
PTR_ADDIU v0, 4
_MTC0 v0, MIPS_COP_0_EXC_PC
COP0_SYNC
PTR_L v1, L_PRIVATE(k1) # rdhwr $3,$29 updates v1
REG_L AT, CALLFRAME_SIZ+TF_REG_AST(k0)# restore reg
REG_L v0, CALLFRAME_SIZ+TF_REG_V0(k0) # restore reg
eret
END(MIPSX(user_reserved_insn))
.p2align 5
NESTED_NOPROFILE(MIPSX(user_gen_exception), CALLFRAME_SIZ, ra)
.set noat
.mask 0x80000000, -4
KERN_ENTRY_ERRATA
PTR_L k0, L_PCB(k1) # XXXuvm_lwp_getuarea
PTR_ADDU k0, USPACE - TF_SIZ - CALLFRAME_SIZ
REG_S AT, CALLFRAME_SIZ+TF_REG_AST(k0)
REG_S v0, CALLFRAME_SIZ+TF_REG_V0(k0)
MIPSX(user_gen_exception_common):
REG_S v1, CALLFRAME_SIZ+TF_REG_V1(k0)
mflo v0
REG_S a0, CALLFRAME_SIZ+TF_REG_A0(k0)
REG_S a1, CALLFRAME_SIZ+TF_REG_A1(k0)
REG_S a2, CALLFRAME_SIZ+TF_REG_A2(k0)
REG_S a3, CALLFRAME_SIZ+TF_REG_A3(k0)
mfhi v1
REG_S t0, CALLFRAME_SIZ+TF_REG_T0(k0)
REG_S t1, CALLFRAME_SIZ+TF_REG_T1(k0)
REG_S t2, CALLFRAME_SIZ+TF_REG_T2(k0)
REG_S t3, CALLFRAME_SIZ+TF_REG_T3(k0)
mfc0 a0, MIPS_COP_0_STATUS # 1st arg is STATUS
REG_S ta0, CALLFRAME_SIZ+TF_REG_TA0(k0)
REG_S ta1, CALLFRAME_SIZ+TF_REG_TA1(k0)
REG_S ta2, CALLFRAME_SIZ+TF_REG_TA2(k0)
REG_S ta3, CALLFRAME_SIZ+TF_REG_TA3(k0)
mfc0 a1, MIPS_COP_0_CAUSE # 2nd arg is CAUSE
REG_S s0, CALLFRAME_SIZ+TF_REG_S0(k0)
REG_S s1, CALLFRAME_SIZ+TF_REG_S1(k0)
REG_S s2, CALLFRAME_SIZ+TF_REG_S2(k0)
REG_S s3, CALLFRAME_SIZ+TF_REG_S3(k0)
_MFC0 a2, MIPS_COP_0_BAD_VADDR # 3rd arg is fault address
REG_S s4, CALLFRAME_SIZ+TF_REG_S4(k0)
REG_S s5, CALLFRAME_SIZ+TF_REG_S5(k0)
REG_S s6, CALLFRAME_SIZ+TF_REG_S6(k0)
REG_S s7, CALLFRAME_SIZ+TF_REG_S7(k0)
_MFC0 a3, MIPS_COP_0_EXC_PC # 4th arg is exception PC
REG_S t8, CALLFRAME_SIZ+TF_REG_T8(k0) # will be MIPS_CURLWP
REG_S t9, CALLFRAME_SIZ+TF_REG_T9(k0)
REG_S v0, CALLFRAME_SIZ+TF_REG_MULLO(k0)
REG_S v1, CALLFRAME_SIZ+TF_REG_MULHI(k0)
REG_S gp, CALLFRAME_SIZ+TF_REG_GP(k0)
REG_S sp, CALLFRAME_SIZ+TF_REG_SP(k0)
REG_S s8, CALLFRAME_SIZ+TF_REG_S8(k0)
REG_S ra, CALLFRAME_SIZ+TF_REG_RA(k0)
REG_S a0, CALLFRAME_SIZ+TF_REG_SR(k0)
REG_S a3, CALLFRAME_SIZ+TF_REG_EPC(k0)
#ifdef __GP_SUPPORT__
PTR_LA gp, _C_LABEL(_gp) # switch to kernel GP
#endif
move sp, k0 # switch to kernel SP
move MIPS_CURLWP, k1
#ifdef NOFPU
and t0, a0, MIPS_SR_EXL|MIPS_SR_KSU_MASK # bits to clear
xor t0, a0 # clear them.
#else
lui t0, %hi(~(MIPS_SR_COP_1_BIT|MIPS_SR_EXL|MIPS_SR_KSU_MASK))
addiu t0, %lo(~(MIPS_SR_COP_1_BIT|MIPS_SR_EXL|MIPS_SR_KSU_MASK))
and t0, a0
#endif
mtc0 t0, MIPS_COP_0_STATUS
COP0_SYNC
jal _C_LABEL(trap)
REG_S a3, CALLFRAME_RA(sp) # for debugging
INT_L v0, L_MD_ASTPENDING(MIPS_CURLWP)# any pending ast?
beqz v0, MIPSX(user_return) # if no, skip ast processing
nop
lui ra, %hi(MIPSX(user_return)) # return directly to user return
j _C_LABEL(ast)
PTR_ADDIU ra, %lo(MIPSX(user_return)) # return directly to user return
.set at
END(MIPSX(user_gen_exception))
.p2align 5
NESTED_NOPROFILE(MIPSX(user_intr), CALLFRAME_SIZ, ra)
.set noat
.mask 0x80000000, -4
KERN_ENTRY_ERRATA
PTR_L k0, L_PCB(k1) # XXXuvm_lwp_getuarea
PTR_ADDU k0, USPACE - TF_SIZ - CALLFRAME_SIZ
REG_S AT, CALLFRAME_SIZ+TF_REG_AST(k0) # $1
REG_S v0, CALLFRAME_SIZ+TF_REG_V0(k0) # $2
REG_S v1, CALLFRAME_SIZ+TF_REG_V1(k0) # $3
mflo v0
REG_S a0, CALLFRAME_SIZ+TF_REG_A0(k0) # $4
REG_S a1, CALLFRAME_SIZ+TF_REG_A1(k0) # $5
REG_S a2, CALLFRAME_SIZ+TF_REG_A2(k0) # $6
REG_S a3, CALLFRAME_SIZ+TF_REG_A3(k0) # $7
mfhi v1
REG_S t0, CALLFRAME_SIZ+TF_REG_T0(k0) # $12
REG_S t1, CALLFRAME_SIZ+TF_REG_T1(k0) # $13
REG_S t2, CALLFRAME_SIZ+TF_REG_T2(k0) # $14
REG_S t3, CALLFRAME_SIZ+TF_REG_T3(k0) # $15
mfc0 t0, MIPS_COP_0_CAUSE
REG_S ta0, CALLFRAME_SIZ+TF_REG_TA0(k0) # $8
REG_S ta1, CALLFRAME_SIZ+TF_REG_TA1(k0) # $9
REG_S ta2, CALLFRAME_SIZ+TF_REG_TA2(k0) # $10
REG_S ta3, CALLFRAME_SIZ+TF_REG_TA3(k0) # $11
REG_S s0, CALLFRAME_SIZ+TF_REG_S0(k0) # $16
REG_S s1, CALLFRAME_SIZ+TF_REG_S1(k0) # $17
mfc0 s1, MIPS_COP_0_STATUS
REG_S t8, CALLFRAME_SIZ+TF_REG_T8(k0) # $24 MIPS_CURLWP
REG_S t9, CALLFRAME_SIZ+TF_REG_T9(k0) # $25
REG_S gp, CALLFRAME_SIZ+TF_REG_GP(k0) # $28
REG_S sp, CALLFRAME_SIZ+TF_REG_SP(k0) # $29
REG_S ra, CALLFRAME_SIZ+TF_REG_RA(k0) # $31
REG_S s1, CALLFRAME_SIZ+TF_REG_SR(k0)
_MFC0 ta0, MIPS_COP_0_EXC_PC
REG_S v0, CALLFRAME_SIZ+TF_REG_MULLO(k0)
REG_S v1, CALLFRAME_SIZ+TF_REG_MULHI(k0)
REG_S ta0, CALLFRAME_SIZ+TF_REG_EPC(k0)
REG_S t0, CALLFRAME_SIZ+TF_REG_CAUSE(k0)
move sp, k0 # switch to kernel SP
move MIPS_CURLWP, k1 # set curlwp reg (t8)
#if defined(DDB) || defined(DEBUG) || defined(KGDB)
REG_S ta0, CALLFRAME_RA(sp) # for debugging
#endif
#ifdef __GP_SUPPORT__
PTR_LA gp, _C_LABEL(_gp) # switch to kernel GP
#endif
jal _C_LABEL(splhigh_noprof) # splhigh()
nop
move s0, v0 # remember previous priority
mfc0 v1, MIPS_COP_0_STATUS
#ifdef NOFPU
MFC0_HAZARD
and v0, v1, MIPS_SR_EXL|MIPS_SR_KSU_MASK # bits to clear
xor v0, v1 # clear them.
#else
lui v0, %hi(~(MIPS_SR_COP_1_BIT|MIPS_SR_EXL|MIPS_SR_KSU_MASK))
addiu v0, %lo(~(MIPS_SR_COP_1_BIT|MIPS_SR_EXL|MIPS_SR_KSU_MASK))
and v0, v1
#endif
mtc0 v0, MIPS_COP_0_STATUS # write new status
COP0_SYNC
PTR_L t0, L_CPU(MIPS_CURLWP)
li t1, 1
INT_S t1, CPU_INFO_IDEPTH(t0) # store new interrupt depth (1)
move a1, ta0 # 2nd arg is exception pc
move a2, s1 # 3rd arg is status
jal _C_LABEL(cpu_intr) # cpu_intr(ppl, pc, status)
move a0, s0 # 1st arg is previous pri level
PTR_L t0, L_CPU(MIPS_CURLWP)
INT_S zero, CPU_INFO_IDEPTH(t0)
#ifdef __HAVE_FAST_SOFTINTS
#ifdef PARANOIA
and a0, s1, MIPS_SOFT_INT_MASK # get softints enabled bits
xor a0, MIPS_SOFT_INT_MASK # invert them.
1: bnez a0, 1b # loop forever if disabled
nop
#endif
mfc0 a0, MIPS_COP_0_CAUSE # grab the pending softints
MFC0_HAZARD
and a0, MIPS_SOFT_INT_MASK # are there softints pending
beqz a0, 4f # nope
nop
jal _C_LABEL(softint_process) # softint_process(pending)
nop
4:
#endif
#ifdef MIPSNNR2
di v1 # disable interrupts
#else
mfc0 v1, MIPS_COP_0_STATUS
MFC0_HAZARD
and v0, v1, MIPS_SR_INT_IE # clear interrupt enable
xor v0, v1
mtc0 v0, MIPS_COP_0_STATUS # interrupts are disabled
#endif
COP0_SYNC
jal _C_LABEL(splx_noprof)
move a0, s0 # fetch previous priority level
REG_L s0, CALLFRAME_SIZ+TF_REG_S0(sp) # restore
REG_L s1, CALLFRAME_SIZ+TF_REG_S1(sp) # restore
INT_L v0, L_MD_ASTPENDING(MIPS_CURLWP)# any pending ast?
beqz v0, MIPSX(user_intr_return) # if no, skip ast processing
nop
REG_S s2, CALLFRAME_SIZ+TF_REG_S2(sp) # $18
REG_S s3, CALLFRAME_SIZ+TF_REG_S3(sp) # $19
REG_S s4, CALLFRAME_SIZ+TF_REG_S4(sp) # $20
REG_S s5, CALLFRAME_SIZ+TF_REG_S5(sp) # $21
REG_S s6, CALLFRAME_SIZ+TF_REG_S6(sp) # $22
REG_S s7, CALLFRAME_SIZ+TF_REG_S7(sp) # $23
REG_S s8, CALLFRAME_SIZ+TF_REG_S8(sp) # $30
#if !defined(MIPS_DYNAMIC_STATUS_MASK) && defined(MIPSNNR2)
ei # enable interrupts
#else
mfc0 t0, MIPS_COP_0_STATUS #
MFC0_HAZARD
or t0, MIPS_SR_INT_IE # enable interrupts
DYNAMIC_STATUS_MASK(t0, t1) # machine dependent masking
mtc0 t0, MIPS_COP_0_STATUS # enable interrupts (spl0)
#endif
COP0_SYNC
PTR_LA ra, MIPSX(user_return)
j _C_LABEL(ast) # ast()
nop
.set at
END(MIPSX(user_intr))
.p2align 5
NESTED_NOPROFILE(MIPSX(systemcall), CALLFRAME_SIZ, ra)
.set noat
.mask 0x80000000, -4
KERN_ENTRY_ERRATA
PTR_L k0, L_PCB(k1) # XXXuvm_lwp_getuarea
PTR_ADDU k0, USPACE - TF_SIZ - CALLFRAME_SIZ
#.set at
REG_S v0, CALLFRAME_SIZ+TF_REG_V0(k0) # syscall #
REG_S v1, CALLFRAME_SIZ+TF_REG_V1(k0) # used by syscall()
mflo v0
REG_S a0, CALLFRAME_SIZ+TF_REG_A0(k0)
REG_S a1, CALLFRAME_SIZ+TF_REG_A1(k0)
REG_S a2, CALLFRAME_SIZ+TF_REG_A2(k0)
REG_S a3, CALLFRAME_SIZ+TF_REG_A3(k0)
mfhi v1
mfc0 a1, MIPS_COP_0_STATUS # 2nd arg is STATUS
REG_S s0, CALLFRAME_SIZ+TF_REG_S0(k0)
REG_S s1, CALLFRAME_SIZ+TF_REG_S1(k0)
REG_S s2, CALLFRAME_SIZ+TF_REG_S2(k0)
REG_S s3, CALLFRAME_SIZ+TF_REG_S3(k0)
mfc0 a2, MIPS_COP_0_CAUSE # 3rd arg is CAUSE
REG_S s4, CALLFRAME_SIZ+TF_REG_S4(k0)
REG_S s5, CALLFRAME_SIZ+TF_REG_S5(k0)
REG_S s6, CALLFRAME_SIZ+TF_REG_S6(k0)
REG_S s7, CALLFRAME_SIZ+TF_REG_S7(k0)
_MFC0 a3, MIPS_COP_0_EXC_PC # 4th arg is PC
REG_S t0, CALLFRAME_SIZ+TF_REG_T0(k0)
REG_S t1, CALLFRAME_SIZ+TF_REG_T1(k0)
REG_S t2, CALLFRAME_SIZ+TF_REG_T2(k0)
REG_S t3, CALLFRAME_SIZ+TF_REG_T3(k0) # syscall saved gp for fork
#if defined(__mips_n32) || defined(__mips_n64)
REG_S a4, CALLFRAME_SIZ+TF_REG_A4(k0)
REG_S a5, CALLFRAME_SIZ+TF_REG_A5(k0)
REG_S a6, CALLFRAME_SIZ+TF_REG_A6(k0)
REG_S a7, CALLFRAME_SIZ+TF_REG_A7(k0)
#else
REG_S ta0, CALLFRAME_SIZ+TF_REG_TA0(k0)
REG_S ta1, CALLFRAME_SIZ+TF_REG_TA1(k0)
REG_S ta2, CALLFRAME_SIZ+TF_REG_TA2(k0)
REG_S ta3, CALLFRAME_SIZ+TF_REG_TA3(k0)
#endif
REG_S t8, CALLFRAME_SIZ+TF_REG_T8(k0) # will be MIPS_CURLWP
REG_S t9, CALLFRAME_SIZ+TF_REG_T9(k0)
REG_S gp, CALLFRAME_SIZ+TF_REG_GP(k0)
REG_S sp, CALLFRAME_SIZ+TF_REG_SP(k0)
REG_S s8, CALLFRAME_SIZ+TF_REG_S8(k0)
REG_S ra, CALLFRAME_SIZ+TF_REG_RA(k0)
REG_S a1, CALLFRAME_SIZ+TF_REG_SR(k0)
REG_S v0, CALLFRAME_SIZ+TF_REG_MULLO(k0)
REG_S v1, CALLFRAME_SIZ+TF_REG_MULHI(k0)
REG_S a3, CALLFRAME_SIZ+TF_REG_EPC(k0)
move MIPS_CURLWP, k1 # set curlwp reg
move sp, k0 # switch to kernel SP
#ifdef __GP_SUPPORT__
PTR_LA gp, _C_LABEL(_gp) # switch to kernel GP
#endif
#if defined(DDB) || defined(DEBUG) || defined(KGDB)
move ra, a3
REG_S ra, CALLFRAME_RA(sp)
#endif
PTR_L s0, L_PROC(MIPS_CURLWP) # curlwp->l_proc
PTR_L t9, P_MD_SYSCALL(s0) # t9 = syscall
#ifdef NOFPU
and t0, a1, MIPS_SR_EXL|MIPS_SR_KSU_MASK # bits to clear
xor t0, a1 # clear them.
#else
lui t0, %hi(~(MIPS_SR_COP_1_BIT|MIPS_SR_EXL|MIPS_SR_KSU_MASK))
addiu t0, %lo(~(MIPS_SR_COP_1_BIT|MIPS_SR_EXL|MIPS_SR_KSU_MASK))
and t0, a1
#endif
mtc0 t0, MIPS_COP_0_STATUS
COP0_SYNC
.set at
jalr t9
move a0, MIPS_CURLWP # 1st arg is curlwp
INT_L v0, L_MD_ASTPENDING(MIPS_CURLWP)# any pending ast?
beqz v0, MIPSX(user_return) # no, skip ast processing
nop
lui ra, %hi(MIPSX(user_return)) # return directly to user return
j _C_LABEL(ast)
PTR_ADDIU ra, %lo(MIPSX(user_return)) # return directly to user return
END(MIPSX(systemcall))
.p2align 5
NESTED_NOPROFILE(MIPSX(cache_exception), KERNFRAME_SIZ, ra)
.set noat
.mask 0x80000000, -4
#ifdef sbmips
eret
nop
#endif
PTR_LA k0, panic # return to panic
PTR_LA a0, 9f # panicstr
_MFC0 a1, MIPS_COP_0_ERROR_PC
#if defined(MIPS64_XLS) && defined(MIPS64)
.set push
.set arch=xlr
li k1, 0x309
mfcr a2, k1
li k1, 0x30b
mfcr a3, k1
.set pop
#if defined(__mips_o32)
#error O32 not supported.
#endif
mfc0 a4, MIPS_COP_0_STATUS
mfc0 a5, MIPS_COP_0_CAUSE
#else
mfc0 a2, MIPS_COP_0_ECC
mfc0 a3, MIPS_COP_0_CACHE_ERR
#endif
_MTC0 k0, MIPS_COP_0_ERROR_PC # set return address
COP0_SYNC
mfc0 k0, MIPS_COP_0_STATUS # restore status
li k1, MIPS3_SR_DIAG_PE # ignore further errors
or k0, k1
mtc0 k0, MIPS_COP_0_STATUS # restore status
COP0_SYNC
eret
#if defined(MIPS64_XLS)
MSG("cache error @ EPC %#lx\nL1D_CACHE_ERROR_LOG %#lx\nL1D_CACHE_INTERRUPT %#lx\nstatus %#x, cause %#x");
#else
MSG("cache error @ EPC 0x%x ErrCtl 0x%x CacheErr 0x%x");
#endif
.set at
END(MIPSX(cache_exception))
#if (PGSHIFT & 1) == 0
LEAF_NOPROFILE(MIPSX(kern_tlb_invalid_exception))
.set noat
_MFC0 k0, MIPS_COP_0_BAD_VADDR # get the fault address
#if !defined(_LP64) && (MIPS64 + MIPS64R2) > 0
#if VM_MIN_KERNEL_ADDRESS == MIPS_KSEG2_START
li k1, VM_MIN_KERNEL_ADDRESS # compute index
slt k1, k0, k1
bnez k1, _C_LABEL(MIPSX(kern_gen_exception)) # full trap processing
nop
#elif VM_MIN_KERNEL_ADDRESS > MIPS_XKSEG_START
li k1, VM_MIN_KERNEL_ADDRESS>>32 # compute index
dsll32 k1, k1, 0
slt k1, k0, k1
bnez k1, _C_LABEL(MIPSX(kern_gen_exception)) # full trap processing
nop
#endif
#endif
PTR_LA k1, _C_LABEL(pmap_limits)
PTR_L k1, PMAP_LIMITS_VIRTUAL_END(k1)
PTR_SUBU k1, k0
blez k1, _C_LABEL(MIPSX(kern_gen_exception)) # full trap processing
nop
PTR_LA k1, _C_LABEL(pmap_kern_segtab)
#ifdef _LP64
#ifdef MIPSNNR2
_EXT k0, k0, XSEGSHIFT, XSEGLENGTH
_INS k1, k0, PTR_SCALESHIFT, XSEGLENGTH
#else
PTR_SRL k0, XSEGSHIFT - PTR_SCALESHIFT
andi k0, (NXSEGPG-1) << PTR_SCALESHIFT
PTR_ADDU k1, k0
#endif
_MFC0 k0, MIPS_COP_0_BAD_VADDR # get the fault address (again)
PTR_L k1, (k1) # load segtab address
beqz k1, _C_LABEL(MIPSX(kern_gen_exception))
nop
#endif
#ifdef MIPSNNR2
_EXT k0, k0, SEGSHIFT, SEGLENGTH
_INS k1, k0, PTR_SCALESHIFT, SEGLENGTH
#else
PTR_SRL k0, SEGSHIFT - PTR_SCALESHIFT
andi k0, (NSEGPG-1) << PTR_SCALESHIFT
PTR_ADDU k1, k0
#endif
_MFC0 k0, MIPS_COP_0_BAD_VADDR # get the fault address (again)
PTR_L k1, (k1) # load page table address
beqz k1, _C_LABEL(MIPSX(kern_gen_exception))
nop
#ifdef MIPSNNR2
_EXT k0, k0, PGSHIFT, PTPLENGTH
_INS k1, k0, PTPSHIFT, PTPLENGTH
#else
PTR_SRL k0, PTPLENGTH
andi k0, (NPTEPG-1) << PTPSHIFT
PTR_ADDU k1, k0
#endif
tlbp # Probe the invalid entry
COP0_SYNC
mfc0 k0, MIPS_COP_0_TLB_INDEX
MFC0_HAZARD
bltz k0, _C_LABEL(MIPSX(kern_gen_exception)) # ASSERT(TLB entry exists)
nop # - delay slot -
and k0, k1, 4 # check even/odd page
#ifdef MIPS3
nop # required for QED 5230
#endif
bnez k0, MIPSX(kern_tlbi_odd)
nop
INT_L k0, 0(k1) # get PTE entry
#ifdef MIPSNNR2
_EXT k0, k0, 0, WIRED_POS # get rid of "wired" bit
#else
_SLL k0, k0, WIRED_SHIFT # get rid of "wired" bit
_SRL k0, k0, WIRED_SHIFT
#endif
_MTC0 k0, MIPS_COP_0_TLB_LO0 # load PTE entry
and k0, k0, MIPS3_PG_V # check for valid entry
#ifdef MIPS3
nop # required for QED5230
#endif
beqz k0, _C_LABEL(MIPSX(kern_gen_exception)) # PTE invalid
nop # - delay slot -
INT_L k0, 4(k1) # get odd PTE entry
mfc0 k1, MIPS_COP_0_TLB_INDEX
#ifdef MIPSNNR2
_EXT k0, k0, 0, WIRED_POS
#else
_SLL k0, k0, WIRED_SHIFT
_SRL k0, k0, WIRED_SHIFT
#endif
#if UPAGES == 1
sltiu k1, k1, MIPS3_TLB_WIRED_UPAGES # Luckily this is MIPS3_PG_G
or k1, k1, k0
#endif
_MTC0 k0, MIPS_COP_0_TLB_LO1 # load PTE entry
COP0_SYNC
#ifdef MIPS3
nop
nop # required for QED5230
#endif
tlbwi # write TLB
COP0_SYNC
#ifdef MIPS3_LOONGSON2
li k0, MIPS_DIAG_ITLB_CLEAR
mtc0 k0, MIPS_COP_0_DIAG # invalidate ITLB
#elif defined(MIPS3)
nop
nop
#endif
eret
MIPSX(kern_tlbi_odd):
INT_L k0, 0(k1) # get PTE entry
#ifdef MIPSNNR2
_EXT k0, k0, 0, WIRED_POS
#else
_SLL k0, k0, WIRED_SHIFT # get rid of wired bit
_SRL k0, k0, WIRED_SHIFT
#endif
_MTC0 k0, MIPS_COP_0_TLB_LO1 # load PTE entry
COP0_SYNC
and k0, k0, MIPS3_PG_V # check for valid entry
#ifdef MIPS3
nop # required for QED5230
#endif
beqz k0, _C_LABEL(MIPSX(kern_gen_exception)) # PTE invalid
nop # - delay slot -
INT_L k0, -4(k1) # get even PTE entry
mfc0 k1, MIPS_COP_0_TLB_INDEX
#ifdef MIPSNNR2
_EXT k0, k0, 0, WIRED_POS
#else
_SLL k0, k0, WIRED_SHIFT
_SRL k0, k0, WIRED_SHIFT
#endif
#if UPAGES == 1
sltiu k1, k1, MIPS3_TLB_WIRED_UPAGES # Luckily this is MIPS3_PG_G
or k1, k1, k0
#endif
_MTC0 k0, MIPS_COP_0_TLB_LO0 # load PTE entry
COP0_SYNC
#ifdef MIPS3
nop # required for QED5230
#endif
tlbwi # update TLB
COP0_SYNC
#ifdef MIPS3_LOONGSON2
li k0, MIPS_DIAG_ITLB_CLEAR
mtc0 k0, MIPS_COP_0_DIAG # invalidate ITLB
#elif defined(MIPS3)
nop
nop
#endif
eret
END(MIPSX(kern_tlb_invalid_exception))
#endif
.globl _C_LABEL(MIPSX(exceptionentry_end))
_C_LABEL(MIPSX(exceptionentry_end)):
.set at
LEAF(MIPSX(tlb_get_asid))
_MFC0 v0, MIPS_COP_0_TLB_HI # read the hi reg value
MFC0_HAZARD
jr ra
and v0, v0, MIPS3_TLB_ASID # make off ASID
END(MIPSX(tlb_get_asid))
LEAF(MIPSX(tlb_set_asid))
_MFC0 v0, MIPS_COP_0_TLB_HI # read the hi reg value
#ifdef MIPSNNR2
_INS v0, a0, V_MIPS3_PG_ASID, S_MIPS3_PG_ASID
#else
li t0, MIPS3_PG_ASID
not t1, t0
and v0, v0, t1
and a0, a0, t0
or v0, v0, a0
#endif
_MTC0 v0, MIPS_COP_0_TLB_HI # Write the hi reg value
JR_HB_RA
END(MIPSX(tlb_set_asid))
LEAF(MIPSX(tlb_update_addr))
#ifdef MIPSNNR2
di ta0 # Disable interrupts
#else
mfc0 ta0, MIPS_COP_0_STATUS # Save the status register.
mtc0 zero, MIPS_COP_0_STATUS # Disable interrupts
#endif
COP0_SYNC
#if (PGSHIFT & 1) == 0
and t1, a0, MIPS3_PG_ODDPG # t1 = Even/Odd flag
#endif
and a1, a1, MIPS3_PG_ASID
#ifdef MIPSNNR2
_INS a0, a1, 0, V_MIPS3_PG_HVPN # insert ASID + clear other bits
#else
li v0, MIPS3_PG_HVPN
and a0, a0, v0
or a0, a0, a1 # Merge ASID
#endif
_MFC0 ta1, MIPS_COP_0_TLB_HI # Save current ASID
_MTC0 a0, MIPS_COP_0_TLB_HI # Init high reg
COP0_SYNC
#if (PGSHIFT & 1) == 0
and t0, a2, MIPS3_PG_G # Copy global bit
#endif
tlbp # Probe for the entry.
COP0_SYNC
#ifdef MIPSNNR2
_EXT a1, a2, 0, WIRED_POS # clear top bits of new pte
#else
_SLL a2, WIRED_SHIFT # clear top bits of new pte
_SRL a1, a2, WIRED_SHIFT
#endif
mfc0 v1, MIPS_COP_0_TLB_INDEX # See what we got
#ifdef MIPS3
nop
nop # required for QED5230
#endif
#if (PGSHIFT & 1)
bgez v1, 1f # index < 0 => !present
REG_ADDU a2, a1, MIPS3_PG_NEXT
beqz a3, 7f
li v0, 0
1: _MTC0 a1, MIPS_COP_0_TLB_LO0 # init low reg0.
_MTC0 a2, MIPS_COP_0_TLB_LO1 # init low reg1.
bltz v1, 5f # index < 0 => !present
nop
COP0_SYNC
tlbwi # overwrite entry
b 6f
nop
#else
bltz v1, 3f # index < 0 => !found
nop
tlbr # update, read entry first
COP0_SYNC
bnez t1, 1f # Decide even odd
nop
_MTC0 a1, MIPS_COP_0_TLB_LO0 # init low reg0.
b 2f
nop
1:
_MTC0 a1, MIPS_COP_0_TLB_LO1 # init low reg1.
2:
COP0_SYNC
tlbwi # update slot found
b 6f
nop
3:
beqz a3, 7f # not found and no insert
li v0, 0 # assume failure
bnez t1, 4f # Decide even odd
nop
move t3, a1 # swap a1 and t0
move a1, t0 #
move t0, t3 #
4:
_MTC0 t0, MIPS_COP_0_TLB_LO0 # init low reg0.
_MTC0 a1, MIPS_COP_0_TLB_LO1 # init low reg1.
#endif
5:
COP0_SYNC
tlbwr # enter randomly
6:
COP0_SYNC
#ifdef MIPS3_LOONGSON2
li t1, MIPS_DIAG_ITLB_CLEAR
mtc0 t1, MIPS_COP_0_DIAG # invalidate ITLB
#elif defined(MIPS3)
nop # required for QED5230
nop # required for QED5230
#endif
li v0, 1 # found or inserted
#ifdef MIPS3
nop # Make sure pipeline
nop # advances before we
nop # use the TLB.
nop
#endif
7:
_MTC0 ta1, MIPS_COP_0_TLB_HI # restore ASID
COP0_SYNC
#ifdef MIPS3
nop # required for QED5230
nop # required for QED5230
#endif
mtc0 ta0, MIPS_COP_0_STATUS # Restore the status register
JR_HB_RA
END(MIPSX(tlb_update_addr))
LEAF(MIPSX(tlb_read_entry))
mfc0 v1, MIPS_COP_0_STATUS # Save the status register.
mtc0 zero, MIPS_COP_0_STATUS # Disable interrupts
COP0_SYNC
#ifdef MIPS3
nop
#endif
mfc0 ta2, MIPS_COP_0_TLB_PG_MASK # save current pgMask
#ifdef MIPS3
nop
#endif
_MFC0 t0, MIPS_COP_0_TLB_HI # Get current ASID
mtc0 a0, MIPS_COP_0_TLB_INDEX # Set the index register
COP0_SYNC
#ifdef MIPS3
nop
nop # required for QED5230
#endif
tlbr # Read from the TLB
COP0_SYNC
#ifdef MIPS3
nop
nop
nop
#endif
mfc0 t2, MIPS_COP_0_TLB_PG_MASK # fetch the pgMask
_MFC0 t3, MIPS_COP_0_TLB_HI # fetch the hi entry
_MFC0 ta0, MIPS_COP_0_TLB_LO0 # See what we got
_MFC0 ta1, MIPS_COP_0_TLB_LO1 # See what we got
_MTC0 t0, MIPS_COP_0_TLB_HI # restore ASID
mtc0 ta2, MIPS_COP_0_TLB_PG_MASK # restore pgMask
COP0_SYNC
mtc0 v1, MIPS_COP_0_STATUS # Restore the status register
COP0_SYNC
PTR_S t3, TLBMASK_HI(a1)
REG_S ta0, TLBMASK_LO0(a1)
REG_S ta1, TLBMASK_LO1(a1)
jr ra
INT_S t2, TLBMASK_MASK(a1)
END(MIPSX(tlb_read_entry))
LEAF_NOPROFILE(MIPSX(tlb_invalidate_addr))
mfc0 ta0, MIPS_COP_0_STATUS # save status register
mtc0 zero, MIPS_COP_0_STATUS # disable interrupts
COP0_SYNC
#if (PGSHIFT & 1) == 0
_SRL a2, a0, V_MIPS3_PG_ODDPG - V_MIPS3_PG_V
and a2, MIPS3_PG_V # lo0 V bit
xor a3, a2, MIPS3_PG_V # lo1 V bit
#endif
and a1, a1, MIPS3_PG_ASID
#ifdef MIPSNNR2
_INS a0, a1, 0, V_MIPS3_PG_HVPN
#else
_SRA a0, V_MIPS3_PG_HVPN # clear bottom bits of VA
_SLL a0, V_MIPS3_PG_HVPN # clear bottom bits of VA
or a0, a0, a1
#endif
_MFC0 ta1, MIPS_COP_0_TLB_HI # save current ASID
mfc0 ta2, MIPS_COP_0_TLB_PG_MASK # save current pgMask
_MTC0 a0, MIPS_COP_0_TLB_HI # look for the vaddr & ASID
COP0_SYNC
tlbp # probe the entry in question
COP0_SYNC
mfc0 v0, MIPS_COP_0_TLB_INDEX # see what we got
MFC0_HAZARD
bltz v0, 2f # index < 0 then skip
li t2, MIPS_KSEG0_START # invalid address
PTR_SLL v0, PGSHIFT | 1 # PAGE_SHIFT | 1
PTR_ADDU t2, v0
move t0, zero
move t1, zero
#if (PGSHIFT & 1) == 0
tlbr # read entry
COP0_SYNC
_MFC0 t0, MIPS_COP_0_TLB_LO0 # fetch entryLo0
_MFC0 t1, MIPS_COP_0_TLB_LO1 # fetch entryLo1
#ifdef MIPS3
nop
#endif
and a2, t0 # a2=valid entryLo0 afterwards
and a3, t1 # a3=valid entryLo1 afterwards
or v0, a2, a3 # will one be valid?
#ifdef MIPSNNX
#error Global bit is lost here when V==0 and it needs to be preserved
movz t0, zero, a2 # zero lo0 if V would not be set
movz t1, zero, a3 # zero lo1 if V would not be set
movn t2, a0, v0 # yes, keep VA the same
#else
_SLL a2, a2, PG_V_LSHIFT # move V to MSB
_SRA a2, a2, PG_V_RSHIFT # fill with MSB
or a2, MIPS3_PG_G # mask needs to preserve G
and t0, t0, a2 # zero lo0 if V would not be set
_SLL a3, a3, PG_V_LSHIFT # move V to MSB
_SRA a3, a3, PG_V_RSHIFT # fill with MSB
or a3, MIPS3_PG_G # mask needs to preserve G
beqz v0, 1f # no valid entry
and t1, t1, a3 # zero lo1 if V would not be set
move t2, a0 # we need entryHi to be valid
1:
#endif
#endif
_MTC0 t0, MIPS_COP_0_TLB_LO0 # zero out entryLo0
_MTC0 t1, MIPS_COP_0_TLB_LO1 # zero out entryLo1
_MTC0 t2, MIPS_COP_0_TLB_HI # make entryHi invalid
#if 0
mtc0 zero, MIPS_COP_0_TLB_PG_MASK # zero out pageMask
#endif
COP0_SYNC
#ifdef MIPS3
nop
nop
#endif
tlbwi
COP0_SYNC
#ifdef MIPS3_LOONGSON2
li v0, MIPS_DIAG_ITLB_CLEAR
mtc0 v0, MIPS_COP_0_DIAG # invalidate ITLB
#elif defined(MIPS3)
nop
nop
#endif
2:
mtc0 ta2, MIPS_COP_0_TLB_PG_MASK # restore pgMask
_MTC0 ta1, MIPS_COP_0_TLB_HI # restore current ASID
COP0_SYNC
mtc0 ta0, MIPS_COP_0_STATUS # restore status register
JR_HB_RA
END(MIPSX(tlb_invalidate_addr))
LEAF_NOPROFILE(MIPSX(tlb_invalidate_asids))
mfc0 v1, MIPS_COP_0_STATUS # save status register
mtc0 zero, MIPS_COP_0_STATUS # disable interrupts
COP0_SYNC
_MFC0 t0, MIPS_COP_0_TLB_HI # Save the current ASID.
mfc0 t1, MIPS_COP_0_TLB_WIRED
li v0, MIPS_KSEG0_START # invalid address
INT_L t2, _C_LABEL(mips_options) + MO_NUM_TLB_ENTRIES
mfc0 t3, MIPS_COP_0_TLB_PG_MASK # save current pgMask
1:
mtc0 t1, MIPS_COP_0_TLB_INDEX # set index
COP0_SYNC
sll ta0, t1, PGSHIFT | 1 # PAGE_SHIFT | 1
tlbr # obtain an entry
COP0_SYNC
_MFC0 ta1, MIPS_COP_0_TLB_LO1
MFC0_HAZARD
and ta1, MIPS3_PG_G # check to see it has G bit
bnez ta1, 2f # yep, skip this one.
nop
_MFC0 ta1, MIPS_COP_0_TLB_HI # get VA and ASID
MFC0_HAZARD
and ta1, MIPS3_PG_ASID # focus on ASID
sltu a3, ta1, a0 # asid < base?
bnez a3, 2f # yes, skip this entry.
nop
sltu a3, a1, ta1 # limit < asid
bnez a3, 2f # yes, skip this entry.
nop
PTR_ADDU ta0, v0
_MTC0 ta0, MIPS_COP_0_TLB_HI # make entryHi invalid
_MTC0 zero, MIPS_COP_0_TLB_LO0 # zero out entryLo0
_MTC0 zero, MIPS_COP_0_TLB_LO1 # zero out entryLo1
mtc0 zero, MIPS_COP_0_TLB_PG_MASK # zero out mask entry
COP0_SYNC
tlbwi # invalidate the TLB entry
COP0_SYNC
2:
addu t1, 1
bne t1, t2, 1b
nop
_MTC0 t0, MIPS_COP_0_TLB_HI # restore ASID.
mtc0 t3, MIPS_COP_0_TLB_PG_MASK # restore pgMask
COP0_SYNC
#ifdef MIPS3_LOONGSON2
li v0, MIPS_DIAG_ITLB_CLEAR
mtc0 v0, MIPS_COP_0_DIAG # invalidate ITLB
#endif
mtc0 v1, MIPS_COP_0_STATUS # restore status register
JR_HB_RA # new ASID will be set soon
END(MIPSX(tlb_invalidate_asids))
#ifdef MULTIPROCESSOR
LEAF_NOPROFILE(MIPSX(tlb_invalidate_globals))
mfc0 v1, MIPS_COP_0_STATUS # save status register
mtc0 zero, MIPS_COP_0_STATUS # disable interrupts
COP0_SYNC
_MFC0 t0, MIPS_COP_0_TLB_HI # save current ASID
mfc0 t1, MIPS_COP_0_TLB_WIRED
li v0, MIPS_KSEG0_START # invalid address
INT_L t2, _C_LABEL(mips_options) + MO_NUM_TLB_ENTRIES
mfc0 t3, MIPS_COP_0_TLB_PG_MASK # save current pgMask
1:
mtc0 t1, MIPS_COP_0_TLB_INDEX # set index
COP0_SYNC
sll ta0, t1, PGSHIFT | 1 # PAGE_SHIFT | 1
tlbr # obtain an entry
COP0_SYNC
_MFC0 a0, MIPS_COP_0_TLB_LO1
MFC0_HAZARD
and a0, MIPS3_PG_G # check to see it has G bit
beqz a0, 2f # no, skip this entry
nop
PTR_ADDU ta0, v0
_MTC0 ta0, MIPS_COP_0_TLB_HI # make entryHi invalid
_MTC0 zero, MIPS_COP_0_TLB_LO0 # zero out entryLo0
_MTC0 zero, MIPS_COP_0_TLB_LO1 # zero out entryLo1
mtc0 zero, MIPS_COP_0_TLB_PG_MASK # zero out mask entry
COP0_SYNC
tlbwi # invalidate the TLB entry
COP0_SYNC
2:
addu t1, 1
bne t1, t2, 1b
nop
_MTC0 t0, MIPS_COP_0_TLB_HI # restore current ASID
mtc0 t3, MIPS_COP_0_TLB_PG_MASK # restore pgMask
COP0_SYNC
#ifdef MIPS3_LOONGSON2
li v0, MIPS_DIAG_ITLB_CLEAR
mtc0 v0, MIPS_COP_0_DIAG # invalidate ITLB
#endif
mtc0 v1, MIPS_COP_0_STATUS # restore status register
JR_HB_RA
END(MIPSX(tlb_invalidate_globals))
#endif
LEAF_NOPROFILE(MIPSX(tlb_invalidate_all))
mfc0 ta0, MIPS_COP_0_STATUS # save status register
mtc0 zero, MIPS_COP_0_STATUS # disable interrupts
COP0_SYNC
INT_L a0, _C_LABEL(mips_options) + MO_NUM_TLB_ENTRIES
mfc0 t0, MIPS_COP_0_TLB_WIRED
_MFC0 ta1, MIPS_COP_0_TLB_HI # save current ASID
mfc0 ta2, MIPS_COP_0_TLB_PG_MASK # save current pgMask
COP0_SYNC
li v0, MIPS_KSEG0_START # invalid address
sll v1, t0, PGSHIFT | 1 # PAGE_SHIFT | 1
PTR_ADDU v0, v1
#if (1 << (PGSHIFT|1)) >= 0x8000
li v1, 1
sll v1, PGSHIFT | 1 # PAGE_SHIFT | 1
#else
li v1, 1 << (PGSHIFT | 1)
#endif
_MTC0 zero, MIPS_COP_0_TLB_LO0 # zero out entryLo0
_MTC0 zero, MIPS_COP_0_TLB_LO1 # zero out entryLo1
mtc0 zero, MIPS_COP_0_TLB_PG_MASK # zero out pageMask
1:
mtc0 t0, MIPS_COP_0_TLB_INDEX # set TLBindex
_MTC0 v0, MIPS_COP_0_TLB_HI # make entryHi invalid
COP0_SYNC
tlbwi # clear the entry
COP0_SYNC
addu t0, 1 # increment index
bne t0, a0, 1b
PTR_ADDU v0, v1
mtc0 ta2, MIPS_COP_0_TLB_PG_MASK # restore pgMask
_MTC0 ta1, MIPS_COP_0_TLB_HI # restore ASID
COP0_SYNC
#ifdef MIPS3_LOONGSON2
li v0, MIPS_DIAG_ITLB_CLEAR
mtc0 v0, MIPS_COP_0_DIAG # invalidate ITLB
#endif
mtc0 ta0, MIPS_COP_0_STATUS # restore status register
JR_HB_RA
END(MIPSX(tlb_invalidate_all))
LEAF_NOPROFILE(MIPSX(tlb_record_asids))
_MFC0 a3, MIPS_COP_0_TLB_HI # Save the current ASID.
mfc0 ta0, MIPS_COP_0_TLB_WIRED
INT_L ta1, _C_LABEL(mips_options) + MO_NUM_TLB_ENTRIES
mfc0 t3, MIPS_COP_0_TLB_PG_MASK # save current pgMask
move ta2, zero
li ta3, 1
move v0, zero # start at zero ASIDs
#ifdef MIPSNNR2
di v1 # disable interrupts
#else
mfc0 v1, MIPS_COP_0_STATUS # save status register
#ifdef _LP64
and t0, v1, MIPS_SR_INT_IE
xor t0, v1
mtc0 t0, MIPS_COP_0_STATUS # disable interrupts
#else
mtc0 zero, MIPS_COP_0_STATUS # disable interrupts
#endif
#endif
COP0_SYNC
1:
mtc0 ta0, MIPS_COP_0_TLB_INDEX # set index
COP0_SYNC
tlbr # obtain an entry
COP0_SYNC
_MFC0 t0, MIPS_COP_0_TLB_LO1
MFC0_HAZARD
and t0, MIPS3_PG_G # check to see it has G bit
bnez t0, 4f # yep, skip this one.
nop
_MFC0 t0, MIPS_COP_0_TLB_HI # get VA and ASID
MFC0_HAZARD
and t0, t0, MIPS3_PG_ASID # focus on ASID
bgt t0, a1, 4f # > ASID max? skip
nop
srl a2, t0, 3 + LONG_SCALESHIFT # drop low 5 or 6 bits
sll a2, LONG_SCALESHIFT # make an index for the bitmap
_SLLV t0, ta3, t0 # t0 is mask (ta3 == 1)
PTR_ADDU a2, a0 # index into the bitmap
beq a2, ta2, 3f # is the desired cell loaded?
nop # yes, don't reload it
beqz ta2, 2f # have we ever loaded it?
nop # nope, so don't save it
LONG_S t2, 0(ta2) # save the updated value.
2:
move ta2, a2 # remember the new cell's addr
LONG_L t2, 0(ta2) # and load it
3:
and t1, t2, t0 # see if this asid was recorded
sltu t1, t1, ta3 # t1 = t1 < 1 (aka t1 == 0)
addu v0, t1 # v0 += t1
or t2, t0 # or in the new ASID bits
4:
addu ta0, 1 # increment TLB entry #
bne ta0, ta1, 1b # keep lookup if not limit
nop
beqz ta2, 5f # do we have a cell to write?
nop # nope, nothing.
LONG_S t2, 0(ta2) # save the updated value.
5:
mtc0 t3, MIPS_COP_0_TLB_PG_MASK # restore pgMask
_MTC0 a3, MIPS_COP_0_TLB_HI # restore ASID
COP0_SYNC
mtc0 v1, MIPS_COP_0_STATUS # restore status register
JR_HB_RA
END(MIPSX(tlb_record_asids))
LEAF_NOPROFILE(MIPSX(lwp_trampoline))
PTR_ADDU sp, -CALLFRAME_SIZ
move a0, v0
jal _C_LABEL(lwp_startup)
move a1, MIPS_CURLWP
jalr s0
move a0, s1
#
#
#
.set noat
MIPSX(user_return):
REG_L s0, CALLFRAME_SIZ+TF_REG_S0(sp) # $16
REG_L s1, CALLFRAME_SIZ+TF_REG_S1(sp) # $17
REG_L s2, CALLFRAME_SIZ+TF_REG_S2(sp) # $18
REG_L s3, CALLFRAME_SIZ+TF_REG_S3(sp) # $19
REG_L s4, CALLFRAME_SIZ+TF_REG_S4(sp) # $20
REG_L s5, CALLFRAME_SIZ+TF_REG_S5(sp) # $21
REG_L s6, CALLFRAME_SIZ+TF_REG_S6(sp) # $22
REG_L s7, CALLFRAME_SIZ+TF_REG_S7(sp) # $23
REG_L s8, CALLFRAME_SIZ+TF_REG_S8(sp) # $30
MIPSX(user_intr_return):
#ifdef PARANOIA
PTR_L t0, L_CPU(MIPS_CURLWP)
INT_L t1, CPU_INFO_CPL(t0) # get curcpu()->ci_cpl
2: bnez t1, 2b
nop
#endif
RESET_EXCEPTION_LEVEL_DISABLE_INTERRUPTS(v0)
COP0_SYNC
SET_EXCEPTION_LEVEL(v0) # set exception level
COP0_SYNC
REG_L t0, CALLFRAME_SIZ+TF_REG_MULLO(sp)
REG_L t1, CALLFRAME_SIZ+TF_REG_MULHI(sp)
REG_L v0, CALLFRAME_SIZ+TF_REG_EPC(sp)
mtlo t0
mthi t1
_MTC0 v0, MIPS_COP_0_EXC_PC
COP0_SYNC
move k1, sp
REG_L AT, CALLFRAME_SIZ+TF_REG_AST(k1) # $1
REG_L v0, CALLFRAME_SIZ+TF_REG_V0(k1) # $2
REG_L v1, CALLFRAME_SIZ+TF_REG_V1(k1) # $3
REG_L a0, CALLFRAME_SIZ+TF_REG_A0(k1) # $4
REG_L a1, CALLFRAME_SIZ+TF_REG_A1(k1) # $5
REG_L a2, CALLFRAME_SIZ+TF_REG_A2(k1) # $6
REG_L a3, CALLFRAME_SIZ+TF_REG_A3(k1) # $7
REG_L t0, CALLFRAME_SIZ+TF_REG_T0(k1) # $12 / $8
REG_L t1, CALLFRAME_SIZ+TF_REG_T1(k1) # $13 / $9
REG_L t2, CALLFRAME_SIZ+TF_REG_T2(k1) # $14 / $10
REG_L t3, CALLFRAME_SIZ+TF_REG_T3(k1) # $15 / $11
REG_L ta0, CALLFRAME_SIZ+TF_REG_TA0(k1) # $8 / $12
REG_L ta1, CALLFRAME_SIZ+TF_REG_TA1(k1) # $9 / $13
REG_L ta2, CALLFRAME_SIZ+TF_REG_TA2(k1) # $10 / $14
REG_L ta3, CALLFRAME_SIZ+TF_REG_TA3(k1) # $11 / $15
REG_L t8, CALLFRAME_SIZ+TF_REG_T8(k1) # $24 MIPS_CURLWP
REG_L t9, CALLFRAME_SIZ+TF_REG_T9(k1) # $25
REG_L k0, CALLFRAME_SIZ+TF_REG_SR(k1) # status register
DYNAMIC_STATUS_MASK(k0, sp) # machine dependent masking
REG_L gp, CALLFRAME_SIZ+TF_REG_GP(k1) # $28
REG_L sp, CALLFRAME_SIZ+TF_REG_SP(k1) # $29
REG_L ra, CALLFRAME_SIZ+TF_REG_RA(k1) # $31
mtc0 k0, MIPS_COP_0_STATUS
COP0_SYNC
eret
.set at
END(MIPSX(lwp_trampoline))
LEAF_NOPROFILE(MIPSX(cpu_switch_resume))
#if !defined(_LP64)
#if (PAGE_SIZE < 16384)
#if (USPACE > PAGE_SIZE) || !defined(_LP64)
INT_L a1, L_MD_UPTE_0(a0) # a1 = upte[0]
#if (PGSHIFT & 1)
#if (USPACE > PAGE_SIZE)
#error Unsupported
#else
INT_ADD a2, a1, MIPS3_PG_NEXT # a2 = upper half
#endif
#else
INT_L a2, L_MD_UPTE_1(a0) # a2 = upte[1]
#endif
PTR_L v0, L_PCB(a0) # va = l->l_addr
#if VM_MIN_KERNEL_ADDRESS == MIPS_KSEG2_START
li t0, VM_MIN_KERNEL_ADDRESS # compute index
blt v0, t0, MIPSX(resume)
nop
#else
li t0, MIPS_KSEG0_START # below KSEG0?
blt t0, v0, MIPSX(resume)
nop
li t0, VM_MIN_KERNEL_ADDRESS>>32 # below XKSEG?
dsll32 t0, t0, 0
blt v0, t0, MIPSX(resume)
nop
#endif
#if (PGSHIFT & 1) == 0
and t0, v0, MIPS3_PG_ODDPG
beqz t0, MIPSX(entry0)
nop
break
PANIC("USPACE sat on odd page boundary")
MIPSX(entry0):
#endif
_MFC0 ta1, MIPS_COP_0_TLB_HI # save TLB_HI
_MTC0 v0, MIPS_COP_0_TLB_HI # VPN = va
COP0_SYNC
tlbp # probe VPN
COP0_SYNC
mfc0 t0, MIPS_COP_0_TLB_INDEX
MFC0_HAZARD
bltz t0, MIPSX(entry0set)
sll t0, t0, PGSHIFT | 1 # PAGE_SHIFT | 1
PTR_LA t0, MIPS_KSEG0_START(t0)
_MTC0 t0, MIPS_COP_0_TLB_HI
_MTC0 zero, MIPS_COP_0_TLB_LO0
_MTC0 zero, MIPS_COP_0_TLB_LO1
COP0_SYNC
tlbwi
COP0_SYNC
_MTC0 v0, MIPS_COP_0_TLB_HI # set VPN again
COP0_SYNC
MIPSX(entry0set):
#ifdef MULTIPROCESSOR
PTR_L t0, L_CPU(a0) # get cpu_info
INT_L t1, CPU_INFO_KSP_TLB_SLOT(t0) # get TLB# for KSP
mtc0 t1, MIPS_COP_0_TLB_INDEX # TLB entry (virtual)
#else
mtc0 zero, MIPS_COP_0_TLB_INDEX # TLB entry #0 (virtual)
#endif
COP0_SYNC
_MTC0 a1, MIPS_COP_0_TLB_LO0 # upte[0] | PG_G
_MTC0 a2, MIPS_COP_0_TLB_LO1 # upte[1] | PG_G
COP0_SYNC
tlbwi # set TLB entry #0
COP0_SYNC
_MTC0 ta1, MIPS_COP_0_TLB_HI # restore TLB_HI
COP0_SYNC
MIPSX(resume):
#endif
#endif
#endif
#ifdef MIPSNNR2
PTR_L v0, L_PRIVATE(a0) # get lwp private
_MTC0 v0, MIPS_COP_0_USERLOCAL # make available for rdhwr
#endif
jr ra
nop
END(MIPSX(cpu_switch_resume))
LEAF(MIPSX(tlb_write_entry))
mfc0 ta0, MIPS_COP_0_STATUS # Save the status register.
RESET_EXCEPTION_LEVEL_DISABLE_INTERRUPTS(v0)
COP0_SYNC
REG_L a2, TLBMASK_LO0(a1) # fetch tlb->tlb_lo0
REG_L a3, TLBMASK_LO1(a1) # fetch tlb->tlb_lo1
mfc0 ta2, MIPS_COP_0_TLB_PG_MASK # Save current page mask.
_MFC0 ta1, MIPS_COP_0_TLB_HI # Save the current ASID.
_MTC0 a2, MIPS_COP_0_TLB_LO0 # Set up entry low0.
_MTC0 a3, MIPS_COP_0_TLB_LO1 # Set up entry low1.
COP0_SYNC
INT_L a2, TLBMASK_MASK(a1) # fetch tlb->tlb_mask
INT_ADD v0, a0, 1 # add 1 to it
#ifdef MIPSNNR2
movz a2, ta2, v0 # a2 = ta2 if v0 is 0
#else
bnez a2, 1f # branch if tlb_mask != -1
nop # --delay-slot--
move a2, ta2 # use existing tlb_mask
1:
#endif
PTR_L a3, TLBMASK_HI(a1) # fetch tlb->tlb_hi
mtc0 a0, MIPS_COP_0_TLB_INDEX # Set the index.
mtc0 a2, MIPS_COP_0_TLB_PG_MASK # Set up entry pagemask.
_MTC0 a3, MIPS_COP_0_TLB_HI # Set up entry high.
COP0_SYNC
tlbwi # Write the TLB
COP0_SYNC
#ifdef MIPS3
nop
#endif
_MTC0 ta1, MIPS_COP_0_TLB_HI # Restore the ASID.
mtc0 ta2, MIPS_COP_0_TLB_PG_MASK # Restore page mask.
COP0_SYNC
#ifdef MIPS3_LOONGSON2
li v0, MIPS_DIAG_ITLB_CLEAR
mtc0 v0, MIPS_COP_0_DIAG # invalidate ITLB
#endif
mtc0 ta0, MIPS_COP_0_STATUS # Restore the status register
JR_HB_RA
END(MIPSX(tlb_write_entry))
#if defined(MIPS3)
LEAF_NOPROFILE(MIPSX(VCED))
.set noat
_MFC0 k0, MIPS_COP_0_BAD_VADDR # fault addr.
li k1, -16
and k0, k1
cache (CACHE_R4K_SD | CACHEOP_R4K_HIT_WB_INV), 0(k0)
cache (CACHE_R4K_D | CACHEOP_R4K_HIT_INV), 0(k0)
#ifdef DEBUG
_MFC0 k0, MIPS_COP_0_BAD_VADDR
PTR_LA k1, MIPSX(VCED_vaddr)
PTR_S k0, 0(k1)
_MFC0 k0, MIPS_COP_0_EXC_PC
PTR_LA k1, MIPSX(VCED_epc)
PTR_S k0, 0(k1)
PTR_LA k1, MIPSX(VCED_count) # count number of exceptions
PTR_SRL k0, k0, 26 # position upper 4 bits of VA
and k0, k0, 0x3c # mask it off
PTR_ADDU k1, k0 # get address of count table
LONG_L k0, 0(k1)
LONG_ADDU k0, 1
LONG_S k0, 0(k1)
#endif
eret
.set at
#ifdef DEBUG
.data
.globl _C_LABEL(MIPSX(VCED_count))
_C_LABEL(MIPSX(VCED_count)):
LONG_WORD 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.globl _C_LABEL(MIPSX(VCED_epc))
_C_LABEL(MIPSX(VCED_epc)):
PTR_WORD 0
.globl _C_LABEL(MIPSX(VCED_vaddr))
_C_LABEL(MIPSX(VCED_vaddr)):
PTR_WORD 0
.text
#endif
END(MIPSX(VCED))
LEAF_NOPROFILE(MIPSX(VCEI))
.set noat
_MFC0 k0, MIPS_COP_0_BAD_VADDR # fault addr.
cache (CACHE_R4K_SD | CACHEOP_R4K_HIT_WB_INV), 0(k0)
cache (CACHE_R4K_I | CACHEOP_R4K_HIT_INV), 0(k0)
#ifdef DEBUG
_MFC0 k0, MIPS_COP_0_BAD_VADDR
PTR_LA k1, MIPSX(VCEI_vaddr)
PTR_S k0, 0(k1)
PTR_LA k1, MIPSX(VCEI_count) # count number of exceptions
PTR_SRL k0, k0, 26 # position upper 4 bits of VA
and k0, k0, 0x3c # mask it off
PTR_ADDU k1, k0 # get address of count table
LONG_L k0, 0(k1)
PTR_ADDU k0, 1
LONG_S k0, 0(k1)
#endif
eret
.set at
#ifdef DEBUG
.data
.globl _C_LABEL(MIPSX(VCEI_count))
_C_LABEL(MIPSX(VCEI_count)):
LONG_WORD 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.globl _C_LABEL(MIPSX(VCEI_vaddr))
_C_LABEL(MIPSX(VCEI_vaddr)):
PTR_WORD 0
.text
#endif
END(MIPSX(VCEI))
#endif
#ifdef USE_64BIT_INSTRUCTIONS
LEAF(MIPSX(pagezero))
li a1, PAGE_SIZE >> 6
1: sd zero, 0(a0) # try to miss cache first
sd zero, 32(a0)
subu a1, 1
sd zero, 16(a0)
sd zero, 48(a0)
sd zero, 8(a0) # fill in cache lines
sd zero, 40(a0)
sd zero, 24(a0)
sd zero, 56(a0)
bgtz a1, 1b
addu a0, 64
jr ra
nop
END(MIPSX(pagezero))
#endif
.rdata
.globl _C_LABEL(MIPSX(locore_vec))
_C_LABEL(MIPSX(locore_vec)):
PTR_WORD _C_LABEL(MIPSX(cpu_switch_resume))
PTR_WORD _C_LABEL(MIPSX(lwp_trampoline))
PTR_WORD _C_LABEL(MIPSX(wbflush)) # wbflush
PTR_WORD _C_LABEL(MIPSX(tlb_get_asid))
PTR_WORD _C_LABEL(MIPSX(tlb_set_asid))
PTR_WORD _C_LABEL(MIPSX(tlb_invalidate_asids))
PTR_WORD _C_LABEL(MIPSX(tlb_invalidate_addr))
#ifdef MULTIPROCESSOR
PTR_WORD _C_LABEL(MIPSX(tlb_invalidate_globals))
#else
PTR_WORD _C_LABEL(nullop)
#endif
PTR_WORD _C_LABEL(MIPSX(tlb_invalidate_all))
PTR_WORD _C_LABEL(MIPSX(tlb_record_asids))
PTR_WORD _C_LABEL(MIPSX(tlb_update_addr))
PTR_WORD _C_LABEL(MIPSX(tlb_read_entry))
PTR_WORD _C_LABEL(MIPSX(tlb_write_entry))
.globl _C_LABEL(MIPSX(locoresw))
_C_LABEL(MIPSX(locoresw)):
PTR_WORD _C_LABEL(MIPSX(wbflush)) # lsw_wbflush
PTR_WORD _C_LABEL(nullop) # lsw_cpu_idle
PTR_WORD _C_LABEL(nullop) # lsw_send_ipi
PTR_WORD _C_LABEL(nullop) # lsw_cpu_offline_md
PTR_WORD _C_LABEL(nullop) # lsw_cpu_init
PTR_WORD _C_LABEL(nullop) # lsw_cpu_run
PTR_WORD _C_LABEL(nullop) # lsw_bus_error
MIPSX(excpt_sw):
####
#### The kernel exception handlers.
####
PTR_WORD _C_LABEL(MIPSX(kern_intr)) # 0 external interrupt
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 1 TLB modification
#if (PGSHIFT & 1) == 0
PTR_WORD _C_LABEL(MIPSX(kern_tlb_invalid_exception)) # 2 TLB miss (LW/I-fetch)
PTR_WORD _C_LABEL(MIPSX(kern_tlb_invalid_exception)) # 3 TLB miss (SW)
#else
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 2 TLB miss (LW/I-fetch)
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 3 TLB miss (SW)
#endif
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 4 address error (LW/I-fetch)
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 5 address error (SW)
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 6 bus error (I-fetch)
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 7 bus error (load or store)
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 8 system call
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 9 breakpoint
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 10 reserved instruction
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 11 coprocessor unusable
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 12 arithmetic overflow
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 13 r4k trap exception
#if defined(MIPS3)
PTR_WORD _C_LABEL(MIPSX(VCEI)) # 14 r4k virt coherence
#else
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 14 reserved
#endif
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 15 r4k FP exception
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 16 reserved
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 17 reserved
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 18 reserved
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 19 reserved
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 20 reserved
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 21 reserved
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 22 reserved
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 23 watch exception
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 24 reserved
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 25 reserved
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 26 reserved
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 27 reserved
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 28 reserved
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 29 reserved
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 30 reserved
#if defined(MIPS3)
PTR_WORD _C_LABEL(MIPSX(VCED)) # 31 v. coherence exception data
#else
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception)) # 31 reserved
#endif
#####
##### The user exception handlers.
#####
PTR_WORD _C_LABEL(MIPSX(user_intr)) # 0
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 1
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 2
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 3
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 4
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 5
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 6
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 7
PTR_WORD _C_LABEL(MIPSX(systemcall)) # 8
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 9
#ifdef MIPS64_OCTEON
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 10
#else
PTR_WORD _C_LABEL(MIPSX(user_reserved_insn)) # 10
#endif
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 11
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 12
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 13
#if defined(MIPS3)
PTR_WORD _C_LABEL(MIPSX(VCEI)) # 14
#else
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 14
#endif
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 15
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 16
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 17
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 18
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 19
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 20
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 21
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 22
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 23
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 24
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 25
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 26
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 27
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 28
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 29
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 30
#if defined(MIPS3)
PTR_WORD _C_LABEL(MIPSX(VCED)) # 31 v. coherence exception data
#else
PTR_WORD _C_LABEL(MIPSX(user_gen_exception)) # 31
#endif
#ifdef MIPS3_LOONGSON2
loongson2_xtlb_miss_str:
.string "loongson2_xtlb_miss"
#endif