📄 mdarm.c
字号:
/* Copyright (c) 1996-2000 Microsoft Corporation. All rights reserved. */
#include "kernel.h"
#ifdef THUMBSUPPORT
#define THUMB_SUPPORT_STR TEXT("(Thumb Enabled)")
#else
#define THUMB_SUPPORT_STR TEXT(" ")
#endif
#ifdef THUMB
const wchar_t NKSignon[] = TEXT("Windows CE Kernel for THUMB ") THUMB_SUPPORT_STR TEXT(" Built on ") TEXT(__DATE__) TEXT(" at ") TEXT(__TIME__) TEXT("\r\n");
#else
const wchar_t NKSignon[] = TEXT("Windows CE Kernel for ARM ") THUMB_SUPPORT_STR TEXT(" Built on ") TEXT(__DATE__) TEXT(" at ") TEXT(__TIME__) TEXT("\r\n");
#endif
DWORD CEProcessorType;
WORD ProcessorLevel = 4;
WORD ProcessorRevision;
DWORD CurMSec;
DWORD DiffMSec;
// Fault Status register fields:
#define FSR_DOMAIN 0xF0
#define FSR_STATUS 0x0D
#define FSR_PAGE_ERROR 0x02
#define FSR_ALIGNMENT 0x01
#define FSR_TRANSLATION 0x05
#define FSR_DOMAIN_ERROR 0x09
#define FSR_PERMISSION 0x0D
#define BREAKPOINT 0x06000010 // special undefined instruction
#define THM_BREAKPOINT 0xDEFE // Thumb equivalent
const LPCSTR IdStrings[] = {
"RaiseException", "Reschedule", "Undefined Instruction", "SWI",
"Prefetch Abort", "Data Abort", "IRQ", "<Invalid>", "<Invalid>", "[Stack fault]", "[HW Break]",
};
void DumpDwords(PDWORD pdw, int len) {
int lc;
lc = 0;
NKDbgPrintfW(L"Dumping %d dwords", len);
for (lc = 0 ; len ; ++pdw, ++lc, --len) {
if (!(lc & 3))
NKDbgPrintfW(L"\r\n%8.8lx -", pdw);
NKDbgPrintfW(L" %8.8lx", *pdw);
}
NKDbgPrintfW(L"\r\n");
}
void DumpFrame(PTHREAD pth, PCPUCONTEXT pctx, int id, ulong addr, int level) {
NKDbgPrintfW(L"Exception '%a' Thread=%8.8lx AKY=%8.8lx PC=%8.8lx BVA=%8.8lx\r\n",
IdStrings[id+1], pth, pCurThread->aky, pctx->Pc, addr);
NKDbgPrintfW(L" R0=%8.8lx R1=%8.8lx R2=%8.8lx R3=%8.8lx\r\n",
pctx->R0, pctx->R1, pctx->R2, pctx->R3);
NKDbgPrintfW(L" R4=%8.8lx R5=%8.8lx R6=%8.8lx R7=%8.8lx\r\n",
pctx->R4, pctx->R5, pctx->R6, pctx->R7);
NKDbgPrintfW(L" R8=%8.8lx R9=%8.8lx R10=%8.8lx R11=%8.8lx\r\n",
pctx->R8, pctx->R9, pctx->R10, pctx->R11);
NKDbgPrintfW(L"R12=%8.8lx SP=%8.8lx Lr=%8.8lx Psr=%8.8lx\r\n",
pctx->R12, pctx->Sp, pctx->Lr, pctx->Psr);
}
void NextThread(void);
void KCNextThread(void);
void OEMIdle(void);
void DoPowerOff(void);
void __declspec(iw32) TLBClear(void);
ulong OEMInterruptHandler(void);
extern char InterlockedAPIs[], InterlockedEnd[];
void ARMInit(int cpuType, int abSp, int iSp, int uSp) {
int ix;
/* 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((PWSTR)NKSignon);
/* 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);
/* setup processor version information */
CEProcessorType = cpuType >> 4 & 0xFFF;
ProcessorRevision = cpuType & 0x0f;
NKDbgPrintfW(L"ProcessorType=%4.4x Revision=%d\r\n", CEProcessorType, ProcessorRevision);
NKDbgPrintfW(L"sp_abt=%8.8x sp_irq=%8.8x sp_undef=%8.8x\r\n", abSp, iSp, uSp);
OEMInit(); // initialize firmware
KernelFindMemory();
NKDbgPrintfW(L"Sp=%8.8x\r\n", &cpuType);
#ifdef DEBUG
OEMWriteDebugString(TEXT("ARMInit done.\r\n"));
#endif
}
typedef struct ExcInfo {
DWORD linkage;
ULONG oldPc;
UINT oldMode;
char id;
BYTE lowSpBits;
ushort fsr;
ULONG addr;
} EXCINFO;
typedef EXCINFO *PEXCINFO;
ERRFALSE(sizeof(EXCINFO) <= sizeof(CALLSTACK));
ERRFALSE(offsetof(EXCINFO,linkage) == offsetof(CALLSTACK,pcstkNext));
ERRFALSE(offsetof(EXCINFO,oldPc) == offsetof(CALLSTACK,retAddr));
ERRFALSE(offsetof(EXCINFO,oldMode) == offsetof(CALLSTACK,pprcLast));
ERRFALSE(64 >= sizeof(CALLSTACK));
PTHREAD HandleException(PTHREAD pth, int id, ulong addr, ushort info) {
PEXCINFO pexi;
DWORD stackaddr;
if (id != ID_RESCHEDULE) {
#if 0
NKDbgPrintfW(L"%a: Thread=%8.8lx Proc=%8.8lx AKY=%8.8lx\r\n",
IdStrings[id+1], pth, pCurProc, pCurThread->aky);
NKDbgPrintfW(L"PC=%8.8lx Lr=%8.8lx Sp=%8.8lx Psr=%4.4x\r\n",
pth->ctx.Pc, pth->ctx.Lr, pth->ctx.Sp, pth->ctx.Psr);
if (id == ID_DATA_ABORT)
NKDbgPrintfW(L"FAR=%8.8lx FSR=%4.4x\r\n", addr, info);
#endif
KCALLPROFON(0);
pexi = (struct ExcInfo *)((pth->ctx.Sp & ~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 pth; // restart instruction
}
SET_STACKFAULT(pth);
id = ID_STACK_FAULT; // stack fault exception code
addr = (DWORD)pexi;
}
if (pth->ctx.Pc != (ulong)CaptureContext+4) {
pexi->id = id;
pexi->lowSpBits = (uchar)pth->ctx.Sp & 63;
pexi->oldPc = pth->ctx.Pc;
pexi->oldMode = pth->ctx.Psr & 0xFF;
pexi->addr = addr;
pexi->fsr = info;
pexi->linkage = (DWORD)pth->pcstkTop | 1;
pth->pcstkTop = (PCALLSTACK)pexi;
pth->ctx.Sp = (DWORD)pexi;
if ((pexi->oldMode & 0x1F) == USER_MODE)
pth->ctx.Psr = (pth->ctx.Psr & ~0xFF) | SYSTEM_MODE;
else
pth->ctx.Psr &= ~THUMB_STATE;
pth->ctx.Pc = (ULONG)CaptureContext;
KCALLPROFOFF(0);
return pth; // continue execution
}
DumpFrame(pth, &pth->ctx, id, addr, 10);
RETAILMSG(1, (TEXT("Halting thread %8.8lx\r\n"), pth));
SurrenderCritSecs();
SET_RUNSTATE(pth,RUNSTATE_BLOCKED);
RunList.pth = 0;
SetReschedule();
KCALLPROFOFF(0);
return 0;
}
if (PowerOffFlag) {
DoPowerOff();
PowerOffFlag = 0;
}
reschedTop:
if (ReschedFlag) {
ReschedFlag = 0;
NextThread();
}
if (KCResched) {
KCResched = 0;
KCNextThread();
}
if (KCResched)
goto reschedTop;
if (!RunList.pth) {
INTERRUPTS_OFF();
if (!ReschedFlag && !KCResched) {
OEMIdle();
INTERRUPTS_ON();
ReschedFlag = 1;
goto reschedTop;
} else {
INTERRUPTS_ON();
goto reschedTop;
}
}
SetCPUASID(RunList.pth);
hCurThread = RunList.pth->hTh;
pCurThread = RunList.pth;
KPlpvTls = RunList.pth->tlsPtr;
return RunList.pth;
}
// LoadPageTable - load entries into page tables from kernel structures
//
// LoadPageTable is called for prefetch and data aborts to copy page table
// entries from the kernel virtual memory tables to the ARM h/w page tables.
DWORD currsecond;
DWORD secondpos[16];
DWORD secondslot[16];
DWORD used[16];
LPDWORD SecondAddr(DWORD ind, DWORD ent) {
return (LPDWORD)&ArmHigh->aPT[ind].PTEs[ent];
}
LPDWORD FirstAddr(DWORD ind) {
return (LPDWORD)&ArmHigh->firstPT[ind];
}
int LoadPageTable(ulong addr) {
PSECTION pscn;
MEMBLOCK *pmb;
ulong entry;
unsigned ix1st, ix2nd;
int loop;
if ((addr < 0x80000000) && (pscn = SectionTable[addr>>VA_SECTION]) &&
(pmb = (*pscn)[(addr>>VA_BLOCK)&BLOCK_MASK]) && (pmb != RESERVED_BLOCK) && TestAccess(&pmb->alk, &CurAKey) &&
((entry = pmb->aPages[(addr>>VA_PAGE)&PAGE_MASK]) & PG_VALID_MASK)) {
ix1st = addr >> 20; // index into 1st level page table
ix2nd = (addr >> VA_PAGE) & L2_MASK; // index into 2nd level page table
// Remove previous entry from the page tables.
if (*FirstAddr(ix1st)) {
for (loop = 0; loop < 16; loop++)
if (used[loop] && (secondpos[loop] == ix1st))
break;
DEBUGCHK(loop != 16);
*SecondAddr(loop,secondslot[loop]) = 0;
secondslot[loop] = ix2nd;
*SecondAddr(loop,ix2nd) = entry;
} else {
if (used[currsecond]) {
*FirstAddr(secondpos[currsecond]) = 0;
*SecondAddr(currsecond,secondslot[currsecond]) = 0;
} else
used[currsecond] = 1;
secondpos[currsecond] = ix1st;
secondslot[currsecond] = ix2nd;
*SecondAddr(currsecond,ix2nd) = entry;
*FirstAddr(ix1st) = PageTableDescriptor + currsecond*sizeof(PAGETBL);
currsecond = (currsecond+1)&0xf;
}
return TRUE; // tell abort handler to retry
}
return FALSE;
}
void InvalidateSoftwareTLB(void) {
int loop;
if (!InSysCall()) {
KCall((PKFN)InvalidateSoftwareTLB);
return;
}
KCALLPROFON(63);
for (loop = 0; loop < 16; loop++) {
// Remove previous entry from the page tables.
if (used[loop]) {
*FirstAddr(secondpos[loop]) = 0;
*SecondAddr(loop,secondslot[loop]) = 0;
used[loop] = 0;
}
}
KCALLPROFOFF(63);
}
// FlushTLB - clear TLBs and cached page table entries
//
// FlushTLB is called by the virtual memory system whenever the permissions on
// any pages are changed or when any pages are freed.
void FlushTLB(void) {
FlushICache();
FlushDCache();
InvalidateSoftwareTLB();
TLBClear(); // clear h/w TLBs
}
void ExceptionDispatch(PCONTEXT pctx) {
EXCEPTION_RECORD er;
ULONG FaultAddr;
ULONG addr;
int id;
BOOL bHandled;
BOOL ThumbMode;
PTHREAD pth;
PEXCINFO pexi;
uint fsr;
pth = pCurThread;
pexi = (PEXCINFO)pth->pcstkTop;
DEBUGMSG(ZONE_SEH, (TEXT("ExceptionDispatch: pexi=%8.8lx Pc=%8.8lx\r\n"), pexi, pexi->oldPc));
pctx->Pc = pexi->oldPc;
SetContextMode(pctx, pexi->oldMode);
pctx->Sp = (ULONG)pctx + sizeof(CONTEXT);
memset(&er, 0, sizeof(er));
er.ExceptionAddress = (PVOID)pctx->Pc;
#if defined(THUMBSUPPORT)
ThumbMode = (pctx->Psr & THUMB_STATE) != 0;
#else
ThumbMode = FALSE;
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -