#include <machine/param.h>
#include <machine/asm.h>
#include <machine/cpu.h>
#include <mips64/mips_cpu.h>
#include <machine/regnum.h>
#include <machine/cpustate.h>
#ifdef CPU_LOONGSON2
#include <machine/loongson2.h>
#endif
#include "assym.h"
.set mips3
.text
k_exception_table:
PTR_VAL k_intr
PTR_VAL k_general
PTR_VAL k_tlb_inv
PTR_VAL k_tlb_inv
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
PTR_VAL k_general
u_exception_table:
PTR_VAL u_intr
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
PTR_VAL u_general
.set noreorder # Noreorder is default style!
.globl exception
exception:
.set noat
#ifdef CPU_LOONGSON2
li k0, COP_0_DIAG_BTB_CLEAR | COP_0_DIAG_RAS_DISABLE
dmtc0 k0, COP_0_DIAG
#endif
MFC0 k0, COP_0_STATUS_REG
MFC0 k1, COP_0_CAUSE_REG
and k0, k0, SR_KSU_USER
beqz k0, k_exception # Kernel mode mode
and k1, k1, CR_EXC_CODE
LA k0, u_exception_table
PTR_ADDU k0, k0, k1
PTR_ADDU k0, k0, k1 # yes, twice...
PTR_L k0, 0(k0)
j k0
nop
k_exception:
LA k0, k_exception_table
PTR_ADDU k0, k0, k1
PTR_ADDU k0, k0, k1 # yes, twice...
PTR_L k0, 0(k0)
j k0
nop
.set at
.globl e_exception
e_exception:
NNON_LEAF(k_intr, FRAMESZ(KERN_EXC_FRAME_SIZE), ra)
.set noat
.mask 0x80000000, (CF_RA_OFFS - FRAMESZ(KERN_EXC_FRAME_SIZE))
PTR_SUB k0, sp, FRAMESZ(KERN_EXC_FRAME_SIZE)
SAVE_CPU(k0, CF_RA_OFFS)
.set at
move sp, k0 # Already on kernel stack
and t0, a1, ~(SR_COP_1_BIT | SR_EXL | SR_INT_ENAB | SR_KSU_MASK)
MTC0 t0, COP_0_STATUS_REG
MTC0_SR_IE_HAZARD
PTR_S a0, 0(sp)
jal interrupt
PTR_S a3, CF_RA_OFFS + KERN_REG_SIZE(sp)
PTR_L a0, CF_RA_OFFS + KERN_REG_SIZE(sp)
.set noat
RESTORE_CPU(sp, CF_RA_OFFS)
PTR_ADDU sp, sp, FRAMESZ(KERN_EXC_FRAME_SIZE)
ERET
.set at
END(k_intr)
NNON_LEAF(u_intr, FRAMESZ(CF_SZ), ra)
.set noat
.mask 0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ))
GET_CPU_INFO(k1, k0)
PTR_L k0, CI_CURPROCPADDR(k1)
SAVE_CPU(k0, 0)
PTR_ADDU sp, k0, USPACE-FRAMESZ(CF_SZ)
.set at
and t0, a1, ~(SR_COP_1_BIT | SR_EXL | SR_INT_ENAB | SR_KSU_MASK)
MTC0 t0, COP_0_STATUS_REG
MTC0_SR_IE_HAZARD
PTR_S a0, 0(sp)
jal interrupt
PTR_S a3, CF_RA_OFFS(sp) # for debugging
GET_CPU_INFO(t1, t0)
0:
MFC0 t0, COP_0_STATUS_REG # disable interrupts for checking AST
LI v0, ~SR_INT_ENAB
and t0, t0, v0
MTC0 t0, COP_0_STATUS_REG
MTC0_SR_IE_HAZARD
PTR_L v1, CI_CURPROC(t1)
lw v0, P_ASTPENDING(v1) # any pending AST?
beq v0, zero, 4f
nop
ori t0, SR_INT_ENAB # enable interrupts for handling AST
MTC0 t0, COP_0_STATUS_REG
MTC0_SR_IE_HAZARD
PTR_L t0, CI_CURPROCPADDR(t1) # curprocpaddr
SAVE_CPU_SREG(t0, 0)
jal ast
nop
GET_CPU_INFO(t1, t0)
PTR_L t0, CI_CURPROCPADDR(t1)
RESTORE_CPU_SREG(t0, 0)
b 0b
nop
4:
ori t0, SR_EXL # restoring to user mode.
MTC0 t0, COP_0_STATUS_REG # must set exception level bit.
MTC0_SR_IE_HAZARD
move k1, t1
PTR_L k0, CI_CURPROCPADDR(k1)
RESTORE_REG(a3, CPL, k0, 0)
sw a3, CI_IPL(k1)
.set noat
RESTORE_REG(a0, PC, k0, 0)
RESTORE_CPU(k0, 0)
RESTORE_REG(sp, SP, k0, 0)
LI k0, 0
LI k1, 0
ERET
.set at
END(u_intr)
NNON_LEAF(k_general, FRAMESZ(KERN_EXC_FRAME_SIZE), ra)
.set noat
.mask 0x80000000, (CF_RA_OFFS - FRAMESZ(KERN_EXC_FRAME_SIZE))
PTR_SUB k0, sp, FRAMESZ(KERN_EXC_FRAME_SIZE)
SAVE_CPU(k0, CF_RA_OFFS)
#if defined(DDB)
SAVE_CPU_SREG(k0, CF_RA_OFFS)
#endif
.set at
move sp, k0 # Already on kernel stack
and t0, a1, ~(SR_COP_1_BIT | SR_EXL | SR_INT_ENAB | SR_KSU_MASK)
MTC0 t0, COP_0_STATUS_REG
MTC0_SR_IE_HAZARD
PTR_S a0, 0(sp)
jal trap
PTR_S a3, CF_RA_OFFS + KERN_REG_SIZE(sp)
MFC0 t0, COP_0_STATUS_REG # disable interrupts
LI t1, ~SR_INT_ENAB
and t0, t0, t1
MTC0 t0, COP_0_STATUS_REG
MTC0_SR_IE_HAZARD
.set noat
RESTORE_REG(a0, PC, sp, CF_RA_OFFS)
RESTORE_CPU(sp, CF_RA_OFFS)
PTR_ADDU sp, sp, FRAMESZ(KERN_EXC_FRAME_SIZE)
ERET
.set at
END(k_general)
NNON_LEAF(u_general, FRAMESZ(CF_SZ), ra)
.set noat
.mask 0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ))
GET_CPU_INFO(k1, k0)
PTR_L k0, CI_CURPROCPADDR(k1)
SAVE_CPU(k0, 0)
SAVE_CPU_SREG(k0, 0)
PTR_ADDU sp, k0, USPACE-FRAMESZ(CF_SZ)
.set at
and t0, a1, ~(SR_COP_1_BIT | SR_EXL | SR_INT_ENAB | SR_KSU_MASK)
MTC0 t0, COP_0_STATUS_REG
MTC0_SR_IE_HAZARD
jal trap
PTR_S a3, CF_RA_OFFS(sp) # for debugging
0:
MFC0 t0, COP_0_STATUS_REG # disable interrupts for checking AST
LI t1, ~SR_INT_ENAB
and t0, t0, t1
MTC0 t0, COP_0_STATUS_REG
MTC0_SR_IE_HAZARD
GET_CPU_INFO(t1, v0)
PTR_L v1, CI_CURPROC(t1)
lw v0, P_ASTPENDING(v1) # any pending AST?
beq v0, zero, 4f
nop
ori t0, SR_INT_ENAB # enable interrupts for handling AST
MTC0 t0, COP_0_STATUS_REG
MTC0_SR_IE_HAZARD
jal ast
nop
b 0b
nop
4:
ori t0, SR_EXL # restoring to user mode.
MTC0 t0, COP_0_STATUS_REG # must set exception level bit.
MTC0_SR_IE_HAZARD
move k1, t1
PTR_L k0, CI_CURPROCPADDR(k1)
RESTORE_REG(a3, CPL, k0, 0)
sw a3, CI_IPL(k1)
.set noat
RESTORE_CPU_SREG(k0, 0)
RESTORE_REG(a0, PC, k0, 0)
RESTORE_CPU(k0, 0)
RESTORE_REG(sp, SP, k0, 0)
LI k0, 0
LI k1, 0
ERET
.set at
END(u_general)