📄 except.s
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
//------------------------------------------------------------------------------
// TITLE("Interrupt and Exception Processing")
//------------------------------------------------------------------------------
//
//
// Module Name:
//
// except.s
//
// Abstract:
//
// This module implements the code necessary to field and process MIPS
// interrupt and exception conditions.
//
// WARNING: This module executes in KSEG0 and, in general, cannot
// tolerate a TLB Miss. Registers k0 and k1 are used during initial
// interrupt and exception processing, and therefore, extreme care must
// be exercised when modifying this module.
//
//------------------------------------------------------------------------------
#include "ksmips.h"
#include "nkintr.h"
#include "kpage.h"
#include "mem_mips.h"
#include "psyscall.h"
#define VR5432_BP_BUG 1
// must match the value in kernel.h
#define SECURESTK_RESERVE (32 + 4*REG_SIZE) // SIZE_PRETLS + 4 * REG_SIZE
#define MAX_PSL_ARGS (14 * REG_SIZE) // 14 max PSL args
#define CALLEE_SAVED_REGS (10 * REG_SIZE) // (s0 - s8, gp)
#define PERFORMCALLBACK -113 // MUST be -PerformCallback Win32Methods in kwin32.c
// 113 == -(APISet 0, method 113)
#define RAISEEXCEPTION -114 // MUST be -RaiseException Win32Methods in kwin32.c
#define KERN_TRUST_FULL 2
#if defined(VR5432_BP_BUG)
//
// An external routine calling into this code is at risk for
// this bug if there is a conditional branch close to the call
// and interrupts are enabled at the time of the branch
//
// MAKE SURE THE LABEL 199 IS NOT USED IN THIS FILE
#define CP0_STOP_PREFETCH(inst, parm1, parm2, tempreg) \
la tempreg, 199f; \
j tempreg; \
nop; \
199: \
inst parm1, parm2;
#else
#define CP0_STOP_PREFETCH(inst, parm1, parm2, tempreg) \
inst parm1, parm2;
#endif
.text
.globl MD_CBRtn
.globl PtrCurMSec
PtrCurMSec:
.word AddrCurMSec
PosTable:
.byte 0,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
.byte 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
.byte 7,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
.byte 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
.byte 8,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
.byte 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
.byte 7,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
.byte 6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LEAF_ENTRY (GetHighPos)
.set noreorder
addi t0, zero, -1
andi t1, a0, 0xff
lb v0, PosTable(t1)
bne zero, v0, res
srl a0, a0, 8
addi t0, t0, 8
andi t1, a0, 0xff
lb v0, PosTable(t1)
bne zero, v0, res
srl a0, a0, 8
addi t0, t0, 8
andi t1, a0, 0xff
lb v0, PosTable(t1)
bne zero, v0, res
srl a0, a0, 8
addi t0, t0, 8
andi t1, a0, 0xff
lb v0, PosTable(t1)
bne zero, v0, res
nop
addi v0, v0, 9
res:
j ra
add v0, v0, t0
.end GetHighPos
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LEAF_ENTRY(INTERRUPTS_ON)
.set noreorder
lw t0, BasePSR
nop
or t0, 1
j ra
mtc0 t0, psr
.end INTERRUPTS_ON
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LEAF_ENTRY(INTERRUPTS_OFF)
.set noreorder
CP0_STOP_PREFETCH(mtc0, zero, psr, t0);
nop // 3 cycle delay
j ra
nop
.end INTERRUPTS_OFF
//------------------------------------------------------------------------------
// Enable interrupts if input parameter is non-zero (previously had interrupts on)
//------------------------------------------------------------------------------
LEAF_ENTRY(INTERRUPTS_ENABLE)
.set noreorder
CP0_STOP_PREFETCH(mfc0, v0, psr, t0);
sltu a0, zero, a0 // (a0) = 1 if non-zero, 0 otherwise
move t0, v0 // (t0) = current PSR
// clear IE bit of t0
srl t0, 1
sll t0, 1
// update IE bit of t0 based on the argument
add t0, t0, a0
// update PSR
mtc0 t0, psr
// return
j ra
and v0, v0, 1 // (v0) = 1 if interrupt was enabled, 0 otherwise. (delay slot)
.end INTERRUPTS_ENABLE
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
NESTED_ENTRY(NKCallIntChain, 0, zero)
subu sp, sp, 5*REG_SIZE // reserve space on stack, 4 extra register save area per C calling convention
S_REG ra, 4*REG_SIZE(sp) // save return address
PROLOGUE_END
jal NKCallIntChainWrapped
nop
L_REG ra, 4*REG_SIZE(sp) // restore return address
j ra // return
addu sp, sp, 5*REG_SIZE // (delay slot) reclaim stack
.end NKCallIntChain
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LEAF_ENTRY (NKIsSysIntrValid)
.set noreorder
.set noat
subu a0, SYSINTR_DEVICES // (a0) = idInt - SYSINTR_DEVICE?
bltz a0, NKIRet // invalid idInt if (a0) < 0
move v0, zero // (delay slot) return 0
sltu v0, a0, SYSINTR_MAX_DEVICES // v0 = (a0 < SYSINTR_MAX_DEVICES)
beq v0, zero, NKIRet // out of range, return 0
sll a0, a0, 2 // (delay slot) a0 *= 4
// valid range, return IntrEvents[idInt-SYSINTR_DEVICES]
lw v0, IntrEvents(a0)
NKIRet:
j ra
nop
.set at
.set reorder
.end NKIsSysIntrValid
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LEAF_ENTRY(SetCPUHardwareWatch)
.set noreorder
lui t0, 0x1fff
ori t0, t0, 0xfff8
and a0, a0, t0
or a0, a0, a1
CP0_STOP_PREFETCH(mtc0, a0, $18, t0);
nop
nop
mtc0 zero, $19
nop
nop
j ra
nop
.end SetCPUHardwareWatch
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LEAF_ENTRY(SetCPUASID)
.set noreorder
//----- CeLogThreadMigrate -----
//
// NOTE : To make things relatively consistent, I'm going to make
// the registers v0, t0-t9, a0, a1 available for use. On entry to
// CeLogThreadMigrateMIPS, a0 will contain the handle of the new process.
//
// I'm assuming that at this point the only registers of these that
// I need to preserve are A0 and RA.
//
lw t0, CeLogStatus // (t0) = KInfoTable[KINX_CELOGSTATUS]
lui t1, 0x2000 // (t1) = CELOGSTATUS_ENABLED_GENERAL
and t0, t0, t1 // (t0) = IsCeLogStatus(CELOGSTATUS_ENABLED_GENERAL)
beq zero, t0, celog10 // if false then skip CeLog call
nop
lw t0, ThProc(a0) // (t0) = ptr to new process
lw t1, PrcHandle(t0) // (t1) = handle of new process
lw t0, hCurProc // (t0) = current process handle
beq t0, t1, celog10 // if procs are equal then skip CeLog call
nop
subu sp, 6*REG_SIZE // adjust sp (2 for register save, + 4 for C calling convention
S_REG a0, 5*REG_SIZE(sp) // save arg (pth)
sw ra, 4*REG_SIZE(sp) // save RA
move a1, zero // (a1) = 0
jal CeLogThreadMigrate
move a0, t1 // (delay slot) (a0) = handle of new process
lw ra, 4*REG_SIZE(sp) // restore RA
L_REG a0, 5*REG_SIZE(sp) // restore arg
addu sp, 6*REG_SIZE // adjust sp
celog10:
//--- End CeLogThreadMigrate ---
lw t0, ThProc(a0) // (t0) = ptr to current process
lw t1, ThAKey(a0) // (t1) = thread's access key
lw t2, PrcHandle(t0) // (t2) = handle of current process
sw t0, CurPrcPtr // remember current process pointer
sw t1, CurAKey // save access key for TLB handler
lb t1, PrcID(t0) // (t0) = process ID
beq t1, zero, UseNKSection // slot 1 -- use NKSection
sw t2, hCurProc // remember current process handle (delay slot)
// not slot 1, find it from section table
lw t2, PrcVMBase(t0) // (t2) = memory section base address
srl t2, VA_SECTION-2 // (t2) = index into section table
b ContinueSetCpuASID
lw t2, SectionTable(t2) // (t2) = process's memory section (delay slot)
UseNKSection:
la t2, NKSection
ContinueSetCpuASID:
#if ENTRYHI_PID != 0
sll t1, ENTRYHI_PID
#endif
CP0_STOP_PREFETCH(mtc0, t1, entryhi, t0); // set ASID
j ra
sw t2, SectionTable(zero) // swap in default process slot
.end SetCPUASID
.struct 0
KCF_A0: .space REG_SIZE
KCF_A1: .space REG_SIZE
KCF_A2: .space REG_SIZE
KCF_A3: .space REG_SIZE
KCF_RA: .space REG_SIZE
KCF_SP:
KCF_LENGTH:
//------------------------------------------------------------------------------
//++
// The following code is never executed. Its purpose is to support unwinding
// through the call to the exception dispatcher.
//------------------------------------------------------------------------------
NESTED_ENTRY(xKCall, 0, zero)
.set noreorder
.set noat
sw sp,KCF_LENGTH(sp) // save stack pointer
sw ra,KCF_RA(sp) // save return address
PROLOGUE_END
//------------------------------------------------------------------------------
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -