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

📄 mdarm.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------

#include "kernel.h"

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

#ifdef THUMB
const wchar_t NKCpuType [] = TEXT("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 NKCpuType [] = TEXT("ARM");
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

extern void (*lpNKHaltSystem)(void);
extern void FakeNKHaltSystem (void);

DWORD CEProcessorType;
WORD ProcessorLevel = 4;
WORD ProcessorRevision;
#if defined(ARMV4T)
DWORD CEInstructionSet = PROCESSOR_ARM_V4T_INSTRUCTION;
#elif defined(ARMV4I)
DWORD CEInstructionSet = PROCESSOR_ARM_V4I_INSTRUCTION;
#elif defined(ARMV4)
DWORD CEInstructionSet = PROCESSOR_ARM_V4_INSTRUCTION;
#endif

DWORD CurMSec;

// 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]",
};


#define VFP_ENABLE_BIT  0x40000000
#define VFP_EX_BIT      0x80000000

DWORD vfpStat = VFP_NOT_EXIST;
extern BOOL TestVFP (void);
extern DWORD ReadAndSetFpexc (DWORD dwNewFpExc);

// NOTE: Save/Restore FloatContext do not Save/Restore fpexc
//       it needs to be handled differently
extern void SaveFloatContext(PTHREAD);
extern void RestoreFloatContext(PTHREAD);


// OEM defined VFP save/restore for implementation defined control registers
typedef void (* PFN_OEMSaveRestoreVFPCtrlRegs) (LPDWORD lpExtra, int nMaxRegs);
typedef BOOL (* PFN_OEMHandleVFPException) (EXCEPTION_RECORD *er, PCONTEXT pctx);

static void FakedSaveVFPExtra (LPDWORD lpExtra, int nMaxRegs)
{
}
static void FakedRestoreVFPExtra (LPDWORD lpExtra, int nMaxRegs)
{
}

// this is a stub for now
static BOOL FakedHandleVFPException (EXCEPTION_RECORD *er, PCONTEXT pctx)
{
    return FALSE;
}

PFN_OEMSaveRestoreVFPCtrlRegs pOEMSaveVFPCtrlRegs    = FakedSaveVFPExtra;
PFN_OEMSaveRestoreVFPCtrlRegs pOEMRestoreVFPCtrlRegs = FakedRestoreVFPExtra;
PFN_OEMHandleVFPException     pOEMHandleVFPException = FakedHandleVFPException;

// flag to indicate if VFP is touched. NOTE: Flushing VFP is NOT considered
// touching VFP
BOOL g_fVFPTouched;

#define PG_COARSE_TBL_BIT       0x01

extern CRITICAL_SECTION VAcs;
LPBYTE GrabFirstPhysPage(DWORD dwCount);

// hardware pagetable for the 2nd gig address and secure section
ulong gHwPTBL2G[32*HARDWARE_PT_PER_PROC];    // 32 == shared section + mapping address from 0x42000000 -> 0x7fffffff

DWORD gdwSlotTouched, gfObjStoreTouched;
PPTE g_pOEMAddressTable;

extern void _SetCPUASID (PTHREAD);

#define MAPPER_SLOT_TO_PTBL(slot)   (gHwPTBL2G + HARDWARE_PT_PER_PROC * ((slot) - 32))

BOOL MDValidateRomChain (ROMChain_t *pROMChain)
{
    PPTE ppte;
    DWORD dwEnd;
    
    for ( ; pROMChain; pROMChain = pROMChain->pNext) {
        for (ppte = g_pOEMAddressTable; ppte->dwSize; ppte ++) {
            dwEnd = ppte->dwVA + (ppte->dwSize << 20);
            if (IsInRange (pROMChain->pTOC->physfirst, ppte->dwVA, dwEnd)) {
                if (IsInRange (pROMChain->pTOC->physlast, ppte->dwVA, dwEnd)) {
                    // good XIP, break inner loop and go on to the next region
                    break;
                }
                // bad
                NKDbgPrintfW (L"MDValidateRomChain: XIP (%8.8lx -> %8.8lx) span accross multiple memory region\r\n", 
                    pROMChain->pTOC->physfirst, pROMChain->pTOC->physlast);
                return FALSE;
            }
        }
        if (!ppte->dwSize) {
            NKDbgPrintfW (L"MDValidateRomChain: XIP (%8.8lx -> %8.8lx) doesn't exist in OEMAddressTable \r\n",
                        pROMChain->pTOC->physfirst, pROMChain->pTOC->physlast);
            return FALSE;
        }
    }
    return TRUE;
}



MEMBLOCK *MDAllocMemBlock (DWORD dwBase, DWORD ixBlock)
{
    LPDWORD pPtbls;                         // which hardware PT to use
    DWORD   ixTbl  = ixBlock >> 6;          // ixTbl == which 4M block
    MEMBLOCK *pmb;

    DEBUGMSG (ZONE_VIRTMEM, (L"MDAllocMemBlock: dwBase = %8.8lx, ixBlock = %8.8lx\r\n", dwBase, ixBlock));
    DEBUGCHK (!IsKernelVa (dwBase));
    DEBUGCHK (!VAcs.hCrit || (VAcs.OwnerThread == hCurThread));

    switch (dwBase) {
    case SECURE_VMBASE:
        // secure section, use NK's page table
        pPtbls = ProcArray[0].pPTBL;
        break;
        
    case MODULE_BASE_ADDRESS:
        // module section (slot 1), use 1st 8 entries of gHwPTBL2G
        pPtbls = gHwPTBL2G;
        break;
        
    case 0:
        // current process
        pPtbls = pCurProc->pPTBL;
        break;
        
    default:
        // either a sloted process address or 2nd gig
        if (dwBase < FIRST_MAPPER_ADDRESS) {
            // process address
            pPtbls = ProcArray[(dwBase >> VA_SECTION) - 1].pPTBL;
        } else {
            // in the 2nd gig
            pPtbls = MAPPER_SLOT_TO_PTBL (dwBase >> VA_SECTION);
        }
        break;
    }

    //
    // allocate a page if not allocate yet
    //
    if (!pPtbls[ixTbl]) {

        // allocate a new page for page table
        DEBUGMSG (ZONE_VIRTMEM, (L"MDAllocMemBlock: pPtbls = %8.8lx ixTbl = %8.8lx\r\n", pPtbls, ixTbl));
        if (!(pPtbls[ixTbl] = (DWORD) KCall((PKFN)GrabFirstPhysPage,1))) {
            // Out of memory
            return NULL;
        }

        // we're relying on the fact that the page we just got has already been zero'd
        // or we need to memset it to 0 here.
        
        pPtbls[ixTbl] |= 0x20000000;    // uncached access only

        DEBUGMSG (ZONE_VIRTMEM, (L"MDAllocMemBlock: Allocated a new page for Page Table va = %8.8lx\r\n",
            pPtbls[ixTbl]));

    }

    DEBUGMSG (ZONE_VIRTMEM, (L"MDAllocMemBlock: Allocating MemBlock\r\n"));
    // allocate MEM_BLOCK
    if (pmb = AllocMem (HEAP_MEMBLOCK)) {

        // initialize memblock
        memset (pmb, 0, sizeof(MEMBLOCK));

        // pagetable access needs to be uncached.
        pmb->aPages = (LPDWORD) (pPtbls[ixTbl] + ((ixBlock << 6) & (PAGE_SIZE-1)));

    }

    DEBUGMSG (ZONE_VIRTMEM, (L"MDAllocMemBlock: returning %8.8lx, aPages = %8.8lx\r\n", pmb, pmb->aPages));
    return pmb;
}

void FreeHardwarePT (DWORD dwVMBase)
{
    LPDWORD pPtbls;                             // which hardware PT to use
    int i;
    // cannot free current process, shared section, or secure section
    DEBUGCHK ((dwVMBase != pCurProc->dwVMBase) && ((int) dwVMBase >= (2 << VA_SECTION)));
    DEBUGCHK (!VAcs.hCrit || (VAcs.OwnerThread == hCurThread));

    // clear first-level page table
    memset (&FirstPT[(dwVMBase >> 20)], 0, HARDWARE_PT_PER_PROC * 4 * sizeof (ULONG));

    if (dwVMBase < FIRST_MAPPER_ADDRESS) {
        pPtbls = ProcArray [(dwVMBase >> VA_SECTION) - 1].pPTBL;
        // per process
    } else {
        // 2nd gig
        DEBUGCHK ((dwVMBase >= FIRST_MAPPER_ADDRESS) && (dwVMBase < LAST_MAPPER_ADDRESS));

        pPtbls = MAPPER_SLOT_TO_PTBL (dwVMBase >> VA_SECTION);
    }
    for (i = 0; i < HARDWARE_PT_PER_PROC; i ++) {
        if (pPtbls[i]) {
            FreePhysPage (GetPFN (pPtbls[i]));
            pPtbls[i] = 0;
        }
    }
    OEMCacheRangeFlush (0, 0, CACHE_SYNC_FLUSH_TLB);
}

void MDFreeMemBlock (MEMBLOCK *pmb)
{
    DEBUGCHK ((NULL_BLOCK != pmb) && (RESERVED_BLOCK != pmb));
    DEBUGCHK (!VAcs.hCrit || (VAcs.OwnerThread == hCurThread));
#ifdef DEBUG
    {
        int i;
        for (i = 0; i < PAGES_PER_BLOCK; i ++) {
            DEBUGCHK (!pmb->aPages[i] || (pmb->aPages[i] == BAD_PAGE));
        }
    }
#endif
    // need to zero it out incase there're bad pages.
    memset (pmb->aPages, 0, PAGES_PER_BLOCK * sizeof (ulong));
    FreeMem (pmb, HEAP_MEMBLOCK);
}

_inline void ClearOneSlot (DWORD dwVMBase)
{
    //DEBUGMSG (ZONE_VIRTMEM, (L"ClearProcessSlot: dwVMBase = %8.8lx, PT entry = %8.8lx\r\n", dwVMBase, FirstPT + (dwVMBase >> 20)));
    memset (FirstPT + (dwVMBase >> 20), 0, 32 * sizeof (DWORD));
}


void ClearSlots (void)
{
    DWORD dwSlotRst;
    BOOL fCleared = FALSE;
    KCALLPROFON (0);
    if (dwSlotRst = gdwSlotTouched & ~CurAKey) {
        int i;
        for (i = 1; dwSlotRst; i ++) {
            if (dwSlotRst & (1 << i)) {
                dwSlotRst &= ~(1 << i);
                ClearOneSlot (ProcArray[i].dwVMBase);
            }
        }
        fCleared = TRUE;
        gdwSlotTouched &= CurAKey;
    }
    if (gfObjStoreTouched && !(pFileSysProc->aky & CurAKey)) {
        DWORD dwBits = g_ObjStoreSlotBits;
        int i;
        for (i = 0; dwBits; i ++) {
            if (dwBits & (1 << i)) {
                dwBits &= ~(1 << i);
                ClearOneSlot ((FIRST_MAPPER_SLOT + i) << VA_SECTION);
            }
        }
        
        fCleared = TRUE;
        gfObjStoreTouched = FALSE;
    }
    if (fCleared) {
        OEMCacheRangeFlush (0, 0, CACHE_SYNC_FLUSH_TLB);
    }

    KCALLPROFOFF (0);
}

void SetCPUASID (PTHREAD pth)
{
    _SetCPUASID (pth);
    KCall ((FARPROC) ClearSlots);
}

void DetectVFP (void)
{
    DEBUGMSG (1, (L"Detecting VFP..."));
    vfpStat = VFP_TESTING | VFP_EXIST;
    TestVFP ();    // would generate an undefined-instruction exception if FPU not exist
                   // and ExceptionDispatch will unset the VFP_EXIST bit
    vfpStat &= ~VFP_TESTING;
    if (vfpStat)

⌨️ 快捷键说明

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