📄 except.s
字号:
// KCall - call kernel function
//
// KCall invokes a kernel function in a non-preemtable state by incrementing
// the kernel nest level and switching onto a kernel stack.
//
// While in a preemtible state, the thread's register save area is
// volatile. On the way in, nothing can be saved into the thread
// structure until KNest is set and on the way out anything needed from the
// thread structure must be loaded before restoring KNest.
//
// The sequence of stack switching must be handled carefully because
// whenever KNest != 1, the general exception handler assumes that the kernel
// stack is current and will not switch stacks. On the way in, we must switch
// to the kernel stack before setting KNest but not use it until after KNest
// is set. On the way out, we must reset KNest before restoring the thread's
// stack pointer.
//
// Entry (a0) = ptr to function to call
// (a1) = first function arg
// (a2) = second fucntion arg
// (a3) = third function arg
// Exit (v0) = function return value
// Uses v0, a0-a3, t0-t9
//
//------------------------------------------------------------------------------
ALTERNATE_ENTRY(KCall)
.set noreorder
move t0, a0 // (t0) = ptr to function to call
lh t1, ReschedFlag // (t1) = resched flag + nest level
move a0, a1 // ripple args down
move a1, a2
subu t1, 256
bltz t1, 50f // nested kernel call
move a2, a3
//
// Entering non-preemptible state. We must switch onto the kernel stack
// before setting KNest in case an interrupt occurs during the switch.
//
move t2, sp // (t2) = original stack pointer
la sp, KStack // switch to kernel stack
sh t1, ReschedFlag // enter non-preemtible state
sw ra, KCF_RA(sp) // thread will resume at return address
jal t0
sw t2, KCF_SP(sp) // save thread's stack pointer
//
// Function complete. Return to preemtible state after checking if a reschedule
// is needed.
//
mtc0 zero, psr
nop
nop
nop
lh t9, ReschedFlag // (t9) = resched flag + nest level
li t1, 1
beq t9, t1, 20f // reschedule needed
lw ra, KCF_RA(sp) // (ra) = return address
lw t2, dwKCRes
bne t2, zero, 20f // reschedule needed
nop
lw t2, KCF_SP(sp) // (t2) = original stack pointer
addu t9, 256
sh t9, ReschedFlag // leave non-preemtible state
lw t9, BasePSR
or t9, 1
#ifdef MIPS_HAS_FPU
lw t8, g_CurFPUOwner
lw t7, CurThdPtr
bne t7, t8, 19f
nop
la t8, dwNKCoProcEnableBits
lw t8, (t8)
or t9, t8
19:
#endif
mtc0 t9, psr
j ra
move sp, t2 // restore stack pointer
//
// ReschedFlag set, so must run the scheduler to find which thread
// to dispatch next.
//
// (v0) = KCall return value
//
20:
lw t9, BasePSR
or t9, 1
mtc0 t9, psr
lw t0, CurThdPtr // (t0) = ptr to current thread
lw t2, KCF_SP(sp) // (t2) = original stack pointer
li t3, KERNEL_MODE
sw ra, TcxFir(t0) // thread will resume at return address
sw t3, TcxPsr(t0) // & in kernel mode
S_REG t2, TcxIntSp(t0) // save stack pointer
S_REG v0, TcxIntV0(t0) // save return value
S_REG s0, TcxIntS0(t0) // save thread's permanent registers
S_REG s1, TcxIntS1(t0) // ...
S_REG s2, TcxIntS2(t0) // ...
S_REG s3, TcxIntS3(t0) // ...
S_REG s4, TcxIntS4(t0) // ...
S_REG s5, TcxIntS5(t0) // ...
S_REG s6, TcxIntS6(t0) // ...
S_REG s7, TcxIntS7(t0) // ...
S_REG s8, TcxIntS8(t0) // ...
S_REG gp, TcxIntGp(t0)
sw zero, TcxContextFlags(t0)
j resched
move s0, t0 // (s0) = ptr to current thread struct
25: j resched
move s0, zero // no current thread
// Nested KCall. Just invoke the function directly.
//
// (t0) = function address
// (a0) = 1st function argument
// (a1) = 2nd function argument
// (a2) = 3rd function argument
//
50: j t0
nop
.set reorder
.end xKCall
//------------------------------------------------------------------------------
//
// Interlocked singly-linked list functions.
//
// These functions are used internally by the kernel. They are not exported
// because they require privileged instructions on some CPUs.
//
// InterlockedPopList - remove first item from list
//
// Entry (a0) = ptr to list head
// Return (v0) = item at head of list
// If (list not emtpy) next item is now head of list
// Usea t0, t1
//
//------------------------------------------------------------------------------
LEAF_ENTRY(InterlockedPopList)
#if NO_LL
la t0, IPopRestart
.set noreorder
IPopRestart:
addiu k1, t0, 6 * 4 // (k1) = &IPopDone, indicate interlocked
// operation in progress
lw v0, (a0) // (v0) = original contents
beq v0, zero, 10f
nop
lw t1, (v0) // (t1) = next item on the list
sw t1, (a0) // update head of list
IPopDone:
10: j ra
move k1, zero // interlocked operation complete
#else
#error Unimplemented.
#endif
.end InterlockedPopList
//------------------------------------------------------------------------------
// InterlockedPushList - add an item to head of list
//
// Entry (a0) = ptr to list head
// (a1) = ptr to item
// Return (v0) = old head of list
// Uses t0, v0
//------------------------------------------------------------------------------
LEAF_ENTRY(InterlockedPushList)
#if NO_LL
la t0, IPushRestart
.set noreorder
IPushRestart:
addiu k1, t0, 4 * 4 // (k1) = &IPushDone, indicate interlocked
// operation in progress
lw v0, (a0) // (v0) = original list head
sw v0, (a1) // store linkage
sw a1, (a0) // store new list head
IPushDone:
j ra
move k1, zero // interlocked operation complete
#else
#error Unimplemented.
#endif
.end InterlockedPushList
#ifdef MIPS_HAS_FPU
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LEAF_ENTRY(GetAndClearFloatCode)
CP0_STOP_PREFETCH(mfc0, a1, psr, a2);
lui a2, 0x2000
or a1, a2
mtc0 a1, psr
nop
nop
nop
cfc1 v0, fsr
li t0, 0xfffc0fff
and t0, t0, v0
ctc1 t0, fsr
j ra
nop
.end GetCode
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LEAF_ENTRY(SaveFloatContext)
CP0_STOP_PREFETCH(mfc0, t0, psr, t1);
lui t1, 0x2000
or t0, t1
mtc0 t0, psr
nop
nop
nop
cfc1 t0, fsr
sw t0, TcxFsr(a0)
// MIPSII - use sdc1 on all even number FP registers
sdc1 f0, TcxFltF0(a0)
sdc1 f2, TcxFltF2(a0)
sdc1 f4, TcxFltF4(a0)
sdc1 f6, TcxFltF6(a0)
sdc1 f8, TcxFltF8(a0)
sdc1 f10, TcxFltF10(a0)
sdc1 f12, TcxFltF12(a0)
sdc1 f14, TcxFltF14(a0)
sdc1 f16, TcxFltF16(a0)
sdc1 f18, TcxFltF18(a0)
sdc1 f20, TcxFltF20(a0)
sdc1 f22, TcxFltF22(a0)
sdc1 f24, TcxFltF24(a0)
sdc1 f26, TcxFltF26(a0)
sdc1 f28, TcxFltF28(a0)
sdc1 f30, TcxFltF30(a0)
#ifdef MIPSIV
// MIPSIV - also save the odd number FP registers
sdc1 f1, TcxFltF1(a0)
sdc1 f3, TcxFltF3(a0)
sdc1 f5, TcxFltF5(a0)
sdc1 f7, TcxFltF7(a0)
sdc1 f9, TcxFltF9(a0)
sdc1 f11, TcxFltF11(a0)
sdc1 f13, TcxFltF13(a0)
sdc1 f15, TcxFltF15(a0)
sdc1 f17, TcxFltF17(a0)
sdc1 f19, TcxFltF19(a0)
sdc1 f21, TcxFltF21(a0)
sdc1 f23, TcxFltF23(a0)
sdc1 f25, TcxFltF25(a0)
sdc1 f27, TcxFltF27(a0)
sdc1 f29, TcxFltF29(a0)
sdc1 f31, TcxFltF31(a0)
#endif
j ra
nop
.end SaveFloatContext
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LEAF_ENTRY(RestoreFloatContext)
CP0_STOP_PREFETCH(mfc0, t0, psr, t1);
lui t1, 0x2000
or t0, t1
mtc0 t0, psr
nop
nop
nop
lw t0, TcxFsr(a0)
// For some reason unknown, bit 17 of FSR can be set, which
// causes the ctc1 instruction to except. Mask bit 17 off the FSR
// for now.
li t1, 0xfffdffff
and t0, t0, t1
ctc1 t0, fsr
// MIPSII - use sdc1 on all even number FP registers
ldc1 f0, TcxFltF0(a0)
ldc1 f2, TcxFltF2(a0)
ldc1 f4, TcxFltF4(a0)
ldc1 f6, TcxFltF6(a0)
ldc1 f8, TcxFltF8(a0)
ldc1 f10, TcxFltF10(a0)
ldc1 f12, TcxFltF12(a0)
ldc1 f14, TcxFltF14(a0)
ldc1 f16, TcxFltF16(a0)
ldc1 f18, TcxFltF18(a0)
ldc1 f20, TcxFltF20(a0)
ldc1 f22, TcxFltF22(a0)
ldc1 f24, TcxFltF24(a0)
ldc1 f26, TcxFltF26(a0)
ldc1 f28, TcxFltF28(a0)
ldc1 f30, TcxFltF30(a0)
#ifdef MIPSIV
// MIPSIV - also save the odd number FP registers
ldc1 f1, TcxFltF1(a0)
ldc1 f3, TcxFltF3(a0)
ldc1 f5, TcxFltF5(a0)
ldc1 f7, TcxFltF7(a0)
ldc1 f9, TcxFltF9(a0)
ldc1 f11, TcxFltF11(a0)
ldc1 f13, TcxFltF13(a0)
ldc1 f15, TcxFltF15(a0)
ldc1 f17, TcxFltF17(a0)
ldc1 f19, TcxFltF19(a0)
ldc1 f21, TcxFltF21(a0)
ldc1 f23, TcxFltF23(a0)
ldc1 f25, TcxFltF25(a0)
ldc1 f27, TcxFltF27(a0)
ldc1 f29, TcxFltF29(a0)
ldc1 f31, TcxFltF31(a0)
#endif
j ra
nop
.end RestoreFloatContext
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -