⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mdarm.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    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 + -