📄 shexcept.src
字号:
;
; 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.
;
.HEADING "SH3 Interrupt and Exception Processing"
;++
;
;
; Module Name:
;
; shexcept.src
;
; Abstract:
;
; This module implements the code necessary to field and process SH3
; 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.
;
; Revision History:
;
;--
.list OFF
.include "ksshx.h"
.list ON
VALIDATE_CACHE: .equ 0 ; set to force cache validation.
INTRLOCK_LEDS: .equ 0
PERFORMCALLBACK: .equ -113
RAISEEXCEPTION: .equ -114
CALLEE_SAVED_REGS: .equ 32 ; (7 registers) {r8-r14}, add 1 to make 8 byte alignment)
; must match the value in kernel.h
SECURESTK_RESERVE: .equ 48 ; SIZE_PRETLS + 16
MAX_PSL_ARGS: .equ 56
SECURE_SECTION: .equ h'61
SHARED_SLOT_BASE: .equ h'7c000000 ; shared section
SLOT_MASK: .equ h'fe000000 ; mask of the top 7 bits
READONLY_MASK .equ h'ffffffdf ; == ~0x20 (mask to clear write bit)
; must match the value in celog.h
CELOGSTATUS_ENABLED_GENERAL .equ h'20000000
API_MAX: .equ FIRST_METHOD - (h'3fff * 2)
.import _DumpFrame
.import _HandleException
.import _KernelInit
.import _NextThread
.import _KCNextThread
.import _RunList
.import _SleepList
.import _ObjectCall
.import _ServerCallReturn
.import _CallbackReturn
.import _PerformCallBackExt
.import _SH3Init
.import _ExceptionDispatch
.import OEMNMI
.import _OEMIdle
.import _SetBadHandleError
.import _NKSection
.import _NKCallIntChainWrapped
.aif SH_CPU eq h'40
.import _dwStoreQueueBase
.import _SH4CacheLines
.aelse
.import _SH3CacheLines
.aendi
.aif NKPROF eq h'01
.import _CeLogInterrupt
.import _dwCeLogTLBMiss
.aendi
.import _CeLogThreadMigrate
;; for ISR hook
.import _pfnOEMIntrOccurs
.PAGE
.section .data,data
.align 4
.export _InterruptTable
.export ExceptionTable
ExceptionTable:
.data.l _UnusedHandler ; 0x000 power-on reset (intr resched)
.data.l _UnusedHandler ; 0x020 manual restart
.data.l _UnusedHandler ; 0x040 TLB miss load
.data.l _UnusedHandler ; 0x060 TLB miss store
.data.l _UnusedHandler ; 0x080 initial page write
.data.l _UnusedHandler ; 0x0A0 TLB protection violation (load)
.data.l _UnusedHandler ; 0x0c0 TLB protection violation (store)
.data.l _UnusedHandler ; 0x0e0 address error (load)
.data.l _UnusedHandler ; 0x100 address error (store)
.data.l _UnusedHandler ; 0x120 reserved
.data.l _UnusedHandler ; 0x140 reserved
.data.l _UnusedHandler ; 0x160 TRAPA instruction
.data.l _UnusedHandler ; 0x180 reserved instruction
.data.l _UnusedHandler ; 0x1A0 invalid delay slot instruction
.data.l OEMNMI ; 0x1C0 NMI (general interrupt request)
.data.l _UnusedHandler ; 0x1E0 user breakpoint (HW breakpoints)
_InterruptTable:
.arepeat 112 ; 0x200-0xfe0 HW interrupts
.data.l _UnusedHandler
.aendr
.aif SH_CPU eq h'40
_bEnableRAMMode:
.res.l 1
;--------- Work around for SH4 sleep problem. ----------------------------------
fInIdle:
.data.l 0
.aendi
.export _IntrPrio
.data.b 0xf,0xf,0xf,0xf
_IntrPrio:
.data.b 0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0 ; 0x200-0x3e0
.data.b 0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1 ; 0x400-0x5e0
.data.b 0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1 ; 0x600-0x7e0
.data.b 0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1 ; 0x800-0x9e0
.data.b 0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1 ; 0xa00-0xbe0
.data.b 0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1 ; 0xc00-0xde0
.data.b 0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1 ; 0xe00-0xfe0
.section .KDATA,stack
.export _KDBase
.export _KStack
_KDBase: .res.b h'1000 ; reserve an extra page for the debugger
.res.b h'7e0
_KStack: .res.l 8
.export _KData
_KData: .res.b cMsec
.export _CurMSec
_CurMSec: .res.b h'400 - cMsec
.section .text,code,align=16
KPAGE_PTEL: .equ _KData + h'14a ; user read-only, 1k, cachable, !dirty, shared, valid
.aif SH_CPU eq h'40
PR_B1_BK: .equ h'70008000 ; privileged mode, bank 1, exceptions blocked
PR_B0_IE: .equ h'40008000 ; privileged mode, bank 0, un-blocked, intr unmasked
PR_B0_IM: .equ h'400080f0 ; privileged mode, bank 0, un-blocked, intr masked
PR_B0_BK: .equ h'50008000 ; privileged mode, bank 0, exceptions blocked
.aelse
PR_B1_BK: .equ h'70000000 ; privileged mode, bank 1, exceptions blocked
PR_B0_IE: .equ h'40000000 ; privileged mode, bank 0, un-blocked, intr unmasked
PR_B0_IM: .equ h'400000f0 ; privileged mode, bank 0, un-blocked, intr masked
PR_B0_BK: .equ h'50000000 ; privileged mode, bank 0, exceptions blocked
.aendi
START_REGION ExceptionBase ; base to load into VBR
LEAF_ENTRY _DebugBreak
trapa #1
rts
nop
.endf
LEAF_ENTRY _INTERRUPTS_ON
mov #h'ffffff0f, r1
stc SR, r0
and r1, r0
ldc r0, SR
rts
nop
.endf
LEAF_ENTRY _INTERRUPTS_OFF
stc SR, r0
or #h'f0, r0
ldc r0, SR
rts
nop
.endf
.align 4
.export _PtrCurMSec
_PtrCurMSec: .data.l _CurMSec
; SetCPUASID - set address space id
;
; SetCPUASID updates the MMU control registers and kernel page info
; when a thread's current process or access key is changed.
;
; Entry (r4) = ptr to thread
; Return nothing
; Uses r0, r1, r2, r3, r7
LEAF_ENTRY _SetCPUASID
;------ CeLogThreadMigrate ------
;
; NOTE : To make things relatively consistent, I'm going to make
; the registers R0-R3, R6 available for use. On entry to
; CELOG_ThreadMigrateSHx R0 will contain the handle of the process.
;
; I'm assuming that at this point the only registers that I need to
; preserve are R4 (ptr to thread) and PR (return address)
;
mov #_KData+CeLogStatus, r0 ; (r0) = &KInfoTable[KINX_CELOGSTATUS]
mov @r0, r0 ; (r0) = KInfoTable[KINX_CELOGSTATUS]
mov #CELOGSTATUS_ENABLED_GENERAL, r1 ; (r1) = CELOGSTATUS_ENABLED_GENERAL
and r1, r0 ; mask off KInfoTable entry with flag
tst r0, r0 ; if !IsCeLogStatus(CELOGSTATUS_ENABLED_GENERAL)
bt/s celog10 ; then skip CeLog call
nop
mov.l @(ThProc,r4), r0 ; (r0) = ptr to current process
mov @(PrcHandle,r0), r0 ; (r0) = handle of current process
mov #_KData+hCurProc, r1 ; (r1) = &hCurProc
mov @r1, r1 ; (r1) = old process handle
cmp/eq r0, r1 ; if new process == old process
bt/s celog10 ; then skip CeLog call
nop
sts pr, @-r15 ; Save current return address
mov.l r4, @-r15 ; Save register
mov.l @(ThProc,r4), r5 ; (r5) = ptr to current process
mov @(PrcHandle,r5), r4 ; (r4) = handle of current process
mov #_CeLogThreadMigrate, r2
mov #1, r5 ; (r5) = 1
jsr @r2 ; CELOG_ThreadMigrateSHx(hProc)
add.l #-16, r15 ; (delay slot) room for 4 arguments, C calling convention
add.l #16, r15 ; restore sp
mov.l @r15+, r4 ; Restore register
lds @r15+, pr ; Restore return address
celog10:
;---- End CeLogThreadMigrate ----
mov.l @(ThProc,r4), r1 ; (r1) = ptr to current process
mov #_KData+hCurProc, r0 ; (r0) = &hCurProc
mov @(PrcHandle,r1), r7 ; (r7) = handle of current process
mov r7, @r0 ; set current process handle
add #bResched-hCurProc, r0 ; (r0) = &bResched
mov.l r1, @(pCurPrc-bResched,r0) ; set current process pointer |
mov.l @(PrcVMBase,r1), r3 ; (r3) = memory section base address |
mov #SH3CTL_BASE, r7 ; |
ERRNZ PrcID ; |
mov.b @r1, r1 ; (r1) = process ID |
mov #_NKSection, r2 ; (r2) = process section, default to NKSection
tst r1, r1 ; is it NK?
bt/s ContinueSetASID ; just use NKSection if it is
add #aSections-bResched, r0 ; (r0) = ptr to SectionTable (delay slot) |
; not NK, find the process VM section
; (r3) = pCurProc->dwVMBase
mov #2-VA_SECTION, r2 ; (r2) = right shift count
shld r2, r3 ; (r3) = section index * 4 |
mov.l @(r0,r3), r2 ; (r2) = process's memory section |
ContinueSetASID:
;
; (r1) = procid
; (r2) = SectionTable of pCurProc (NKSection if it's NK)
;
mov.l r1, @(MMUPTEH,r7) ; set ASID |
rts
mov.l r2, @r0 ; swap in default process slot
.endf
LEAF_ENTRY _SetCPUGlobals
mov #_KData+pCurThd, r0
mov @r0, r0
ldc r0, r4_bank
rts
nop
.endf
.PAGE
LEAF_ENTRY KernelStart
;* Inititalize Status register:
; Kernel mode,
; exceptions blocked,
; register bank 1
mov #PR_B1_BK, r0
ldc r0, SR ; (SR) = kmode, blocked, bank1
mov #h'A0000000, r2 ; (r2) = un-cached, un-mapped region base
mov #_SH3Init, r1
mov #_KStack, r15
or r2, r15 ; (r15) = un-cached stack
or r2, r1 ; (r1) = un-cached destination
mov #SH_CPU, r4 ; (r4) = processor type
jsr @r1 ; perform general SH3 initialization
nop
; Switch stack to cached, un-mapped region.
mov #_KStack, r15 ; switch to normal kernel stack
; Load new status register with:
; kernel mode,
; excpetions enabled,
; register bank 0,
; interrupts un-masked.
mov #SH3CTL_BASE, r7 ; (r7_priv) = ptr to SH3 control registers
mov #ExceptionBase, r3 ; (r3) = kernel exception handlers
ldc r3, VBR ; switch to kernel's exception handlers
mov #PR_B0_IE, r1
mov #_KernelInit, r8
ldc r1, SR ; (SR) = privileged, bank 0, unblocked
jsr @r8
nop
bra resched
mov #0, r14 ; no current thread
.endf
.PAGE
;
; APICall is the starting of SHx general exception handlers. It will
; never be invoked directly but indirectly. All SHx general exceptions
; except TLBMiss exceptions will be forwarded to the handler defined in
; the address computed from the sum of VBR, which stores the exception
; handler base address, and the offset 0x100. This is exactly where
; APICall starts as you see ".org h'100" in the following lines:
;
LEAF_ENTRY APICall
.PAGE
; Bank 1 registers are pre-loaded with the following values:
;
; (r4) - ptr to current thread
; (r5) - ptr to context save area
; (r7) - SH3CTL_BASE (used to access MMU & exception data)
.org h'100
; Please note that at this point, SPC will contain the saved PC so does SSR
; to the saved SR. Also SR.MD will be set to the previledge mode, SR.BL will
; be set to disable interrupt, and SR.BR will be set to Bank 1 mode. Thus
; a handful of general registers, [r1..r7][_bank1], will be freely available
; to exception handler right away while [r1..r7][_bank0|_user] will be kept
; around but only access through LDC instruction.
;
mov @(EXPEVT,r7), r0 ; (r0) = exception code
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -