📄 mmupro36lib.c
字号:
/* modify the directory table entry to point to the new page table */ pDte = &pDirectoryTable [((UINT) virtPageAddr & (DIR_PTR_BITS | DIR_BITS)) >> DIR_INDEX]; pDte->field.page = (UINT) pPageTable >> ADDR_TO_PAGE; pDte->field.present = 1; pDte->field.rw = 1; /* write protect the directory pointer table and the directory table */ for (ix = 0; ix < nDirPages; ix++) { mmuStateSet (&mmuGlobalTransTbl, (void *) ((UINT32)pDirectoryTable + (mmuPageSize * ix)), 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/write_protected* MMU_STATE_CACHEABLE MMU_STATE_CACHEABLE_NOT notcachable/cachable* 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; INT32 oldIntLev = 0; BOOL wasEnabled; if (mmuPteGet (transTbl, pageAddr, &pPte) != OK) return (ERROR); /* modify the PTE with mmu turned off and interrupts locked out */ MMU_WP_UNLOCK (wasEnabled, oldIntLev); pPte->bits[0] = (pPte->bits[0] & ~stateMask) | (state & stateMask); MMU_WP_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/write_protected* MMU_STATE_CACHEABLE MMU_STATE_CACHEABLE_NOT notcachable/cachable* 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, /* 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]; 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; INT32 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); } if (mmuPageSize != PAGE_SIZE_4KB) (UINT)physPage &= ADDR_TO_PAGEBASE; MMU_WP_UNLOCK (wasEnabled, oldIntLev); pPte->field.page = (UINT)physPage >> ADDR_TO_PAGE; MMU_WP_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; INT32 oldIntLev = 0; 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 */ mmuStateSet (&mmuGlobalTransTbl, globalPageBlock, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE); ix = ((UINT) virtualAddress & (DIR_PTR_BITS | DIR_BITS)) >> DIR_INDEX; globalPageBlock [ix] = (UINT8) TRUE; mmuStateSet (&mmuGlobalTransTbl, globalPageBlock, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE_NOT); } if (mmuPageSize != PAGE_SIZE_4KB) (UINT)physPage &= ADDR_TO_PAGEBASE; MMU_WP_UNLOCK (wasEnabled, oldIntLev); pPte->field.page = (UINT)physPage >> ADDR_TO_PAGE; MMU_WP_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[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 */ ) { INT32 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 (); /* LOCK INTERRUPTS */ mmuCurrentTransTbl = transTbl; mmuPro36PdbrSet (transTbl); intUnlock (oldLev); /* UNLOCK INTERRUPTS */ }/******************************************************************************** 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 ) { PTE * pDirectoryTable; void * thisPage; INT32 ix; pDirectoryTable = (PTE *)(transTbl->pDirectoryTable->bits[0] & PDP_TO_ADDR); if (mmuPageSize == PAGE_SIZE_4KB) for (ix = 0; ix < ((PD_SIZE * 4) / sizeof(PTE)); ix++) { thisPage = (void *)(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 < nDirPages; ix++) { thisPage = (void *)((UINT)pDirectoryTable + (mmuPageSize * ix)); mmuStateSet (transTbl, thisPage, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE_NOT); } mmuStateSet (transTbl, transTbl->pDirectoryTable, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE_NOT); }/******************************************************************************** mmuPro36PageMap - map 36bit physical memory page to virtual memory page** The 36bit 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. */STATUS mmuPro36PageMap ( MMU_TRANS_TBL * transTbl, /* translation table */ void * virtualAddress, /* 32bit virtual address */ LL_INT physPage /* 36bit physical address */ ) { PTE * pPte; BOOL wasEnabled; INT32 oldIntLev = 0; UINT32 * pPhysPage = (UINT32 *)&physPage; 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); } if (mmuPageSize != PAGE_SIZE_4KB) pPhysPage[0] &= ADDR_TO_PAGEBASE; MMU_WP_UNLOCK (wasEnabled, oldIntLev); pPte->field.page = pPhysPage[0] >> ADDR_TO_PAGE; pPte->field.page36 = pPhysPage[1] & 0x0000000f; MMU_WP_LOCK (wasEnabled, oldIntLev); MMU_TLB_FLUSH (); cacheArchClearEntry (DATA_CACHE, pPte); return (OK); }/******************************************************************************** mmuPro36Translate - translate a virtual address to a 36bit physical address** Traverse the translation table and extract the 36bit 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.*/STATUS mmuPro36Translate ( MMU_TRANS_TBL * transTbl, /* translation table */ void * virtAddress, /* 32bit virtual address */ LL_INT * physAddress /* place to return 36bit result */ ) { PTE * pPte; UINT32 * pPhysAddr = (UINT32 *) physAddress; 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) pPhysAddr[0] = (UINT32)(pPte->bits[0] & PTE_TO_ADDR_4KB) + ((UINT32)virtAddress & OFFSET_BITS_4KB); else pPhysAddr[0] = (UINT32)(pPte->bits[0] & PTE_TO_ADDR_2MB) + ((UINT32)virtAddress & OFFSET_BITS_2MB); pPhysAddr[1] = pPte->bits[1]; return (OK); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -