📄 mdarm.c
字号:
CEInstructionSet |= PROCESSOR_FEATURE_FP;
DEBUGMSG (1, (L" VFP %s!\n", vfpStat? L"Found" : L"Not Found"));
}
BOOL IsVFPInstruction (DWORD dwInst)
{
DWORD dwCoProc = (dwInst >> 8) & 0xf;
return (VFP_EXIST == vfpStat) && ((dwCoProc == 10) || (dwCoProc == 11));
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL SwitchFPUOwner (PCONTEXT pctx, BOOL *fFirstAccess)
{
BOOL fRet;
KCALLPROFON(61);
*fFirstAccess = !g_fVFPTouched;
if (g_CurFPUOwner != pCurThread) {
// DEBUGCHK (!g_fVFPTouched);
if (g_CurFPUOwner) {
SaveFloatContext(g_CurFPUOwner);
}
g_CurFPUOwner = pCurThread;
RestoreFloatContext(pCurThread);
fRet = (pCurThread->ctx.FpExc & VFP_EX_BIT);
// restore the control registers
pOEMRestoreVFPCtrlRegs (pCurThread->ctx.FpExtra, NUM_EXTRA_CONTROL_REGS);
} else {
if (g_fVFPTouched) {
// we hit an exception, save fpexc and contrl registers
pOEMSaveVFPCtrlRegs (pCurThread->ctx.FpExtra, NUM_EXTRA_CONTROL_REGS);
pCurThread->ctx.FpExc = ReadAndSetFpexc (VFP_ENABLE_BIT);
DEBUGCHK (pCurThread->ctx.FpExc & VFP_EX_BIT);
} else {
// we're preempted and switched back before anyone touching VFP
// do nothing (resotre fpexc, which will be done on the next statement)
}
if (fRet = (pCurThread->ctx.FpExc & VFP_EX_BIT))
SaveFloatContext(pCurThread);
}
g_fVFPTouched = TRUE;
ReadAndSetFpexc (pCurThread->ctx.FpExc = (pCurThread->ctx.FpExc | VFP_ENABLE_BIT) & ~VFP_EX_BIT);
KCALLPROFOFF(61);
return fRet;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
FPUFlushContext(void)
{
if (VFP_EXIST == vfpStat) {
if (!InSysCall ())
KCall ((FARPROC) FPUFlushContext);
else if (g_CurFPUOwner) {
// if VFP has been touched, we need to save the control
// registers. Otherwise, the control registers have already been
// saved and we CANNOT save it again.
if (g_fVFPTouched) {
DEBUGCHK (pCurThread == g_CurFPUOwner);
pOEMSaveVFPCtrlRegs (g_CurFPUOwner->ctx.FpExtra, NUM_EXTRA_CONTROL_REGS);
g_CurFPUOwner->ctx.FpExc = ReadAndSetFpexc (VFP_ENABLE_BIT);
}
// save the general purpose registers
SaveFloatContext(g_CurFPUOwner);
// disable VFP so we'll reload the control registers
// on the nexe VFP instruction (SaveFloatContext is destructive
// to control registers).
ReadAndSetFpexc (0);
g_fVFPTouched = FALSE;
g_CurFPUOwner = 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 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);
ulong OEMInterruptHandler(void);
extern char InterlockedAPIs[], InterlockedEnd[];
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
ARMInit(
int cpuType,
int abSp,
int iSp,
int uSp,
PPTE pOEMAddressTable
)
{
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);
/* update g_pOEMAddressTable */
g_pOEMAddressTable = pOEMAddressTable;
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 OEMAddressTable = %8.8lx\r\n", abSp, iSp, uSp, g_pOEMAddressTable);
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 oldMode0;
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));
ERRFALSE (THUMB_STATE == CST_THUMB_MODE);
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
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));
// before we touch pexi, we need to commit stack or we'll fault while
// accessing it.
switch (DemandCommit ((DWORD) pexi, pth)) {
case DCMT_FAILED:
// fatal stack error
NKDbgPrintfW (L"Fatal Stack Error, Terminating thread %8.8lx, pexi = %8.8lx\r\n", pth, pexi);
DumpFrame(pth, &pth->ctx, id, addr, 10);
pth->ctx.R0 = STATUS_STACK_OVERFLOW;
pth->ctx.R1 = pth->ctx.Pc;
pth->ctx.Sp = (DWORD) pth->tlsPtr - SIZE_PRETLS - 512; // arbitrary safe address
pth->ctx.Pc = (DWORD) pExcpExitThread;
KCALLPROFOFF(0);
return pth;
case DCMT_NEW:
// commited a new page. check if we hit the last page.
// generate stack overflow exception if yes.
stackaddr = (DWORD)pexi & ~(PAGE_SIZE-1);
if ((stackaddr >= KSTKBOUND(pth))
|| ((KSTKBOUND(pth) = stackaddr) >= (KSTKBASE(pth) + 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;
break;
case DCMT_OLD:
// already commited. do nothing
break;
default:
DEBUGCHK (0);
}
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;
((PCALLSTACK) pexi)->dwPrcInfo = CST_IN_KERNEL | ((KERNEL_MODE == GetThreadMode(pth))? 0 : CST_MODE_FROM_USER) | (pth->ctx.Psr & THUMB_STATE);
pexi->addr = addr;
pexi->fsr = info;
pexi->linkage = (DWORD)pth->pcstkTop | 1;
pth->pcstkTop = (PCALLSTACK)pexi;
pth->ctx.Sp = (DWORD)pexi;
if (GetThreadMode(pth) == 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;
}
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;
}
}
// save the exception state of the thread being preempted if fpu has been touched.
if (g_fVFPTouched) {
// read and clear is guaranteed not to generate an exception
pOEMSaveVFPCtrlRegs (pCurThread->ctx.FpExtra, NUM_EXTRA_CONTROL_REGS);
pCurThread->ctx.FpExc = ReadAndSetFpexc (0);
g_fVFPTouched = FALSE;
}
_SetCPUASID(RunList.pth);
hCurThread = RunList.pth->hTh;
pCurThread = RunList.pth;
KPlpvTls = RunList.pth->tlsPtr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -