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

📄 mdarm.c

📁 windows ce 3.00 嵌入式操作系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    // 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)) {
				DEBUGMSG(ZONE_SEH, (TEXT("Raising exception %x flags=%x args=%d pexi=%8.8lx\r\n"),
				pctx->R0, pctx->R1, pctx->R2, pexi));
		er.ExceptionCode = pctx->R0;
		er.ExceptionFlags = pctx->R1;
		if (pctx->R3 && pctx->R2) {
			if (pctx->R2 > EXCEPTION_MAXIMUM_PARAMETERS) {
				er.ExceptionCode = STATUS_INVALID_PARAMETER;
				er.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
			} else {
				memcpy(er.ExceptionInformation, (void*)pctx->R3, pctx->R2*sizeof(DWORD));
				er.NumberParameters = pctx->R2;
			}
		}
		id = -1;
    } else {
        // CPU detected exception. Extract some additional information about
        // the cause of the exception from the EXCINFO (CALLSTACK) structure.

        //
        //  The exception handling code uses bit 0 to indicate Thumb vs. ARM 
        //  execution. This bit is not set by the hardware on exceptions. Set
        //  the bit here:
        //
        if ( ThumbMode ){
            pctx->Pc |= 0x01;
        }
        
    	addr = pexi->addr;
    	id = pexi->id;
    	pctx->Sp += pexi->lowSpBits + sizeof(CALLSTACK);
    	fsr = pexi->fsr;
		if (((id == ID_DATA_ABORT) && ((fsr & FSR_STATUS) == FSR_TRANSLATION)) && AutoCommit(addr)) {
			pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);
			goto continueExecution;
		}
    	switch (id) {
	    	case ID_UNDEF_INSTR:
	            er.ExceptionCode = STATUS_ILLEGAL_INSTRUCTION;
	            if ( ThumbMode ){
	                FaultAddr = pctx->Pc & ~0x01;
	                if ( *(PUSHORT)FaultAddr == THM_BREAKPOINT ){
	                    er.ExceptionCode = STATUS_BREAKPOINT;
	                    er.ExceptionInformation[0] = *(PUSHORT)FaultAddr;
	                }
	            } else if ( (*(PULONG)pctx->Pc & 0x0fffffff) == BREAKPOINT ){
	                er.ExceptionCode = STATUS_BREAKPOINT;
	                er.ExceptionInformation[0] = *(PULONG)pctx->Pc;
	            }
	    	    break;
	        case ID_SWI_INSTR:
   		        er.ExceptionCode = STATUS_ILLEGAL_INSTRUCTION;
    		    break;
	    	case ID_DATA_ABORT:		// Data page fault
	            //
    	        // Determine load vs. store depending on whether ARM or Thumb
        	    // mode:
	            if ( ThumbMode ){
	                ULONG Instr;
	                FaultAddr = pctx->Pc & ~0x01;               // Clear Thumb bit
    	            Instr = *(PUSHORT)FaultAddr;
        	        if ((Instr & 0xFE00) == 0x5600){
            	        // Discontinuity in the Thumb instruction set:
                	    //  LDRSB instruction does not have bit 11 set.
                    	er.ExceptionInformation[0] = 0;
	                } else {
    	                //  All other load instructions have bit 11 set. The
        	            //  corresponding store instructions have bit 11 clear
        		        er.ExceptionInformation[0] = !(Instr & (1<<11));
                	}
	            } else {
    	            FaultAddr = pctx->Pc;
        		    er.ExceptionInformation[0] = !((*(PULONG)FaultAddr) & (1<<20));
            	}
    	    	switch(fsr & FSR_STATUS) {
	    		    case FSR_TRANSLATION:
    	    	    case FSR_DOMAIN_ERROR:
		            case FSR_PERMISSION:
		
						DEBUGMSG(ZONE_PAGING, (L"ExD: ID_DATA_ABORT\r\n"));

						goto doPageFault;
		    	    case FSR_ALIGNMENT:
       					er.ExceptionCode = STATUS_DATATYPE_MISALIGNMENT;
		       			break;
		       		default:
		       		    er.ExceptionCode = 0xdfff0123;  		       		    break;
	    	    }
    		    break;
	    	case ID_PREFETCH_ABORT:		// Code page fault
    		    addr = pctx->Pc;
				
				DEBUGMSG(ZONE_PAGING, (L"ExD: ID_PREFETCH_ABORT\r\n"));

    doPageFault:
				DEBUGMSG(ZONE_PAGING, (L"ExD: addr = %8.8lx\r\n",addr));

				if (ProcessPageFault(er.ExceptionInformation[0], addr)) {

					pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);

					DEBUGMSG(ZONE_PAGING, (L"ExD: continuing.  lr = %8.8lx\r\n", pctx->Lr));
					
					goto continueExecution;
    			}
	    		er.ExceptionCode = STATUS_ACCESS_VIOLATION;
    			er.ExceptionInformation[1] = addr;
    			er.NumberParameters = 2;
    			break;
	    	case ID_STACK_FAULT:    // Stack overflow
    		    er.ExceptionCode = STATUS_STACK_OVERFLOW;
    			er.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
    	    	break;
    	}
    }
	if (er.ExceptionCode != STATUS_BREAKPOINT) {
	    NKDbgPrintfW(L"%a: Thread=%8.8lx Proc=%8.8lx '%s'\r\n",IdStrings[id+1], pth, pCurProc, pCurProc->lpszProcName ? pCurProc->lpszProcName : L"");
	    NKDbgPrintfW(L"AKY=%8.8lx PC=%8.8lx RA=%8.8lx BVA=%8.8lx\r\n", pCurThread->aky, pctx->Pc, pctx->Lr, addr);
	    if (UTlsPtr()[TLSSLOT_KERNEL] & TLSKERN_NOFAULT) {
	        NKDbgPrintfW(L"TLSKERN_NOFAULT set... bypassing kernel debugger.\r\n");
	    }
    }
	// Unlink the EXCINFO structure from the threads call stack chain.
	pth->pcstkTop = (PCALLSTACK)(pexi->linkage & ~1);

    // Invoke the kernel debugger to attempt to debug the exception before
    // letting the program resolve the condition via SEH.
	if (!UserDbgTrap(&er,pctx,FALSE) && ((UTlsPtr()[TLSSLOT_KERNEL] & TLSKERN_NOFAULT) || !KDTrap(&er, pctx, FALSE))) {
		if (er.ExceptionCode == STATUS_BREAKPOINT) {
			RETAILMSG(1, (TEXT("DEBUG_BREAK @%8.8lx MD=%2x Ignored.\r\n"), pctx->Pc,
			        pctx->Psr & 0xFF));
			pctx->Pc += ThumbMode ? 2 : 4;  // skip over the BREAK instruction
		} else {
			bHandled = NKDispatchException(pth, &er, pctx);
			if (!bHandled) {
			    if (!UserDbgTrap(&er, pctx, TRUE) && !KDTrap(&er, pctx, TRUE)) {
					// Terminate the process.
					RETAILMSG(1, (TEXT("\r\nUnhandled exception %8.8lx:\r\n"), er.ExceptionCode));
					DumpFrame(pth, (PCPUCONTEXT)&pctx->Psr, id, addr, 0);
					if (InSysCall()) {
	    			    OutputDebugStringW(L"Halting system\r\n");
	    			    for (;;)
	    			        ;
	    			} else {
	    				if (!GET_DEAD(pth)) {
	    					SET_DEAD(pth);
		    				pctx->Pc = (ULONG)pExitThread;
		    				pctx->R0 = 0;
    						RETAILMSG(1, (TEXT("Terminating thread %8.8lx\r\n"), pth));
    					} else {
    						RETAILMSG(1, (TEXT("Can't terminate thread %8.8lx, sleeping forever\r\n"), pth));
    						SurrenderCritSecs();
							Sleep(INFINITE);
							DEBUGCHK(0);    // should never get here
                        }
	    			}
				}
			}

#if defined(THUMBSUPPORT)
            //
            // Update PSR based on ARM/Thumb continuation:
            //
            if ( pctx->Pc & 0x01 ){
                pctx->Psr |= THUMB_STATE;
            } else {
                pctx->Psr &= ~THUMB_STATE;
            }
#endif

		}
	}
	if ((id == ID_DATA_ABORT) || (id == ID_PREFETCH_ABORT))
		GuardCommit(addr);
continueExecution:
	// If returning from handling a stack overflow, reset the thread's stack overflow
	// flag. It would be good to free the tail of the stack at this time
	// so that the thread will stack fault again if the stack gets too big. But we
	// are currently using that stack page.
	if (id == ID_STACK_FAULT)
    	CLEAR_STACKFAULT(pth);
    if (GET_DYING(pth) && !GET_DEAD(pth) && (pCurProc == pth->pOwnerProc)) {
		SET_DEAD(pth);
		CLEAR_USERBLOCK(pth);
		CLEAR_DEBUGWAIT(pth);
		pctx->Pc = (ULONG)pExitThread;
		pctx->R0 = 0;
#if defined(THUMBSUPPORT)
        //
        // Update PSR based on ARM/Thumb continuation:
        //
        if ( pctx->Pc & 0x01 ){
            pctx->Psr |= THUMB_STATE;
        } else {
            pctx->Psr &= ~THUMB_STATE;
        }
#endif
	}   
}

//
// Page Table Entry from OEMAddressTable
//
typedef struct {
    DWORD dwVA;
    DWORD dwPA;
    DWORD dwSize;
} PTE, *PPTE;

//
// The Physical to Virtual mapping table is supplied by OEM.
//
extern PTE OEMAddressTable[];

PVOID Phys2Virt(DWORD pfn) {
    int i = 0;
    DWORD va;       // Virtual Base Address of section
    DWORD pa;       // Physical Base Address of section
    DWORD pau;      // Physical Address Upper Bound of section
    DWORD pfnmb;    // PFN rounded down to 1MB
    //
    // The end of the table is marked by an entry with a ZERO size.
    //
    while(OEMAddressTable[i].dwSize) {
        va = OEMAddressTable[i].dwVA & 0x1FF00000;
        pa = OEMAddressTable[i].dwPA & 0xFFF00000;
        pau = pa + (OEMAddressTable[i].dwSize << 20) - 1;
        pfnmb = pfn & 0xfff00000;
        if ((pfnmb >= pa) && (pfnmb <= pau))
            return ((PVOID) ((pfn - pa) + va + 0x80000000));
        i++;
    }
    DEBUGMSG(ZONE_PHYSMEM, (TEXT("Phys2Virt() : PFN (0x%08X) not found!\r\n"), pfn));
    return NULL;
}

LPVOID VerifyAccess(LPVOID pvAddr, DWORD dwFlags, ACCESSKEY aky) {
    PSECTION pscn;
    MEMBLOCK *pmb;
    ulong entry;
    int i=0;
    if ((long)pvAddr >= 0) {
        if ((pscn = SectionTable[(ulong)pvAddr>>VA_SECTION]) &&
			(pmb = (*pscn)[((ulong)pvAddr>>VA_BLOCK)&BLOCK_MASK]) &&
            (pmb != RESERVED_BLOCK) && (pmb->alk & aky) &&
            ((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)) &&
            (((ulong)pvAddr < 0xC0000000) || ((ulong)pvAddr >= 0xFFFD0000))) {

			// kernel data and page table territory...
            if(((ulong)pvAddr >= 0xFFFD0000) && ((ulong)pvAddr < 0xFFFD8000)) 
            	return pvAddr;
            if(((ulong)pvAddr >= 0xFFFF0000) && ((ulong)pvAddr < 0xFFFF1000))
            	return pvAddr;
            if(((ulong)pvAddr >= 0xFFFF2000) && ((ulong)pvAddr < 0xFFFF3000))
            	return pvAddr;
            if(((ulong)pvAddr >= 0xFFFF4000) && ((ulong)pvAddr < 0xFFFF5000))
            	return pvAddr;
            if(((ulong)pvAddr >= 0xFFFFC000) && ((ulong)pvAddr < 0xFFFFD000))
            	return pvAddr;
            	
			// Need to check the OEM address map to see if the address we've been 
			// handed is indeed mapped...
			while(OEMAddressTable[i].dwSize != 0) {
				if((OEMAddressTable[i].dwVA < (ulong)pvAddr) && 
					((ulong)pvAddr < (OEMAddressTable[i].dwVA + (OEMAddressTable[i].dwSize * 0x00100000)))) {
					return pvAddr;
				}
				i++;
			}

    	}
    }
    return 0;
}

/* 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) {
    PDWORD pTLS;
	if (!((ulong)lpStack>>VA_SECTION))
		lpStack = (LPVOID)((ulong)lpStack + dwVMBase);
	pTh->dwStackBase = (DWORD)lpStack;
	// Leave room for arguments and TLS on the stack
	pTLS = (PDWORD)((PBYTE)lpStack + cbStack - TLS_MINIMUM_AVAILABLE*4);
	pTh->ctx.Sp = (ulong)pTLS;
	pTh->dwStackBound = pTh->ctx.Sp & ~(PAGE_SIZE-1);
	pTh->tlsPtr = pTLS;
	pTh->ctx.R0 = (ulong)lpStart;
	pTh->ctx.R1 = param;
	pTh->ctx.Lr = 4;
    pTh->ctx.Pc = (ULONG)lpBase;
	pTh->ctx.Psr = (kmode || bAllKMode) ? KERNEL_MODE : USER_MODE;
#if defined(THUMBSUPPORT)
    if ( (pTh->ctx.Pc & 0x01) != 0 ){
        pTh->ctx.Psr |= THUMB_STATE;
    }

⌨️ 快捷键说明

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