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

📄 fault.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    DWORD dwSize
    ) 
{
    LPVOID pvRet = NULL;
    DWORD dw4MBase;                         // 4M aligned address

    dwPhysBase <<= 8;                       // Only supports 32-bit physical address.
    dw4MBase = dwPhysBase & -dw4M;          // 4M alignment
    
    if (!dwSize || (dwPhysBase & (PAGE_SIZE-1))) {
        KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
        return NULL;
    }

    if (IsSystemStarted ())
        EnterCriticalSection(&VAcs);
    
    if (dwPhysBase < 0x20000000 && ((dwPhysBase + dwSize) < 0x20000000)) {
        
        pvRet = Phys2VirtUC(dwPhysBase);
        
    } else {

        DWORD dwPDENeeded;
        DWORD pdeStart, pdeWalk;

        dwPDENeeded = ((dwPhysBase + dwSize - dw4MBase - 1) / dw4M) + 1;

        DEBUGCHK (dwPDENeeded);

        if (pdeStart = FindExistingMapping (dw4MBase, dwPDENeeded)) {

            dwPDENeeded = 0;    // indicate success
        
        } else if (pdeStart = FindFreePDE (dwPDENeeded)) {
            
            if (LARGE_PAGE_SUPPORT_DETECTED) {
                //
                // Supports 4MB page mappings.
                //
                for (pdeWalk = pdeStart; dwPDENeeded; pdeWalk ++, dw4MBase += dw4M, dwPDENeeded --) {
                    g_pPageDir->PTE[pdeWalk] = dw4MBase | PG_KERNEL_RW | PG_LARGE_PAGE_MASK | PG_NOCACHE | PG_WRITE_THRU_MASK;
                }

            } else if ((((DWORD)PageFreeCount > dwPDENeeded + MIN_PROCESS_PAGES) || !IsSystemStarted())
                    && AllocPagesForPT (dwPDENeeded)) {
                //
                // Use 4k page tables to map.
                //
                // We've at least got enough pages available and that many have been set
                // aside for us (though not yet assigned). 
                //
                PAGETABLE* pPageTable;
                DWORD pfnAddr;
                int i;
                
                for (pdeWalk = pdeStart; dwPDENeeded; pdeWalk ++, dwPDENeeded --) {
                    
                    pfnAddr = GetNextPageForPT ();

                    pPageTable = (PAGETABLE*) Phys2Virt(pfnAddr);
                    DEBUGCHK(pPageTable);   

                    g_pPageDir->PTE[pdeWalk] = pfnAddr | PG_KERNEL_RW;

                    for (i = 0; i < 1024; i++, dw4MBase += PFN_INCR) {
                        pPageTable->PTE[i] = dw4MBase | PG_KERNEL_RW | PG_NOCACHE | PG_WRITE_THRU_MASK;
                    }

                    DEBUGCHK (!(dw4MBase & (dw4M -1)));
                }
            }

        }
        
        // dwPDENeeded will be zero if success
        if (dwPDENeeded == 0) {
            pvRet = (LPVOID) ((pdeStart << 22) + (dwPhysBase & (dw4M - 1)));  // create a virtual address from PD index
        }
    }
    if (IsSystemStarted ())
        LeaveCriticalSection(&VAcs);
    
    return (pvRet);
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LPVOID
SC_CreateStaticMapping(
    DWORD dwPhysBase,
    DWORD dwSize
    ) 
{
    TRUSTED_API (L"SC_CreateStaticMapping", NULL);

    return NKCreateStaticMapping(dwPhysBase, dwSize);
}






#pragma warning(disable:4035 4733)
//------------------------------------------------------------------------------
//
// System call trap handler.
//
// Pop the iret frame from the stack, switch back to the caller's stack, enable interrupts,
// and dispatch the system call.
//
//      CPU State:  ring1 stack & CS, interrupts disabled.
//                  edx:eax == rtn value if PSL return
//
//------------------------------------------------------------------------------
PVOID __declspec(naked) Int20SyscallHandler (void)
{
    __asm {
        // The following three instructions are only executed once on Init time.
        // It sets up the KData PSL return function pointer and returns the
        // the 'real' address of the Int20 handler (sc00 in this case).
        mov [KData.pAPIReturn], offset APICallReturn
        mov dword ptr [MD_CBRtn], offset CBRtnCommon
        mov eax, offset sc00
        ret

sc00:   pop     ecx                     // (ecx) = EIP of "int SYSCALL"
        sub     ecx, FIRST_METHOD+2     // (ecx) = iMethod * APICALL_SCALE
        cmp     ecx, -APICALL_SCALE     // check callback return
        je      short CallbackRtn       // returning from callback

        sar     ecx, 1                  // (ecx) == iMethod
        pop     eax                     // (eax) == caller's CS
        and     al, 0FCh
        cmp     al, KGDT_R1_CODE
        je      short KPSLCall          // caller was in kernel mode

        // caller was in user mode

        // special casing RaiseException
        cmp     ecx, RAISEEXCEPTION
        je      short UPSLCallTrusted   // do not switch stack for RaiseException
        
        // PerformCallBack MUST BE CALLED IN KMODE (From PSL)
        // cmp     ecx, PERFORMCALLBACK
        // je      short DoPerformCallback

        // check if the caller is trusted
        mov     eax, PtrCurProc         // (eax) == pCurProc
        cmp     byte ptr [eax+OFFSET_TRUSTLVL], KERN_TRUST_FULL     // is it fully trusted?
        je      short UPSLCallTrusted   // do fully trusted if yes

        // not trusted, switch to secure stack (need to update TLSPTR too)
        mov     eax, PtrCurThd          // (eax) == pCurThread
        mov     edx, [eax].tlsSecure    // (eax) == TLSPTR of the secure stack
        mov     [eax].tlsPtr, edx       // update thread's tlsPtr
        mov     [KData].lpvTls, edx     // set KData's TLS pointer

        // find the 'real' callstack if there is one(SEH might create a faked one)
        mov     edx, [eax].pcstkTop     // (edx) == pCurThread->pcstkTop
UPSLNextSTK:        
        test    edx, edx
        je      short UPSLCallFirstTrip // 0 if first trip
        cmp     dword ptr [edx].akyLast, 0  // akyLast == 0 if faked
        jne     short UPSLFoundStkTop   // found the real ccallstack
        mov     edx, [edx].pcstkNext
        jmp     short UPSLNextSTK
        
        
UPSLFoundStkTop:
        // (not trusted) in callback function, calling into PSL again
        // (edx) = 'real' pcstk
        mov     edx, [edx].dwPrevSP     // (edx) == pcstk->dwPrevSP
        jmp     short UPSLCallNonTrusted

UPSLCallFirstTrip:
        // (non-trusted) first trip into PSL, use tlsPtr to figure out where SP should be
        // (eax) == PthCurThd
        mov     edx, [eax].tlsSecure    // (eax) == TLSPTR of the secure stack
        sub     edx, SECURESTK_RESERVE  // (edx) == new stack
        
UPSLCallNonTrusted:
        // (edx) == new SP
        mov     esp, [esp+4]            // (esp) == caller's SP
        xchg    esp, edx                // switch stack
        
        // make roon for arguments on the new stack
        sub     esp, MAX_PSL_ARGS       // save space for MAX # of PSL arguments + return address
        mov     eax, USER_MODE          // calling from user mode
        jmp     short PSLCallCommon
        
UPSLCallTrusted:
        // caller is fully trusted, use current stack
        mov     esp, [esp+4]            // get the user stack
        mov     edx, 0                  // prevSP set to 0 when no stack swtich
        mov     eax, USER_MODE          // calling from user mode
        jmp     short PSLCallCommon
        
KPSLCall:
        // caller was in kernel mode

        // is this a callback?
        cmp     ecx, PERFORMCALLBACK
        je      short DoPerformCallback

        // caller was in kernel mode
        add     esp, 4                  // discard the EFLAGS
        mov     edx, 0                  // prevSP set to 0 when no stack swtich
        mov     eax, KERNEL_MODE        // we're in kernel mode

PSLCallCommon:
        // (eax) == caller's mode
        // (ecx) == iMethod
        // (edx) == caller's stack
        // (esp) == secure stack if not trusted, caller stack if trusted/kmode
        
        push    fs:dword ptr [0]        // save exception chain linkage
        sti                             // interrupt ok now

        cmp     edx, 0                  // are we using the same stack?
        je      short DoObjectCall      

        // stack changed, need to copy argument from one to the other
        push    ecx
        push    esi
        push    edi

        mov     esi, edx
        lea     edi, [esp+16]           // +16 == fs:0 and ecx, esi, edi we just pushed
        mov     ecx, MAX_PSL_ARGS/4
        rep     movsd

        // update fs
        mov     ecx, PtrCurThd
        mov     ecx, [ecx].tlsPtr
        mov     edi, offset g_aGlobalDescriptorTable+KGDT_PCR
        sub     ecx, FS_LIMIT+1         // (ecx) = ptr to NK_PCR base
        mov     word ptr [edi+2], cx    // set low word of FS base
        shr     ecx, 16
        mov     byte ptr [edi+4], cl    // set third byte of FS base
        mov     byte ptr [edi+7], ch    // set high byte of FS base
        push    fs
        pop     fs                      // cause fs to reload

        pop     edi
        pop     esi
        pop     ecx
        pop     fs:dword ptr [0]        // make sure the new fs:[0] is consistent with the old one
        push    fs:dword ptr [0]        // save exception chain linkage

DoObjectCall:
        // PSL Call, setup OBJCALLSTRUCT on stack (linkage already pushed)
        push    eax                     // mode
        push    edx                     // previous ESP
        push    ecx                     // iMethod

        push    esp                     // arg0 == pointer to OBJCALLSTRUCT
        
        call    ObjectCall              // (eax) = api function address (0 if completed)
        add     esp, 20                 // clear ObjectCall args off the stack
        mov     fs:dword ptr [0], -2    // mark PSL boundary in exception chain
        mov     ecx, PtrCurThd          // (ecx) = ptr to THREAD struct
        mov     ecx, [ecx].pcstkTop     // (ecx) = ptr to CALLSTACK struct
        mov     [ecx].ExEsp, esp        // .\     v
        mov     [ecx].ExEbp, ebp        // ..\    v
        mov     [ecx].ExEbx, ebx        // ...> save registers for possible exception recovery
        mov     [ecx].ExEsi, esi        // ../
        mov     [ecx].ExEdi, edi        // ./

        pop     edx                     // get rid of return address
        call    eax                     // & call the api function in KMODE (all PSL calls in KMODE now)
APICallReturn:

        push    0                       // space for exception chain linkage
        push    KERNEL_MODE             // current thread mode

// Retrieve return address, mode, and exception linkage from the
// thread's call stack.
//
//  (eax:edx) = function return value
//  (TOS) = thread's execution mode
//  (TOS+4) = space to receive previous exception chain linkage
        sub     esp, 4              // room for dwPrevSP (must be at esp+8 when returned from ServerCallReturn)
        push    eax                 // save return value
        push    edx                 // ...
        
        lea     eax, [esp+8]        // (eax) = ptr to SVRRTNSTRUCT
        push    eax                 // arg0 - ptr to SVRRTNSTRUCT
        call    ServerCallReturn    // (eax) = api return address
        add     esp, 4              // get rid of arg 0
        mov     edx, [esp]          // restore edx
        mov     [esp], eax          // save return address
        mov     eax, [esp+4]        // restore eax
        mov     ecx, [esp+16]       // (ecx) = saved exception linkage
        cmp     dword ptr [esp+12], KERNEL_MODE
        mov     fs:[0], ecx         // restore exception linkage
        jne     short UPSLRtn       // dispatch thread in kernel mode

        // returning to KMode caller, just pop working data and return
        ret     16

UPSLRtn:        
        // returning to user mode process

        // check if stack switch is needed
        cmp     dword ptr [esp+8], 0 // need stack switch?
        je      short UPSLRtnNoStkSwitch

        // not trusted, dwPrevSP has the right value
        add     dword ptr [esp+8], 4  // [esp+8] is already dwPrevSP, add 4 to remove the return address

        // update TLS
        push    edx
        mov     edx, PtrCurThd          // (edx) == pCurThread
        mov     ecx, [edx].tlsNonSecure // (ecx) == TLSPTR of the non-secure stack
        mov     [edx].tlsPtr, ecx       // update thread's tlsPtr
        mov     [KData].lpvTls, ecx     // set KData's TLS pointer

        // need to update fs
        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                      // cause fs to reload

        pop     edx

        // restore fs:[0] on new stack
        mov     ecx, [esp+16]
        mov     fs:[0], ecx
        
        jmp     short UPSLRtnToCaller

UPSLRtnNoStkSwitch:
        // pCurProc is fully trusted, no stack switch required
        lea     ecx, [esp+20]
        mov     [esp+8], ecx        // ESP restore value

UPSLRtnToCaller:
        
        // [esp] == return address, [esp+8] == stack, both must have already been setup correctly
        mov     dword ptr [esp+4], KGDT_R3_CODE | 3
        mov     dword ptr [esp+12], KGDT_R3_DATA | 3
        retf                        // return to ring3 & restore stack pointer

////////////////////////////////////////////////////////////////////////////////////////
// callback returns from user mode process
//
CallbackRtn:
        pop     ecx                     // (eax) == caller's CS
        and     cl, 0FCh
        cmp     cl, KGDT_R1_CODE
        je      short CBRtnKMode        // Are we in kmode? (User called SetKMode in the callback function)

        // we're in user mode
        mov     esp, [esp+4]            // edx == stack of returning thread
        jmp     short CBRtnChkTrust
        
CBRtnKMode:
        // in KMODE
        add     esp, 4                   // skip the EFLAGS

CBRtnChkTrust:
        sti                             // interrupt okay now

        // do we need to switch stack?
        mov     edx, PtrCurThd              // (edx) == pCurThread
        mov     ecx, [edx].pcstkTop         // (ecx) == pCurThread->pcstkTop
        cmp     dword ptr [ecx].dwPrevSP, 0 // need stack change?
        je      short CBRtnCommon

        // the stack needs to be changed

        // get the new SP
        mov     esp, [ecx].dwPrevSP
        add     esp, 4                  // less retrun address

        // update TLS   (edx == pCurThread on entrance)
        mov     ecx, [edx].tlsSecure    // (ecx) == TLSPTR of the secure stack

⌨️ 快捷键说明

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