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

📄 fault.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:

#pragma warning(default:4035)               // Turn warning back on


_inline void ClearOneSlot (DWORD dwVMBase)
{
    memset (&g_pPageDir->PTE[dwVMBase >> 22], 0, 32);
}


void ClearSlots (BOOL fNeedFlush)
{
    DWORD dwSlotRst;
    if (dwSlotRst = gdwSlotTouched & ~CurAKey) {
        int i;
        for (i = 1; dwSlotRst; i ++) {
            if (dwSlotRst & (1 << i)) {
                dwSlotRst &= ~(1 << i);
                ClearOneSlot (ProcArray[i].dwVMBase);
            }
        }
        fNeedFlush = TRUE;
        gdwSlotTouched &= CurAKey;
    }
    if (gfObjStoreTouched && !(pFileSysProc->aky & CurAKey)) {
        DWORD dwBits = g_ObjStoreSlotBits;
        int i;
        for (i = 0; dwBits; i ++) {
            if (dwBits & (1 << i)) {
                dwBits &= ~(1 << i);
                ClearOneSlot ((FIRST_MAPPER_SLOT + i) << VA_SECTION);
            }
        }
        fNeedFlush = TRUE;
        gfObjStoreTouched = FALSE;
    }
    if (fNeedFlush) {
        OEMCacheRangeFlush (0, 0, CACHE_SYNC_FLUSH_TLB);
    }
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void 
SetCPUASID(
    PTHREAD pth
    )
{
    if (!InSysCall ()) {
        KCall ((FARPROC) SetCPUASID, pth);
    } else {
        BOOL fNeedFlush = (pCurProc != pth->pProc);
        if (fNeedFlush) {
            DWORD dwPDE = SHARED_BASE_ADDRESS >> 22;
            int   i;
            if (IsCeLogStatus(CELOGSTATUS_ENABLED_GENERAL)) {
                CeLogThreadMigrate(pth->pProc->hProc, 0);
            }
            memcpy (&g_pPageDir->PTE[0], &pth->pProc->pPTBL[0], 32);

            // make shared section read-only
            for (i = 0; i < PDES_PER_SLOT; i ++) {
                g_pPageDir->PTE[dwPDE+i] &= ~PG_WRITE_MASK;
            }
        }
        ClearSlots (fNeedFlush);
        pCurProc = pth->pProc;
        hCurProc = pCurProc->hProc;
        SectionTable[0] = pCurProc->procnum? SectionTable[pCurProc->procnum+1] : &NKSection;
    }
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LPVOID MDValidateKVA (DWORD dwAddr)
{
    DWORD       dwPageDir;
    PPAGETABLE  pPageTable;

    //
    // Find entry in 1st level page dir
    //
    if ((dwPageDir = g_pPageDir->PTE[VA_TO_PD_IDX (dwAddr)]) != 0) {
        if ((dwPageDir & (PG_LARGE_PAGE_MASK|PG_VALID_MASK)) == (PG_LARGE_PAGE_MASK|PG_VALID_MASK)) {
            return (LPVOID) dwAddr;
        } else {
            pPageTable = (PPAGETABLE)PHYS_TO_LIN(dwPageDir & PG_PHYS_ADDR_MASK);
            if (pPageTable->PTE[(dwAddr>>VA_PAGE)&0x3FF] & PG_VALID_MASK)
            return (LPVOID) dwAddr;
        }
    }
    return 0;
}


//------------------------------------------------------------------------------
//
// Function:
//  CommonFault
//
// Description:
//  CommonFault is jumped to by the specific fault handlers for unhandled
//  exceptions which are then dispatched to the C routine HandleException.
//
// At entry:
//  ESP     points to stack frame containing PUSHAD, ERROR CODE, EIP, CS,
//          EFLAGS, (and optionally Old ESP, Old SS).  Normally this is the
//          last part of the thread structure, the saved context.  In the case
//          of a nested exception the context has been saved on the ring 0
//          stack.  We will create a fake thread structure on the stack to hold
//          the captured context.  The remaining segment registers are added by
//          this routine.
//
//  ECX     is the faulting address which is passed to HandleException
//
//  ESI     is the exception id which is passed to HandleException
//
//  Return:
//   CommonFault jumps to Reschedule or resumes execution based on the return
//   value of HandleException.
//
//------------------------------------------------------------------------------
Naked 
CommonFault()
{
    _asm {
        cld
        mov     eax, KGDT_R3_DATA
        mov     ds, ax
        mov     es, ax
        dec     [KData].cNest
        jnz     short cf20          // nested fault
        mov     esp, offset KData-4
        mov     edi, PtrCurThd
cf10:   sti
        push    ecx
        push    esi
        push    edi
        call    HandleException
        add     esp, 3*4
        test    eax, eax
        jnz     short NoReschedule
        jmp     Reschedule
NoReschedule:
        jmp     RunThread

// Nested exception. Create a fake thread structure on the stack
cf20:   push    ds
        push    es
        push    fs
        push    gs
        sub     esp, THREAD_CONTEXT_OFFSET
        mov     edi, esp            // (edi) = ptr to fake thread struct
        jmp     short cf10
    }
}




//------------------------------------------------------------------------------
//
// Do a reschedule.
//
//  (edi) = ptr to current thread or 0 to force a context reload
//
//------------------------------------------------------------------------------
Naked 
Reschedule()
{
    __asm {
rsd10:
        sti
        cmp     word ptr ([KData].bResched), 1
        jne     short rsd11
        mov     word ptr ([KData].bResched), 0
        call    NextThread
rsd11:
        cmp     dword ptr ([KData].dwKCRes), 1
        jne     short rsd12
        mov     dword ptr ([KData].dwKCRes), 0
        call    KCNextThread

        cmp     dword ptr ([KData].dwKCRes), 1
        je      short rsd10

rsd12:
        mov     eax, [RunList.pth]
        test    eax, eax
        jz      short rsd50           // nothing to run
        cmp     eax, edi
        jne     short rsd20
        jmp     RunThread           // redispatch the same thread

// Switch to a new thread's process context.
// Switching to a new thread. Update current process and address space
// information. Edit the ring0 stack pointer in the TSS to point to the
// new thread's register save area.
//
//      (eax) = ptr to thread structure

rsd20:  mov     edi, eax                // Save thread pointer
        mov     esi, (THREAD)[eax].hTh          // (esi) = thread handle
        push    edi
        call    SetCPUASID              // Sets hCurProc for us!
        pop     ecx                     // Clean up stack

        mov     hCurThd, esi            // set the current thread handle
        mov     PtrCurThd, edi          //   and the current thread pointer
        mov     ecx, [edi].tlsPtr       // (ecx) = thread local storage ptr
        mov     [KData].lpvTls, ecx     // set TLS pointer

        cmp     edi, g_CurFPUOwner
        jne     SetTSBit
        clts
        jmp     MuckWithFSBase

SetTSBit:
        mov     eax, CR0
        test    eax, TS_MASK
        jnz     MuckWithFSBase
        or      eax, TS_MASK
        mov     CR0, eax

MuckWithFSBase:
        mov     edx, offset g_aGlobalDescriptorTable+KGDT_PCR
        sub     ecx, FS_LIMIT+1         // (ecx) = ptr to NK_PCR base
        mov     word ptr [edx+2], cx    // set low word of FS base
        shr     ecx, 16
        mov     byte ptr [edx+4], cl    // set third byte of FS base
        mov     byte ptr [edx+7], ch    // set high byte of FS base

        push    fs
        pop     fs

        lea     ecx, [edi].ctx.TcxSs+4  // (ecx) = ptr to end of context save area
        mov     [MainTSS].Esp0, ecx
        jmp     RunThread               // Run thread pointed to by edi

// No threads ready to run. Call OEMIdle to shutdown the cpu.

rsd50:  cli

        cmp     word ptr ([KData].bResched), 1
        je      short DoReschedule
        call    OEMIdle
        mov     byte ptr ([KData].bResched), 1
        jmp     Reschedule
DoReschedule:
        sti
        jmp     Reschedule
    }
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Naked 
CommonIntDispatch()
{
    _asm {
        cld
        mov     eax, KGDT_R3_DATA
        mov     ds, ax
        mov     es, ax
        dec     [KData].cNest
        jnz     short cid20         // nested fault
        mov     esp, offset KData-4
        mov     edi, PtrCurThd
cid10:
#ifdef NKPROF
        push    esi                 // save ESI
        mov     eax, 80000000h      // mark as ISR entry
        push    eax                 // Arg 0, cNest + SYSINTR_xxx
        call    CeLogInterrupt
        pop     eax                 // cleanup the stack from the call
        pop     esi                 // restore ESI
#endif // NKPROF

        sti

        call    esi

        mov     ecx, dword ptr [pfnOEMIntrOccurs]   // (ecx) = pfnOEMIntrOccurs
        push    eax                 // push argument == SYSINTR returned
        call    ecx                 // call pfnOEMintrOccurs
        pop     ecx                 // dummy pop

        cli

#ifdef NKPROF
        push    eax                 // Save original SYSINTR return value.
        bswap   eax                 // Reverse endian
        mov     ah, [KData].cNest   // Nesting level (0 = no nesting, -1 = nested once)
        neg     ah                  // Nesting level (0 = no nesting,  1 = nested once)
        bswap   eax                 // Reverse endian
        push    eax                 // Arg 0, cNest + SYSINTR_xxx
        call    CeLogInterrupt
        pop     eax                 // cleanup the stack from the call
        pop     eax                 // restore original SYSINTR value
#endif // NKPROF
        test    eax, eax
        jz      short RunThread     // SYSINTR_NOP: nothing more to do

#ifdef NKPROF
        cmp     eax, SYSINTR_PROFILE
        jne     short cid13
        call    ProfilerHit
        jmp     RunThread           // Continue on our merry way...
cid13:
#endif // NKPROF

        cmp     eax, SYSINTR_RESCHED
        je      short cid15
        lea     ecx, [eax-SYSINTR_DEVICES]
        cmp     ecx, SYSINTR_MAX_DEVICES
        jae     short cid15         // force a reschedule for good measure

// A device interrupt has been signaled. Set the appropriate bit in the pending
// events mask and set the reschedule flag. The device event will be signaled
// by the scheduler.

        mov     eax, 1              // (eax) = 1
        cmp     ecx, 32             // ISR# >= 32?
        jae     cid18               // take care of ISR# >= 32 if true

        // ISR# < 32
        shl     eax, cl             // (eax) = 1 << ISR#
        or      [KData].aPend1, eax // update PendEvent1
cid15:  or      [KData].bResched, 1 // must reschedule
        jmp     RunThread

        // ISR# >= 32
cid18:  sub     cl, 32              // ISR# -= 32
        shl     eax, cl             // (eax) = 1 << (ISR#-32)
        or      [KData].aPend2, eax // update PendEvent2
        or      [KData].bResched, 1 // must reschedule
        jmp     RunThread

// Nested exception. Create a fake thread structure on the stack
cid20:  push    ds
        push    es
        push    fs
        push    gs
        sub     esp, THREAD_CONTEXT_OFFSET
        mov     edi, esp            // (edi) = ptr to fake thread struct
#ifdef NKPROF
        mov     dword ptr (pthFakeStruct), edi
#endif        
        jmp     short cid10
    }
}




//------------------------------------------------------------------------------
//
// Continue thread execution.
//
//  (edi) = ptr to Thread structure
//
//------------------------------------------------------------------------------
Naked 
RunThread()
{
    _asm {
        cli
        cmp     word ptr ([KData].bResched), 1
        jne short NotReschedule
        jmp     Reschedule
NotReschedule:
        inc     [KData].cNest
        lea     esp, [edi].ctx.TcxGs
        pop     gs
        pop     fs
        pop     es
        pop     ds
        popad
        add     esp, 4

⌨️ 快捷键说明

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