📄 mmupro36lib.c
字号:
pDte = &thisTbl->pDirectoryTable [((UINT) virtPageAddr & DIR_BITS) >> DIR_INDEX]; /* modify the directory table entry to point to the new page table */ pDte->field.page = (UINT) pPageTable >> ADDR_TO_PAGE; pDte->field.present = 1; pDte->field.rw = 1; /* write protect the directory table */ for (ix = 0; ix < 4; ix++) { pDirectoryTable = (PTE *)((UINT)thisTbl->pDirectoryTable + (PAGE_SIZE * ix)); mmuStateSet (&mmuGlobalTransTbl, pDirectoryTable, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE_NOT); } mmuPro36TLBFlush (); return (OK); }/******************************************************************************** mmuStateSet - set state of virtual memory page** mmuStateSet is used to modify the state bits of the pte for the given* virtual page. The following states are provided:** MMU_STATE_VALID MMU_STATE_VALID_NOT vailid/invalid* MMU_STATE_WRITABLE MMU_STATE_WRITABLE_NOT writable/writeprotected* MMU_STATE_CACHEABLE MMU_STATE_CACHEABLE_NOT notcachable/cachable** these may be or'ed together in the state parameter. Additionally, masks* are provided so that only specific states may be set:** MMU_STATE_MASK_VALID * MMU_STATE_MASK_WRITABLE* MMU_STATE_MASK_CACHEABLE** These may be or'ed together in the stateMask parameter. ** Accesses to a virtual page marked as invalid will result in a page fault.** RETURNS: OK or ERROR if virtual page does not exist.*/LOCAL STATUS mmuStateSet ( MMU_TRANS_TBL *transTbl, /* translation table */ void *pageAddr, /* page whose state to modify */ UINT stateMask, /* mask of which state bits to modify */ UINT state /* new state bit values */ ) { PTE *pPte; int oldIntLev; BOOL wasEnabled; if (mmuPteGet (transTbl, pageAddr, &pPte) != OK) return (ERROR); /* modify the pte with mmu turned off and interrupts locked out */ /* XXX can't dynamically turn mmu on and off if virtual stack */ /* only way is if you make mmuEnable inline and guarantee that this code is in physical memory */ MMU_UNLOCK (wasEnabled, oldIntLev); pPte->bits[0] = (pPte->bits[0] & ~stateMask) | (state & stateMask); if ((sysProcessor != X86CPU_386) && (cacheDataMode & CACHE_COPYBACK)) if ((state & MMU_STATE_MASK_CACHEABLE) == MMU_STATE_CACHEABLE) pPte->bits[0] &= ~MMU_STATE_CACHEABLE_WT; MMU_LOCK (wasEnabled, oldIntLev); mmuPro36TLBFlush (); cacheArchClearEntry (DATA_CACHE, pPte); return (OK); }/******************************************************************************** mmuStateGet - get state of virtual memory page** mmuStateGet is used to retrieve the state bits of the pte for the given* virtual page. The following states are provided:** MMU_STATE_VALID MMU_STATE_VALID_NOT vailid/invalid* MMU_STATE_WRITABLE MMU_STATE_WRITABLE_NOT writable/writeprotected* MMU_STATE_CACHEABLE MMU_STATE_CACHEABLE_NOT notcachable/cachable** these are or'ed together in the returned state. Additionally, masks* are provided so that specific states may be extracted from the returned state:** MMU_STATE_MASK_VALID * MMU_STATE_MASK_WRITABLE* MMU_STATE_MASK_CACHEABLE** RETURNS: OK or ERROR if virtual page does not exist.*/LOCAL STATUS mmuStateGet ( MMU_TRANS_TBL *transTbl, /* tranlation table */ void *pageAddr, /* page whose state we're querying */ UINT *state /* place to return state value */ ) { PTE *pPte; if (mmuPteGet (transTbl, pageAddr, &pPte) != OK) return (ERROR); *state = pPte->bits[0]; if ((sysProcessor != X86CPU_386) && (cacheDataMode & CACHE_COPYBACK)) if ((*state & MMU_STATE_MASK_CACHEABLE) != MMU_STATE_CACHEABLE_NOT) *state |= MMU_STATE_CACHEABLE_WT; return (OK); }/******************************************************************************** mmuPageMap - map physical memory page to virtual memory page** The physical page address is entered into the pte corresponding to the* given virtual page. The state of a newly mapped page is undefined. ** RETURNS: OK or ERROR if translation table creation failed. */LOCAL STATUS mmuPageMap ( MMU_TRANS_TBL *transTbl, /* translation table */ void *virtualAddress, /* virtual address */ void *physPage /* physical address */ ) { PTE *pPte; int oldIntLev; BOOL wasEnabled; BOOL status = mmuPteGet (transTbl, virtualAddress, &pPte); if ((mmuPageSize == PAGE_SIZE_4KB) && (status != OK)) { /* build the translation table for the virtual address */ if (mmuVirtualPageCreate (transTbl, virtualAddress) != OK) return (ERROR); if (mmuPteGet (transTbl, virtualAddress, &pPte) != OK) return (ERROR); } MMU_UNLOCK (wasEnabled, oldIntLev); if (mmuPageSize == PAGE_SIZE_2MB) (int)physPage &= ADDR_TO_PAGEBASE; pPte->field.page = (UINT)physPage >> ADDR_TO_PAGE; MMU_LOCK (wasEnabled, oldIntLev); mmuPro36TLBFlush (); cacheArchClearEntry (DATA_CACHE, pPte); return (OK); }/******************************************************************************** mmuGlobalPageMap - map physical memory page to global virtual memory page** mmuGlobalPageMap is used to map physical pages into global virtual memory* that is shared by all virtual memory contexts. The translation tables* for this section of the virtual space are shared by all virtual memory* contexts.** RETURNS: OK or ERROR if no pte for given virtual page.*/LOCAL STATUS mmuGlobalPageMap ( void *virtualAddress, /* virtual address */ void *physPage /* physical address */ ) { PTE *pPte; int oldIntLev; BOOL wasEnabled; BOOL status = mmuPteGet (&mmuGlobalTransTbl, virtualAddress, &pPte); int ix; if ((mmuPageSize == PAGE_SIZE_4KB) && (status != OK)) { /* build the translation table for the virtual address */ if (mmuVirtualPageCreate (&mmuGlobalTransTbl, virtualAddress) != OK) return (ERROR); if (mmuPteGet (&mmuGlobalTransTbl, virtualAddress, &pPte) != OK) return (ERROR); /* the globalPageBlock array is write protected */ for (ix = 0; ix < 2; ix++) mmuStateSet (&mmuGlobalTransTbl, (void *)((UINT)globalPageBlock + (PAGE_SIZE * ix)), MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE); globalPageBlock [((UINT) virtualAddress & DIR_BITS) >> DIR_INDEX] = TRUE; for (ix = 0; ix < 2; ix++) mmuStateSet (&mmuGlobalTransTbl, (void *)((UINT)globalPageBlock + (PAGE_SIZE * ix)), MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE_NOT); } MMU_UNLOCK (wasEnabled, oldIntLev); if (mmuPageSize == PAGE_SIZE_2MB) (int)physPage &= ADDR_TO_PAGEBASE; pPte->field.page = (UINT)physPage >> ADDR_TO_PAGE; MMU_LOCK (wasEnabled, oldIntLev); mmuPro36TLBFlush (); cacheArchClearEntry (DATA_CACHE, pPte); return (OK); }/******************************************************************************** mmuTranslate - translate a virtual address to a physical address** Traverse the translation table and extract the physical address for the* given virtual address from the pte corresponding to the virtual address.** RETURNS: OK or ERROR if no pte for given virtual address.*/LOCAL STATUS mmuTranslate ( MMU_TRANS_TBL *transTbl, /* translation table */ void *virtAddress, /* virtual address */ void **physAddress /* place to return result */ ) { PTE *pPte; if (mmuPteGet (transTbl, virtAddress, &pPte) != OK) { errno = S_mmuLib_NO_DESCRIPTOR; return (ERROR); } if (pPte->field.present == 0) { errno = S_mmuLib_INVALID_DESCRIPTOR; return (ERROR); } /* add offset into page */ if (mmuPageSize == PAGE_SIZE_4KB) *physAddress = (void *)((UINT)(pPte->bits[0] & PTE_TO_ADDR_4KB) + ((UINT)virtAddress & OFFSET_BITS_4KB)); else *physAddress = (void *)((UINT)(pPte->bits[0] & PTE_TO_ADDR_2MB) + ((UINT)virtAddress & OFFSET_BITS_2MB)); return (OK); }/******************************************************************************** mmuCurrentSet - change active translation table** mmuCurrent set is used to change the virtual memory context.* Load the CRP (root pointer) register with the given translation table.**/LOCAL void mmuCurrentSet ( MMU_TRANS_TBL *transTbl /* new active tranlation table */ ) { FAST int oldLev; int ix; if (firstTime) { mmuMemPagesWriteDisable (&mmuGlobalTransTbl); mmuMemPagesWriteDisable (transTbl); firstTime = FALSE; } oldLev = intLock (); mmuCurrentTransTbl = transTbl; intUnlock (oldLev); mmuStateSet (transTbl, mmuPdpTable, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE); for (ix = 0; ix < 4; ix++) { mmuPdpTable[ix].bits[0] = (UINT)transTbl->pDirectoryTable + (PAGE_SIZE * ix); mmuPdpTable[ix].bits[1] = 0; } mmuStateSet (transTbl, mmuPdpTable, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE_NOT); oldLev = intLock (); mmuPro36PdbrSet (&mmuPdpTable); intUnlock (oldLev); }/******************************************************************************** mmuMemPagesWriteDisable - write disable memory holding a table's descriptors** Memory containing translation table descriptors is marked as read only* to protect the descriptors from being corrupted. This routine write protects* all the memory used to contain a given translation table's descriptors.**/LOCAL void mmuMemPagesWriteDisable ( MMU_TRANS_TBL *transTbl ) { void *thisPage; int ix; if (mmuPageSize == PAGE_SIZE_4KB) for (ix = 0; ix < (PAGE_SIZE / sizeof(PTE)); ix++) { thisPage = (void *) (transTbl->pDirectoryTable[ix].bits[0] & PTE_TO_ADDR_4KB); if ((int)thisPage != (0xffffffff & PTE_TO_ADDR_4KB)) mmuStateSet (transTbl, thisPage, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE_NOT); } for (ix = 0; ix < 4; ix++) { thisPage = (void *)((UINT)transTbl->pDirectoryTable + (PAGE_SIZE * ix)); mmuStateSet (transTbl, thisPage, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE_NOT); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -