📄 mmui86lib.c
字号:
/* 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 */ mmuStateSet (&mmuGlobalTransTbl, thisTbl->pDirectoryTable, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE_NOT); /* defer the TLB flush to the mmuCurrentSet() at init time */ if (!firstTime) { MMU_TLB_FLUSH (); } 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 = 0; BOOL wasEnabled; if (mmuPteGet (transTbl, pageAddr, &pPte) != OK) return (ERROR); /* modify the pte with MMU turned off and interrupts locked out */ MMU_UNLOCK (wasEnabled, oldIntLev); pPte->bits = (pPte->bits & ~stateMask) | (state & stateMask); if ((sysProcessor != X86CPU_386) && (cacheDataMode & CACHE_COPYBACK)) if ((state & MMU_STATE_MASK_CACHEABLE) == MMU_STATE_CACHEABLE) pPte->bits &= ~MMU_STATE_CACHEABLE_WT; MMU_LOCK (wasEnabled, oldIntLev); /* defer the TLB and Cache flush to the mmuCurrentSet() */ if (!firstTime) { MMU_TLB_FLUSH (); 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; 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 = 0; FAST UINT page = (UINT)physPage >> ADDR_TO_PAGE; BOOL wasEnabled; if (mmuPteGet (transTbl, virtualAddress, &pPte) != 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); pPte->field.page = page; MMU_LOCK (wasEnabled, oldIntLev); MMU_TLB_FLUSH (); 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 = 0; FAST UINT page = (UINT)physPage >> ADDR_TO_PAGE; BOOL wasEnabled; if (mmuPteGet (&mmuGlobalTransTbl, virtualAddress, &pPte) != 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 */ mmuStateSet (&mmuGlobalTransTbl, globalPageBlock, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE); globalPageBlock [(unsigned) virtualAddress >> DIRECTORY_INDEX] = TRUE; mmuStateSet (&mmuGlobalTransTbl, globalPageBlock, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE_NOT); } MMU_UNLOCK (wasEnabled, oldIntLev); pPte->field.page = page; MMU_LOCK (wasEnabled, oldIntLev); /* defer the TLB and Cache flush to the mmuCurrentSet() */ if (!firstTime) { MMU_TLB_FLUSH (); 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); } *physAddress = (void *)(pPte->bits & PTE_TO_ADDR); /* add offset into page */ *physAddress = (void *)((UINT)*physAddress + ((UINT)virtAddress & OFFSET_BITS)); 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; if (firstTime) { mmuMemPagesWriteDisable (&mmuGlobalTransTbl); mmuMemPagesWriteDisable (transTbl); /* perform the deferred TLB and Cache flush */ /* MMU_TLB_FLUSH (); */ /* done by following mmuI86PdbrSet () */ if (sysProcessor != X86CPU_386) WRS_ASM ("wbinvd"); /* flush the entire cache */ firstTime = FALSE; } oldLev = intLock (); mmuCurrentTransTbl = transTbl; mmuI86PdbrSet (transTbl); 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 i; for (i = 0; i < (PAGE_SIZE / sizeof(PTE)) ;i++) { thisPage = (void *) (transTbl->pDirectoryTable[i].bits & PTE_TO_ADDR); if ((int)thisPage != 0xfffff000) mmuStateSet (transTbl, thisPage, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE_NOT); } mmuStateSet (transTbl, transTbl->pDirectoryTable, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE_NOT); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -