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

📄 mdsched.c

📁 可用于嵌入式编程学习
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Copyright (c) 1999-2000 Microsoft Corporation.  All rights reserved. */
#include "kernel.h"

#ifdef MIPS_HAS_FPU
void SaveFloatContext(PTHREAD);
void RestoreFloatContext(PTHREAD);
DWORD GetAndClearFloatCode(void);
BOOL HandleHWFloatException(EXCEPTION_RECORD *er, PCONTEXT pctx, CAUSE cause);
void FPUFlushContext(void);
#endif

#ifdef MIPS16SUPPORT
const wchar_t NKSignon[] = TEXT("Windows CE Kernel for MIPS16 Built on ") TEXT(__DATE__) TEXT(" at ") TEXT(__TIME__) TEXT("\r\n");
#else
const wchar_t NKSignon[] = TEXT("Windows CE Kernel for MIPS Built on ") TEXT(__DATE__) TEXT(" at ") TEXT(__TIME__) TEXT("\r\n");
#endif

// Define breakpoint instruction values.

#define MIPS32_BREAK(_t) ((SPEC_OP << 26) | ((_t) << 16) | BREAK_OP)
#if defined(MIPS16SUPPORT)
#define MIPS16_BREAK(_t) ((RR_OP16 << 11) | ((_t) << 5) | BREAK_OP16)
#endif

void DumpDwords(PDWORD pdw, int len) {
    int lc;
    lc = 0;
    NKDbgPrintfW(L"Dumping %d dwords", len);
    for (lc = 0 ; len ; ++pdw, ++lc, --len) {
        if (!(lc & 3))
            NKDbgPrintfW(L"\r\n%8.8lx -", pdw);
        NKDbgPrintfW(L" %8.8lx", *pdw);
    }
    NKDbgPrintfW(L"\r\n");
}

void DumpFrame(PTHREAD pth, PICONTEXT pctx, CAUSE cause, ULONG badVAddr, int level) {
    ulong addr;
    PDWORD pdw;
    NKDbgPrintfW(L"Exception %03x Thread=%8.8lx AKY=%8.8lx PC=%8.8lx BVA=%8.8lx\r\n",
            cause.XCODE, pth, pCurThread->aky, pctx->Fir, badVAddr);
    NKDbgPrintfW(L"SR=%8.8lx AT=%8.8lx V0=%8.8lx V1=%8.8lx\r\n",
            pctx->Psr, pctx->IntAt, pctx->IntV0, pctx->IntV1);
    NKDbgPrintfW(L"A0=%8.8lx A1=%8.8lx A2=%8.8lx A3=%8.8lx\r\n",
            pctx->IntA0, pctx->IntA1, pctx->IntA2, pctx->IntA3);
    NKDbgPrintfW(L"T0=%8.8lx T1=%8.8lx T2=%8.8lx T3=%8.8lx\r\n",
            pctx->IntT0, pctx->IntT1, pctx->IntT2, pctx->IntT3);
    NKDbgPrintfW(L"T4=%8.8lx T5=%8.8lx T6=%8.8lx T7=%8.8lx\r\n",
            pctx->IntT4, pctx->IntT5, pctx->IntT6, pctx->IntT7);
    NKDbgPrintfW(L"S0=%8.8lx S1=%8.8lx S2=%8.8lx S3=%8.8lx\r\n",
            pctx->IntS0, pctx->IntS1, pctx->IntS2, pctx->IntS3);
    NKDbgPrintfW(L"S4=%8.8lx S5=%8.8lx S6=%8.8lx S7=%8.8lx\r\n",
            pctx->IntS4, pctx->IntS5, pctx->IntS6, pctx->IntS7);
    NKDbgPrintfW(L"T8=%8.8lx T9=%8.8lx LO=%8.8lx HI=%8.8lx\r\n",
            pctx->IntT8, pctx->IntT9, pctx->IntLo, pctx->IntHi);
    NKDbgPrintfW(L"GP=%8.8lx SP=%8.8lx S8=%8.8lx RA=%8.8lx\r\n",
            pctx->IntGp, pctx->IntSp, pctx->IntS8, pctx->IntRa);
    if (level > 1) {
        addr = (pctx->Fir & -4) - 8*4;
        pdw = VerifyAccess((PVOID)addr, VERIFY_KERNEL_OK, CurAKey);
        if (pdw)
            DumpDwords((PDWORD)addr, 12);
    }
}

typedef struct _tlbentry {
    ulong   lo0;
    ulong   lo1;
    ulong   hi;
    ulong   mask;
} TLBENTRY;
typedef TLBENTRY *PTLBENTRY;

// Value of PRId register (least significant 16 bits)
WORD ProcessorRevision;

BOOL HookInterrupt(int hwInterruptNumber, FARPROC pfnHandler) {
    if (hwInterruptNumber > 5)
        return FALSE;
    ISRTable[hwInterruptNumber] = (DWORD)pfnHandler;
    KData.basePSR |= (0x0400 << hwInterruptNumber);
    return TRUE;
}

BOOL UnhookInterrupt(int hwInterruptNumber, FARPROC pfnHandler) {
    extern int DisabledInterruptHandler();
    if (hwInterruptNumber > 5 || ISRTable[hwInterruptNumber] != (DWORD)pfnHandler)
        return FALSE;
    ISRTable[hwInterruptNumber] = (DWORD)DisabledInterruptHandler;
    KData.basePSR &= ~(0x0400 << hwInterruptNumber);
    return TRUE;
}

/* Machine dependent thread creation */

#define STKALIGN 8
#define STKMSK (STKALIGN-1)

// normal thread stack: from top, TLS then args then free

void MDCreateThread(PTHREAD pTh, LPVOID lpStack, DWORD cbStack, LPVOID lpBase, LPVOID lpStart, DWORD dwVMBase, BOOL kmode, ulong param) {
    if (!((ulong)lpStack>>VA_SECTION))
        lpStack = (LPVOID)((ulong)(lpStack) + dwVMBase);
    pTh->dwStackBase = (DWORD)lpStack;
        memset(&pTh->ctx, 0xBD, sizeof(pTh->ctx));
    // Leave room for arguments and TLS on the stack
    pTh->ctx.IntSp = (ulong)lpStack + cbStack - (TLS_MINIMUM_AVAILABLE*4) - 4*4;
    pTh->dwStackBound = pTh->ctx.IntSp & ~(PAGE_SIZE-1);
    pTh->tlsPtr = (LPDWORD)((ulong)lpStack+cbStack-(TLS_MINIMUM_AVAILABLE*4));
    pTh->ctx.IntA0 = (ulong)lpStart;
    pTh->ctx.IntA1 = param;
    pTh->ctx.IntK0 = 0;
    pTh->ctx.IntK1 = 0;
    pTh->ctx.IntRa = 0;
    pTh->ctx.Fir = (ULONG)lpBase;
	pTh->ctx.Psr = (kmode || bAllKMode) ? KERNEL_MODE : USER_MODE;
#ifdef MIPS_HAS_FPU
    pTh->ctx.Fsr = 0x01000000; // handle no exceptions
#endif
    pTh->ctx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
}

// main thread stack: from top, TLS then buf then buf2 then buf2 (ascii) then args then free

LPCWSTR MDCreateMainThread1(PTHREAD pTh, LPVOID lpStack, DWORD cbStack, DWORD dwVMBase,
    LPBYTE buf, ulong buflen, LPBYTE buf2, ulong buflen2) {
    LPCWSTR pcmdline;
    if (!((ulong)lpStack>>VA_SECTION))
        lpStack = (LPVOID)((ulong)(lpStack) + dwVMBase);
    pTh->dwStackBase = (DWORD)lpStack;
    pcmdline = (LPCWSTR)((LPBYTE)lpStack+cbStack-(TLS_MINIMUM_AVAILABLE*4)-((buflen+STKMSK)&~STKMSK));
    memcpy((LPBYTE)lpStack+cbStack-(TLS_MINIMUM_AVAILABLE*4)-((buflen+STKMSK)&~STKMSK),
        buf,buflen);
    memcpy((LPBYTE)lpStack+cbStack-(TLS_MINIMUM_AVAILABLE*4)-((buflen+STKMSK)&~STKMSK)-
        ((buflen2+STKMSK)&~STKMSK),buf2,buflen2);
    pTh->pOwnerProc->lpszProcName = (LPWSTR)((ulong)lpStack+cbStack-(TLS_MINIMUM_AVAILABLE*4)-((buflen+STKMSK)&~STKMSK)-((buflen2+STKMSK)&~STKMSK));
    KPlpvTls = pTh->tlsPtr = (LPDWORD)((ulong)lpStack+cbStack-(TLS_MINIMUM_AVAILABLE*4));
    return pcmdline;
}

void MDCreateMainThread2(PTHREAD pTh, DWORD cbStack, LPVOID lpBase, LPVOID lpStart, BOOL kmode,
    ulong p1, ulong p2, ulong buflen, ulong buflen2, ulong p4) {
        memset(&pTh->ctx, 0xBD, sizeof(pTh->ctx));
    // Leave room for arguments on the stack
    pTh->ctx.IntSp = pTh->dwStackBase + cbStack -
            (TLS_MINIMUM_AVAILABLE*4) - 8*4 - ((buflen+STKMSK)&~STKMSK) -
            ((buflen2+STKMSK)&~STKMSK);
    pTh->dwStackBound = pTh->ctx.IntSp & ~(PAGE_SIZE-1);
    pTh->ctx.IntA0 = (ulong)lpStart;
    pTh->ctx.IntA1 = p1;
    pTh->ctx.IntA2 = p2;
    pTh->ctx.IntA3 = pTh->dwStackBase+cbStack-(TLS_MINIMUM_AVAILABLE*4)-((buflen+STKMSK)&~STKMSK);
    ((LPDWORD)pTh->ctx.IntSp)[4] = p4;
    pTh->ctx.IntK0 = 0;
    pTh->ctx.IntK1 = 0;
    pTh->ctx.IntRa = 0;
    pTh->ctx.Fir = (ULONG)lpBase;
	pTh->ctx.Psr = (kmode || bAllKMode) ? KERNEL_MODE : USER_MODE;
#ifdef MIPS_HAS_FPU
    pTh->ctx.Fsr = 0x01000000; // handle no exceptions
#endif
    pTh->ctx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
}

typedef struct ExcInfo {
    DWORD   linkage;
    ULONG   oldFir;
    UINT    oldMode;
    CAUSE   causeAndMode;
    ULONG   badVAddr;
    UCHAR	lowSp;
    UCHAR	pad[3];
} EXCINFO;
typedef 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, CAUSE cause, ULONG badVAddr) {
    PEXCINFO pexi;
    DWORD stackaddr;
    KCALLPROFON(0);
#if 0
    NKDbgPrintfW(L"Exception %03x Thread=%8.8lx(%8.8lx) Proc=%8.8lx '%s'\r\n",
		cause.XCODE, pCurThread,pth, hCurProc, pCurProc->lpszProcName ? pCurProc->lpszProcName : L"");
	NKDbgPrintfW(L"AKY=%8.8lx PC=%8.8lx RA=%8.8lx BVA=%8.8lx\r\n",
		pCurThread->aky, pth->ctx.Fir, pth->ctx.IntRa, badVAddr);
#endif
    pexi = (struct ExcInfo *)((pth->ctx.IntSp & ~63) - sizeof(CALLSTACK));
    if (!((DWORD)pexi & 0x80000000) && DemandCommit((DWORD)pexi)) {
		stackaddr = (DWORD)pexi & ~(PAGE_SIZE-1);
		if ((stackaddr >= pth->dwStackBound) || (stackaddr < pth->dwStackBase) ||
			((pth->dwStackBound = stackaddr) >= (pth->dwStackBase + MIN_STACK_RESERVE)) ||
			TEST_STACKFAULT(pth)) {
			KCALLPROFOFF(0);
			return 1; // restart instruction
		}
		SET_STACKFAULT(pth);
       	cause.XCODE = 30;   // stack fault exception code
		badVAddr = (DWORD)pexi;
	}
    if (pth->ctx.Fir != (ulong)CaptureContext+4) {
        pexi->causeAndMode = cause;
        pexi->lowSp = (UCHAR)(pth->ctx.IntSp & 63);
        pexi->oldFir = pth->ctx.Fir;
        pexi->oldMode = GetThreadMode(pth);
        pexi->badVAddr = badVAddr;
        pexi->linkage = (DWORD)pCurThread->pcstkTop | 1;
        pCurThread->pcstkTop = (PCALLSTACK)pexi;
        pth->ctx.IntSp = (DWORD)pexi;
        pth->ctx.Psr = KERNEL_MODE;
        pth->ctx.Fir = (ulong)CaptureContext;
        KCALLPROFOFF(0);
        return TRUE;            // continue execution
    }
    DumpFrame(pth, &pth->ctx, cause, badVAddr, 10);
    RETAILMSG(1, (TEXT("Halting thread %8.8lx\r\n"), pth));
    SurrenderCritSecs();
    SET_RUNSTATE(pth,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;
typedef EXCARGS *PEXCARGS;
    
extern BOOL SetCPUHardwareWatch(LPVOID, DWORD);

#ifdef MIPS_HAS_FPU
void SwitchFPUOwner(PCONTEXT pctx) {
	KCALLPROFON(61);
	if (g_CurFPUOwner != pCurThread) {
		if (g_CurFPUOwner)
			SaveFloatContext(g_CurFPUOwner);
		g_CurFPUOwner = pCurThread;
		RestoreFloatContext(pCurThread);
	}
	KCALLPROFOFF(61);
}
#endif

void ExceptionDispatch(PCONTEXT pctx) {
    PTHREAD pth;
    PEXCINFO pexi;
    EXCEPTION_RECORD er;
    ULONG badVAddr;
    int xcode;
    CAUSE cause;
    PEXCARGS pea;
    BOOL bHandled;
    pth = pCurThread;
    
	// Get the EXCINFO off the thread's callstack.
	pexi = (PEXCINFO)pth->pcstkTop;

    DEBUGMSG(ZONE_SEH, (TEXT("ExceptionDispatch: pexi=%8.8lx Fir=%8.8lx\r\n"),pexi, pexi->oldFir));
    // Update CONTEXT with infomation saved in the EXCINFO structure
    pctx->Fir = pexi->oldFir;
    SetContextMode(pctx, pexi->oldMode);
    pctx->IntSp = (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->IntSp;
        xcode = -1;
        pctx->Fir -= 4;     // 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.
        badVAddr = pexi->badVAddr;
        cause = pexi->causeAndMode;
        xcode = pexi->causeAndMode.XCODE;
        pctx->Fir = pexi->oldFir;
        pctx->IntSp += pexi->lowSp + sizeof(CALLSTACK);
        if (((xcode == 2) || (xcode == 3)) && AutoCommit(badVAddr)) {
			pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
			goto continueExecution;
        }
		switch (xcode) {
        case 0:     // RaiseException or invalid system call
            er.ExceptionCode = STATUS_INVALID_SYSTEM_SERVICE;
            if ((pea = (PEXCARGS)badVAddr) != 0) {
                                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;
                    }
                }
            }

⌨️ 快捷键说明

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