o) Eliminate the "stand" frame and its use. Use CALLFRAME_* everywhere.
o) Use <machine/asm.h> macros for register-width, etc., rather than doing it by hand in a few more assembly files. o) Reduce diffs between various bits of TLB refill code in exception.S and between interrupt processing code. o) Use PTR_* to operate on registers that are pointers (e.g. sp). o) Add and use a macro, CLEAR_PTE_SWBITS rather than using the mysteriously-named WIRED_SHIFT to select bits to truncate when loading PTEs. o) Don't doubly disable interrupts by moving zero to the status register, especially since that has the nasty side-effect of taking us out of 64-bit mode. o) Use CLEAR_STATUS to disable interrupts the first time. o) Keep SR_PX set as well as SR_[KSU]X when doing exception processing. This is the bit that determines whether 64-bit operations are allowed. o) Don't enable interrupts until configure_final(), like most other ports.
This commit is contained in:
parent
5f3173b517
commit
745bba1ab0
@ -42,10 +42,6 @@
|
||||
#ifndef _MACHINE_REGNUM_H_
|
||||
#define _MACHINE_REGNUM_H_
|
||||
|
||||
#define STAND_ARG_SIZE 16
|
||||
#define STAND_FRAME_SIZE 24
|
||||
#define STAND_RA_OFFSET 20
|
||||
|
||||
/* This must match the numbers
|
||||
* in pcb.h and is used by
|
||||
* swtch.S
|
||||
|
@ -102,6 +102,7 @@ static void
|
||||
configure_final(dummy)
|
||||
void *dummy;
|
||||
{
|
||||
intr_enable();
|
||||
|
||||
cninit_finish();
|
||||
|
||||
|
@ -66,37 +66,14 @@
|
||||
|
||||
#include "assym.s"
|
||||
|
||||
#if defined(ISA_MIPS32)
|
||||
#undef WITH_64BIT_CP0
|
||||
#elif defined(ISA_MIPS64)
|
||||
#define WITH_64BIT_CP0
|
||||
#elif defined(ISA_MIPS3)
|
||||
#define WITH_64BIT_CP0
|
||||
#else
|
||||
#error "Please write the code for this ISA"
|
||||
#endif
|
||||
/*
|
||||
* Clear the software-managed bits in a PTE in register pr.
|
||||
*/
|
||||
#define CLEAR_PTE_SWBITS(pr) \
|
||||
sll pr, 2 ; \
|
||||
srl pr, 2 # keep bottom 30 bits
|
||||
|
||||
#ifdef WITH_64BIT_CP0
|
||||
#define _SLL dsll
|
||||
#define _SRL dsrl
|
||||
#define _MFC0 dmfc0
|
||||
#define _MTC0 dmtc0
|
||||
#define WIRED_SHIFT 34
|
||||
#else
|
||||
#define _SLL sll
|
||||
#define _SRL srl
|
||||
#define _MFC0 mfc0
|
||||
#define _MTC0 mtc0
|
||||
#define WIRED_SHIFT 2
|
||||
#endif
|
||||
.set noreorder # Noreorder is default style!
|
||||
#if defined(ISA_MIPS32)
|
||||
.set mips32
|
||||
#elif defined(ISA_MIPS64)
|
||||
.set mips64
|
||||
#elif defined(ISA_MIPS3)
|
||||
.set mips3
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Reasonable limit
|
||||
@ -125,12 +102,12 @@
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
.set noat
|
||||
VECTOR(MipsTLBMiss, unknown)
|
||||
j _C_LABEL(MipsDoTLBMiss)
|
||||
mfc0 k0, COP_0_BAD_VADDR # get the fault address
|
||||
nop
|
||||
.set push
|
||||
.set noat
|
||||
j MipsDoTLBMiss
|
||||
MFC0 k0, COP_0_BAD_VADDR # get the fault address
|
||||
.set pop
|
||||
VECTOR_END(MipsTLBMiss)
|
||||
|
||||
/*
|
||||
@ -145,42 +122,40 @@ VECTOR_END(MipsTLBMiss)
|
||||
* let the processor trap to load the correct value after service.
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
.set push
|
||||
.set noat
|
||||
MipsDoTLBMiss:
|
||||
#k0 already has BadVA
|
||||
bltz k0, 1f #02: k0<0 -> 1f (kernel fault)
|
||||
srl k0, k0, SEGSHIFT - 2 #03: k0=seg offset (almost)
|
||||
bltz k0, 1f #02: k0<0 -> 1f (kernel fault)
|
||||
PTR_SRL k0, k0, SEGSHIFT - 2 #03: k0=seg offset (almost)
|
||||
|
||||
GET_CPU_PCPU(k1)
|
||||
lw k1, PC_SEGBASE(k1)
|
||||
beqz k1, 2f #05: make sure segbase is not null
|
||||
andi k0, k0, 0x7fc #06: k0=seg offset (mask 0x3)
|
||||
#xxx mips64 unsafe?
|
||||
addu k1, k0, k1 #07: k1=seg entry address
|
||||
lw k1, 0(k1) #08: k1=seg entry
|
||||
mfc0 k0, COP_0_BAD_VADDR #09: k0=bad address (again)
|
||||
beq k1, zero, 2f #0a: ==0 -- no page table
|
||||
srl k0, PAGE_SHIFT - 2 #0b: k0=VPN (aka va>>10)
|
||||
PTR_L k1, PC_SEGBASE(k1)
|
||||
beqz k1, 2f #05: make sure segbase is not null
|
||||
andi k0, k0, 0xffc #06: k0=seg offset (mask 0x3)
|
||||
PTR_ADDU k1, k0, k1 #07: k1=seg entry address
|
||||
|
||||
andi k0, k0, ((NPTEPG/2) - 1) << 3 #0c: k0=page tab offset
|
||||
#xxx mips64 unsafe?
|
||||
addu k1, k1, k0 #0d: k1=pte address
|
||||
lw k0, 0(k1) #0e: k0=lo0 pte
|
||||
lw k1, 4(k1) #0f: k1=lo1 pte
|
||||
_SLL k0, k0, WIRED_SHIFT #10: keep bottom 30 bits
|
||||
_SRL k0, k0, WIRED_SHIFT #11: keep bottom 30 bits
|
||||
_MTC0 k0, COP_0_TLB_LO0 #12: lo0 is loaded
|
||||
_SLL k1, k1, WIRED_SHIFT #13: keep bottom 30 bits
|
||||
_SRL k1, k1, WIRED_SHIFT #14: keep bottom 30 bits
|
||||
_MTC0 k1, COP_0_TLB_LO1 #15: lo1 is loaded
|
||||
PTR_L k1, 0(k1) #08: k1=seg entry
|
||||
MFC0 k0, COP_0_BAD_VADDR #09: k0=bad address (again)
|
||||
beq k1, zero, 2f #0a: ==0 -- no page table
|
||||
srl k0, PAGE_SHIFT - 2 #0b: k0=VPN (aka va>>10)
|
||||
andi k0, k0, 0xff8 #0c: k0=page tab offset
|
||||
PTR_ADDU k1, k1, k0 #0d: k1=pte address
|
||||
lw k0, 0(k1) #0e: k0=lo0 pte
|
||||
lw k1, 4(k1) #0f: k1=lo0 pte
|
||||
CLEAR_PTE_SWBITS(k0)
|
||||
MTC0 k0, COP_0_TLB_LO0 #12: lo0 is loaded
|
||||
COP0_SYNC
|
||||
CLEAR_PTE_SWBITS(k1)
|
||||
MTC0 k1, COP_0_TLB_LO1 #15: lo1 is loaded
|
||||
COP0_SYNC
|
||||
tlbwr #1a: write to tlb
|
||||
HAZARD_DELAY
|
||||
tlbwr #1a: write to tlb
|
||||
HAZARD_DELAY
|
||||
eret #1f: retUrn from exception
|
||||
1: j _C_LABEL(MipsTLBMissException) #20: kernel exception
|
||||
nop #21: branch delay slot
|
||||
2: j SlowFault #22: no page table present
|
||||
nop #23: branch delay slot
|
||||
|
||||
.set at
|
||||
eret #1f: retUrn from exception
|
||||
1: j MipsTLBMissException #20: kernel exception
|
||||
nop #21: branch delay slot
|
||||
2: j SlowFault #22: no page table present
|
||||
nop #23: branch delay slot
|
||||
.set pop
|
||||
|
||||
/*
|
||||
* This code is copied to the general exception vector address to
|
||||
@ -207,7 +182,7 @@ VECTOR(MipsException, unknown)
|
||||
# the cause is already
|
||||
# shifted left by 2 bits so
|
||||
# we dont have to shift.
|
||||
lw k0, 0(k0) # Get the function address
|
||||
PTR_L k0, 0(k0) # Get the function address
|
||||
nop
|
||||
j k0 # Jump to the function.
|
||||
nop
|
||||
@ -244,20 +219,9 @@ SlowFault:
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
#if defined(ISA_MIPS32)
|
||||
#define STORE sw /* 32 bit mode regsave instruction */
|
||||
#define LOAD lw /* 32 bit mode regload instruction */
|
||||
#define RSIZE 4 /* 32 bit mode register size */
|
||||
#elif defined(ISA_MIPS64)
|
||||
#define STORE sd /* 64 bit mode regsave instruction */
|
||||
#define LOAD ld /* 64 bit mode regload instruction */
|
||||
#define RSIZE 8 /* 64 bit mode register size */
|
||||
#else
|
||||
#error "Please write code for this isa."
|
||||
#endif
|
||||
|
||||
#define SAVE_REG(reg, offs, base) \
|
||||
STORE reg, STAND_ARG_SIZE + (RSIZE * offs) (base)
|
||||
REG_S reg, CALLFRAME_SIZ + (SZREG * offs) (base)
|
||||
|
||||
#ifdef TARGET_OCTEON
|
||||
#define CLEAR_STATUS \
|
||||
@ -274,7 +238,7 @@ SlowFault:
|
||||
and a0, a0, a2 ; \
|
||||
mtc0 a0, COP_0_STATUS_REG
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Save CPU and CP0 register state.
|
||||
*
|
||||
@ -317,8 +281,8 @@ SlowFault:
|
||||
mfhi v1 ;\
|
||||
mfc0 a0, COP_0_STATUS_REG ;\
|
||||
mfc0 a1, COP_0_CAUSE_REG ;\
|
||||
mfc0 a2, COP_0_BAD_VADDR ;\
|
||||
mfc0 a3, COP_0_EXC_PC ;\
|
||||
MFC0 a2, COP_0_BAD_VADDR ;\
|
||||
MFC0 a3, COP_0_EXC_PC ;\
|
||||
SAVE_REG(v0, MULLO, sp) ;\
|
||||
SAVE_REG(v1, MULHI, sp) ;\
|
||||
SAVE_REG(a0, SR, sp) ;\
|
||||
@ -332,20 +296,20 @@ SlowFault:
|
||||
PTR_ADDU v0, sp, KERN_EXC_FRAME_SIZE ;\
|
||||
SAVE_REG(v0, SP, sp) ;\
|
||||
CLEAR_STATUS ;\
|
||||
PTR_ADDU a0, sp, STAND_ARG_SIZE ;\
|
||||
PTR_ADDU a0, sp, CALLFRAME_SIZ ;\
|
||||
ITLBNOPFIX
|
||||
|
||||
#define RESTORE_REG(reg, offs, base) \
|
||||
LOAD reg, STAND_ARG_SIZE + (RSIZE * offs) (base)
|
||||
REG_L reg, CALLFRAME_SIZ + (SZREG * offs) (base)
|
||||
|
||||
#define RESTORE_CPU \
|
||||
mtc0 zero,COP_0_STATUS_REG ;\
|
||||
CLEAR_STATUS ;\
|
||||
RESTORE_REG(k0, SR, sp) ;\
|
||||
RESTORE_REG(t0, MULLO, sp) ;\
|
||||
RESTORE_REG(t1, MULHI, sp) ;\
|
||||
mtlo t0 ;\
|
||||
mthi t1 ;\
|
||||
_MTC0 v0, COP_0_EXC_PC ;\
|
||||
MTC0 v0, COP_0_EXC_PC ;\
|
||||
.set noat ;\
|
||||
RESTORE_REG(AT, AST, sp) ;\
|
||||
RESTORE_REG(v0, V0, sp) ;\
|
||||
@ -384,13 +348,13 @@ SlowFault:
|
||||
* the status register and the multiply lo and high registers.
|
||||
* In addition, we set this up for linkage conventions.
|
||||
*/
|
||||
#define KERN_REG_SIZE (NUMSAVEREGS * RSIZE)
|
||||
#define KERN_EXC_FRAME_SIZE (STAND_FRAME_SIZE + KERN_REG_SIZE + 16)
|
||||
#define KERN_REG_SIZE (NUMSAVEREGS * SZREG)
|
||||
#define KERN_EXC_FRAME_SIZE (CALLFRAME_SIZ + KERN_REG_SIZE + 16)
|
||||
|
||||
NNON_LEAF(MipsKernGenException, KERN_EXC_FRAME_SIZE, ra)
|
||||
.set noat
|
||||
subu sp, sp, KERN_EXC_FRAME_SIZE
|
||||
.mask 0x80000000, (STAND_RA_OFFSET - KERN_EXC_FRAME_SIZE)
|
||||
PTR_SUBU sp, sp, KERN_EXC_FRAME_SIZE
|
||||
.mask 0x80000000, (CALLFRAME_RA - KERN_EXC_FRAME_SIZE)
|
||||
/*
|
||||
* Save CPU state, building 'frame'.
|
||||
*/
|
||||
@ -401,7 +365,7 @@ NNON_LEAF(MipsKernGenException, KERN_EXC_FRAME_SIZE, ra)
|
||||
PTR_LA gp, _C_LABEL(_gp)
|
||||
PTR_LA k0, _C_LABEL(trap)
|
||||
jalr k0
|
||||
sw a3, STAND_RA_OFFSET + KERN_REG_SIZE(sp) # for debugging
|
||||
REG_S a3, CALLFRAME_RA + KERN_REG_SIZE(sp) # for debugging
|
||||
|
||||
/*
|
||||
* Update interrupt mask in saved status register
|
||||
@ -410,7 +374,6 @@ NNON_LEAF(MipsKernGenException, KERN_EXC_FRAME_SIZE, ra)
|
||||
* in trap handler
|
||||
*/
|
||||
mfc0 a0, COP_0_STATUS_REG
|
||||
mtc0 zero, COP_0_STATUS_REG
|
||||
and a0, a0, SR_INT_MASK
|
||||
RESTORE_REG(a1, SR, sp)
|
||||
and a1, a1, ~SR_INT_MASK
|
||||
@ -424,10 +387,10 @@ END(MipsKernGenException)
|
||||
|
||||
|
||||
#define SAVE_U_PCB_REG(reg, offs, base) \
|
||||
STORE reg, U_PCB_REGS + (RSIZE * offs) (base)
|
||||
REG_S reg, U_PCB_REGS + (SZREG * offs) (base)
|
||||
|
||||
#define RESTORE_U_PCB_REG(reg, offs, base) \
|
||||
LOAD reg, U_PCB_REGS + (RSIZE * offs) (base)
|
||||
REG_L reg, U_PCB_REGS + (SZREG * offs) (base)
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
*
|
||||
@ -443,14 +406,14 @@ END(MipsKernGenException)
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
NNON_LEAF(MipsUserGenException, STAND_FRAME_SIZE, ra)
|
||||
NNON_LEAF(MipsUserGenException, CALLFRAME_SIZ, ra)
|
||||
.set noat
|
||||
.mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
|
||||
.mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
|
||||
/*
|
||||
* Save all of the registers except for the kernel temporaries in u.u_pcb.
|
||||
*/
|
||||
GET_CPU_PCPU(k1)
|
||||
lw k1, PC_CURPCB(k1)
|
||||
PTR_L k1, PC_CURPCB(k1)
|
||||
SAVE_U_PCB_REG(AT, AST, k1)
|
||||
.set at
|
||||
SAVE_U_PCB_REG(v0, V0, k1)
|
||||
@ -476,17 +439,17 @@ NNON_LEAF(MipsUserGenException, STAND_FRAME_SIZE, ra)
|
||||
SAVE_U_PCB_REG(s2, S2, k1)
|
||||
SAVE_U_PCB_REG(s3, S3, k1)
|
||||
SAVE_U_PCB_REG(s4, S4, k1)
|
||||
mfc0 a2, COP_0_BAD_VADDR # Third arg is the fault addr
|
||||
MFC0 a2, COP_0_BAD_VADDR # Third arg is the fault addr
|
||||
SAVE_U_PCB_REG(s5, S5, k1)
|
||||
SAVE_U_PCB_REG(s6, S6, k1)
|
||||
SAVE_U_PCB_REG(s7, S7, k1)
|
||||
SAVE_U_PCB_REG(t8, T8, k1)
|
||||
mfc0 a3, COP_0_EXC_PC # Fourth arg is the pc.
|
||||
MFC0 a3, COP_0_EXC_PC # Fourth arg is the pc.
|
||||
SAVE_U_PCB_REG(t9, T9, k1)
|
||||
SAVE_U_PCB_REG(gp, GP, k1)
|
||||
SAVE_U_PCB_REG(sp, SP, k1)
|
||||
SAVE_U_PCB_REG(s8, S8, k1)
|
||||
subu sp, k1, STAND_FRAME_SIZE # switch to kernel SP
|
||||
PTR_SUBU sp, k1, CALLFRAME_SIZ # switch to kernel SP
|
||||
SAVE_U_PCB_REG(ra, RA, k1)
|
||||
SAVE_U_PCB_REG(v0, MULLO, k1)
|
||||
SAVE_U_PCB_REG(v1, MULHI, k1)
|
||||
@ -494,12 +457,12 @@ NNON_LEAF(MipsUserGenException, STAND_FRAME_SIZE, ra)
|
||||
SAVE_U_PCB_REG(a1, CAUSE, k1)
|
||||
SAVE_U_PCB_REG(a2, BADVADDR, k1)
|
||||
SAVE_U_PCB_REG(a3, PC, k1)
|
||||
sw a3, STAND_RA_OFFSET(sp) # for debugging
|
||||
REG_S a3, CALLFRAME_RA(sp) # for debugging
|
||||
PTR_LA gp, _C_LABEL(_gp) # switch to kernel GP
|
||||
# Turn off fpu and enter kernel mode
|
||||
and t0, a0, ~(SR_COP_1_BIT | SR_EXL | SR_KSU_MASK | SR_INT_ENAB)
|
||||
#ifdef TARGET_OCTEON
|
||||
or t0, t0, (MIPS_SR_KX | MIPS_SR_SX | MIPS_SR_UX)
|
||||
or t0, t0, (MIPS_SR_KX | MIPS_SR_SX | MIPS_SR_UX | MIPS32_SR_PX)
|
||||
#endif
|
||||
mtc0 t0, COP_0_STATUS_REG
|
||||
PTR_ADDU a0, k1, U_PCB_REGS
|
||||
@ -518,10 +481,7 @@ NNON_LEAF(MipsUserGenException, STAND_FRAME_SIZE, ra)
|
||||
*/
|
||||
DO_AST
|
||||
|
||||
mfc0 t0, COP_0_STATUS_REG # disable int
|
||||
and t0, t0, ~(MIPS_SR_INT_IE)
|
||||
mtc0 t0, COP_0_STATUS_REG
|
||||
ITLBNOPFIX
|
||||
CLEAR_STATUS
|
||||
|
||||
/*
|
||||
* The use of k1 for storing the PCB pointer must be done only
|
||||
@ -529,7 +489,7 @@ NNON_LEAF(MipsUserGenException, STAND_FRAME_SIZE, ra)
|
||||
* by the interrupt code.
|
||||
*/
|
||||
GET_CPU_PCPU(k1)
|
||||
lw k1, PC_CURPCB(k1)
|
||||
PTR_L k1, PC_CURPCB(k1)
|
||||
|
||||
/*
|
||||
* Update interrupt mask in saved status register
|
||||
@ -549,7 +509,7 @@ NNON_LEAF(MipsUserGenException, STAND_FRAME_SIZE, ra)
|
||||
mthi t1
|
||||
RESTORE_U_PCB_REG(a0, PC, k1)
|
||||
RESTORE_U_PCB_REG(v0, V0, k1)
|
||||
_MTC0 a0, COP_0_EXC_PC # set return address
|
||||
MTC0 a0, COP_0_EXC_PC # set return address
|
||||
RESTORE_U_PCB_REG(v1, V1, k1)
|
||||
RESTORE_U_PCB_REG(a0, A0, k1)
|
||||
RESTORE_U_PCB_REG(a1, A1, k1)
|
||||
@ -578,9 +538,6 @@ NNON_LEAF(MipsUserGenException, STAND_FRAME_SIZE, ra)
|
||||
RESTORE_U_PCB_REG(k0, SR, k1)
|
||||
RESTORE_U_PCB_REG(s8, S8, k1)
|
||||
RESTORE_U_PCB_REG(ra, RA, k1)
|
||||
#ifdef TARGET_OCTEON
|
||||
and k0, k0, ~(MIPS_SR_KX | MIPS_SR_SX | MIPS_SR_UX)
|
||||
#endif
|
||||
.set noat
|
||||
RESTORE_U_PCB_REG(AT, AST, k1)
|
||||
|
||||
@ -610,27 +567,25 @@ END(MipsUserGenException)
|
||||
|
||||
NNON_LEAF(MipsKernIntr, KERN_EXC_FRAME_SIZE, ra)
|
||||
.set noat
|
||||
subu sp, sp, KERN_EXC_FRAME_SIZE
|
||||
.mask 0x80000000, (STAND_RA_OFFSET - KERN_EXC_FRAME_SIZE)
|
||||
PTR_SUBU sp, sp, KERN_EXC_FRAME_SIZE
|
||||
.mask 0x80000000, (CALLFRAME_RA - KERN_EXC_FRAME_SIZE)
|
||||
/*
|
||||
* Save the relevant kernel registers onto the stack.
|
||||
* Save CPU state, building 'frame'.
|
||||
*/
|
||||
SAVE_CPU
|
||||
|
||||
/*
|
||||
* Call the interrupt handler.
|
||||
* Call the interrupt handler. a0 points at the saved frame.
|
||||
*/
|
||||
PTR_LA gp, _C_LABEL(_gp)
|
||||
PTR_ADDU a0, sp, STAND_ARG_SIZE
|
||||
PTR_LA k0, _C_LABEL(cpu_intr)
|
||||
jalr k0
|
||||
sw a3, STAND_RA_OFFSET + KERN_REG_SIZE(sp)
|
||||
/* Why no AST processing here? */
|
||||
REG_S a3, CALLFRAME_RA + KERN_REG_SIZE(sp) # for debugging
|
||||
|
||||
/*
|
||||
* Update interrupt mask in saved status register
|
||||
* Some of interrupts could be disabled by
|
||||
* intr filters
|
||||
* intr filters if interrupts are enabled later
|
||||
* in trap handler
|
||||
*/
|
||||
mfc0 a0, COP_0_STATUS_REG
|
||||
and a0, a0, SR_INT_MASK
|
||||
@ -638,12 +593,8 @@ NNON_LEAF(MipsKernIntr, KERN_EXC_FRAME_SIZE, ra)
|
||||
and a1, a1, ~SR_INT_MASK
|
||||
or a1, a1, a0
|
||||
SAVE_REG(a1, SR, sp)
|
||||
|
||||
/*
|
||||
* Restore registers and return from the interrupt.
|
||||
*/
|
||||
lw v0, STAND_RA_OFFSET + KERN_REG_SIZE(sp)
|
||||
RESTORE_CPU
|
||||
REG_L v0, CALLFRAME_RA + KERN_REG_SIZE(sp)
|
||||
RESTORE_CPU # v0 contains the return address.
|
||||
sync
|
||||
eret
|
||||
.set at
|
||||
@ -668,15 +619,15 @@ END(MipsKernIntr)
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
NNON_LEAF(MipsUserIntr, STAND_FRAME_SIZE, ra)
|
||||
NNON_LEAF(MipsUserIntr, CALLFRAME_SIZ, ra)
|
||||
.set noat
|
||||
.mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
|
||||
.mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
|
||||
/*
|
||||
* Save the relevant user registers into the u.u_pcb struct.
|
||||
* We don't need to save s0 - s8 because the compiler does it for us.
|
||||
*/
|
||||
GET_CPU_PCPU(k1)
|
||||
lw k1, PC_CURPCB(k1)
|
||||
PTR_L k1, PC_CURPCB(k1)
|
||||
SAVE_U_PCB_REG(AT, AST, k1)
|
||||
.set at
|
||||
SAVE_U_PCB_REG(v0, V0, k1)
|
||||
@ -715,19 +666,19 @@ NNON_LEAF(MipsUserIntr, STAND_FRAME_SIZE, ra)
|
||||
mfhi v1
|
||||
mfc0 a0, COP_0_STATUS_REG
|
||||
mfc0 a1, COP_0_CAUSE_REG
|
||||
mfc0 a3, COP_0_EXC_PC
|
||||
MFC0 a3, COP_0_EXC_PC
|
||||
SAVE_U_PCB_REG(v0, MULLO, k1)
|
||||
SAVE_U_PCB_REG(v1, MULHI, k1)
|
||||
SAVE_U_PCB_REG(a0, SR, k1)
|
||||
SAVE_U_PCB_REG(a1, CAUSE, k1)
|
||||
SAVE_U_PCB_REG(a3, PC, k1) # PC in a3, note used later!
|
||||
subu sp, k1, STAND_FRAME_SIZE # switch to kernel SP
|
||||
PTR_SUBU sp, k1, CALLFRAME_SIZ # switch to kernel SP
|
||||
PTR_LA gp, _C_LABEL(_gp) # switch to kernel GP
|
||||
|
||||
# Turn off fpu, disable interrupts, set kernel mode kernel mode, clear exception level.
|
||||
and t0, a0, ~(SR_COP_1_BIT | SR_EXL | SR_INT_ENAB | SR_KSU_MASK)
|
||||
#ifdef TARGET_OCTEON
|
||||
or t0, t0, (MIPS_SR_KX | MIPS_SR_SX | MIPS_SR_UX)
|
||||
or t0, t0, (MIPS_SR_KX | MIPS_SR_SX | MIPS_SR_UX | MIPS32_SR_PX)
|
||||
#endif
|
||||
mtc0 t0, COP_0_STATUS_REG
|
||||
ITLBNOPFIX
|
||||
@ -737,7 +688,7 @@ NNON_LEAF(MipsUserIntr, STAND_FRAME_SIZE, ra)
|
||||
*/
|
||||
PTR_LA k0, _C_LABEL(cpu_intr)
|
||||
jalr k0
|
||||
sw a3, STAND_RA_OFFSET(sp) # for debugging
|
||||
REG_S a3, CALLFRAME_RA(sp) # for debugging
|
||||
|
||||
/*
|
||||
* Enable interrupts before doing ast().
|
||||
@ -759,13 +710,10 @@ NNON_LEAF(MipsUserIntr, STAND_FRAME_SIZE, ra)
|
||||
/*
|
||||
* Restore user registers and return.
|
||||
*/
|
||||
mfc0 t0, COP_0_STATUS_REG # disable int
|
||||
and t0, t0, ~(MIPS_SR_INT_IE)
|
||||
mtc0 t0, COP_0_STATUS_REG
|
||||
ITLBNOPFIX
|
||||
CLEAR_STATUS
|
||||
|
||||
GET_CPU_PCPU(k1)
|
||||
lw k1, PC_CURPCB(k1)
|
||||
PTR_L k1, PC_CURPCB(k1)
|
||||
|
||||
/*
|
||||
* Update interrupt mask in saved status register
|
||||
@ -793,7 +741,7 @@ NNON_LEAF(MipsUserIntr, STAND_FRAME_SIZE, ra)
|
||||
RESTORE_U_PCB_REG(t2, PC, k1)
|
||||
mtlo t0
|
||||
mthi t1
|
||||
_MTC0 t2, COP_0_EXC_PC # set return address
|
||||
MTC0 t2, COP_0_EXC_PC # set return address
|
||||
RESTORE_U_PCB_REG(v0, V0, k1)
|
||||
RESTORE_U_PCB_REG(v1, V1, k1)
|
||||
RESTORE_U_PCB_REG(a0, A0, k1)
|
||||
@ -814,9 +762,6 @@ NNON_LEAF(MipsUserIntr, STAND_FRAME_SIZE, ra)
|
||||
RESTORE_U_PCB_REG(k0, SR, k1)
|
||||
RESTORE_U_PCB_REG(sp, SP, k1)
|
||||
RESTORE_U_PCB_REG(ra, RA, k1)
|
||||
#ifdef TARGET_OCTEON
|
||||
and k0, k0, ~(MIPS_SR_KX | MIPS_SR_SX | MIPS_SR_UX)
|
||||
#endif
|
||||
.set noat
|
||||
RESTORE_U_PCB_REG(AT, AST, k1)
|
||||
|
||||
@ -832,78 +777,78 @@ NLEAF(MipsTLBInvalidException)
|
||||
.set noat
|
||||
.set noreorder
|
||||
|
||||
mfc0 k0, COP_0_BAD_VADDR
|
||||
li k1, VM_MAXUSER_ADDRESS
|
||||
sltu k1, k0, k1
|
||||
bnez k1, 1f
|
||||
MFC0 k0, COP_0_BAD_VADDR
|
||||
PTR_LI k1, VM_MAXUSER_ADDRESS
|
||||
sltu k1, k0, k1
|
||||
bnez k1, 1f
|
||||
nop
|
||||
|
||||
/* badvaddr = kernel address */
|
||||
lui k1, %hi(_C_LABEL(kernel_segmap))
|
||||
b 2f
|
||||
lw k1, %lo(_C_LABEL(kernel_segmap))(k1)
|
||||
/* Kernel address. */
|
||||
lui k1, %hi(kernel_segmap) # k1=hi of segbase
|
||||
b 2f
|
||||
PTR_L k1, %lo(kernel_segmap)(k1) # k1=segment tab base
|
||||
|
||||
1:
|
||||
/* badvaddr = user address */
|
||||
1: /* User address. */
|
||||
GET_CPU_PCPU(k1)
|
||||
lw k1, PC_SEGBASE(k1)
|
||||
PTR_L k1, PC_SEGBASE(k1)
|
||||
|
||||
2:
|
||||
beqz k1, 3f /* invalid page directory pointer */
|
||||
2: /* Validate page directory pointer. */
|
||||
beqz k1, 3f
|
||||
nop
|
||||
|
||||
srl k0, SEGSHIFT - 2
|
||||
andi k0, 0xffc
|
||||
addu k1, k1, k0
|
||||
lw k1, 0(k1)
|
||||
beqz k1, 3f /* invalid page table page pointer */
|
||||
PTR_SRL k0, SEGSHIFT - 2 # k0=seg offset (almost)
|
||||
beq k1, zero, MipsKernGenException # ==0 -- no seg tab
|
||||
andi k0, k0, 0xffc # k0=seg offset (mask 0x3)
|
||||
PTR_ADDU k1, k0, k1 # k1=seg entry address
|
||||
PTR_L k1, 0(k1) # k1=seg entry
|
||||
|
||||
/* Validate page table pointer. */
|
||||
beqz k1, 3f
|
||||
nop
|
||||
|
||||
mfc0 k0, COP_0_BAD_VADDR
|
||||
srl k0, PAGE_SHIFT - 2
|
||||
andi k0, 0xffc
|
||||
addu k1, k1, k0
|
||||
MFC0 k0, COP_0_BAD_VADDR # k0=bad address (again)
|
||||
PTR_SRL k0, PAGE_SHIFT - 2 # k0=VPN
|
||||
andi k0, k0, 0xffc # k0=page tab offset
|
||||
PTR_ADDU k1, k1, k0 # k1=pte address
|
||||
lw k0, 0(k1) # k0=this PTE
|
||||
|
||||
lw k0, 0(k1)
|
||||
andi k0, PTE_V
|
||||
beqz k0, 3f /* invalid page table entry */
|
||||
/* Validate page table entry. */
|
||||
andi k0, PTE_V
|
||||
beqz k0, 3f
|
||||
nop
|
||||
|
||||
andi k0, k1, 4
|
||||
bnez k0, odd_page
|
||||
/* Check whether this is an even or odd entry. */
|
||||
andi k0, k1, 4
|
||||
bnez k0, odd_page
|
||||
nop
|
||||
|
||||
even_page:
|
||||
lw k0, 0(k1)
|
||||
_SLL k0, k0, WIRED_SHIFT
|
||||
_SRL k0, k0, WIRED_SHIFT
|
||||
_MTC0 k0, COP_0_TLB_LO0
|
||||
lw k0, 0(k1)
|
||||
lw k1, 4(k1)
|
||||
CLEAR_PTE_SWBITS(k0)
|
||||
MTC0 k0, COP_0_TLB_LO0
|
||||
COP0_SYNC
|
||||
CLEAR_PTE_SWBITS(k1)
|
||||
MTC0 k1, COP_0_TLB_LO1
|
||||
COP0_SYNC
|
||||
|
||||
lw k0, 4(k1)
|
||||
_SLL k0, k0, WIRED_SHIFT
|
||||
_SRL k0, k0, WIRED_SHIFT
|
||||
_MTC0 k0, COP_0_TLB_LO1
|
||||
|
||||
b tlb_insert_entry
|
||||
b tlb_insert_entry
|
||||
nop
|
||||
|
||||
odd_page:
|
||||
lw k0, 0(k1)
|
||||
_SLL k0, k0, WIRED_SHIFT
|
||||
_SRL k0, k0, WIRED_SHIFT
|
||||
_MTC0 k0, COP_0_TLB_LO1
|
||||
|
||||
lw k0, -4(k1)
|
||||
_SLL k0, k0, WIRED_SHIFT
|
||||
_SRL k0, k0, WIRED_SHIFT
|
||||
_MTC0 k0, COP_0_TLB_LO0
|
||||
lw k0, -4(k1)
|
||||
lw k1, 0(k1)
|
||||
CLEAR_PTE_SWBITS(k0)
|
||||
MTC0 k0, COP_0_TLB_LO0
|
||||
COP0_SYNC
|
||||
CLEAR_PTE_SWBITS(k1)
|
||||
MTC0 k1, COP_0_TLB_LO1
|
||||
COP0_SYNC
|
||||
|
||||
tlb_insert_entry:
|
||||
tlbp
|
||||
HAZARD_DELAY
|
||||
mfc0 k0, COP_0_TLB_INDEX
|
||||
HAZARD_DELAY
|
||||
bltz k0, tlb_insert_random
|
||||
mfc0 k0, COP_0_TLB_INDEX
|
||||
bltz k0, tlb_insert_random
|
||||
nop
|
||||
tlbwi
|
||||
eret
|
||||
@ -927,8 +872,8 @@ tlb_insert_random:
|
||||
* Check for kernel stack overflow.
|
||||
*/
|
||||
GET_CPU_PCPU(k1)
|
||||
lw k0, PC_CURTHREAD(k1)
|
||||
lw k0, TD_KSTACK(k0)
|
||||
PTR_L k0, PC_CURTHREAD(k1)
|
||||
PTR_L k0, TD_KSTACK(k0)
|
||||
sltu k0, k0, sp
|
||||
bnez k0, _C_LABEL(MipsKernGenException)
|
||||
nop
|
||||
@ -944,8 +889,8 @@ tlb_insert_random:
|
||||
sll k1, k1, PAGE_SHIFT + 1
|
||||
|
||||
PTR_LA k0, _C_LABEL(pcpu_space)
|
||||
addiu k0, (PAGE_SIZE * 2)
|
||||
addu k0, k0, k1
|
||||
PTR_ADDU k0, PAGE_SIZE * 2
|
||||
PTR_ADDU k0, k0, k1
|
||||
|
||||
/*
|
||||
* Stash the original value of 'sp' so we can update trapframe later.
|
||||
@ -954,12 +899,12 @@ tlb_insert_random:
|
||||
move k1, sp
|
||||
|
||||
move sp, k0
|
||||
subu sp, sp, KERN_EXC_FRAME_SIZE
|
||||
PTR_SUBU sp, sp, KERN_EXC_FRAME_SIZE
|
||||
|
||||
move k0, ra
|
||||
move ra, zero
|
||||
sw ra, CALLFRAME_RA(sp) /* stop the ddb backtrace right here */
|
||||
sw zero, CALLFRAME_SP(sp)
|
||||
REG_S ra, CALLFRAME_RA(sp) /* stop the ddb backtrace right here */
|
||||
REG_S zero, CALLFRAME_SP(sp)
|
||||
move ra, k0
|
||||
|
||||
SAVE_CPU
|
||||
@ -974,8 +919,8 @@ tlb_insert_random:
|
||||
* Squelch any more overflow checks by setting the stack base to 0.
|
||||
*/
|
||||
GET_CPU_PCPU(k1)
|
||||
lw k0, PC_CURTHREAD(k1)
|
||||
sw zero, TD_KSTACK(k0)
|
||||
PTR_L k0, PC_CURTHREAD(k1)
|
||||
PTR_S zero, TD_KSTACK(k0)
|
||||
|
||||
move a1, a0
|
||||
PANIC("kernel stack overflow - trapframe at %p")
|
||||
@ -1008,34 +953,30 @@ END(MipsTLBInvalidException)
|
||||
*/
|
||||
NLEAF(MipsTLBMissException)
|
||||
.set noat
|
||||
mfc0 k0, COP_0_BAD_VADDR # k0=bad address
|
||||
li k1, (VM_MAX_KERNEL_ADDRESS) # check fault address against
|
||||
sltu k1, k1, k0 # upper bound of kernel_segmap
|
||||
bnez k1, _C_LABEL(MipsKernGenException) # out of bound
|
||||
lui k1, %hi(_C_LABEL(kernel_segmap)) # k1=hi of segbase
|
||||
srl k0, 20 # k0=seg offset (almost)
|
||||
lw k1, %lo(_C_LABEL(kernel_segmap))(k1) # k1=segment tab base
|
||||
beq k1, zero, _C_LABEL(MipsKernGenException) # ==0 -- no seg tab
|
||||
andi k0, k0, 0xffc # k0=seg offset (mask 0x3)
|
||||
#xxx mips64 unsafe
|
||||
addu k1, k0, k1 # k1=seg entry address
|
||||
lw k1, 0(k1) # k1=seg entry
|
||||
mfc0 k0, COP_0_BAD_VADDR # k0=bad address (again)
|
||||
beq k1, zero, _C_LABEL(MipsKernGenException) # ==0 -- no page table
|
||||
srl k0, 10 # k0=VPN (aka va>>10)
|
||||
andi k0, k0, 0xff8 # k0=page tab offset
|
||||
#xxx mips64 unsafe
|
||||
addu k1, k1, k0 # k1=pte address
|
||||
lw k0, 0(k1) # k0=lo0 pte
|
||||
lw k1, 4(k1) # k1=lo1 pte
|
||||
_SLL k0, WIRED_SHIFT # chop bits [31..30]
|
||||
_SRL k0, WIRED_SHIFT # chop bits [31..30]
|
||||
_MTC0 k0, COP_0_TLB_LO0 # lo0 is loaded
|
||||
_SLL k1, WIRED_SHIFT # chop bits [31..30]
|
||||
_SRL k1, WIRED_SHIFT # chop bits [31..30]
|
||||
_MTC0 k1, COP_0_TLB_LO1 # lo1 is loaded
|
||||
|
||||
HAZARD_DELAY
|
||||
MFC0 k0, COP_0_BAD_VADDR # k0=bad address
|
||||
PTR_LI k1, VM_MAX_KERNEL_ADDRESS # check fault address against
|
||||
sltu k1, k1, k0 # upper bound of kernel_segmap
|
||||
bnez k1, MipsKernGenException # out of bound
|
||||
lui k1, %hi(kernel_segmap) # k1=hi of segbase
|
||||
PTR_SRL k0, SEGSHIFT - 2 # k0=seg offset (almost)
|
||||
PTR_L k1, %lo(kernel_segmap)(k1) # k1=segment tab base
|
||||
beq k1, zero, MipsKernGenException # ==0 -- no seg tab
|
||||
andi k0, k0, 0xffc # k0=seg offset (mask 0x3)
|
||||
PTR_ADDU k1, k0, k1 # k1=seg entry address
|
||||
PTR_L k1, 0(k1) # k1=seg entry
|
||||
MFC0 k0, COP_0_BAD_VADDR # k0=bad address (again)
|
||||
beq k1, zero, MipsKernGenException # ==0 -- no page table
|
||||
PTR_SRL k0, PAGE_SHIFT - 2 # k0=VPN
|
||||
andi k0, k0, 0xff8 # k0=page tab offset
|
||||
PTR_ADDU k1, k1, k0 # k1=pte address
|
||||
lw k0, 0(k1) # k0=lo0 pte
|
||||
lw k1, 4(k1) # k1=lo1 pte
|
||||
CLEAR_PTE_SWBITS(k0)
|
||||
MTC0 k0, COP_0_TLB_LO0 # lo0 is loaded
|
||||
COP0_SYNC
|
||||
CLEAR_PTE_SWBITS(k1)
|
||||
MTC0 k1, COP_0_TLB_LO1 # lo1 is loaded
|
||||
COP0_SYNC
|
||||
tlbwr # write to tlb
|
||||
HAZARD_DELAY
|
||||
eret # return from exception
|
||||
@ -1061,11 +1002,11 @@ END(MipsTLBMissException)
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
NON_LEAF(MipsFPTrap, STAND_FRAME_SIZE, ra)
|
||||
subu sp, sp, STAND_FRAME_SIZE
|
||||
NON_LEAF(MipsFPTrap, CALLFRAME_SIZ, ra)
|
||||
PTR_SUBU sp, sp, CALLFRAME_SIZ
|
||||
mfc0 t0, COP_0_STATUS_REG
|
||||
sw ra, STAND_RA_OFFSET(sp)
|
||||
.mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
|
||||
REG_S ra, CALLFRAME_RA(sp)
|
||||
.mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
|
||||
|
||||
or t1, t0, SR_COP_1_BIT
|
||||
mtc0 t1, COP_0_STATUS_REG
|
||||
@ -1086,10 +1027,10 @@ NON_LEAF(MipsFPTrap, STAND_FRAME_SIZE, ra)
|
||||
* The instruction is in the branch delay slot so the branch will have to
|
||||
* be emulated to get the resulting PC.
|
||||
*/
|
||||
sw a2, STAND_FRAME_SIZE + 8(sp)
|
||||
PTR_S a2, CALLFRAME_SIZ + 8(sp)
|
||||
GET_CPU_PCPU(a0)
|
||||
#mips64 unsafe?
|
||||
lw a0, PC_CURPCB(a0)
|
||||
PTR_L a0, PC_CURPCB(a0)
|
||||
PTR_ADDU a0, a0, U_PCB_REGS # first arg is ptr to CPU registers
|
||||
move a1, a2 # second arg is instruction PC
|
||||
move a2, t1 # third arg is floating point CSR
|
||||
@ -1100,7 +1041,7 @@ NON_LEAF(MipsFPTrap, STAND_FRAME_SIZE, ra)
|
||||
* Now load the floating-point instruction in the branch delay slot
|
||||
* to be emulated.
|
||||
*/
|
||||
lw a2, STAND_FRAME_SIZE + 8(sp) # restore EXC pc
|
||||
PTR_L a2, CALLFRAME_SIZ + 8(sp) # restore EXC pc
|
||||
b 2f
|
||||
lw a0, 4(a2) # a0 = coproc instruction
|
||||
/*
|
||||
@ -1110,10 +1051,10 @@ NON_LEAF(MipsFPTrap, STAND_FRAME_SIZE, ra)
|
||||
1:
|
||||
lw a0, 0(a2) # a0 = coproc instruction
|
||||
#xxx mips64 unsafe?
|
||||
addu v0, a2, 4 # v0 = next pc
|
||||
PTR_ADDU v0, a2, 4 # v0 = next pc
|
||||
2:
|
||||
GET_CPU_PCPU(t2)
|
||||
lw t2, PC_CURPCB(t2)
|
||||
PTR_L t2, PC_CURPCB(t2)
|
||||
SAVE_U_PCB_REG(v0, PC, t2) # save new pc
|
||||
/*
|
||||
* Check to see if the instruction to be emulated is a floating-point
|
||||
@ -1127,7 +1068,7 @@ NON_LEAF(MipsFPTrap, STAND_FRAME_SIZE, ra)
|
||||
*/
|
||||
3:
|
||||
GET_CPU_PCPU(a0)
|
||||
lw a0, PC_CURTHREAD(a0) # get current thread
|
||||
PTR_L a0, PC_CURTHREAD(a0) # get current thread
|
||||
cfc1 a2, FPC_CSR # code = FP execptions
|
||||
ctc1 zero, FPC_CSR # Clear exceptions
|
||||
PTR_LA t3, _C_LABEL(trapsignal)
|
||||
@ -1149,12 +1090,12 @@ NON_LEAF(MipsFPTrap, STAND_FRAME_SIZE, ra)
|
||||
*/
|
||||
FPReturn:
|
||||
mfc0 t0, COP_0_STATUS_REG
|
||||
lw ra, STAND_RA_OFFSET(sp)
|
||||
PTR_L ra, CALLFRAME_RA(sp)
|
||||
and t0, t0, ~SR_COP_1_BIT
|
||||
mtc0 t0, COP_0_STATUS_REG
|
||||
ITLBNOPFIX
|
||||
j ra
|
||||
PTR_ADDU sp, sp, STAND_FRAME_SIZE
|
||||
PTR_ADDU sp, sp, CALLFRAME_SIZ
|
||||
END(MipsFPTrap)
|
||||
|
||||
/*
|
||||
@ -1182,7 +1123,7 @@ VECTOR(MipsCache, unknown)
|
||||
PTR_LA k0, _C_LABEL(MipsCacheException)
|
||||
li k1, MIPS_PHYS_MASK
|
||||
and k0, k1
|
||||
li k1, MIPS_KSEG1_START
|
||||
PTR_LI k1, MIPS_KSEG1_START
|
||||
or k0, k1
|
||||
j k0
|
||||
nop
|
||||
@ -1200,16 +1141,16 @@ NESTED_NOPROFILE(MipsCacheException, KERN_EXC_FRAME_SIZE, ra)
|
||||
.mask 0x80000000, -4
|
||||
PTR_LA k0, _C_LABEL(panic) # return to panic
|
||||
PTR_LA a0, 9f # panicstr
|
||||
_MFC0 a1, COP_0_ERROR_PC
|
||||
MFC0 a1, COP_0_ERROR_PC
|
||||
mfc0 a2, COP_0_CACHE_ERR # 3rd arg cache error
|
||||
|
||||
_MTC0 k0, COP_0_ERROR_PC # set return address
|
||||
MTC0 k0, COP_0_ERROR_PC # set return address
|
||||
|
||||
mfc0 k0, COP_0_STATUS_REG # restore status
|
||||
li k1, SR_DIAG_DE # ignore further errors
|
||||
or k0, k1
|
||||
mtc0 k0, COP_0_STATUS_REG # restore status
|
||||
HAZARD_DELAY
|
||||
COP0_SYNC
|
||||
|
||||
eret
|
||||
|
||||
|
@ -94,9 +94,9 @@
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
NON_LEAF(MipsEmulateFP, STAND_FRAME_SIZE, ra)
|
||||
subu sp, sp, STAND_FRAME_SIZE
|
||||
sw ra, STAND_RA_OFFSET(sp)
|
||||
NON_LEAF(MipsEmulateFP, CALLFRAME_SIZ, ra)
|
||||
subu sp, sp, CALLFRAME_SIZ
|
||||
sw ra, CALLFRAME_RA(sp)
|
||||
/*
|
||||
* Decode the FMT field (bits 24-21) and FUNCTION field (bits 5-0).
|
||||
*/
|
||||
@ -2247,8 +2247,8 @@ result_fs_d: # result is FS
|
||||
jal set_fd_d # save result (in t0,t1,t2,t3)
|
||||
|
||||
done:
|
||||
lw ra, STAND_RA_OFFSET(sp)
|
||||
addu sp, sp, STAND_FRAME_SIZE
|
||||
lw ra, CALLFRAME_RA(sp)
|
||||
addu sp, sp, CALLFRAME_SIZ
|
||||
j ra
|
||||
END(MipsEmulateFP)
|
||||
|
||||
|
@ -369,7 +369,6 @@ mips_vector_init(void)
|
||||
* when handler is installed for it
|
||||
*/
|
||||
set_intr_mask(ALL_INT_MASK);
|
||||
intr_enable();
|
||||
|
||||
/* Clear BEV in SR so we start handling our own exceptions */
|
||||
mips_wr_status(mips_rd_status() & ~SR_BOOT_EXC_VEC);
|
||||
|
@ -65,53 +65,7 @@
|
||||
|
||||
#include "assym.s"
|
||||
|
||||
#if defined(ISA_MIPS32)
|
||||
#undef WITH_64BIT_CP0
|
||||
#elif defined(ISA_MIPS64)
|
||||
#define WITH_64BIT_CP0
|
||||
#elif defined(ISA_MIPS3)
|
||||
#define WITH_64BIT_CP0
|
||||
#else
|
||||
#error "Please write the code for this ISA"
|
||||
#endif
|
||||
|
||||
#ifdef WITH_64BIT_CP0
|
||||
#define _SLL dsll
|
||||
#define _SRL dsrl
|
||||
#define _MFC0 dmfc0
|
||||
#define _MTC0 dmtc0
|
||||
#define WIRED_SHIFT 34
|
||||
#else
|
||||
#define _SLL sll
|
||||
#define _SRL srl
|
||||
#define _MFC0 mfc0
|
||||
#define _MTC0 mtc0
|
||||
#define WIRED_SHIFT 2
|
||||
#endif
|
||||
.set noreorder # Noreorder is default style!
|
||||
#if defined(ISA_MIPS32)
|
||||
.set mips32
|
||||
#elif defined(ISA_MIPS64)
|
||||
.set mips64
|
||||
#elif defined(ISA_MIPS3)
|
||||
.set mips3
|
||||
#endif
|
||||
|
||||
#if defined(ISA_MIPS32)
|
||||
#define STORE sw /* 32 bit mode regsave instruction */
|
||||
#define LOAD lw /* 32 bit mode regload instruction */
|
||||
#define RSIZE 4 /* 32 bit mode register size */
|
||||
#define STORE_FP swc1 /* 32 bit mode fp regsave instruction */
|
||||
#define LOAD_FP lwc1 /* 32 bit mode fp regload instruction */
|
||||
#define FP_RSIZE 4 /* 32 bit mode fp register size */
|
||||
#else
|
||||
#define STORE sd /* 64 bit mode regsave instruction */
|
||||
#define LOAD ld /* 64 bit mode regload instruction */
|
||||
#define RSIZE 8 /* 64 bit mode register size */
|
||||
#define STORE_FP sdc1 /* 64 bit mode fp regsave instruction */
|
||||
#define LOAD_FP ldc1 /* 64 bit mode fp regload instruction */
|
||||
#define FP_RSIZE 8 /* 64 bit mode fp register size */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* FREEBSD_DEVELOPERS_FIXME
|
||||
@ -125,28 +79,28 @@
|
||||
#endif
|
||||
|
||||
#define SAVE_U_PCB_REG(reg, offs, base) \
|
||||
STORE reg, U_PCB_REGS + (RSIZE * offs) (base)
|
||||
REG_S reg, U_PCB_REGS + (SZREG * offs) (base)
|
||||
|
||||
#define RESTORE_U_PCB_REG(reg, offs, base) \
|
||||
LOAD reg, U_PCB_REGS + (RSIZE * offs) (base)
|
||||
REG_L reg, U_PCB_REGS + (SZREG * offs) (base)
|
||||
|
||||
#define SAVE_U_PCB_FPREG(reg, offs, base) \
|
||||
STORE_FP reg, U_PCB_FPREGS + (FP_RSIZE * offs) (base)
|
||||
FP_S reg, U_PCB_FPREGS + (SZFPREG * offs) (base)
|
||||
|
||||
#define RESTORE_U_PCB_FPREG(reg, offs, base) \
|
||||
LOAD_FP reg, U_PCB_FPREGS + (FP_RSIZE * offs) (base)
|
||||
FP_L reg, U_PCB_FPREGS + (SZFPREG * offs) (base)
|
||||
|
||||
#define SAVE_U_PCB_FPSR(reg, offs, base) \
|
||||
STORE reg, U_PCB_FPREGS + (FP_RSIZE * offs) (base)
|
||||
REG_S reg, U_PCB_FPREGS + (SZFPREG * offs) (base)
|
||||
|
||||
#define RESTORE_U_PCB_FPSR(reg, offs, base) \
|
||||
LOAD reg, U_PCB_FPREGS + (FP_RSIZE * offs) (base)
|
||||
REG_L reg, U_PCB_FPREGS + (SZFPREG * offs) (base)
|
||||
|
||||
#define SAVE_U_PCB_CONTEXT(reg, offs, base) \
|
||||
STORE reg, U_PCB_CONTEXT + (RSIZE * offs) (base)
|
||||
REG_S reg, U_PCB_CONTEXT + (SZREG * offs) (base)
|
||||
|
||||
#define RESTORE_U_PCB_CONTEXT(reg, offs, base) \
|
||||
LOAD reg, U_PCB_CONTEXT + (RSIZE * offs) (base)
|
||||
REG_L reg, U_PCB_CONTEXT + (SZREG * offs) (base)
|
||||
|
||||
#define ITLBNOPFIX nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;
|
||||
|
||||
@ -172,7 +126,7 @@ LEAF(fork_trampoline)
|
||||
*/
|
||||
.set noat
|
||||
GET_CPU_PCPU(k1)
|
||||
lw k1, PC_CURPCB(k1)
|
||||
PTR_L k1, PC_CURPCB(k1)
|
||||
|
||||
RESTORE_U_PCB_REG(t0, MULLO, k1)
|
||||
RESTORE_U_PCB_REG(t1, MULHI, k1)
|
||||
@ -181,7 +135,7 @@ LEAF(fork_trampoline)
|
||||
RESTORE_U_PCB_REG(a0, PC, k1)
|
||||
RESTORE_U_PCB_REG(AT, AST, k1)
|
||||
RESTORE_U_PCB_REG(v0, V0, k1)
|
||||
_MTC0 a0, COP_0_EXC_PC # set return address
|
||||
MTC0 a0, COP_0_EXC_PC # set return address
|
||||
|
||||
RESTORE_U_PCB_REG(v1, V1, k1)
|
||||
RESTORE_U_PCB_REG(a0, A0, k1)
|
||||
@ -265,7 +219,7 @@ END(savectx)
|
||||
|
||||
KSEG0TEXT_START;
|
||||
|
||||
NON_LEAF(mips_cpu_throw, STAND_FRAME_SIZE, ra)
|
||||
NON_LEAF(mips_cpu_throw, CALLFRAME_SIZ, ra)
|
||||
mfc0 t0, COP_0_STATUS_REG # t0 = saved status register
|
||||
nop
|
||||
nop
|
||||
@ -285,7 +239,7 @@ END(mips_cpu_throw)
|
||||
* a2 - mtx
|
||||
* Find the highest priority process and resume it.
|
||||
*/
|
||||
NON_LEAF(cpu_switch, STAND_FRAME_SIZE, ra)
|
||||
NON_LEAF(cpu_switch, CALLFRAME_SIZ, ra)
|
||||
mfc0 t0, COP_0_STATUS_REG # t0 = saved status register
|
||||
nop
|
||||
nop
|
||||
@ -294,11 +248,11 @@ NON_LEAF(cpu_switch, STAND_FRAME_SIZE, ra)
|
||||
ITLBNOPFIX
|
||||
beqz a0, mips_sw1
|
||||
move a3, a0
|
||||
lw a0, TD_PCB(a0) # load PCB addr of curproc
|
||||
PTR_L a0, TD_PCB(a0) # load PCB addr of curproc
|
||||
SAVE_U_PCB_CONTEXT(sp, PREG_SP, a0) # save old sp
|
||||
subu sp, sp, STAND_FRAME_SIZE
|
||||
sw ra, STAND_RA_OFFSET(sp)
|
||||
.mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
|
||||
PTR_SUBU sp, sp, CALLFRAME_SIZ
|
||||
REG_S ra, CALLFRAME_RA(sp)
|
||||
.mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
|
||||
SAVE_U_PCB_CONTEXT(s0, PREG_S0, a0) # do a 'savectx()'
|
||||
SAVE_U_PCB_CONTEXT(s1, PREG_S1, a0)
|
||||
SAVE_U_PCB_CONTEXT(s2, PREG_S2, a0)
|
||||
@ -321,13 +275,13 @@ getpc:
|
||||
* to be saved with the other registers do so here.
|
||||
*/
|
||||
|
||||
sw a2, TD_LOCK(a3) # Switchout td_lock
|
||||
PTR_S a2, TD_LOCK(a3) # Switchout td_lock
|
||||
|
||||
mips_sw1:
|
||||
#if defined(SMP) && defined(SCHED_ULE)
|
||||
PTR_LA t0, _C_LABEL(blocked_lock)
|
||||
blocked_loop:
|
||||
lw t1, TD_LOCK(a1)
|
||||
PTR_L t1, TD_LOCK(a1)
|
||||
beq t0, t1, blocked_loop
|
||||
nop
|
||||
#endif
|
||||
@ -336,20 +290,16 @@ blocked_loop:
|
||||
* Switch to new context.
|
||||
*/
|
||||
GET_CPU_PCPU(a3)
|
||||
sw a1, PC_CURTHREAD(a3)
|
||||
lw a2, TD_PCB(a1)
|
||||
sw a2, PC_CURPCB(a3)
|
||||
lw v0, TD_KSTACK(a1)
|
||||
li s0, MIPS_KSEG2_START # If Uarea addr is below kseg2,
|
||||
PTR_S a1, PC_CURTHREAD(a3)
|
||||
PTR_L a2, TD_PCB(a1)
|
||||
PTR_S a2, PC_CURPCB(a3)
|
||||
PTR_L v0, TD_KSTACK(a1)
|
||||
#if !defined(__mips_n64)
|
||||
PTR_LI s0, MIPS_KSEG2_START # If Uarea addr is below kseg2,
|
||||
bltu v0, s0, sw2 # no need to insert in TLB.
|
||||
lw a1, TD_UPTE+0(s7) # t0 = first u. pte
|
||||
lw a2, TD_UPTE+4(s7) # t1 = 2nd u. pte
|
||||
and s0, v0, PTE_ODDPG
|
||||
beq s0, zero, entry0
|
||||
nop
|
||||
|
||||
PANIC_KSEG0("USPACE sat on odd page boundary", t1)
|
||||
|
||||
#endif
|
||||
lw a1, TD_UPTE + 0(s7) # a1 = u. pte #0
|
||||
lw a2, TD_UPTE + 4(s7) # a2 = u. pte #1
|
||||
/*
|
||||
* Wiredown the USPACE of newproc in TLB entry#0. Check whether target
|
||||
* USPACE is already in another place of TLB before that, and if so
|
||||
@ -357,31 +307,32 @@ blocked_loop:
|
||||
* NOTE: This is hard coded to UPAGES == 2.
|
||||
* Also, there should be no TLB faults at this point.
|
||||
*/
|
||||
entry0:
|
||||
mtc0 v0, COP_0_TLB_HI # VPN = va
|
||||
MTC0 v0, COP_0_TLB_HI # VPN = va
|
||||
HAZARD_DELAY
|
||||
tlbp # probe VPN
|
||||
HAZARD_DELAY
|
||||
mfc0 s0, COP_0_TLB_INDEX
|
||||
nop
|
||||
pgm:
|
||||
HAZARD_DELAY
|
||||
|
||||
PTR_LI t1, MIPS_KSEG0_START # invalidate tlb entry
|
||||
bltz s0, entry0set
|
||||
li t1, MIPS_KSEG0_START # invalidate tlb entry
|
||||
nop
|
||||
sll s0, PAGE_SHIFT + 1
|
||||
addu t1, s0
|
||||
mtc0 t1, COP_0_TLB_HI
|
||||
MTC0 t1, COP_0_TLB_HI
|
||||
mtc0 zero, COP_0_TLB_LO0
|
||||
mtc0 zero, COP_0_TLB_LO1
|
||||
HAZARD_DELAY
|
||||
tlbwi
|
||||
HAZARD_DELAY
|
||||
mtc0 v0, COP_0_TLB_HI # set VPN again
|
||||
MTC0 v0, COP_0_TLB_HI # set VPN again
|
||||
|
||||
entry0set:
|
||||
/* SMP!! - Works only for unshared TLB case - i.e. no v-cpus */
|
||||
mtc0 zero, COP_0_TLB_INDEX # TLB entry #0
|
||||
# or a1, PG_G
|
||||
HAZARD_DELAY
|
||||
mtc0 a1, COP_0_TLB_LO0 # upte[0]
|
||||
# or a2, PG_G
|
||||
HAZARD_DELAY
|
||||
mtc0 a2, COP_0_TLB_LO1 # upte[1]
|
||||
HAZARD_DELAY
|
||||
tlbwi # set TLB entry #0
|
||||
@ -396,7 +347,7 @@ sw2:
|
||||
/*
|
||||
* Restore registers and return.
|
||||
*/
|
||||
lw a0, TD_PCB(s7)
|
||||
PTR_L a0, TD_PCB(s7)
|
||||
RESTORE_U_PCB_CONTEXT(gp, PREG_GP, a0)
|
||||
RESTORE_U_PCB_CONTEXT(v0, PREG_SR, a0) # restore kernel context
|
||||
RESTORE_U_PCB_CONTEXT(ra, PREG_RA, a0)
|
||||
@ -457,7 +408,7 @@ LEAF(MipsSwitchFPState)
|
||||
* First read out the status register to make sure that all FP operations
|
||||
* have completed.
|
||||
*/
|
||||
lw a0, TD_PCB(a0) # get pointer to pcb for proc
|
||||
PTR_L a0, TD_PCB(a0) # get pointer to pcb for proc
|
||||
cfc1 t0, FPC_CSR # stall til FP done
|
||||
cfc1 t0, FPC_CSR # now get status
|
||||
li t3, ~SR_COP_1_BIT
|
||||
@ -567,13 +518,13 @@ END(MipsSwitchFPState)
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
LEAF(MipsSaveCurFPState)
|
||||
lw a0, TD_PCB(a0) # get pointer to pcb for thread
|
||||
PTR_L a0, TD_PCB(a0) # get pointer to pcb for thread
|
||||
mfc0 t1, COP_0_STATUS_REG # Disable interrupts and
|
||||
li t0, SR_COP_1_BIT # enable the coprocessor
|
||||
mtc0 t0, COP_0_STATUS_REG
|
||||
ITLBNOPFIX
|
||||
GET_CPU_PCPU(a1)
|
||||
sw zero, PC_FPCURTHREAD(a1) # indicate state has been saved
|
||||
PTR_S zero, PC_FPCURTHREAD(a1) # indicate state has been saved
|
||||
/*
|
||||
* First read out the status register to make sure that all FP operations
|
||||
* have completed.
|
||||
|
@ -144,7 +144,7 @@ cpu_fork(register struct thread *td1,register struct proc *p2,
|
||||
pcb2->pcb_context[PCB_REG_RA] = (register_t)fork_trampoline;
|
||||
/* Make sp 64-bit aligned */
|
||||
pcb2->pcb_context[PCB_REG_SP] = (register_t)(((vm_offset_t)td2->td_pcb &
|
||||
~(sizeof(__int64_t) - 1)) - STAND_FRAME_SIZE);
|
||||
~(sizeof(__int64_t) - 1)) - CALLFRAME_SIZ);
|
||||
pcb2->pcb_context[PCB_REG_S0] = (register_t)fork_return;
|
||||
pcb2->pcb_context[PCB_REG_S1] = (register_t)td2;
|
||||
pcb2->pcb_context[PCB_REG_S2] = (register_t)td2->td_frame;
|
||||
@ -339,7 +339,7 @@ cpu_set_upcall(struct thread *td, struct thread *td0)
|
||||
pcb2->pcb_context[PCB_REG_RA] = (register_t)fork_trampoline;
|
||||
/* Make sp 64-bit aligned */
|
||||
pcb2->pcb_context[PCB_REG_SP] = (register_t)(((vm_offset_t)td->td_pcb &
|
||||
~(sizeof(__int64_t) - 1)) - STAND_FRAME_SIZE);
|
||||
~(sizeof(__int64_t) - 1)) - CALLFRAME_SIZ);
|
||||
pcb2->pcb_context[PCB_REG_S0] = (register_t)fork_return;
|
||||
pcb2->pcb_context[PCB_REG_S1] = (register_t)td;
|
||||
pcb2->pcb_context[PCB_REG_S2] = (register_t)td->td_frame;
|
||||
@ -386,7 +386,7 @@ cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
|
||||
* in ``See MIPS Run'' by D. Sweetman, p. 269
|
||||
* align stack */
|
||||
sp = ((register_t)(stack->ss_sp + stack->ss_size) & ~0x7) -
|
||||
STAND_FRAME_SIZE;
|
||||
CALLFRAME_SIZ;
|
||||
|
||||
/*
|
||||
* Set the trap frame to point at the beginning of the uts
|
||||
|
Loading…
x
Reference in New Issue
Block a user