?? mmu40lib.c
字號:
/* add buffers to the free table descriptor list */ pMem = mmuBufBlockAlloc (&newTransTbl->freeTableDescBlockList, sizeof (LEVEL_1_TABLE_DESC) * NUM_LEVEL_1_TABLE_DESCRIPTORS, newTransTbl); if (pMem == NULL) return (ERROR); /* pMem points to a physical page that we allocate table descriptor blocks * out of - add it to the translation table's list of pages that it owns. */ lstAdd (&newTransTbl->memPageList, (NODE *) pMem); /* allocate memory to hold the level 1 descriptor array - we can get it * from the freeTableDescBlockList since the level 1 tables are the same * size as the level 2 tables. */ newTransTbl->pLevel1 = pLevel1Table = (LEVEL_1_TABLE_DESC *) lstGet (&newTransTbl->freeTableDescBlockList); if (pLevel1Table == NULL) return (ERROR); /* copy the level 1 table from mmuGlobalTransTbl, * so we get the global virtual memory */ bcopy ((char *) mmuGlobalTransTbl.pLevel1, (char *) pLevel1Table, sizeof (LEVEL_1_TABLE_DESC) * NUM_LEVEL_1_TABLE_DESCRIPTORS); mmuMemPagesWriteDisable (newTransTbl); return (OK); }/******************************************************************************** mmuTransTblDelete - delete a translation table.* * mmuTransTblDelete deallocates all the memory used to store the translation* table entries. It does not deallocate physical pages mapped into the* virtual memory space.** RETURNS: OK**/LOCAL STATUS mmuTransTblDelete ( MMU_TRANS_TBL *transTbl /* translation table to be deleted */ ) { char *thisBlock = (char *) lstFirst (&transTbl->memBlockList); char *nextBlock; /* free all the pages in the translation table's memory partition */ mmuMemPagesWriteEnable (transTbl); while (thisBlock != NULL) { nextBlock = (void *) lstNext ((NODE *) thisBlock); thisBlock = (char *)((NODE *) thisBlock - 1); free ((void *) thisBlock); thisBlock = nextBlock; } /* free the translation table data structure */ free (transTbl); return (OK); }/******************************************************************************** mmuVirtualPageCreate - set up translation tables for a virtual page** simply check if there's already a page descriptor array that has a* page descriptor for the given virtual page. If there isn't, create one.** RETURNS OK or ERROR if couldn't allocate space. */LOCAL STATUS mmuVirtualPageCreate ( MMU_TRANS_TBL *pTransTbl, /* translation table */ void *virtAddr /* virtual addr to create */ ) { FAST UINT i; LEVEL_1_TABLE_DESC *pLevel1; LEVEL_2_TABLE_DESC *pLevel2; PAGE_DESC *pPageDescTable; UINT level1Index = LEVEL_1_TABLE_INDEX (virtAddr); UINT level2Index = LEVEL_2_TABLE_INDEX (virtAddr); pLevel1 = &pTransTbl->pLevel1[level1Index]; if (pLevel1->udt == UDT_INVALID) { /* create the level 2 table */ pLevel2 = mmuTableDescBlockAlloc (pTransTbl); if (pLevel2 == NULL) return (ERROR); /* invalidate all the level 2 descriptors */ mmuMemPagesWriteEnable (pTransTbl); for (i = 0; i < NUM_LEVEL_2_TABLE_DESCRIPTORS; i++) { pLevel2 [i].pageSize8k.addr = -1; pLevel2 [i].generic.used = 0; pLevel2 [i].generic.writeProtect = 0; pLevel2 [i].generic.udt = UDT_INVALID; } pLevel1->addr = (UINT) pLevel2 >> 9; pLevel1->udt = UDT_VALID; mmuMemPagesWriteDisable (pTransTbl); } pLevel2 = &(((LEVEL_2_TABLE_DESC *)(pLevel1->addr << 9))[level2Index]); if (pLevel2->generic.udt == UDT_INVALID) { UINT numDesc = ((mmuPageSize == PAGE_SIZE_4K) ? 64 : 32); /* create page descriptor table */ pPageDescTable = mmuPageDescBlockAlloc (pTransTbl); if (pPageDescTable == NULL) return (ERROR); /* invalidate all the page descriptors */ mmuMemPagesWriteEnable (pTransTbl); for (i = 0; i < numDesc; i++) { pPageDescTable[i].pageSize4k.addr = -1; pPageDescTable[i].generic.global = 0; pPageDescTable[i].generic.u1 = 0; pPageDescTable[i].generic.u0 = 0; pPageDescTable[i].generic.supervisor = 0; pPageDescTable[i].generic.cacheMode = 1; /* cachable, copyback */ pPageDescTable[i].generic.modified = 0; pPageDescTable[i].generic.used = 0; pPageDescTable[i].generic.writeProtect = 0; pPageDescTable[i].generic.pdt = PDT_INVALID; } if (mmuPageSize == PAGE_SIZE_4K) pLevel2->pageSize4k.addr = (UINT) pPageDescTable >> 8; else pLevel2->pageSize8k.addr = (UINT) pPageDescTable >> 7; pLevel2->generic.udt = UDT_VALID; mmuMemPagesWriteDisable (pTransTbl); } mmuATCFlush (virtAddr); return (OK); }/******************************************************************************** mmuPageDescBlockAlloc - allocate a block of page descriptors** This routine is used to allocate a block of page descriptors.** RETURNS: pointer to new page descriptor block*/LOCAL PAGE_DESC *mmuPageDescBlockAlloc ( MMU_TRANS_TBL *transTbl ) { PAGE_DESC *newPageDescBlock; mmuMemPagesWriteEnable (transTbl); newPageDescBlock = (PAGE_DESC *) lstGet (&transTbl->freePageDescBlockList); if (newPageDescBlock == NULL) { UINT numDesc = ((mmuPageSize == PAGE_SIZE_4K) ? 64 : 32); PAGE_DESC *pMem; /* get some more memory for page descriptor blocks */ pMem = (PAGE_DESC *) mmuBufBlockAlloc (&transTbl->freePageDescBlockList, numDesc * sizeof (PAGE_DESC), transTbl); if (pMem == NULL) return (NULL); lstAdd (&transTbl->memPageList, (NODE *) pMem); newPageDescBlock = (PAGE_DESC *) lstGet (&transTbl->freePageDescBlockList); if (newPageDescBlock == NULL) return (NULL); } mmuMemPagesWriteDisable (transTbl); return (newPageDescBlock); }/******************************************************************************** mmuTableDescBlockAlloc - allocate a block of table descriptors** This routine is used to allocate a block of table descriptors.** RETURNS: pointer to new table descriptor block*/LOCAL LEVEL_2_TABLE_DESC *mmuTableDescBlockAlloc ( MMU_TRANS_TBL *transTbl ) { LEVEL_2_TABLE_DESC *newTableDescBlock; mmuMemPagesWriteEnable (transTbl); newTableDescBlock = (LEVEL_2_TABLE_DESC *) lstGet (&transTbl->freeTableDescBlockList); if (newTableDescBlock == NULL) { LEVEL_2_TABLE_DESC *pMem; /* get some more memory for table descriptor blocks */ pMem = (LEVEL_2_TABLE_DESC *) mmuBufBlockAlloc (&transTbl->freeTableDescBlockList, NUM_LEVEL_2_TABLE_DESCRIPTORS * sizeof (LEVEL_2_TABLE_DESC), transTbl); if (pMem == NULL) return (NULL); lstAdd (&transTbl->memPageList, (NODE *) pMem); newTableDescBlock = (LEVEL_2_TABLE_DESC *) lstGet (&transTbl->freeTableDescBlockList); if (newTableDescBlock == NULL) return (NULL); } mmuMemPagesWriteDisable (transTbl); return (newTableDescBlock); }/******************************************************************************** mmuBufBlockAlloc - get memory and break it up into fixed length blocks** Allocates a page of memory, breaks it up into as many buffers as it can,* and hangs all the buffers on the specified list. The first buffer is* not hung on the list, so that the beginning of the page can be used to* keep track of the page (on a seperate linked list).** RETURNS: pointer to allocated page or NULL if allocation fails*/LOCAL void *mmuBufBlockAlloc ( LIST *pList, UINT bufSize, MMU_TRANS_TBL *pTransTbl ) { char *pPage; char *nextBuf; UINT numBufs = mmuPageSize / bufSize; int i; if ((pPage = (char *) lstGet (&pTransTbl->memFreePageList)) == NULL) { pPage = memPartAlignedAlloc (mmuPageSource, mmuPageSize * mmuNumPagesInFreeList, mmuPageSize); if (pPage == NULL) return (NULL); /* the beginning of each page is devoted to a NODE that strings pages together on memPageList; a second NODE immediately following will string together blocks of memory that we malloc on memBlockList. */ lstAdd (&pTransTbl->memBlockList, (NODE *) (pPage + sizeof (NODE))); /* break the buffer up into individual pages and stash them in the free page list. */ for (i = 0; i < mmuNumPagesInFreeList; i++, pPage += mmuPageSize) lstAdd (&pTransTbl->memFreePageList, (NODE *) pPage); pPage = (char *) lstGet (&pTransTbl->memFreePageList); } if (pPage == NULL) return (NULL); nextBuf = pPage + bufSize; for (i = 1; i < numBufs; i++) { lstAdd (pList, (NODE *) nextBuf); nextBuf += bufSize; } return ((void *) pPage); }/******************************************************************************** mmuEnable - turn mmu on or off** RETURNS: OK*/LOCAL STATUS mmuEnable ( BOOL enable /* TRUE to enable, FALSE to disable MMU */ ) { FAST int oldIntLev; LOCAL BOOL firstTime = TRUE; /* lock out interrupts to protect kludgey static data structure */ oldIntLev = intLock (); mmuEnableInline(enable); mmuEnabled = enable; intUnlock (oldIntLev);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -