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

📄 mdarm.c

📁 windows ce 3.00 嵌入式操作系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Copyright (c) 1996-2000 Microsoft Corporation.  All rights reserved. */

#include "kernel.h"

#ifdef THUMBSUPPORT
#define THUMB_SUPPORT_STR TEXT("(Thumb Enabled)")
#else
#define THUMB_SUPPORT_STR TEXT(" ")
#endif

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

DWORD CEProcessorType;
WORD ProcessorLevel = 4;
WORD ProcessorRevision;

DWORD CurMSec;
DWORD DiffMSec;

// Fault Status register fields:
#define FSR_DOMAIN      0xF0
#define FSR_STATUS      0x0D
#define FSR_PAGE_ERROR  0x02

#define FSR_ALIGNMENT	    0x01
#define FSR_TRANSLATION	    0x05
#define FSR_DOMAIN_ERROR	0x09
#define FSR_PERMISSION	    0x0D

#define BREAKPOINT 0x06000010	// special undefined instruction
#define THM_BREAKPOINT  0xDEFE              // Thumb equivalent

const LPCSTR IdStrings[] = {
    "RaiseException", "Reschedule", "Undefined Instruction", "SWI",
    "Prefetch Abort", "Data Abort", "IRQ", "<Invalid>", "<Invalid>", "[Stack fault]", "[HW Break]",
};

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, PCPUCONTEXT pctx, int id, ulong addr, int level) {
    NKDbgPrintfW(L"Exception '%a' Thread=%8.8lx AKY=%8.8lx PC=%8.8lx BVA=%8.8lx\r\n",
    		IdStrings[id+1], pth, pCurThread->aky, pctx->Pc, addr);
    NKDbgPrintfW(L" R0=%8.8lx  R1=%8.8lx  R2=%8.8lx  R3=%8.8lx\r\n",
    		pctx->R0, pctx->R1, pctx->R2, pctx->R3);
    NKDbgPrintfW(L" R4=%8.8lx  R5=%8.8lx  R6=%8.8lx  R7=%8.8lx\r\n",
    		pctx->R4, pctx->R5, pctx->R6, pctx->R7);
    NKDbgPrintfW(L" R8=%8.8lx  R9=%8.8lx R10=%8.8lx R11=%8.8lx\r\n",
    		pctx->R8, pctx->R9, pctx->R10, pctx->R11);
    NKDbgPrintfW(L"R12=%8.8lx  SP=%8.8lx  Lr=%8.8lx Psr=%8.8lx\r\n",
    		pctx->R12, pctx->Sp, pctx->Lr, pctx->Psr);
}

void NextThread(void);
void KCNextThread(void);
void OEMIdle(void);
void DoPowerOff(void);
void __declspec(iw32) TLBClear(void);
ulong OEMInterruptHandler(void);

extern char InterlockedAPIs[], InterlockedEnd[];

void ARMInit(int cpuType, int abSp, int iSp, int uSp) {
    int ix;
    /* Initialize SectionTable in KPage */
    for (ix = 1 ; ix <= SECTION_MASK ; ++ix)
        SectionTable[ix] = NULL_SECTION;
    /* Copy kernel data to RAM & zero out BSS */
	KernelRelocate(pTOC);
	OEMInitDebugSerial();			// initialize serial port
	OEMWriteDebugString((PWSTR)NKSignon);
	/* Copy interlocked api code into the kpage */
	DEBUGCHK(sizeof(KData) <= FIRST_INTERLOCK);
	DEBUGCHK((InterlockedEnd-InterlockedAPIs)+FIRST_INTERLOCK <= 0x400);
	memcpy((char *)&KData+FIRST_INTERLOCK, InterlockedAPIs, InterlockedEnd-InterlockedAPIs);
	/* setup processor version information */
	CEProcessorType = cpuType >> 4 & 0xFFF;
	ProcessorRevision = cpuType & 0x0f;
	NKDbgPrintfW(L"ProcessorType=%4.4x  Revision=%d\r\n", CEProcessorType, ProcessorRevision);
	NKDbgPrintfW(L"sp_abt=%8.8x sp_irq=%8.8x sp_undef=%8.8x\r\n", abSp, iSp, uSp);
	OEMInit();			// initialize firmware
	KernelFindMemory();
	NKDbgPrintfW(L"Sp=%8.8x\r\n", &cpuType);
#ifdef DEBUG
	OEMWriteDebugString(TEXT("ARMInit done.\r\n"));
#endif
}

typedef struct ExcInfo {
    DWORD   linkage;
	ULONG	oldPc;
	UINT    oldMode;
	char    id;
	BYTE    lowSpBits;
	ushort  fsr;
	ULONG	addr;
} EXCINFO;
typedef EXCINFO *PEXCINFO;

ERRFALSE(sizeof(EXCINFO) <= sizeof(CALLSTACK));
ERRFALSE(offsetof(EXCINFO,linkage) == offsetof(CALLSTACK,pcstkNext));
ERRFALSE(offsetof(EXCINFO,oldPc) == offsetof(CALLSTACK,retAddr));
ERRFALSE(offsetof(EXCINFO,oldMode) == offsetof(CALLSTACK,pprcLast));
ERRFALSE(64 >= sizeof(CALLSTACK));

PTHREAD HandleException(PTHREAD pth, int id, ulong addr, ushort info) {
	PEXCINFO pexi;
	DWORD stackaddr;
    if (id != ID_RESCHEDULE) {
#if 0
	    NKDbgPrintfW(L"%a: Thread=%8.8lx Proc=%8.8lx AKY=%8.8lx\r\n",
   			IdStrings[id+1], pth, pCurProc, pCurThread->aky);
   	    NKDbgPrintfW(L"PC=%8.8lx Lr=%8.8lx Sp=%8.8lx Psr=%4.4x\r\n",
   			pth->ctx.Pc, pth->ctx.Lr, pth->ctx.Sp, pth->ctx.Psr);
      	if (id == ID_DATA_ABORT)
       	    NKDbgPrintfW(L"FAR=%8.8lx FSR=%4.4x\r\n", addr, info);
#endif
		
		KCALLPROFON(0);
	    pexi = (struct ExcInfo *)((pth->ctx.Sp & ~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 pth; // restart instruction
			}
			SET_STACKFAULT(pth);
	    	id = ID_STACK_FAULT;   // stack fault exception code
			addr = (DWORD)pexi;
		}
	   	if (pth->ctx.Pc != (ulong)CaptureContext+4) {
	   		pexi->id = id;
	   		pexi->lowSpBits = (uchar)pth->ctx.Sp & 63;
	   		pexi->oldPc = pth->ctx.Pc;
	   		pexi->oldMode = pth->ctx.Psr & 0xFF;
	   		pexi->addr = addr;
	   		pexi->fsr = info;
	        pexi->linkage = (DWORD)pth->pcstkTop | 1;
    	    pth->pcstkTop = (PCALLSTACK)pexi;
	   		pth->ctx.Sp = (DWORD)pexi;
	   		if ((pexi->oldMode & 0x1F) == USER_MODE)
   			    pth->ctx.Psr = (pth->ctx.Psr & ~0xFF) | SYSTEM_MODE;
	   		else
    	   		pth->ctx.Psr &= ~THUMB_STATE;
    		pth->ctx.Pc = (ULONG)CaptureContext;
    		KCALLPROFOFF(0);
	   		return pth;			// continue execution
	   	}
		DumpFrame(pth, &pth->ctx, id, addr, 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;
    }
    if (PowerOffFlag) {
        DoPowerOff();
        PowerOffFlag = 0;
    }
reschedTop:
  	if (ReschedFlag) {
        ReschedFlag = 0;
        NextThread();
    }
	if (KCResched) {
		KCResched = 0;
		KCNextThread();
	}
	if (KCResched)
		goto reschedTop;

	if (!RunList.pth) {
		INTERRUPTS_OFF();
		if (!ReschedFlag && !KCResched) {
			OEMIdle();
			INTERRUPTS_ON();
			ReschedFlag = 1;
			goto reschedTop;
		} else {
			INTERRUPTS_ON();
			goto reschedTop;
		}
	}

    SetCPUASID(RunList.pth);
	hCurThread = RunList.pth->hTh;
    pCurThread = RunList.pth;
    KPlpvTls = RunList.pth->tlsPtr;
	return RunList.pth;
}

// LoadPageTable - load entries into page tables from kernel structures
//
//  LoadPageTable is called for prefetch and data aborts to copy page table
// entries from the kernel virtual memory tables to the ARM h/w page tables.

DWORD currsecond;
DWORD secondpos[16];
DWORD secondslot[16];
DWORD used[16];

LPDWORD SecondAddr(DWORD ind, DWORD ent) {
	return (LPDWORD)&ArmHigh->aPT[ind].PTEs[ent];
}

LPDWORD FirstAddr(DWORD ind) {
	return (LPDWORD)&ArmHigh->firstPT[ind];
}

int LoadPageTable(ulong addr) {
    PSECTION pscn;
    MEMBLOCK *pmb;
    ulong entry;
    unsigned ix1st, ix2nd;
    int loop;
    if ((addr < 0x80000000) && (pscn = SectionTable[addr>>VA_SECTION]) &&
        (pmb = (*pscn)[(addr>>VA_BLOCK)&BLOCK_MASK]) && (pmb != RESERVED_BLOCK) && TestAccess(&pmb->alk, &CurAKey) &&
        ((entry = pmb->aPages[(addr>>VA_PAGE)&PAGE_MASK]) & PG_VALID_MASK)) {
        ix1st = addr >> 20;               // index into 1st level page table
        ix2nd = (addr >> VA_PAGE) & L2_MASK; // index into 2nd level page table
        // Remove previous entry from the page tables.
		if (*FirstAddr(ix1st)) {
			for (loop = 0; loop < 16; loop++)
				if (used[loop] && (secondpos[loop] == ix1st))
					break;
			DEBUGCHK(loop != 16);
			*SecondAddr(loop,secondslot[loop]) = 0;
			secondslot[loop] = ix2nd;
			*SecondAddr(loop,ix2nd) = entry;
		} else {
			if (used[currsecond]) {
				*FirstAddr(secondpos[currsecond]) = 0;
				*SecondAddr(currsecond,secondslot[currsecond]) = 0;
			} else
	    	    used[currsecond] = 1;
			secondpos[currsecond] = ix1st;
			secondslot[currsecond] = ix2nd;
			*SecondAddr(currsecond,ix2nd) = entry;
    	    *FirstAddr(ix1st) = PageTableDescriptor + currsecond*sizeof(PAGETBL);
        	currsecond = (currsecond+1)&0xf;
        }
        return TRUE;    // tell abort handler to retry
    }
    return FALSE;
}

void InvalidateSoftwareTLB(void) {
	int loop;
	if (!InSysCall()) {
        KCall((PKFN)InvalidateSoftwareTLB);
       	return;
    }
    KCALLPROFON(63);
    for (loop = 0; loop < 16; loop++) {
	    // Remove previous entry from the page tables.
	    if (used[loop]) {
	    	*FirstAddr(secondpos[loop]) = 0;
			*SecondAddr(loop,secondslot[loop]) = 0;
		    used[loop] = 0;
		}
	}
    KCALLPROFOFF(63);
}

// FlushTLB - clear TLBs and cached page table entries
//
//  FlushTLB is called by the virtual memory system whenever the permissions on
// any pages are changed or when any pages are freed.

void FlushTLB(void) {
    FlushICache();
    FlushDCache();
    InvalidateSoftwareTLB();
    TLBClear();     // clear h/w TLBs
}

void ExceptionDispatch(PCONTEXT pctx) {
	EXCEPTION_RECORD er;
	ULONG FaultAddr;
	ULONG addr;
	int id;
	BOOL bHandled;
    BOOL ThumbMode;
	PTHREAD pth; 
	PEXCINFO pexi;
	uint fsr;
	pth = pCurThread;
	pexi = (PEXCINFO)pth->pcstkTop;
	DEBUGMSG(ZONE_SEH, (TEXT("ExceptionDispatch: pexi=%8.8lx Pc=%8.8lx\r\n"), pexi, pexi->oldPc));
	pctx->Pc = pexi->oldPc;
	SetContextMode(pctx, pexi->oldMode);
	pctx->Sp = (ULONG)pctx + sizeof(CONTEXT);
	memset(&er, 0, sizeof(er));
	er.ExceptionAddress = (PVOID)pctx->Pc;
#if defined(THUMBSUPPORT)
    ThumbMode = (pctx->Psr & THUMB_STATE) != 0;
#else
    ThumbMode = FALSE;
#endif

⌨️ 快捷键说明

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