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

📄 mdsh3.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 4 页
字号:
    DWORD   linkage;
    ULONG   oldFir;
    UINT    oldMode0;
    UCHAR   exc;
    UCHAR   lowSp;
    UCHAR   pad[2];
    ULONG   info;
} EXCINFO, *PEXCINFO;

ERRFALSE(sizeof(EXCINFO) <= sizeof(CALLSTACK));
ERRFALSE(offsetof(EXCINFO,linkage) == offsetof(CALLSTACK,pcstkNext));
ERRFALSE(offsetof(EXCINFO,oldFir) == offsetof(CALLSTACK,retAddr));
//ERRFALSE(offsetof(EXCINFO,oldMode) == offsetof(CALLSTACK,pprcLast));
ERRFALSE(64 >= sizeof(CALLSTACK));



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL 
HandleException(
    PTHREAD pth,
    DWORD dwExc,
    DWORD info
    ) 
{
    PEXCINFO pexi;
    DWORD stackaddr;
    KCALLPROFON(0);
#if 0
    NKDbgPrintfW(L"Exception %03x Thread=%8.8lx(%8.8lx) PC=%8.8lx TEA=%8.8lx AKY=%8.8lx\r\n",
                 dwExc, pCurThread, pth, pth->ctx.Fir, info, CurAKey);
#endif

    if (dwExc == 0x160) pth->ctx.Fir -= 2; // TRAPA instruction was completed

    pexi = (struct ExcInfo *)((pth->ctx.R15 & ~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\r\n", pth);
        DumpFrame(pth, (PCONTEXT)&pth->ctx, dwExc, info);
        pth->ctx.R4 = STATUS_STACK_OVERFLOW;
        pth->ctx.R5 = pth->ctx.Fir;
        pth->ctx.R15 = (DWORD) pth->tlsPtr - SIZE_PRETLS - 512;  // arbitrary safe address
        pth->ctx.Fir = (DWORD) pExcpExitThread;
        KCALLPROFOFF(0);
        return TRUE;
    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 TRUE; // restart instruction
        }
        SET_STACKFAULT(pth);
        dwExc = 0x1fe0;             // stack fault exception code
        info = (DWORD)pexi;
        break;
    case DCMT_OLD:
        // already commited. do nothing
        break;
    default:
        DEBUGCHK (0);
    }

    // Setup to capture the exception context in kernel mode but
    // running in thread context to allow preemption and stack growth.
    if (pth->ctx.Fir != (ulong)CaptureContext+4) {
        pexi->exc = (UCHAR)(dwExc >> 5);
        pexi->lowSp = (UCHAR)(pth->ctx.R15 & 63);
        pexi->oldFir = pth->ctx.Fir;
//        pexi->oldMode = GetThreadMode(pth);
        ((PCALLSTACK) pexi)->dwPrcInfo = CST_IN_KERNEL | ((KERNEL_MODE == GetThreadMode(pth))? 0 : CST_MODE_FROM_USER);
        pexi->info = info;
        pexi->linkage = (DWORD)pCurThread->pcstkTop | 1;
        pCurThread->pcstkTop = (PCALLSTACK)pexi;
        pth->ctx.R15 = (DWORD)pexi;
        pth->ctx.Psr |= 0x40000000; // Kernel mode
        pth->ctx.Fir = (ulong)CaptureContext;
        KCALLPROFOFF(0);
        return TRUE;            // continue execution
    }
    DumpFrame(pth, (PCONTEXT)&pth->ctx, dwExc, info);
    RETAILMSG(1, (TEXT("Halting thread %8.8lx\r\n"), pCurThread));
    SurrenderCritSecs();
    DEBUGCHK(!((pCurThread->wInfo >> DEBUG_LOOPCNT_SHIFT) & 1));
    SET_RUNSTATE(pCurThread,RUNSTATE_BLOCKED);
    RunList.pth = 0;
    SetReschedule();
    KCALLPROFOFF(0);
    return 0;
}

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, *PEXCARGS;



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void 
ExceptionDispatch(
    PCONTEXT pctx
    ) 
{
    EXCEPTION_RECORD er;
    int exc;
    ULONG info;
    PEXCARGS pea;
    PTHREAD pth; 
    PEXCINFO pexi;
    DWORD dwThrdInfo = KTHRDINFO (pCurThread);  // need to save it since it might get changed during exception handling

    pth = pCurThread;
    pexi = (PEXCINFO)pth->pcstkTop;
    DEBUGMSG(ZONE_SEH, (TEXT("ExceptionDispatch: pexi=%8.8lx Fir=%8.8lx RA=%8.8lx exc=%x\r\n"),
            pexi, pexi->oldFir, pctx->PR, pexi->exc << 5));

    // Update CONTEXT with infomation saved in the EXCINFO structure
    pctx->Fir = pexi->oldFir;
    // if (pexi->oldMode != KERNEL_MODE)
    if (((PCALLSTACK)pexi)->dwPrcInfo & CST_MODE_FROM_USER) {
        pctx->Psr &= ~0x40000000;
    }
    pctx->R15 = (ULONG)pctx + sizeof(CONTEXT);
    memset(&er, 0, sizeof(er));
    er.ExceptionAddress = (PVOID)pctx->Fir;

    // 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 = (PEXCARGS)pctx->R15;
        exc = -1;
        pctx->Fir -= 2;     // to avoid boundary problems at the end of a try block.
        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.
        pctx->R15 += pexi->lowSp + sizeof(CALLSTACK);
        exc = pexi->exc;
        info = pexi->info;

        // Construct an EXCEPTION_RECORD from the EXCINFO structure
        er.ExceptionInformation[1] = info;
        // TLB Miss on load or store. Attempt to auto-commit the page. If that fails,
        // fall through into general exception processing.
        if (((exc == 0x3) || (exc == 2)) && AutoCommit(info)) {
            pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
            goto continueExecution;
        }
        switch (exc) {
        case 8:     // Address error (store)
            er.ExceptionInformation[0] = 1;
        case 7:     // Address error (load or instruction fetch)
            if (GetContextMode(pctx) != USER_MODE || !(info&0x80000000)) {
                er.ExceptionCode = STATUS_DATATYPE_MISALIGNMENT;
                break;
            }
 #if defined(SH3)
            // (SH3DSP only)
            // Check for the exceptions caused by accessing XY memory in the range
            // between 0xA5000000 to 0xA5FFFFFF.  Please note that "info" is actually 
            // the value of TEA which is the virtual address caused the exception. 
            //
            // Please also note that this does not work exactly as it states in 7729 
            // HW manaul.  According to the manual, accessing XY memory in the user
            // mode when DSP is disabled should cause an address error.  Hitashi 
            // made a request to change this behavior.  The change is similar to the
            // way we handle the excecution caused by the first DSP instruction when
            // DSP is not enabled.  We simply turn on DSP to enable user to access 
            // the XY memory then continue the execution from the faulting
            // instruction without passing the exception to the user app.
            //
            // XY memory is in the range not mapped by TLB so we don't have worry 
            // about any TLB related exceptions.  Please note we only handle it
            // when DSP is disabled.  Treat it as a normal address error if DSP
            // is already onp
            if ( SH3DSP && info <= XYMEMORY_END && info >= XYMEMORY_BEGIN
                  && ( ( pctx->Psr & SR_DSP_ENABLED ) == 0 )){
                
                // If DSP processor and DSP not enabled, enable the DSP.  Thus user
                // can access the XY memory without causing any exceptions
                KCall((PKFN)SwitchDSPOwner,pctx);
                pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);

                // Continue the exception: we don't want to pass this exception to
                // the user app which trying to access the XY memory
                goto continueExecution;
            }
#endif

           goto accessError;

        case 3:     // TLB Miss (store)
        case 4:     // TLB modification
        case 6:     // TLB protection violation (store)
            er.ExceptionInformation[0] = 1;
        case 2:     // TLB miss (load or instruction fetch)
        case 5:     // TLB protection violation (load)
            if (!InSysCall ()) {
                BOOL fSuccess;
                //
                // since we might be calling out of kernel to perform paging and there's
                // no gurantee that the driver underneath won't touch FPU, we need to save
                // the floating point context and restoring it after paging.
                //
#ifdef SH4
                // get the contents of the floating point registers
                FPUFlushContext ();
                // save FPU context in exception context
                memcpy (pctx->FRegs, pCurThread->ctx.FRegs, sizeof(pctx->FRegs));
                memcpy (pctx->xFRegs, pCurThread->ctx.xFRegs, sizeof(pctx->xFRegs));
                pctx->Fpscr = pCurThread->ctx.Fpscr;
                pctx->Fpul = pCurThread->ctx.Fpul;
#endif
                fSuccess = ProcessPageFault ((exc==3)||(exc==4)||(exc==6), info);
                
#ifdef SH4
                // throw away what's in the floating point registers by flushing it.
                FPUFlushContext ();
                // restore FPU context from excepiton context
                memcpy (pCurThread->ctx.FRegs, pctx->FRegs, sizeof(pctx->FRegs));
                memcpy (pCurThread->ctx.xFRegs, pctx->xFRegs, sizeof(pctx->xFRegs));
                pCurThread->ctx.Fpscr = pctx->Fpscr;
                pCurThread->ctx.Fpul = pctx->Fpul;
#endif
                if (fSuccess) {
                    pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
                    goto continueExecution;
                }
            }
    accessError:            
            er.ExceptionCode = STATUS_ACCESS_VIOLATION;
            er.NumberParameters = 2;
            break;
#ifdef SH4
        case 0x40:
        case 0x41:
            KCall((PKFN)SwitchFPUOwner,pctx);
            pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
            goto continueExecution;
        case 9: {           // floating point exception
            DWORD code;
            code = GetCauseFloatCode();
#if 0
            NKDbgPrintfW(L"ExceptionAddress 0x%x\r\n", er.ExceptionAddress);
            NKDbgPrintfW(L"code 0x%x, exc 0x%x\r\n",code,exc);
#endif
            if (code & 0x10)
                er.ExceptionCode = STATUS_FLOAT_INVALID_OPERATION;
            else if (code & 0x8)
                er.ExceptionCode = STATUS_FLOAT_DIVIDE_BY_ZERO;
            else if (code & 0x4)
                er.ExceptionCode = STATUS_FLOAT_OVERFLOW;
            else if (code & 0x2)
                er.ExceptionCode = STATUS_FLOAT_UNDERFLOW;
            else if (code & 0x1)
                er.ExceptionCode = STATUS_FLOAT_INEXACT_RESULT;
            else
            {
                //
                // Reach here 
                // --if code is 0x20 (FPU error)
                // --if code is 0x0 (processor thinks an ieee
                //   exception is possible)
                //
                // both cases require that fp operation be emulated
                // for correct ieee result.
                //
                // save the fpscr before FPUFlushContext will flush it
                // to zero.
                //
                // FPUFlushContext clears fpscr
                //
                FPUFlushContext();

                //
                // Copy current thread fregs and xfreg to user context
                //
                memcpy(&pctx->FRegs[0],&pCurThread->ctx.FRegs[0],sizeof(DWORD)*16);
                memcpy(&pctx->xFRegs[0],&pCurThread->ctx.xFRegs[0],sizeof(DWORD)*16);
                pctx->Fpscr = pCurThread->ctx.Fpscr;
                pctx->Fpul = pCurThread->ctx.Fpul;

                if (HandleHWFloatException(&er,pctx)) 
                {
                    // flush float context back to thread context after exception was handled
                    FPUFlushContext();

                    //
                    // update current thread context with user context
                    //
                    memcpy(&pCurThread->ctx.FRegs[0],&pctx->FRegs[0],sizeof(DWORD)*16);
                    memcpy(&pCurThread->ctx.xFRegs[0],&pctx->xFRegs[0],sizeof(DWORD)*16);

                    pCurThread->ctx.Fpul = pctx->Fpul;
                    pCurThread->ctx.Fpscr = pctx->Fpscr;
                    pCurThread->ctx.Psr = pctx->Psr;

                    pctx->Fir+=2; // +2: return control to instruction successor
                    pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
                    goto continueExecution;
                }
            }
            //
            // Update user context fpscr and fpul
            //
            pCurThread->ctx.Fpscr = pctx->Fpscr;
            pCurThread->ctx.Fpul = pctx->Fpul;
            pCurThread->ctx.Psr = pctx->Psr;
            break;
        }
#endif
        case 11:        // Breakpoint
            er.ExceptionInformation[0] = info;
            er.ExceptionCode = STATUS_BREAKPOINT;
            break;

        case 12:    // Reserved instruction
        case 13:    // Illegal slot instruction
#ifdef SH3
            //
            // Assume DSP instruction.
            // If DSP processor and DSP not enabled, enable the DSP.
            //

            if ( SH3DSP && ((pctx->Psr & SR_DSP_ENABLED) == 0) ){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -