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

📄 mdarm.c

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