📄 mdarm.c
字号:
ClearSlots ();
return RunList.pth;
}
#define DATA_ABORT_HANDLER_OFFSET 0x3F0
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
PFNVOID
NKSetDataAbortHandler(
PFNVOID pfnDataAbortHandler
)
{
extern DWORD ExceptionVectors[];
LPDWORD pAddrAbortHandler = &ExceptionVectors[DATA_ABORT_HANDLER_OFFSET/sizeof(DWORD)];
PFNVOID pfnOriginalHandler;
pfnOriginalHandler = (PFNVOID) *pAddrAbortHandler;
*pAddrAbortHandler = (DWORD) pfnDataAbortHandler;
return pfnOriginalHandler;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LPVOID
NKCreateStaticMapping(
DWORD dwPhysBase,
DWORD dwSize
)
{
DWORD dwStart, dwEnd;
dwPhysBase <<= 8; // ARM only supports 32-bit physical address.
if (dwStart = (DWORD) Phys2Virt(dwPhysBase)) {
dwEnd = (DWORD) Phys2Virt(dwPhysBase + dwSize - 1);
if (dwStart + dwSize - 1 != dwEnd) {
//
// Start of the requested region was already mapped, but size is too big
//
KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
return NULL;
}
//
// UNCACHED virtual access only.
//
return (LPVOID) (dwStart | 0x20000000);
}
return NULL;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LPVOID
SC_CreateStaticMapping(
DWORD dwPhysBase,
DWORD dwSize
)
{
TRUSTED_API (L"NKCreateStaticMapping", NULL);
return NKCreateStaticMapping(dwPhysBase, dwSize);
}
DWORD dwNKARMFirstLevelSetBits;
//------------------------------------------------------------------------------
// 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.
//------------------------------------------------------------------------------
BOOL LoadPageTable(ulong addr)
{
DWORD dwSlot, aky = 0;
if (!IsKernelVa(addr) // not kernel address
&& (((dwSlot = addr >> VA_SECTION) > MAX_PROCESSES) // if it's a process slot
|| ((aky = 1 << (dwSlot-1)) & CurAKey))) { // we need to have access to the slot
LPDWORD pPtbls;
DWORD ix1M, entry;
DEBUGCHK (dwSlot >= 1);
switch (dwSlot) {
case SECURE_SECTION:
// secure slot, use NK's page table
pPtbls = ProcArray[0].pPTBL;
break;
case MODULE_SECTION:
// module section (slot 1), use 1st 8 entries of gHwPTBL2G
pPtbls = gHwPTBL2G;
break;
default:
// either a sloted process address or 2nd gig
if (dwSlot <= MAX_PROCESSES) {
DEBUGCHK (dwSlot > 1);
// process address
pPtbls = ProcArray[dwSlot-1].pPTBL;
gdwSlotTouched |= aky;
} else {
// in the 2nd gig
pPtbls = MAPPER_SLOT_TO_PTBL (dwSlot);
// check object store
if (IsSlotInObjStore (dwSlot)) {
if (!(CurAKey & pFileSysProc->aky))
return FALSE; // don't have access
gfObjStoreTouched = TRUE;
}
}
break;
}
if ((entry = pPtbls[(addr >> 22) & 7]) // has an entry on the page table
&& !(FirstPT[ix1M = ((addr >> 22) << 2)])) { // no entry on the hardware pagetable
int i;
entry = GetPFN (entry) | PG_COARSE_TBL_BIT | dwNKARMFirstLevelSetBits; // entry is now the physical
// fill all 4 entries on the 1st level page table
for (i = 0; i < 4; i ++) {
FirstPT[ix1M+i] = entry + (i << 10);
}
return TRUE;
}
}
return FALSE;
}
void InvalidateRange (PVOID pvAddr, ULONG ulSize)
{
DWORD dwAddr = (DWORD) pvAddr;
// work on the sloted address
if (dwAddr < (1 << VA_SECTION))
dwAddr += pCurProc->dwVMBase;
OEMCacheRangeFlush ((LPVOID) dwAddr, ulSize, CACHE_SYNC_FLUSH_TLB);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
ExceptionDispatch(
PCONTEXT pctx
)
{
EXCEPTION_RECORD er;
ULONG FaultAddr;
ULONG addr;
int id;
BOOL ThumbMode, fInKMode;
PTHREAD pth;
PEXCINFO pexi;
PCALLSTACK pcstk = pCurThread->pcstkTop;
uint fsr;
DWORD dwThrdInfo = KTHRDINFO (pCurThread); // need to save it since it might get changed during exception handling
pth = pCurThread;
pexi = (PEXCINFO)pcstk;
DEBUGMSG(ZONE_SEH, (TEXT("ExceptionDispatch: pexi=%8.8lx Pc=%8.8lx\r\n"), pexi, pexi->oldPc));
pctx->Pc = pexi->oldPc;
SetContextMode(pctx, ((pcstk->dwPrcInfo & CST_MODE_FROM_USER)? USER_MODE : KERNEL_MODE) | (pcstk->dwPrcInfo & THUMB_STATE));
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
// 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)) {
DEBUGMSG(ZONE_SEH, (TEXT("Raising exception %x flags=%x args=%d pexi=%8.8lx\r\n"),
pctx->R0, pctx->R1, pctx->R2, pexi));
er.ExceptionCode = pctx->R0;
er.ExceptionFlags = pctx->R1;
if (pctx->R3 && pctx->R2) {
if (pctx->R2 > EXCEPTION_MAXIMUM_PARAMETERS) {
er.ExceptionCode = STATUS_INVALID_PARAMETER;
er.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
} else {
memcpy(er.ExceptionInformation, (void*)pctx->R3, pctx->R2*sizeof(DWORD));
er.NumberParameters = pctx->R2;
}
}
id = -1;
} else {
// CPU detected exception. Extract some additional information about
// the cause of the exception from the EXCINFO (CALLSTACK) structure.
//
// The exception handling code uses bit 0 to indicate Thumb vs. ARM
// execution. This bit is not set by the hardware on exceptions. Set
// the bit here:
//
if ( ThumbMode ){
pctx->Pc |= 0x01;
}
addr = pexi->addr;
id = pexi->id;
pctx->Sp += pexi->lowSpBits + sizeof(CALLSTACK);
fsr = pexi->fsr;
DEBUGMSG(ZONE_SEH, (TEXT("addr %x, id %x, sp %8.8lx, fsr=%8.8lx, BVA = %8.8lx\r\n"), addr, id, pctx->Sp, fsr, pctx->Pc));
if (((id == ID_DATA_ABORT) && ((fsr & FSR_STATUS) == FSR_TRANSLATION)) && AutoCommit(addr)) {
pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
goto continueExecution;
}
switch (id) {
case ID_UNDEF_INSTR:
if (VFP_TESTING & vfpStat) {
// we get an exception testing if there is a VFP
vfpStat = VFP_NOT_EXIST;
pctx->Pc += 4; // skip over the fmrx (must be in ARM mode)
pctx->Psr &= ~THUMB_STATE;
pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
goto continueExecution;
}
er.ExceptionCode = STATUS_ILLEGAL_INSTRUCTION;
if ( ThumbMode ){
FaultAddr = pctx->Pc & ~0x01;
if ( *(PUSHORT)FaultAddr == THM_BREAKPOINT ){
er.ExceptionCode = STATUS_BREAKPOINT;
er.ExceptionInformation[0] = *(PUSHORT)FaultAddr;
}
} else if ( (*(PULONG)pctx->Pc & 0x0fffffff) == BREAKPOINT ){
er.ExceptionCode = STATUS_BREAKPOINT;
er.ExceptionInformation[0] = *(PULONG)pctx->Pc;
} else if (IsVFPInstruction (*(PULONG)pctx->Pc)) {
BOOL fFirstAccess, fExcept;
if (!(fExcept = KCall((PKFN)SwitchFPUOwner,pctx, &fFirstAccess))
&& fFirstAccess) {
// first time accessing FPU, and not in exception state
pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
goto continueExecution;
}
// if we're not in exception state, must be an previlege violation
if (!fExcept) {
break;
}
pctx->Fpscr = pth->ctx.Fpscr;
pctx->FpExc = pth->ctx.FpExc;
memcpy (pctx->S, pth->ctx.S, sizeof (pctx->S));
memcpy (pctx->FpExtra, pth->ctx.FpExtra, sizeof (pctx->FpExtra));
// floating point exception
if (pOEMHandleVFPException (&er, pctx)) {
// exception handled, restore thread context
pth->ctx.Fpscr = pctx->Fpscr;
memcpy (pth->ctx.S, pctx->S, sizeof (pctx->S));
memcpy (pth->ctx.FpExtra, pctx->FpExtra, sizeof (pctx->FpExtra));
pth->ctx.FpExc = VFP_ENABLE_BIT;
RestoreFloatContext (pth);
pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
goto continueExecution;
}
// EX bit is already cleared here.
}
break;
case ID_SWI_INSTR:
er.ExceptionCode = STATUS_ILLEGAL_INSTRUCTION;
break;
case ID_DATA_ABORT: // Data page fault
//
// Determine load vs. store depending on whether ARM or Thumb
// mode:
if ( ThumbMode ){
ULONG Instr;
FaultAddr = pctx->Pc & ~0x01; // Clear Thumb bit
Instr = *(PUSHORT)FaultAddr;
if ((Instr & 0xFE00) == 0x5600){
// Discontinuity in the Thumb instruction set:
// LDRSB instruction does not have bit 11 set.
er.ExceptionInformation[0] = 0;
} else {
// All other load instructions have bit 11 set. The
// corresponding store instructions have bit 11 clear
er.ExceptionInformation[0] = !(Instr & (1<<11));
}
} else {
FaultAddr = pctx->Pc;
er.ExceptionInformation[0] = !((*(PULONG)FaultAddr) & (1<<20));
}
switch(fsr & FSR_STATUS) {
case FSR_TRANSLATION:
case FSR_DOMAIN_ERROR:
case FSR_PERMISSION:
DEBUGMSG(ZONE_PAGING, (L"ExD: ID_DATA_ABORT\r\n"));
goto doPageFault;
case FSR_ALIGNMENT:
er.ExceptionCode = STATUS_DATATYPE_MISALIGNMENT;
break;
default:
er.ExceptionCode = 0xdfff0123; break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -