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

📄 fault.c

📁 可用于嵌入式编程学习
💻 C
📖 第 1 页 / 共 4 页
字号:
        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

        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     ticksleft, 0
        je		short skip_force_reched
        mov		byte ptr ([KData].bResched), 1

skip_force_reched:
        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 CELOG
		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

		sti

        call    esi

		cli

#ifdef CELOG
        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
        test    eax, eax
        jz      short cid17         // SYSINTR_NOP: nothing more to do

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

        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
        shl     eax, cl
        or      [KData].aInfo[KINX_PENDEVENTS*4], eax
cid15:  or      [KData].bResched, 1 // must reschedule
cid17:  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
        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
        iretd
        cli
        hlt
    }
}



Naked PageFault()
{
    _asm {
        pushad
        mov     ebx, OFFSET KData
        mov     edi, cr2
        test    edi, edi
        js      short pf50              // Address > 2GB, get out now
        dec     [ebx].cNest             // count kernel reentrancy level
        mov     esi, esp                // (esi) = original stack pointer
        jnz     short pf10
        lea     esp, [ebx-4]            // switch to kernel stack (&KData-4)

//  Process a page fault for the "user" address space (0 to 0x7FFFFFFF)
//
//  (edi) = Faulting address
//  (ebx) = ptr to KData
//  (esi) = Original ESP

pf10:   cld                         // Need to do this since the page fault could have come from anywhere!
		cmp		dword ptr ([KData].dwInDebugger), 0	// see if debugger active
		jne		short pf20							// if so, skip turning on of interrupts
		sti											// enable interrupts

pf20:	push    [esi+32]
        push	edi
        call    LowAddrSpacePageFault
        cli
        test    eax, eax
        jz		short pf40          // page not found in the Virtual memory tree
        cmp     word ptr ([KData].bResched), 1
        je      short pf60          // must reschedule now
        inc     [ebx].cNest         // back out of kernel one level
        mov     esp, esi            // restore stack pointer
        popad
        add     esp, 4
        iretd

//  This one was not a good one!  Jump to common fault handler
//
//  (edi) = faulting address

pf40:   inc     [ebx].cNest         // back out of kernel one level
        mov     esp, esi            // restore stack pointer
pf50:   mov     ecx, edi            // (ecx) = fault effective address
        mov     esi, 0Eh
        jmp     CommonFault

// The reschedule flag was set and we are at the first nest level into the kernel
// so we must reschedule now.

pf60:   mov     edi, PtrCurThd      // (edi) = ptr to current THREAD
        jmp     Reschedule
    }
}

Naked GeneralFault()
{
    _asm {
        pushad
        xor     ecx, ecx            // (ecx) = 0 (fault effective address)
        mov     esi, 13
        jmp     CommonFault
    }
}

Naked InvalidOpcode(void)
{
    __asm {
        push    eax
        pushad
        mov     esi, 6
        xor     ecx, ecx            // (ecx) = 0 (fault effective address)
        jmp     CommonFault
    }
}

Naked ZeroDivide(void)
{
    __asm {
        push    eax
        pushad
        xor     esi, esi            // (esi) = 0 (divide by zero fault)
        xor     ecx, ecx            // (ecx) = 0 (fault effective address)
        jmp     CommonFault
    }
}

const BYTE PosTable[256] = {
	0,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,
	6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,
	7,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,
	6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,
	8,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,
	6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,
	7,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,
	6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
};


void __declspec(naked) GetHighPos(DWORD foo) {
	_asm {
		mov ecx, dword ptr [esp + 4]
		push ebx
		lea ebx, PosTable

		mov dl, 0xff
		xor eax, eax
		mov al, cl
		xlatb
		test al, al
		jne res

		shr ecx, 8
		add dl, 8
		mov al, cl
		xlatb
		test al, al
		jne res

		shr ecx, 8
		add dl, 8
		mov al, cl
		xlatb
		test al, al
		jne res

		shr ecx, 8
		add dl, 8
		mov al, cl
		xlatb
		test al, al
		jne res

		mov al, 9
res:
		add al, dl
		pop ebx
		ret
	}
}

Naked Int1Fault(void)
{
    __asm {
        push    eax                             // Save orig EAX as fake error code
        cmp     word ptr [esp + 6], 0FFFFh      // Is it an API call fault?
        je      skip_debug                      // Yes - handle page fault first
        mov     eax, [esp + 4]                  // (eax) = faulting EIP
        and     dword ptr [esp + 12], not 0100h  // Clear TF if set
        test    byte ptr [esp + 8], 3           // Are we trying to SS ring 0?
        jz      skip_debug                      // Yes - get out quick
        mov     eax, dword ptr [esp]            // Restore original EAX

        pushad
        mov     esi, 1
        xor     ecx, ecx            // (ecx) = 0 (fault effective address)
        jmp     CommonFault

skip_debug:
        pop     eax
        iretd
    }
}

Naked Int2Fault(void)
{
    __asm {
        push    eax                 // Fake error code
        pushad
        mov     esi, 2
        xor     ecx, ecx            // (ecx) = 0 (fault effective address)
        jmp     CommonFault
    }
}

Naked Int3Fault(void)
{
    __asm {
        dec     dword ptr [esp]     // Back up EIP
        push    eax                 // Fake error code
        pushad
        mov     esi, 3
        xor     ecx, ecx            // (ecx) = 0 (fault effective address)
        jmp     CommonFault
    }
}

PPAGETABLE LowAddrSpacePageFault(LPVOID pvAddr, DWORD flags)
{
    PSECTION pscn;
    MEMBLOCK *pmb;
    ULONG entry;
    ACCESSKEY ReqKey;
    DWORD OldPTE = 0;
    DWORD OldPDE = 0;
    if (((pscn = SectionTable[(ulong)pvAddr >> VA_SECTION]) != 0) &&
        ((pmb = (*pscn)[((ulong)pvAddr >> VA_BLOCK)&BLOCK_MASK]) != 0) &&
        (pmb != RESERVED_BLOCK && (ReqKey = TestAccess(&pmb->alk, &CurAKey)) != 0) &&
        ((entry = pmb->aPages[((ulong)pvAddr >> VA_PAGE) & PAGE_MASK]) & PG_VALID_MASK) &&
        (!(flags&2) || (entry & (PG_WRITE_MASK | PG_WRITE_THRU_MASK)))) {
        PPAGETABLE pPageTable;
        ULONG ulDirFaultIdx;
        PDIRTYRANGE pDirtyRange;
        ULONG ulBlockIndex;
        PDWORD pDirEntry;
        //
        // ulDirFaultIdx is the index of the page directory corresponding to
        // the address which faulted.
        //
        ulDirFaultIdx = (ULONG)pvAddr / (ARRAY_SIZE(g_PageDir.PTE) * PAGE_SIZE);
        OldPDE = g_PageDir.PTE[ulDirFaultIdx];
        if (ulDirFaultIdx < PDES_PER_SLOT) {
            // The fault occurred in the alias area, update the index to the
            // appropriate "real" entry.
            ulDirFaultIdx += PID_TO_PT_INDEX(pCurProc->procnum);
        } else {
            if (g_PageDir.PTE[ulDirFaultIdx] == 0
                    && g_ShadowPageDir.PTE[ulDirFaultIdx] != 0)
                g_PageDir.PTE[ulDirFaultIdx] = g_ShadowPageDir.PTE[ulDirFaultIdx];

⌨️ 快捷键说明

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