📄 mmupro32lib.c
字号:
/* write protect the new physical page containing the pte's for this new page block */ mmuStateSet (&mmuGlobalTransTbl, pPageTable, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE_NOT); } else pPageTable = (PTE *) ((int)virtPageAddr & ADDR_TO_PAGEBASE); /* unlock the physical page containing the directory table, so we can modify it */ mmuStateSet (&mmuGlobalTransTbl, thisTbl->pDirectoryTable, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE); 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 */ 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 valid/invalid* MMU_STATE_WRITABLE MMU_STATE_WRITABLE_NOT writable/writeprotected* MMU_STATE_CACHEABLE MMU_STATE_CACHEABLE_NOT cacheable/not_cacheable* MMU_STATE_WBACK MMU_STATE_WBACK_NOT write_back/write_through* MMU_STATE_GLOBAL MMU_STATE_GLOBAL_NOT global/not_global** 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* MMU_STATE_MASK_WBACK* MMU_STATE_MASK_GLOBAL** 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); 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 valid/invalid* MMU_STATE_WRITABLE MMU_STATE_WRITABLE_NOT writable/writeprotected* MMU_STATE_CACHEABLE MMU_STATE_CACHEABLE_NOT cacheable/not_cacheable* MMU_STATE_WBACK MMU_STATE_WBACK_NOT write_back/write_through* MMU_STATE_GLOBAL MMU_STATE_GLOBAL_NOT global/not_global** 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* MMU_STATE_MASK_WBACK* MMU_STATE_MASK_GLOBAL** RETURNS: OK or ERROR if virtual page does not exist.*/LOCAL STATUS mmuStateGet ( MMU_TRANS_TBL *transTbl, /* translation 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; 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; 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_4MB) (int)physPage &= ADDR_TO_PAGEBASE; pPte->field.page = (UINT)physPage >> ADDR_TO_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; BOOL wasEnabled; BOOL status = mmuPteGet (&mmuGlobalTransTbl, virtualAddress, &pPte); 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 */ mmuStateSet (&mmuGlobalTransTbl, globalPageBlock, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE); globalPageBlock [((UINT) virtualAddress & DIR_BITS) >> DIR_INDEX] = TRUE; mmuStateSet (&mmuGlobalTransTbl, globalPageBlock, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE_NOT); } MMU_UNLOCK (wasEnabled, oldIntLev); if (mmuPageSize == PAGE_SIZE_4MB) (int)physPage &= ADDR_TO_PAGEBASE; pPte->field.page = (UINT)physPage >> ADDR_TO_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); } /* add offset into page */ if (mmuPageSize == PAGE_SIZE_4KB) *physAddress = (void *)((UINT)(pPte->bits & PTE_TO_ADDR_4KB) + ((UINT)virtAddress & OFFSET_BITS_4KB)); else *physAddress = (void *)((UINT)(pPte->bits & PTE_TO_ADDR_4MB) + ((UINT)virtAddress & OFFSET_BITS_4MB)); 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 translation table */ ) { FAST int oldLev; if (firstTime) { mmuMemPagesWriteDisable (&mmuGlobalTransTbl); mmuMemPagesWriteDisable (transTbl); /* perform the deferred TLB and Cache flush */ /* MMU_TLB_FLUSH (); */ /* done by following mmuPro32PdbrSet () */ if (sysProcessor != X86CPU_386) WRS_ASM ("wbinvd"); /* flush the entire cache */ firstTime = FALSE; } oldLev = intLock (); mmuCurrentTransTbl = transTbl; mmuPro32PdbrSet (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 ix; if (mmuPageSize == PAGE_SIZE_4KB) for (ix = 0; ix < (PD_SIZE / sizeof(PTE)); ix++) { thisPage = (void *) (transTbl->pDirectoryTable[ix].bits & PTE_TO_ADDR_4KB); if ((int)thisPage != (0xffffffff & PTE_TO_ADDR_4KB)) 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 + -