#include "opt_cputype.h"
#include "opt_ddb.h"
#include "opt_kgdb.h"
#include <sys/cdefs.h>
#include <mips/asm.h>
#include <mips/cpuregs.h>
RCSID("$NetBSD: locore_mips1.S,v 1.99 2024/02/09 22:08:32 andvar Exp $")
#include "assym.h"
#define _SLLV sllv
#define _SLL sll
#define _SRL srl
#define WIRED_SHIFT 2
#define _MFC0 mfc0
#define _MTC0 mtc0
#if defined(__mips_n32) || defined(__mips_n64)
#error MIPS1 does not support N32/N64.
#endif
#define MIPSX(name) __CONCAT(mips1_,name)
.set noreorder
.text
EXPORT(MIPSX(exceptionentry_start))
VECTOR(MIPSX(utlb_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
bltz k0, 1f # R3000 chip bug
PTR_SRL k0, SEGSHIFT-PTR_SCALESHIFT #03: k0=seg offset (almost)
PTR_L k1, %lo(CPUVAR(PMAP_SEG0TAB))(k1) #04: k1=seg0tab
andi k0, (NSEGPG-1)<<PTR_SCALESHIFT #07: k0=seg offset (mask 0x3)
PTR_ADDU k1, k0 #08: k1=seg entry address
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
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
INT_L k0, 0(k1) #0f: k0=lo0 pte
nop #10: load delay
beqz k0, MIPSX(invalidpte) #11: dont load invalid entries
nop #12 branch delay
mtc0 k0, MIPS_COP_0_TLB_LOW #13: lo0 is loaded
nop #14: load delay
tlbwr #15: update TLB
1:
_MFC0 k1, MIPS_COP_0_EXC_PC #16: get return address
nop #17: load delay
j k1 #18: return from
rfe #19: exception
MIPSX(nopagetable):
MIPSX(invalidpte):
j MIPSX(slowfault) #1a: handle the rest
nop #1b: branch delay
.set at
VECTOR_END(MIPSX(utlb_miss))
.org MIPSX(utlb_miss) + 0x80
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, MIPS1_SR_KU_PREV #02: test for user mode
sll k0, 4 #03: shift user bit for cause index
and k1, MIPS1_CR_EXC_CODE #04: mask out the cause bits
or k1, k0 #05: change index to user table
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
nop #0a: load delay
j k0 #0b: jump to the function
nop #0c
nop #0d
nop #0e
nop #0f
.set at
VECTOR_END(MIPSX(exception))
MIPSX(slowfault):
.set noat
mfc0 k0, MIPS_COP_0_STATUS
nop
and k0, MIPS1_SR_KU_PREV
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
#ifdef PARANOIA
PTR_L k0, L_PCB(MIPS_CURLWP)
nop
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)
nop
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
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
PTR_ADDU v0, sp, TF_BASE
REG_S v0, KERNFRAME_ARG5(sp) # 5th arg is p. to trapframe
#ifdef PARANOIA
PTR_L t0, L_CPU(MIPS_CURLWP)
nop
INT_L t1, CPU_INFO_CPL(t0) # get current priority level
nop
INT_S t1, TF_BASE+TF_PPL(sp) # save priority level
#endif
#if 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
jal _C_LABEL(trap)
REG_S a3, KERNFRAME_RA(sp) # for debugging
REG_L a0, TF_BASE+TF_REG_SR(sp)
nop
mtc0 a0, MIPS_COP_0_STATUS # restore the SR, disable intrs
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)
nop
INT_L t1, CPU_INFO_CPL(t0) # get current priority level
nop
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:
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
j k1 # return to interrupted point
rfe
.set at
END(MIPSX(kern_gen_exception))
NESTED_NOPROFILE(MIPSX(kern_intr), KERNFRAME_SIZ, ra)
.set noat
.mask 0x80000000, -4
#ifdef PARANOIA
PTR_L k0, L_PCB(MIPS_CURLWP)
nop
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)
nop
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)
nop
INT_L k0, CPU_INFO_IDEPTH(k0) # grab interrupt depth
nop
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
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)
nop # load delay
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
nop # load delay
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
nop
or v0, v1, MIPS_SR_INT_IE
mtc0 v0, MIPS_COP_0_STATUS # write new status
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
#ifdef PARANOIA
mfc0 t0, MIPS_COP_0_STATUS # verify INT_IE is still set
nop
and t0, MIPS_SR_INT_IE
3: beqz t0, 3b
nop
#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
nop
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
nop
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(kpreempt) # kpreempt(pc)
PTR_L a0, TF_BASE+TF_REG_EPC(sp)
#endif
4:
#endif
mtc0 s1, MIPS_COP_0_STATUS # disable interrupts
srl a0, s0, 8 # get previous priority level
#ifdef PARANOIA
INT_L t0, TF_BASE+TF_PPL(sp) # get saved priority level
nop
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
nop
or v0, MIPS_SR_INT_IE
5: bne v0, s1, 5b
nop
#endif
mtc0 s1, MIPS_COP_0_STATUS
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))
NESTED_NOPROFILE(MIPSX(user_gen_exception), CALLFRAME_SIZ, ra)
.set noat
.mask 0x80000000, -4
PTR_L k1, CPUVAR(CURLWP)
nop
PTR_L k0, L_PCB(k1)
nop
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)
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 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 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)
#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
#ifndef NOFPU
lui t0, %hi(MIPS_SR_COP_1_BIT)
and t0, a0
beqz t0, 1f
xor t0, a0 # turn off the FPU
mtc0 t0, MIPS_COP_0_STATUS
nop
1:
#endif
jal _C_LABEL(trap)
REG_S a3, CALLFRAME_RA(sp) # for debugging
INT_L v0, L_MD_ASTPENDING(MIPS_CURLWP)# any pending ast?
nop
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))
NESTED_NOPROFILE(MIPSX(user_intr), CALLFRAME_SIZ, ra)
.set noat
.mask 0x80000000, -4
PTR_L k1, CPUVAR(CURLWP)
nop
PTR_L k0, L_PCB(k1) # XXXuvm_lwp_getuarea
nop
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) # $8
REG_S t1, CALLFRAME_SIZ+TF_REG_T1(k0) # $9
REG_S t2, CALLFRAME_SIZ+TF_REG_T2(k0) # $10
REG_S t3, CALLFRAME_SIZ+TF_REG_T3(k0) # $11
mfc0 t0, MIPS_COP_0_CAUSE
REG_S ta0, CALLFRAME_SIZ+TF_REG_TA0(k0) # $12
REG_S ta1, CALLFRAME_SIZ+TF_REG_TA1(k0) # $13
REG_S ta2, CALLFRAME_SIZ+TF_REG_TA2(k0) # $14
REG_S ta3, CALLFRAME_SIZ+TF_REG_TA3(k0) # $15
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
#ifndef NOFPU
lui v0, %hi(MIPS_SR_COP_1_BIT)
and v0, v1
or v0, MIPS_SR_INT_IE # make sure intrs are still on
#else
li v0, MIPS_SR_INT_IE # reenable intrs
#endif
xor v0, v1
mtc0 v0, MIPS_COP_0_STATUS
nop
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)
nop
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
nop # load delay
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
mfc0 v1, MIPS_COP_0_STATUS
nop # delay slot
and v0, v1, MIPS_SR_INT_IE # clear interrupt enable
xor v0, v1
mtc0 v0, MIPS_COP_0_STATUS # interrupts are disabled
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?
nop
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
mfc0 t0, MIPS_COP_0_STATUS
PTR_LA ra, MIPSX(user_return) # load delay
or t0, MIPS_SR_INT_IE # enable interrupts
j _C_LABEL(ast) # ast()
mtc0 t0, MIPS_COP_0_STATUS # enable interrupts (spl0)
.set at
END(MIPSX(user_intr))
NESTED_NOPROFILE(MIPSX(systemcall), CALLFRAME_SIZ, ra)
.set noat
.mask 0x80000000, -4
PTR_L k1, CPUVAR(CURLWP)
nop
PTR_L k0, L_PCB(k1)
nop
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)
move a0, k1 # 1st arg is curlwp
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
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)
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)
PTR_L t0, L_PROC(a0) # curlwp->l_proc (used below)
move sp, k0 # switch to kernel SP
move MIPS_CURLWP, a0 # set curlwp reg
#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 t9, P_MD_SYSCALL(t0) # t9 = syscall
#ifdef NOFPU
li t0, MIPS_SR_INT_IE
#else
lui t0, %hi(MIPS_SR_COP_1_BIT)
and t0, a1
ori t0, MIPS_SR_INT_IE # turn on IEc, enable intr.
#endif
xor t0, a1 # turns off the FPU & ints on
mtc0 t0, MIPS_COP_0_STATUS # re-enable interrupts
jalr t9
nop
INT_L v0, L_MD_ASTPENDING(MIPS_CURLWP)# any pending ast?
nop
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
.set at
END(MIPSX(systemcall))
LEAF_NOPROFILE(MIPSX(kern_tlb_miss))
.set noat
_MFC0 k0, MIPS_COP_0_BAD_VADDR # get the fault address
PTR_LA k1, _C_LABEL(pmap_kern_segtab) # get address of kernel segtab
PTR_SRL k0, SEGSHIFT - PTR_SCALESHIFT # get segtab index (part1)
and k0, (NSEGPG-1) << PTR_SCALESHIFT # get segtab index (part2)
PTR_ADDU k1, k0 # add index to segtab addr
PTR_L k1, 0(k1) # load address of PTP
_MFC0 k0, MIPS_COP_0_BAD_VADDR # get the fault address
beqz k1, _C_LABEL(MIPSX(kern_gen_exception)) # full trap processing
PTR_SRL k0, PGSHIFT - PTPSHIFT # - delay slot -
and k0, (NPTEPG-1) << PTPSHIFT # get ptp index (part2)
PTR_ADDU k1, k0 # add to PTP address
INT_L 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, MIPS1_PG_V # check for valid PTE entry
beqz k0, _C_LABEL(MIPSX(kern_gen_exception)) # PTE invalid
nop
tlbwr # write random TLB
j k1
rfe
.set at
END(MIPSX(kern_tlb_miss))
#if 0
LEAF_NOPROFILE(MIPSX(tlb_mod_exception))
.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_DIRTY_BIT # update TLB
blt k1, zero, 4f # not found!!!
mtc0 k0, MIPS_COP_0_TLB_LOW
li k1, MIPS_KSEG0_START
PTR_SUBU k0, k1
srl k0, k0, MIPS1_TLB_PHYS_PAGE_SHIFT
PTR_L k1, pmap_attributes # DANGER! DANGER!
PTR_ADDU 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(MIPSX(tlb_mod_exception))
#endif
.globl _C_LABEL(MIPSX(exceptionentry_end))
_C_LABEL(MIPSX(exceptionentry_end)):
LEAF(MIPSX(tlb_get_asid))
mfc0 v0, MIPS_COP_0_TLB_HI # Read the hi reg value
nop
and v0, MIPS1_TLB_PID # mask out only the PID
j ra
srl v0, MIPS1_TLB_PID_SHIFT # put PID in right spot
END(MIPSX(tlb_get_asid))
LEAF(MIPSX(tlb_set_asid))
sll a0, MIPS1_TLB_PID_SHIFT # put PID in right spot
and a0, MIPS1_TLB_PID
mtc0 a0, MIPS_COP_0_TLB_HI # Write the hi reg value
j ra
nop
END(MIPSX(tlb_set_asid))
LEAF(MIPSX(tlb_update_addr))
mfc0 ta0, MIPS_COP_0_STATUS # save the status register
mtc0 zero, MIPS_COP_0_STATUS # disable interrupts
nop
mfc0 ta1, MIPS_COP_0_TLB_HI # save current PID
nop
sll a1, MIPS1_TLB_PID_SHIFT
or a0, a1
mtc0 a0, MIPS_COP_0_TLB_HI # set entryhi
nop
tlbp # probe the existence
mfc0 v0, MIPS_COP_0_TLB_INDEX # see what we got
mtc0 a2, MIPS_COP_0_TLB_LOW # set new entrylo
bltz v0, 2f # index < 0 => !found
nop
tlbwi # update slot found
b 3f # return
li v0, 1 # and show success
2:
beqz a2, 3f # return
li v0, 0 # and show failure
tlbwr # put it in a new slot
li v0, 1 # show success
3:
mtc0 ta1, MIPS_COP_0_TLB_HI # restore current PID
j ra
mtc0 ta0, MIPS_COP_0_STATUS # restore interrupts
END(MIPSX(tlb_update_addr))
LEAF(MIPSX(tlb_read_entry))
mfc0 ta0, MIPS_COP_0_STATUS # Save the status register.
mtc0 zero, MIPS_COP_0_STATUS # Disable interrupts
mfc0 ta1, MIPS_COP_0_TLB_HI # Get current PID
sll a0, MIPS1_TLB_INDEX_SHIFT
mtc0 a0, MIPS_COP_0_TLB_INDEX # Set the index register
nop
tlbr # Read from the TLB
mfc0 t2, MIPS_COP_0_TLB_HI # fetch the hi entry
mfc0 t3, MIPS_COP_0_TLB_LOW # fetch the low entry
mtc0 ta1, MIPS_COP_0_TLB_HI # Restore proper PID
# (before touching memory)
mtc0 ta0, MIPS_COP_0_STATUS # Restore the status register
PTR_S t2, TLBMASK_HI(a1)
REG_S t3, TLBMASK_LO0(a1)
REG_S zero, TLBMASK_LO1(a1)
j ra
INT_S zero, TLBMASK_MASK(a1)
END(MIPSX(tlb_read_entry))
LEAF(MIPSX(tlb_write_entry))
PTR_L t2, TLBMASK_HI(a1) # fetch the hi entry
INT_L t3, TLBMASK_LO0(a1) # fetch the low entry
mfc0 ta0, MIPS_COP_0_STATUS # Save the status register.
mtc0 zero, MIPS_COP_0_STATUS # Disable interrupts
mfc0 ta1, MIPS_COP_0_TLB_HI # Get current PID
sll a0, MIPS1_TLB_INDEX_SHIFT
mtc0 a0, MIPS_COP_0_TLB_INDEX # Set the index register
nop
mtc0 t2, MIPS_COP_0_TLB_HI
mtc0 t3, MIPS_COP_0_TLB_LOW
tlbwi # Write to the TLB entry
mtc0 ta1, MIPS_COP_0_TLB_HI # restore PID
j ra
mtc0 ta0, MIPS_COP_0_STATUS # Restore the status register
END(MIPSX(tlb_write_entry))
LEAF(MIPSX(tlb_invalidate_addr))
mfc0 ta0, MIPS_COP_0_STATUS # save status register
mtc0 zero, MIPS_COP_0_STATUS # disable interrupts
mfc0 ta1, MIPS_COP_0_TLB_HI # save current PID
nop
sll a1, MIPS1_TLB_PID_SHIFT # move ASID into position
and a1, MIPS1_TLB_PID # make it off
or a0, a1 # merge with addr
mtc0 a0, MIPS_COP_0_TLB_HI # look for addr & PID
nop
tlbp # probe the entry in question
mfc0 a0, MIPS_COP_0_TLB_INDEX # see what we got
li t1, MIPS_KSEG0_START # load invalid address
bltz a0, 1f # index < 0 then skip
nop
mtc0 t1, MIPS_COP_0_TLB_HI # make entryHi invalid
mtc0 zero, MIPS_COP_0_TLB_LOW # zero out entryLo
nop
tlbwi
1:
mtc0 ta1, MIPS_COP_0_TLB_HI # restore PID
j ra
mtc0 ta0, MIPS_COP_0_STATUS # restore the status register
END(MIPSX(tlb_invalidate_addr))
LEAF(MIPSX(tlb_invalidate_asids))
mfc0 ta1, MIPS_COP_0_TLB_HI # save EntryHi
mfc0 ta0, MIPS_COP_0_STATUS # save status register
mtc0 zero, MIPS_COP_0_STATUS # disable interrupts
INT_L t2, _C_LABEL(mips_options) + MO_NUM_TLB_ENTRIES
li t1, MIPS1_TLB_FIRST_RAND_ENTRY << MIPS1_TLB_INDEX_SHIFT
li v0, MIPS_KSEG0_START # invalid address
sll t2, MIPS1_TLB_INDEX_SHIFT
1:
mtc0 t1, MIPS_COP_0_TLB_INDEX # set index
nop
tlbr # obtain an entry
mfc0 t0, MIPS_COP_0_TLB_LOW
nop
and t0, t0, MIPS1_PG_G # check to see it has G bit
bnez t0, 2f
nop
mfc0 t0, MIPS_COP_0_TLB_HI # get va and ASID
nop
and t0, MIPS1_TLB_PID # mask off ASID
srl t0, MIPS1_TLB_PID_SHIFT
sltu v1, t0, a0 # < asid_lo
bnez v1, 2f # yes, next tlb entry
nop
sltu v1, t0, a1 # < asid_hi
beqz v1, 2f # no, next tlb entry
nop
mtc0 v0, MIPS_COP_0_TLB_HI # make entryHi invalid
mtc0 zero, MIPS_COP_0_TLB_LOW # zero out entryLo
nop
tlbwi # invalidate the TLB entry
2:
addu t1, t1, 1 << MIPS1_TLB_INDEX_SHIFT # increment index
bne t1, t2, 1b
nop
mtc0 ta1, MIPS_COP_0_TLB_HI # restore entryHi
j ra # new TLBpid will be set soon
mtc0 ta0, MIPS_COP_0_STATUS # restore status register
END(MIPSX(tlb_invalidate_asids))
LEAF(MIPSX(tlb_invalidate_all))
INT_L a0, _C_LABEL(mips_options) + MO_NUM_TLB_ENTRIES
mfc0 ta0, MIPS_COP_0_STATUS # save the status register.
mtc0 zero, MIPS_COP_0_STATUS # disable interrupts
mfc0 ta1, MIPS_COP_0_TLB_HI # save current PID
li t0, MIPS_KSEG0_START # invalid address
mtc0 t0, MIPS_COP_0_TLB_HI # make entryHi invalid
mtc0 zero, MIPS_COP_0_TLB_LOW # zero out entryLo
move t0, zero
sll a0, MIPS1_TLB_INDEX_SHIFT
1:
mtc0 t0, MIPS_COP_0_TLB_INDEX # set TLBindex
addu t0, t0, 1 << MIPS1_TLB_INDEX_SHIFT # increment index
bne t0, a0, 1b
tlbwi # invalidate the entry
mtc0 ta1, MIPS_COP_0_TLB_HI # restore PID
j ra
mtc0 ta0, MIPS_COP_0_STATUS # restore status register
END(MIPSX(tlb_invalidate_all))
LEAF(MIPSX(tlb_record_asids))
mfc0 ta1, MIPS_COP_0_TLB_HI # save EntryHi
li v1, MIPS1_TLB_FIRST_RAND_ENTRY << MIPS1_TLB_INDEX_SHIFT
INT_L a3, _C_LABEL(mips_options) + MO_NUM_TLB_ENTRIES
move ta2, zero
li ta3, 1
sll a3, MIPS1_TLB_INDEX_SHIFT
mfc0 ta0, MIPS_COP_0_STATUS # save status register
mtc0 zero, MIPS_COP_0_STATUS # disable interrupts
move v0, zero # start at zero ASIDs
1:
mtc0 v1, MIPS_COP_0_TLB_INDEX # set index
nop
tlbr # obtain an entry
mfc0 t0, MIPS_COP_0_TLB_LOW
nop
and t0, MIPS1_PG_G # check to see it has G bit
bnez t0, 4f
nop
mfc0 t0, MIPS_COP_0_TLB_HI # get va and ASID
nop
and t0, MIPS1_TLB_PID
srl t0, MIPS1_TLB_PID_SHIFT # shift to low bits
bgt t0, a1, 4f # > ASID max? skip
nop
srl a2, t0, 3 + LONG_SCALESHIFT # drop low 5 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:
LONG_L t2, 0(a2) # and load it
move ta2, a2 # remember the new cell's addr
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 v1, 1 << MIPS1_TLB_INDEX_SHIFT # increment TLB entry #
bne v1, a3, 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 ta1, MIPS_COP_0_TLB_HI # restore entryHi
j ra # new TLBpid will be set soon
mtc0 ta0, MIPS_COP_0_STATUS # restore status register
END(MIPSX(tlb_record_asids))
LEAF(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):
REG_L a0, CALLFRAME_SIZ+TF_REG_SR(sp)
REG_L t0, CALLFRAME_SIZ+TF_REG_MULLO(sp)
REG_L t1, CALLFRAME_SIZ+TF_REG_MULHI(sp)
mtc0 a0, MIPS_COP_0_STATUS # this should disable interrupts
mtlo t0
mthi t1
move k1, sp
REG_L AT, TF_BASE+TF_REG_AST(sp)
REG_L k0, CALLFRAME_SIZ+TF_REG_EPC(k1)
REG_L AT, CALLFRAME_SIZ+TF_REG_AST(k1)
REG_L v0, CALLFRAME_SIZ+TF_REG_V0(k1)
REG_L v1, CALLFRAME_SIZ+TF_REG_V1(k1)
REG_L a0, CALLFRAME_SIZ+TF_REG_A0(k1)
REG_L a1, CALLFRAME_SIZ+TF_REG_A1(k1)
REG_L a2, CALLFRAME_SIZ+TF_REG_A2(k1)
REG_L a3, CALLFRAME_SIZ+TF_REG_A3(k1)
REG_L t0, CALLFRAME_SIZ+TF_REG_T0(k1)
REG_L t1, CALLFRAME_SIZ+TF_REG_T1(k1)
REG_L t2, CALLFRAME_SIZ+TF_REG_T2(k1)
REG_L t3, CALLFRAME_SIZ+TF_REG_T3(k1)
REG_L ta0, CALLFRAME_SIZ+TF_REG_TA0(k1)
REG_L ta1, CALLFRAME_SIZ+TF_REG_TA1(k1)
REG_L ta2, CALLFRAME_SIZ+TF_REG_TA2(k1)
REG_L ta3, CALLFRAME_SIZ+TF_REG_TA3(k1)
REG_L t8, CALLFRAME_SIZ+TF_REG_T8(k1)
REG_L t9, CALLFRAME_SIZ+TF_REG_T9(k1)
REG_L gp, CALLFRAME_SIZ+TF_REG_GP(k1)
REG_L ra, CALLFRAME_SIZ+TF_REG_RA(k1)
REG_L sp, CALLFRAME_SIZ+TF_REG_SP(k1)
nop
j k0
rfe
.set at
END(MIPSX(lwp_trampoline))
LEAF_NOPROFILE(MIPSX(cpu_switch_resume))
INT_L a1, L_MD_UPTE_0(a0) # a1 = upte[0]
INT_L a2, L_MD_UPTE_1(a0) # a2 = upte[1]
PTR_L s0, L_PCB(a0) # va = l->l_addr
li s2, VM_MIN_KERNEL_ADDRESS
blt s0, s2, resume
nop
mfc0 t3, MIPS_COP_0_TLB_HI # save PID
nop
mtc0 s0, MIPS_COP_0_TLB_HI # VPN = va
nop
tlbp # probe 1st VPN
mfc0 s1, MIPS_COP_0_TLB_INDEX
nop
bltz s1, entry0set
li s1, MIPS_KSEG0_START # found, then
mtc0 s1, MIPS_COP_0_TLB_HI
mtc0 zero, MIPS_COP_0_TLB_LOW
nop
tlbwi # TBIS(va)
nop
mtc0 s0, MIPS_COP_0_TLB_HI # set 1st VPN again
entry0set:
mtc0 zero, MIPS_COP_0_TLB_INDEX # TLB index #0
ori a1, a1, MIPS1_PG_G
mtc0 a1, MIPS_COP_0_TLB_LOW # 1st PFN w/ PG_G
nop
tlbwi # set TLB entry #0
addu s0, s0, PAGE_SIZE
mtc0 s0, MIPS_COP_0_TLB_HI # VPN = va+PAGE_SIZE
nop
tlbp # probe 2nd VPN
mfc0 s1, MIPS_COP_0_TLB_INDEX
nop
bltz s1, entry1set
li s1, MIPS_KSEG0_START # found, then
mtc0 s1, MIPS_COP_0_TLB_HI
mtc0 zero, MIPS_COP_0_TLB_LOW
nop
tlbwi # TBIS(va+PAGE_SIZE)
nop
mtc0 s0, MIPS_COP_0_TLB_HI # set 2nd VPN again
entry1set:
li s1, 1 << MIPS1_TLB_INDEX_SHIFT
mtc0 s1, MIPS_COP_0_TLB_INDEX # TLB index #1
ori a2, a2, MIPS1_PG_G
mtc0 a2, MIPS_COP_0_TLB_LOW # 2nd PFN w/ PG_G
nop
tlbwi # set TLB entry #1
nop
mfc0 t3, MIPS_COP_0_TLB_HI # restore PID
resume:
j ra
nop
END(MIPSX(cpu_switch_resume))
#ifndef ENABLE_MIPS_TX3900
LEAF(MIPSX(wbflush))
nop
nop
nop
nop
1: bc0f 1b
nop
j ra
nop
END(MIPSX(wbflush))
#else
LEAF_NOPROFILE(tx3900_cp0_config_read)
mfc0 v0, R3900_COP_0_CONFIG
j ra
nop
END(tx3900_cp0_config_read)
LEAF(MIPSX(wbflush))
.set push
.set mips2
sync
.set pop
j ra
nop
END(MIPSX(wbflush))
#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))
PTR_WORD _C_LABEL(nullop) # tlb_invalidate_globals
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
PTR_WORD _C_LABEL(MIPSX(kern_tlb_miss)) # 2 TLB miss (LW/I-fetch)
PTR_WORD _C_LABEL(MIPSX(kern_tlb_miss)) # 3 TLB miss (SW)
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 r3k reserved
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))# 14 r3k reserved
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))# 15 r3k reserved
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))# 16 never happens w/ MIPS1
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))# 17 never happens w/ MIPS1
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))# 18 never happens w/ MIPS1
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))# 19 never happens w/ MIPS1
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))# 20 never happens w/ MIPS1
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))# 21 never happens w/ MIPS1
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))# 22 never happens w/ MIPS1
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))# 23 never happens w/ MIPS1
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))# 24 never happens w/ MIPS1
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))# 25 never happens w/ MIPS1
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))# 26 never happens w/ MIPS1
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))# 27 never happens w/ MIPS1
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))# 28 never happens w/ MIPS1
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))# 29 never happens w/ MIPS1
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))# 30 never happens w/ MIPS1
PTR_WORD _C_LABEL(MIPSX(kern_gen_exception))# 31 never happens w/ MIPS1
#####
##### 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
PTR_WORD _C_LABEL(MIPSX(user_gen_exception))# 10
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
PTR_WORD _C_LABEL(MIPSX(user_gen_exception))# 14
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))# 20
PTR_WORD _C_LABEL(MIPSX(user_gen_exception))# 31