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

📄 fault.c

📁 wince下的源代码集合打包
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Copyright (c) 1996-2000 Microsoft Corporation.  All rights reserved. *//*+    fault.c - iX86 fault handlers */#include "kernel.h"// disable short jump warning.#pragma warning(disable:4414)///#define LIGHTS(n)   mov dword ptr ss:[0AA001010h], ~(n)&0xFFextern RETADDR ServerCallReturn(PTHREAD pth);extern RETADDR ObjectCall(PTHREAD pth, RETADDR ra, void *args, long iMethod);extern RETADDR MapArgs(const CINFO *pci, int iMethod, void *args);extern BOOL HandleException(PTHREAD pth, int id, ulong addr);extern void NextThread(void);extern void KCNextThread(void);extern void OEMIdle(void);extern void OEMFlushCache(void);extern KTSS MainTSS;extern void Reschedule(void);extern void RunThread(void);extern void DumpTctx(PTHREAD pth, int id, ulong addr, int level);extern void DoPowerOff(void);extern unsigned __int64 g_aGlobalDescriptorTable[];extern DWORD ticksleft;#ifdef NKPROFextern void ProfilerHit(unsigned long ra);#endif#ifdef CELOGextern void CeLogInterrupt(DWORD dwLogValue);#endif#define LOAD_SEGS    0#define ADDR_SLOT_SIZE  0x02000000#define PDES_PER_SLOT   (ADDR_SLOT_SIZE / 1024 / PAGE_SIZE)#define NUM_SLOTS        32#define PID_TO_PT_INDEX(pid) ((pid+1) * PDES_PER_SLOT)#define BLOCKS_PER_PAGE_TABLE (1024 / PAGES_PER_BLOCK)#define BLOCK_SIZE (PAGES_PER_BLOCK * PAGE_SIZE)#define SYSCALL_INT			0x20#define KCALL_INT           0x22#define PT_PTR_TO_INDEX(pp) ((pp) - g_PageTablePool)typedef struct _DIRTYRANGE {    ULONG ulStartBlock;    ULONG ulEndBlock;} DIRTYRANGE, * PDIRTYRANGE;DIRTYRANGE g_PTDirtyRegion[PTE_POOL_SIZE];extern PAGETABLE g_PageTablePool[PTE_POOL_SIZE];extern PAGETABLE g_PageDir;extern PAGETABLE g_ShadowPageDir;       // NOTE:  This really only has 512 entries!extern DWORD ProcessorFeatures;ACCESSKEY g_PageDirAccess = 0;ULONG g_PTMapIdx[PTE_POOL_SIZE];ULONG g_AccessScanIdx = 0;FXSAVE_AREA g_InitialFPUState;PTHREAD g_CurFPUOwner;PPROCESS g_CurASIDProc;////  CR0 bit definitions for numeric coprocessor//#define MP_MASK     0x00000002#define EM_MASK     0x00000004#define TS_MASK     0x00000008#define NE_MASK     0x00000020#define NPX_CW_PRECISION_MASK	0x300#define NPX_CW_PRECISION_24		0x000#define NPX_CW_PRECISION_53		0x200#define NPX_CW_PRECISION_64		0x300PPAGETABLE  LowAddrSpacePageFault(PVOID, DWORD);PPAGETABLE  AllocFreePTE(ULONG);#ifdef DEBUG_VMEMvoid        ValidateVirtualMemory();#endif#define hCurThd  [KData].ahSys[SH_CURTHREAD*4]#define PtrCurThd  [KData].pCurThd#define THREAD_CTX_ES  (THREAD_CONTEXT_OFFSET+8)ERRFALSE(8 == offsetof(CPUCONTEXT, TcxEs));#define THREAD_CTX_EDI  (THREAD_CONTEXT_OFFSET+16)ERRFALSE(16 == offsetof(CPUCONTEXT, TcxEdi));#define Naked void __declspec(naked)#pragma warning(disable:4035)               // Disable warning about no return valueDWORD _inline PhysTLBFlush(void){    __asm {        mov     eax, cr3        mov     cr3, eax    }}void FlushCache(void) {	OEMFlushCache();}#pragma warning(default:4035)               // Turn warning back onvoid SetCPUASID(PTHREAD pth){    PPROCESS pprc;    DWORD aky;    // Make sure this runs without preemption    if (!InSysCall()) {        KCall((PKFN)SetCPUASID, pth);        return;    } else    	KCALLPROFON(62);    pprc = pth->pProc;    if (g_CurASIDProc != pprc)    {        ACCESSKEY akyReset;        PDWORD pAliasPD = &g_PageDir.PTE[0];        PDWORD pRealPD = &g_PageDir.PTE[PID_TO_PT_INDEX(pprc->procnum)];        PDWORD pShadowOld = &g_ShadowPageDir.PTE[PID_TO_PT_INDEX(pCurProc->procnum)];        PDWORD pShadowNew = &g_ShadowPageDir.PTE[PID_TO_PT_INDEX(pprc->procnum)];        CELOG_ThreadMigrate(pprc->hProc, 0);#ifdef DEBUG_VMEM        ValidateVirtualMemory();#endif        //        // Copy the accessed bits out for the current slot 0 process, and copy        // in the new process' page tables        //        do {            // Since page dir entries are either mirrors of the shadow with the            // exception of the access bit, or they are 0, this simple OR will            // only update the accessed bit in the shadow.  It is faster to            // simply do the or than to test the accessed bit for each entry in            // the real page dir#ifdef DEBUG_VMEM            if (g_CurASIDProc != 0)            {                if ((*pShadowOld & ~PG_ACCESSED_MASK) !=                    (*pAliasPD & ~PG_ACCESSED_MASK))                {                    NKDbgPrintfW(                        TEXT("SetCPUASID: Slot 0 PDE doesn't match Process slot PDE\r\n"));                    NKDbgPrintfW(                        TEXT("Slot index = %d, PDE index = %d\r\n"),                        pprc->procnum+1, pAliasPD - &g_PageDir.PTE[0]);                    NKDbgPrintfW(                        TEXT("Slot 0 PDE = 0x%8.8X, Process Slot PDE = 0x%8.8X\r\n"),                        *pAliasPD & ~PG_ACCESSED_MASK, *pShadowOld & ~PG_ACCESSED_MASK);                    DebugBreak();                }            }#endif            *pShadowOld++ |= *pAliasPD;            *pRealPD++ = *pShadowNew;            *pAliasPD++ = *pShadowNew++;        } while (pAliasPD < &g_PageDir.PTE[PDES_PER_SLOT]);		AddAccess(&g_PageDirAccess,pprc->aky);        //  Unmap any sections that the new thread is not allowed to access.        aky = pth->aky | pprc->aky;        akyReset = g_PageDirAccess & (~aky);        if (akyReset)        {            UINT i;            g_PageDirAccess &= aky;            for (i = 0; i < ARRAY_SIZE(g_PageTablePool); i++)            {                UINT j = g_PTMapIdx[i];#ifdef DEBUG_VMEM                if (j < PDES_PER_SLOT)                {                    NKDbgPrintfW(                        TEXT("SetCPUASID: PageTablePool has PDE owned by slot 0\r\n"));                    NKDbgPrintfW(                        TEXT("Pool index = %d, PDE index = %d\r\n"),                        i, j);                    DebugBreak();                }#endif                if (akyReset & (1 << ((j / PDES_PER_SLOT) - 1))) {                    DWORD dwTest = g_PageDir.PTE[j];#ifdef DEBUG_VMEM                    if (dwTest && ((dwTest&PG_PHYS_ADDR_MASK) == (g_PageDir.PTE[j%PDES_PER_SLOT] & PG_PHYS_ADDR_MASK))) {                        NKDbgPrintfW(L"SetCPUASID: Zapping slot0 entry.  PDE=%8.8x j=%4.4x\r\n", dwTest, j);                        NKDbgPrintfW(L"  akyReset=%8.8x g_PageDirAccess=%8.8x new key=%8.8x\r\n", akyReset, g_PageDirAccess, pth->aky);                        NKDbgPrintfW(L"  pCurProc=%8.8lx, pprc=%8.8lx, pth = %8.8lx, &g_PageDir=%8.8lx, &g_ShadowPageDir=%8.8lx\r\n",                        	pCurProc,pprc,pth,&g_PageDir,&g_ShadowPageDir);                        DebugBreak();                    }#endif                    g_PageDir.PTE[j] = 0;                    if (dwTest & PG_ACCESSED_MASK)                    {#ifdef DEBUG_VMEM                        if ((g_ShadowPageDir.PTE[j] & ~PG_ACCESSED_MASK) !=                            (dwTest & ~PG_ACCESSED_MASK))                        {                            NKDbgPrintfW(                                TEXT("SetCPUASID: Real PDE doesn't match Shadow PDE\r\n"));                            NKDbgPrintfW(                                TEXT("Pool index = %d, PDE index = %d\r\n"),                                i, j);                            NKDbgPrintfW(                                TEXT("Real PDE = 0x%8.8X, Shadow PDE = 0x%8.8X\r\n"),                                dwTest & ~PG_ACCESSED_MASK, g_ShadowPageDir.PTE[j] & ~PG_ACCESSED_MASK);                            DebugBreak();                        }#endif                        g_ShadowPageDir.PTE[j] = dwTest;                    }                } else if (aky & (1 << ((j / PDES_PER_SLOT) - 1))) {					g_ShadowPageDir.PTE[j] |= g_PageDir.PTE[j];					g_PageDir.PTE[j] = g_ShadowPageDir.PTE[j];					AddAccess(&g_PageDirAccess,(1 << ((j / PDES_PER_SLOT) - 1)));                }            }        }        SectionTable[0] = SectionTable[(ULONG)pprc->dwVMBase >> VA_SECTION];        g_CurASIDProc = pprc;        PhysTLBFlush();    }    //    //  Change CurProc to the new guy    //    pCurProc = pprc;    hCurProc = pprc->hProc;   	KCALLPROFOFF(62);}LPVOID VerifyAccess(LPVOID pvAddr, DWORD dwFlags, ACCESSKEY aky){    PSECTION pscn;    MEMBLOCK *pmb;    ulong entry;    if ((long)pvAddr >= 0) {        if ((pscn = SectionTable[(ulong)pvAddr>>VA_SECTION]) != 0                && (pmb = (*pscn)[((ulong)pvAddr>>VA_BLOCK)&BLOCK_MASK]) != 0                && pmb != RESERVED_BLOCK                && (pmb->alk & aky) != 0                && (entry = pmb->aPages[((ulong)pvAddr>>VA_PAGE)&PAGE_MASK]) & PG_VALID_MASK                && (!(dwFlags & VERIFY_WRITE_FLAG)                || (entry&PG_PROTECTION) == PG_PROT_WRITE))            return Phys2Virt(PFNfromEntry(entry) | ((ulong)pvAddr & (PAGE_SIZE-1)));    } else {        // Kernel mode only address. If the "kernel mode OK" flag is set or if the        // thread is running in kernel mode, allow the access.        if (dwFlags & VERIFY_KERNEL_OK || GetThreadMode(pCurThread) == KERNEL_MODE) {            DWORD       dwPageDir;            PPAGETABLE  pPageTable;            //            // Find entry in 1st level page dir            //            if ((dwPageDir = g_PageDir.PTE[((ulong)pvAddr) >> 22]) != 0) {		if ((dwPageDir & (PG_LARGE_PAGE_MASK|PG_VALID_MASK)) == (PG_LARGE_PAGE_MASK|PG_VALID_MASK)) {		    return pvAddr;		} else {		    pPageTable = (PPAGETABLE)PHYS_TO_LIN(dwPageDir & PG_PHYS_ADDR_MASK);		    if (pPageTable->PTE[((ulong)pvAddr>>VA_PAGE)&0x3FF] & PG_VALID_MASK)			return pvAddr;		}            }        }    }    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, PtrCurThdcf10:   sti        push    ecx        push    esi        push    edi        call    HandleException        add     esp, 3*4        test    eax, eax        jnz		short NoReschedule        jmp		RescheduleNoReschedule:        jmp     RunThread// Nested exception. Create a fake thread structure on the stackcf20:   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 reloadNaked Reschedule(){	__asm {        test    [KData].bPowerOff, 0FFh    // Was a PowerOff requested?        jz      short rsd10        mov     [KData].bPowerOff, 0        call    DoPowerOff              // Yes - do itrsd10:        sti		cmp 	word ptr ([KData].bResched), 1		jne 	short rsd11        mov     word ptr ([KData].bResched), 0        call    NextThreadrsd11:		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 rsd10rsd12:		mov		eax, [RunList.pth]        test    eax, eax        jz      short rsd50           // nothing to run        cmp     eax, edi

⌨️ 快捷键说明

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