?? mmu40lib.c
字號(hào):
mmu40LibInit, mmuTransTblCreate, mmuTransTblDelete, mmuEnable, mmuStateSet, mmuStateGet, mmuPageMap, mmuGlobalPageMap, mmuTranslate, mmuCurrentSet };IMPORT STATE_TRANS_TUPLE *mmuStateTransArray;IMPORT int mmuStateTransArraySize;IMPORT MMU_LIB_FUNCS mmuLibFuncs;IMPORT int mmuPageBlockSize;int mmuNumPagesInFreeList = 4;PART_ID mmuPageSource = NULL;LOCAL TC_REG localTc;LOCAL CRP_REG localCrp;/* * mmuEnableInline: move the new tc value into d0, * do a movec d0 -> tc. */#define mmuEnableInline(value) \ { \ localTc.enable = value; \ __asm__ ("movew %0, d0; .word 0x4e7b, 0x0003": : "r" (localTc): "d0" ); \ } #define PAGE_SIZE_8K 8192#define PAGE_SIZE_4K 4096/******************************************************************************** mmu40LibInit - initialize module** Build a dummy translation table that will hold the page table entries* for the global translation table. The mmu remains disabled upon* completion. Note that this routine is global so that it may be referenced* in usrConfig.c to pull in the correct mmuLib for the specific architecture.** RETURNS: OK if no error, ERROR otherwise.** ERRNO: S_mmuLib_INVALID_PAGE_SIZE*/STATUS mmu40LibInit ( int pageSize /* system pageSize (4096 or 8192) */ ) { LEVEL_1_TABLE_DESC *pLevel1Table; int i; void *pMem; /* if the user has not specified a memory partition to obtain pages from (by initializing mmuPageSource), then initialize mmuPageSource to the system memory partition. */ if (mmuPageSource == NULL) mmuPageSource = memSysPartId; /* initialize the data objects that are shared with vmLib.c */ mmuStateTransArray = &mmuStateTransArrayLocal [0]; mmuStateTransArraySize = sizeof (mmuStateTransArrayLocal) / sizeof (STATE_TRANS_TUPLE); mmuLibFuncs = mmuLibFuncsLocal; mmuPageBlockSize = PAGE_BLOCK_SIZE; if ((pageSize != PAGE_SIZE_4K) && (pageSize != PAGE_SIZE_8K)) { errno = S_mmuLib_INVALID_PAGE_SIZE; return (ERROR); } /* initialize kludgey static data struct for loading tc reg */ localTc.pageSize = (pageSize == PAGE_SIZE_4K) ? 0 : 1; localTc.enable = 0; localTc.pad = 0; /* initialize kludgey static data struct for loading crp reg */ localCrp.addr = 0; localCrp.pad = 0; mmuEnabled = FALSE; mmuPageSize = pageSize; /* build a dummy translation table which will hold the pte's for * global memory. All real translation tables will point to this * one for controling the state of the global virtual memory */ /* initialize the lists that hold free memory for table descriptors * and page descriptors. */ lstInit (&mmuGlobalTransTbl.freePageDescBlockList); lstInit (&mmuGlobalTransTbl.freeTableDescBlockList); lstInit (&mmuGlobalTransTbl.memPageList); lstInit (&mmuGlobalTransTbl.memBlockList); lstInit (&mmuGlobalTransTbl.memFreePageList); /* if pageSize == 4k, then page descriptor array has 64 elements, * if 8k, then array has 32 elements. */ pMem = mmuBufBlockAlloc (&mmuGlobalTransTbl.freePageDescBlockList, sizeof (PAGE_DESC) * ((mmuPageSize == PAGE_SIZE_4K) ? 64 : 32), &mmuGlobalTransTbl); if (pMem == NULL) return (NULL); /* pMem points to a physical page that we allocate page descriptor blocks * out of - add it to the translation table's list of pages that it owns. */ lstAdd (&mmuGlobalTransTbl.memPageList, (NODE *) pMem); /* both level 1 and level 2 table descriptor arrays have 128 elements */ pMem = mmuBufBlockAlloc (&mmuGlobalTransTbl.freeTableDescBlockList, sizeof (LEVEL_1_TABLE_DESC) * NUM_LEVEL_1_TABLE_DESCRIPTORS, &mmuGlobalTransTbl); if (pMem == NULL) return (NULL); /* 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 (&mmuGlobalTransTbl.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. */ mmuGlobalTransTbl.pLevel1 = pLevel1Table = (LEVEL_1_TABLE_DESC *) lstGet (&mmuGlobalTransTbl.freeTableDescBlockList); if (pLevel1Table == NULL) return (ERROR); /* invalidate all the level 1 descriptors */ for (i = 0; i < NUM_LEVEL_1_TABLE_DESCRIPTORS; i++) { pLevel1Table[i].addr = -1; pLevel1Table[i].used = 0; pLevel1Table[i].writeProtect = 0; pLevel1Table[i].udt = UDT_INVALID; } return (OK); }/******************************************************************************** mmuMemPagesWriteEnable - write enable the memory holding a table's descriptors** Each translation table has a linked list of physical pages that contain its* table and page descriptors. Before you can write into any descriptor, you* must write enable the page it is contained in. This routine enables all* the pages used by a given translation table.**/LOCAL void mmuMemPagesWriteEnable ( MMU_TRANS_TBL_ID transTbl ) { void *thisPage; thisPage = (void *) lstFirst (&transTbl->memPageList); while (thisPage != NULL) { mmuStateSet (transTbl, thisPage, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE); thisPage = (void *) lstNext ((NODE *) thisPage); } }/******************************************************************************** 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; thisPage = (void *) lstFirst (&transTbl->memPageList); while (thisPage != NULL) { mmuStateSet (transTbl, thisPage, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE_NOT);#if (CPU == MC68060) /* * The MC68060 does not use the data cache when performing a table * search because of the tablewalker unit is interfaced directly to * the Bus controller. Therefore translation tables must always be * placed in writethrough space. */ mmuStateSet (transTbl, thisPage, MMU_STATE_MASK_CACHEABLE, MMU_STATE_CACHEABLE_WRITETHROUGH);#endif /* (CPU == MC68060) */ thisPage = (void *) lstNext ((NODE *) thisPage); } }/******************************************************************************** mmuPageDescGet - get the page descriptor for a given page** mmuPageDescGet traverses a translation table and returns the (physical) * address of the page descriptor for the given virtual address.** RETURNS: OK or ERROR if there is no virtual space for the given address **/LOCAL STATUS mmuPageDescGet ( MMU_TRANS_TBL *pTransTbl, /* translation table */ void *virtAddr, /* virtual address */ PAGE_DESC **result /* result is returned here */ ) { 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); UINT pageDescTableIndex = PAGE_DESC_TABLE_INDEX (virtAddr); pLevel1 = &pTransTbl->pLevel1[level1Index]; if (pLevel1->udt == UDT_INVALID) return (ERROR); pLevel2 = &(((LEVEL_2_TABLE_DESC *)(pLevel1->addr << 9))[level2Index]); if (pLevel2->generic.udt == UDT_INVALID) return (ERROR); pPageDescTable = (PAGE_DESC *) ((mmuPageSize == PAGE_SIZE_4K) ? (pLevel2->pageSize4k.addr << 8) : (pLevel2->pageSize8k.addr << 7)); *result = &pPageDescTable[pageDescTableIndex]; return (OK); }/******************************************************************************** mmuTransTblCreate - create a new translation table.** create a 68040 or 68060 translation table. Allocates space for the* MMU_TRANS_TBL data structure and calls mmuTransTblInit on that object. ** RETURNS: address of new object or NULL if allocation failed,* or NULL if initialization failed.*/LOCAL MMU_TRANS_TBL *mmuTransTblCreate ( ) { MMU_TRANS_TBL *newTransTbl; newTransTbl = (MMU_TRANS_TBL *) malloc (sizeof (MMU_TRANS_TBL)); if (newTransTbl == NULL) return (NULL); if (mmuTransTblInit (newTransTbl) == ERROR) { free ((char *) newTransTbl); return (NULL); } return (newTransTbl); }/******************************************************************************** mmuTransTblInit - initialize a new translation table ** Initialize a new translation table. The level 1 table is copyed from the* global translation mmuGlobalTransTbl, so that we* will share the global virtual memory with all* other translation tables.* * RETURNS: OK or ERROR if unable to allocate memory. */LOCAL STATUS mmuTransTblInit ( MMU_TRANS_TBL *newTransTbl /* translation table to be inited */ ) { LEVEL_1_TABLE_DESC *pLevel1Table; void *pMem; lstInit (&newTransTbl->memPageList); lstInit (&newTransTbl->memBlockList); lstInit (&newTransTbl->memFreePageList); /* initialize the lists that hold free memory for table descriptors * and page descriptors. */ lstInit (&newTransTbl->freePageDescBlockList); lstInit (&newTransTbl->freeTableDescBlockList); /* add buffers to the free page descriptor list */ /* if pageSize == 4k, then page descriptor array has 64 elements, * if 8k, then array has 32 elements. */ pMem = mmuBufBlockAlloc (&newTransTbl->freePageDescBlockList, sizeof (PAGE_DESC) * ((mmuPageSize == PAGE_SIZE_4K) ? 64 : 32), newTransTbl); if (pMem == NULL) return (ERROR); /* pMem points to a physical page that we allocate page descriptor blocks * out of - add it to the translation table's list of pages that it owns. */ lstAdd (&newTransTbl->memPageList, (NODE *) pMem);
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -