📄 mdsh3.c
字号:
/* Copyright (c) 1995-2000 Microsoft Corporation. All rights reserved. */
#include "kernel.h"
#include "shx.h"
extern void UnusedHandler(void);
extern void OEMInitDebugSerial(void);
extern void InitClock(void);
extern void FlushTLB(void);
extern void LoadKPage(void);
extern void DumpFrame(PTHREAD pth, PCONTEXT pctx, DWORD dwExc, DWORD info);
extern void APICallReturn(void);
#ifdef SH4
void SaveFloatContext(PTHREAD);
void RestoreFloatContext(PTHREAD);
DWORD GetAndClearFloatCode(void);
DWORD GetAndClearFloatCode(void);
DWORD GetCauseFloatCode(void);
extern BOOL HandleHWFloatException(EXCEPTION_RECORD *ExceptionRecord,
PCONTEXT pctx);
extern unsigned int get_fpscr();
extern void set_fpscr(unsigned int);
extern void clr_fpscr(unsigned int);
#endif
#ifdef SH3
// frequency control register value
extern unsigned short SH3FQCR_Fast;
extern unsigned int SH3DSP;
void SaveSH3DSPContext(PTHREAD);
void RestoreSH3DSPContext(PTHREAD);
#endif
// OEM definable extra bits for the Cache Control Register
unsigned long OEMExtraCCR;
extern char InterlockedAPIs[], InterlockedEnd[];
void SH3Init(int cpuType) {
int ix;
#ifdef SH3
/* initialize frequency control register */
if (SH3FQCR_Fast)
*(volatile ushort *)0xffffff80 = SH3FQCR_Fast;
#endif
/* Disable the cpu cache & flush it. */
CCR = 0;
CCR = CACHE_FLUSH;
/* Zero out kernel data page. */
memset(&KData, 0, sizeof(KData));
KData.handleBase = 0x80000000;
KData.pAPIReturn = (ulong)APICallReturn;
/* Initialize SectionTable in KPage */
for (ix = 1 ; ix <= SECTION_MASK ; ++ix)
SectionTable[ix] = NULL_SECTION;
/* Copy kernel data to RAM & zero out BSS */
KernelRelocate(pTOC);
OEMInitDebugSerial(); // initialize serial port
OEMWriteDebugString(TEXT("\r\nWindows CE Kernel for Hitachi SH Built on ") TEXT(__DATE__)
TEXT(" at ") TEXT(__TIME__) TEXT("\r\n"));
#if defined(SH4)
OEMWriteDebugString(TEXT("SH-4 Kernel\r\n"));
#else
NKDbgPrintfW(L"SH-3 Kernel. FQCR=%x\r\n", *(volatile ushort *)0xffffff80);
#endif
/* Initialize address translation hardware. */
MMUTEA = 0; /* clear transation address */
MMUTTB = (DWORD)SectionTable; /* set translation table base address */
MMUPTEH = 0; /* clear ASID */
MMUCR = TLB_FLUSH | TLB_ENABLE;
LoadKPage();
/* Copy interlocked api code into the kpage */
DEBUGCHK(sizeof(KData) <= FIRST_INTERLOCK);
DEBUGCHK((InterlockedEnd-InterlockedAPIs)+FIRST_INTERLOCK == 0x400);
memcpy((char *)&KData+FIRST_INTERLOCK, InterlockedAPIs, InterlockedEnd-InterlockedAPIs);
// Enable the CPU cache. Can't do this before KernelRelocate because OEMExtraCCR
// may not be properly initialized before that point.
CCR = CACHE_ENABLE | OEMExtraCCR;
NKDbgPrintfW(L"CCR=%4.4x\r\n", CCR);
OEMInit(); // initialize firmware
KernelFindMemory();
#ifdef DEBUG
OEMWriteDebugString(TEXT("SH3Init done.\r\n"));
#endif
}
BOOL HookInterrupt(int hwInterruptNumber, FARPROC pfnHandler) {
if (hwInterruptNumber > 112)
return FALSE;
InterruptTable[hwInterruptNumber] = (DWORD)pfnHandler;
return TRUE;
}
BOOL UnhookInterrupt(int hwInterruptNumber, FARPROC pfnHandler) {
if (hwInterruptNumber > 112 ||
InterruptTable[hwInterruptNumber] != (DWORD)pfnHandler)
return FALSE;
InterruptTable[hwInterruptNumber] = (DWORD)UnusedHandler;
return TRUE;
}
#ifdef SH4
void FlushCache(void) {
FlushDCache();
FlushICache();
}
void SwitchFPUOwner(PCONTEXT pctx) {
KCALLPROFON(61);
if (g_CurFPUOwner != pCurThread) {
if (g_CurFPUOwner)
SaveFloatContext(g_CurFPUOwner);
g_CurFPUOwner = pCurThread;
RestoreFloatContext(pCurThread);
}
KCALLPROFOFF(61);
pctx->Psr &= ~0x8000;
}
void FPUFlushContext(void) {
if (g_CurFPUOwner) {
SaveFloatContext(g_CurFPUOwner);
g_CurFPUOwner->ctx.Psr |= 0x8000;
g_CurFPUOwner = 0;
}
}
DWORD dwStoreQueueBase;
BOOL DoSetRAMMode(BOOL bEnable, LPVOID *lplpvAddress, LPDWORD lpLength);
BOOL SC_SetRAMMode(BOOL bEnable, LPVOID *lplpvAddress, LPDWORD lpLength) {
if (pCurProc->bTrustLevel != KERN_TRUST_FULL) {
ERRORMSG(1,(L"SC_SetRAMMode failed due to insufficient trust\r\n"));
KSetLastError(pCurThread, ERROR_ACCESS_DENIED);
return 0;
}
return DoSetRAMMode(bEnable, lplpvAddress, lpLength);
}
LPVOID SC_SetStoreQueueBase(DWORD dwPhysPage) {
if (pCurProc->bTrustLevel != KERN_TRUST_FULL) {
ERRORMSG(1,(L"SC_SetStoreQueueBase failed due to insufficient trust\r\n"));
KSetLastError(pCurThread, ERROR_ACCESS_DENIED);
return 0;
}
if (dwPhysPage & (1024*1024-1)) {
KSetLastError(pCurThread,ERROR_INVALID_PARAMETER);
return 0;
}
if (dwPhysPage & 0xe0000000) {
KSetLastError(pCurThread,ERROR_INVALID_PARAMETER);
return 0;
}
dwStoreQueueBase = dwPhysPage | PG_VALID_MASK | PG_1M_MASK | PG_PROT_WRITE | PG_DIRTY_MASK | 1;
FlushTLB();
return (LPVOID)0xE0000000;
}
#else // !SH4
void SwitchDSPOwner(PCONTEXT pctx) {
KCALLPROFON(68);
if (g_CurDSPOwner != pCurThread) {
if (g_CurDSPOwner)
SaveSH3DSPContext(g_CurDSPOwner);
g_CurDSPOwner = pCurThread;
RestoreSH3DSPContext(pCurThread);
}
pctx->Psr |= 0x1000; // enable the DSP
KCALLPROFOFF(68);
}
#endif
void FlushTLB(void) {
MMUCR = TLB_FLUSH | TLB_ENABLE;
#if defined(SH4) || (PAGE_SIZE == 1024)
FlushCache();
#endif
}
typedef struct ExcInfo {
DWORD linkage;
ULONG oldFir;
UINT oldMode;
UCHAR exc;
UCHAR lowSp;
UCHAR pad[2];
ULONG info;
} EXCINFO, *PEXCINFO;
ERRFALSE(sizeof(EXCINFO) <= sizeof(CALLSTACK));
ERRFALSE(offsetof(EXCINFO,linkage) == offsetof(CALLSTACK,pcstkNext));
ERRFALSE(offsetof(EXCINFO,oldFir) == offsetof(CALLSTACK,retAddr));
ERRFALSE(offsetof(EXCINFO,oldMode) == offsetof(CALLSTACK,pprcLast));
ERRFALSE(64 >= sizeof(CALLSTACK));
BOOL HandleException(PTHREAD pth, DWORD dwExc, DWORD info) {
PEXCINFO pexi;
DWORD stackaddr;
KCALLPROFON(0);
#if 0
NKDbgPrintfW(L"Exception %03x Thread=%8.8lx(%8.8lx) PC=%8.8lx TEA=%8.8lx AKY=%8.8lx\r\n",
dwExc, pCurThread, pth, pth->ctx.Fir, info, CurAKey);
#endif
// avoid crossing page boundary in structure
pexi = (struct ExcInfo *)((pth->ctx.R15 & ~63) - sizeof(CALLSTACK));
if (!((DWORD)pexi & 0x80000000) && DemandCommit((DWORD)pexi)) {
stackaddr = (DWORD)pexi & ~(PAGE_SIZE-1);
if ((stackaddr >= pth->dwStackBound) || (stackaddr < pth->dwStackBase) ||
((pth->dwStackBound = stackaddr) >= (pth->dwStackBase + MIN_STACK_RESERVE)) ||
TEST_STACKFAULT(pth)) {
KCALLPROFOFF(0);
return 1; // restart instruction
}
SET_STACKFAULT(pth);
dwExc = 0x1fe0;
info = (DWORD)pexi;
}
// Setup to capture the exception context in kernel mode but
// running in thread context to allow preemption and stack growth.
if (pth->ctx.Fir != (ulong)CaptureContext+4) {
pexi->exc = (UCHAR)(dwExc >> 5);
pexi->lowSp = (UCHAR)(pth->ctx.R15 & 63);
pexi->oldFir = pth->ctx.Fir;
pexi->oldMode = GetThreadMode(pth);
pexi->info = info;
pexi->linkage = (DWORD)pCurThread->pcstkTop | 1;
pCurThread->pcstkTop = (PCALLSTACK)pexi;
pth->ctx.R15 = (DWORD)pexi;
pth->ctx.Psr |= 0x40000000; // Kernel mode
pth->ctx.Fir = (ulong)CaptureContext;
KCALLPROFOFF(0);
return TRUE; // continue execution
}
DumpFrame(pth, (PCONTEXT)&pth->ctx, dwExc, info);
RETAILMSG(1, (TEXT("Halting thread %8.8lx\r\n"), pCurThread));
SurrenderCritSecs();
DEBUGCHK(!((pCurThread->wInfo >> DEBUG_LOOPCNT_SHIFT) & 1));
SET_RUNSTATE(pCurThread,RUNSTATE_BLOCKED);
RunList.pth = 0;
SetReschedule();
KCALLPROFOFF(0);
return 0;
}
typedef struct _EXCARGS {
DWORD dwExceptionCode; /* exception code */
DWORD dwExceptionFlags; /* continuable exception flag */
DWORD cArguments; /* number of arguments in array */
DWORD *lpArguments; /* address of array of arguments */
} EXCARGS, *PEXCARGS;
void ExceptionDispatch(PCONTEXT pctx) {
EXCEPTION_RECORD er;
int exc;
ULONG info;
BOOL bHandled;
PEXCARGS pea;
PTHREAD pth;
PEXCINFO pexi;
pth = pCurThread;
pexi = (PEXCINFO)pth->pcstkTop;
DEBUGMSG(ZONE_SEH, (TEXT("ExceptionDispatch: pexi=%8.8lx Fir=%8.8lx RA=%8.8lx exc=%x\r\n"),
pexi, pexi->oldFir, pctx->PR, pexi->exc << 5));
// Update CONTEXT with infomation saved in the EXCINFO structure
pctx->Fir = pexi->oldFir;
if (pexi->oldMode != KERNEL_MODE)
pctx->Psr &= ~0x40000000;
pctx->R15 = (ULONG)pctx + sizeof(CONTEXT);
memset(&er, 0, sizeof(er));
er.ExceptionAddress = (PVOID)pctx->Fir;
// Check for RaiseException call versus a CPU detected exception.
// RaiseException just becomes a call to CaptureContext as a KPSL.
// HandleExcepion sets the LSB of the callstack linkage but ObjectCall
// does not.
if (!(pexi->linkage & 1)) {
pea = (PEXCARGS)pctx->R15;
exc = -1;
pctx->Fir -= 2; // to avoid boundary problems at the end of a try block.
DEBUGMSG(ZONE_SEH, (TEXT("Raising exception %x flags=%x args=%d pexi=%8.8lx\r\n"),
pea->dwExceptionCode, pea->dwExceptionFlags, pea->cArguments, pexi));
er.ExceptionCode = pea->dwExceptionCode;
er.ExceptionFlags = pea->dwExceptionFlags;
if (pea->lpArguments && pea->cArguments) {
if (pea->cArguments > EXCEPTION_MAXIMUM_PARAMETERS) {
er.ExceptionCode = STATUS_INVALID_PARAMETER;
er.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
} else {
memcpy(er.ExceptionInformation, pea->lpArguments,
pea->cArguments*sizeof(DWORD));
er.NumberParameters = pea->cArguments;
}
}
} else {
// CPU detected exception. Extract some additional information about
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -