📄 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 SH4void 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 valueextern unsigned short SH3FQCR_Fast;extern unsigned int SH3DSP;void SaveSH3DSPContext(PTHREAD);void RestoreSH3DSPContext(PTHREAD);#endif// OEM definable extra bits for the Cache Control Registerunsigned 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 SH4void 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 // !SH4void 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);}#endifvoid 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 + -