📄 mdppc.c
字号:
/* Copyright (c) 1996-2000 Microsoft Corporation. All rights reserved. */
/*+
mdppc.c - PowerPC machine dependent code & data
*/
#include "kernel.h"
#include "kxppc.h"
#if defined(PPC403)
extern void SetPID(int);
#elif defined(PPC821)
#include "mmu821.h"
#define MAX_ASID 15 // Maximum Address Space ID supported by the 821
uchar ASIDMap[MAX_PROCESSES] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
}; // map from process number to address space ID
int NextASID = 0; // next available address space ID
extern void SetCASID(int);
#endif
// These are filled in by KernelStart
DWORD CEProcessorType = 0; // 821, 823, 401, or 403
WORD ProcessorLevel = 0; // PVR[0:15]
WORD ProcessorRevision = 0; // PVR[16:31]
const wchar_t NKSignon[] = TEXT("Windows CE Kernel for PowerPC Built on ") TEXT(__DATE__) TEXT(" at ") TEXT(__TIME__) TEXT("\r\n");
void NextThread(void);
void KCNextThread(void);
ulong OEMInterruptHandler(void);
ulong OEMDecrementer(void);
void OEMIdle(void);
void DoPowerOff(void);
#define KERNEL_MSR (KData.kMSR) // Default kernel MSR
#define USER_MSR (KERNEL_MSR | MSR_PR) // Problem state=1
#define SRR1_TRAP 0x20000 // SRR1 bit indicating program trap
#define TO_BKP 0x16 // trap BREAKPOINT
#define TO_DIV0 0x06 // trap Integer DIV by zero
#define TO_DIV0U 0x07 // trap unconditional DIV by 0
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 excInfo, int level) {
UINT32 addr;
NKDbgPrintfW(L"Exception %03x Thread=%8.8lx AKY=%8.8lx PC=%8.8lx excInfo=%8.8lx\r\n",
id, pth, pCurThread->aky, pctx->Iar, excInfo);
NKDbgPrintfW(L"SR=%8.8lx CR=%8.8lx XER=%8.8lx LR=%8.8lx CTR=%8.8lx\r\n",
pctx->Msr, pctx->Cr, pctx->Xer, pctx->Lr, pctx->Ctr);
NKDbgPrintfW(L" G0=%8.8lx G1=%8.8lx G2=%8.8lx G3=%8.8lx\r\n",
pctx->Gpr0, pctx->Gpr1, pctx->Gpr2, pctx->Gpr3);
NKDbgPrintfW(L" G4=%8.8lx G5=%8.8lx G6=%8.8lx G7=%8.8lx\r\n",
pctx->Gpr4, pctx->Gpr5, pctx->Gpr6, pctx->Gpr7);
NKDbgPrintfW(L" G8=%8.8lx G9=%8.8lx G10=%8.8lx G11=%8.8lx\r\n",
pctx->Gpr8, pctx->Gpr9, pctx->Gpr10, pctx->Gpr11);
NKDbgPrintfW(L"G12=%8.8lx G13=%8.8lx G14=%8.8lx G15=%8.8lx\r\n",
pctx->Gpr12, pctx->Gpr13, pctx->Gpr14, pctx->Gpr15);
NKDbgPrintfW(L"G16=%8.8lx G17=%8.8lx G18=%8.8lx G19=%8.8lx\r\n",
pctx->Gpr16, pctx->Gpr17, pctx->Gpr18, pctx->Gpr19);
NKDbgPrintfW(L"G20=%8.8lx G21=%8.8lx G22=%8.8lx G23=%8.8lx\r\n",
pctx->Gpr20, pctx->Gpr21, pctx->Gpr22, pctx->Gpr23);
NKDbgPrintfW(L"G24=%8.8lx G25=%8.8lx G26=%8.8lx G27=%8.8lx\r\n",
pctx->Gpr24, pctx->Gpr25, pctx->Gpr26, pctx->Gpr27);
NKDbgPrintfW(L"G28=%8.8lx G29=%8.8lx G30=%8.8lx G31=%8.8lx\r\n",
pctx->Gpr28, pctx->Gpr29, pctx->Gpr30, pctx->Gpr31);
if (level > 1) {
addr = (pctx->Iar & -4) - 8*4;
if (VerifyAccess((PVOID)addr, VERIFY_KERNEL_OK, CurAKey))
DumpDwords((PDWORD)addr, 12);
}
}
typedef struct ExcInfo {
DWORD linkage;
ULONG oldIar;
UINT oldMode;
char id;
char StoreOp;
WORD lowSp;
ULONG excInfo;
} EXCINFO;
typedef EXCINFO *PEXCINFO;
ERRFALSE(sizeof(EXCINFO) <= sizeof(CALLSTACK));
ERRFALSE(offsetof(EXCINFO,linkage) == offsetof(CALLSTACK,pcstkNext));
ERRFALSE(offsetof(EXCINFO,oldIar) == offsetof(CALLSTACK,retAddr));
ERRFALSE(offsetof(EXCINFO,oldMode) == offsetof(CALLSTACK,pprcLast));
ERRFALSE(1024 >= sizeof(CALLSTACK) + STK_SLACK_SPACE + sizeof(CONTEXT) + 0x28); // 0x28 == StackFrameHeaderLength
BOOL HandleException(PTHREAD pth, int id, ulong addr, uint StoreOp) {
PEXCINFO pexi;
DWORD stackaddr;
#if 0
NKDbgPrintfW(L"Exception %02x00 Thread=%8.8lx Proc=%8.8lx\r\n",id, pth, hCurProc);
NKDbgPrintfW(L"AKY=%8.8lx PC=%8.8lx Lr=%8.8lx DAR=%8.8lx\r\n",pCurThread->aky, pth->ctx.Iar, pth->ctx.Lr, addr);
#endif
KCALLPROFON(0);
pexi = (struct ExcInfo *)((pth->ctx.Gpr1 & ~1023) - ALIGN8(STK_SLACK_SPACE + 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 TRUE; // restart instruction
}
SET_STACKFAULT(pth);
id = ID_STACK_FAULT; // stack fault exception code
addr = (DWORD)pexi;
}
if (pth->ctx.Iar != (ulong)CaptureContext) {
pexi->id = id;
pexi->lowSp = (WORD)(pth->ctx.Gpr1 & 1023);
pexi->oldIar = pth->ctx.Iar;
pexi->oldMode = GetThreadMode(pth);
pexi->excInfo = (id == ID_PROGRAM) ? pth->ctx.Msr : addr;
pexi->StoreOp = StoreOp;
pexi->linkage = (DWORD)pCurThread->pcstkTop | 1;
pCurThread->pcstkTop = (PCALLSTACK)pexi;
pth->ctx.Gpr1 = (DWORD)pexi;
SetThreadMode(pth, KERNEL_MODE);
pth->ctx.Iar = (ULONG)CaptureContext;
KCALLPROFOFF(0);
return TRUE; // 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 FALSE;
}
// SetCPUASID - setup processor specific address space information
//
// SetCPUASID will update the virtual memory tables so that new current process
// is mapped into slot 0 and set the h/w address space ID register for the new
// process.
//
// Entry (pth) = ptr to THREAD structure
// Return nothing
void SetCPUASID(PTHREAD pth) {
PPROCESS pprc;
int ix;
CurAKey = pth->aky;
pCurProc = pprc = pth->pProc;
#ifdef CELOG
if (hCurProc != pprc->hProc) {
CELOG_ThreadMigrate(pprc->hProc, 0);
}
#endif
hCurProc = pprc->hProc;
SectionTable[0] = SectionTable[pprc->dwVMBase>>VA_SECTION];
ix = pprc->procnum;
#if defined(PPC821)
INTERRUPTS_OFF();
if (ASIDMap[ix] == 0xFF) {
// Assign an address space ID to this process
if (NextASID > MAX_ASID) {
memset(ASIDMap, 0xff, sizeof(ASIDMap));
NextASID = 0;
FlushTLB();
}
ASIDMap[ix] = NextASID++;
}
SetCASID(ASIDMap[ix]);
INTERRUPTS_ON();
#elif defined(PPC403)
SetPID(ix+1);
#else
#error "Unsupported CPU type"
#endif
}
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;
void ExceptionDispatch(PCONTEXT pctx) {
EXCEPTION_RECORD er;
int id;
EXCARGS *pea;
BOOL bHandled;
PTHREAD pth;
PEXCINFO pexi;
pth = pCurThread;
pexi = (PEXCINFO)pth->pcstkTop;
DEBUGMSG(ZONE_SEH, (TEXT("ExceptionDispatch: pexi=%8.8lx Iar=%8.8lx Id=0x%x\r\n"), pexi, pexi->oldIar, pexi->id));
pctx->Iar = pexi->oldIar;
pctx->Msr = pexi->oldMode==KERNEL_MODE ? KERNEL_MSR : USER_MSR;
pctx->Gpr1 = (ULONG)pctx + sizeof(CONTEXT);
memset(&er, 0, sizeof(er));
er.ExceptionAddress = (PVOID)pctx->Iar;
// 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 = (EXCARGS *)(pctx->Gpr1 + offsetof(STACK_FRAME_HEADER, Parameter0));
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
// the cause of the exception from the EXCINFO (CALLSTACK) structure.
id = pexi->id;
pctx->Gpr1 += pexi->lowSp + ALIGN8(sizeof(CALLSTACK) + STK_SLACK_SPACE);
if (((id == ID_CPAGE_FAULT) || (id == ID_DPAGE_FAULT)) && AutoCommit(pexi->excInfo)) {
pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
goto continueExecution;
}
switch (id) {
case ID_ALIGNMENT:
er.ExceptionCode = STATUS_DATATYPE_MISALIGNMENT;
break;
case ID_PROGRAM:
//
// Extract the exception cause from the SRR1 value.
// In the case of program exceptions the general handler stores
// the SRR1 value in the pexi->excInfo field.
//
if (pexi->excInfo & SRR1_TRAP) { // program trap ??
er.ExceptionInformation[0] = *(ULONG *)pctx->Iar & 0xffff;
if ( er.ExceptionInformation[0] == TO_BKP )
er.ExceptionCode = STATUS_BREAKPOINT;
else // if ( er.ExceptionInformation[0] == TO_DIV0 )
er.ExceptionCode = STATUS_INTEGER_DIVIDE_BY_ZERO;
}
break;
case ID_DPAGE_FAULT: // Data page fault
er.ExceptionInformation[0] = pexi->StoreOp; // == 1 if Store
// fall through:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -