📄 mmuppclib.c
字号:
) { u_int thisPage; thisPage = pTransTbl->hTabOrg; while (thisPage < (pTransTbl->hTabOrg + pTransTbl->pteTableSize)) { if (mmuPpcStateSet (pTransTbl,(void *) thisPage, MMU_STATE_MASK_WIMG_AND_WRITABLE, MMU_STATE_WRITABLE_NOT | MMU_STATE_GUARDED_NOT | MMU_STATE_MEM_COHERENCY | MMU_STATE_CACHEABLE_COPYBACK) == ERROR) return ; thisPage += PAGE_SIZE; } }/******************************************************************************** mmuPpcTransTblCreate - create a new translation table.**/LOCAL MMU_TRANS_TBL * mmuPpcTransTblCreate ( ) { MMU_TRANS_TBL * pNewTransTbl; static BOOL firstTime = TRUE; /* first time call flag */ if (firstTime) { firstTime = FALSE; pNewTransTbl = &mmuGlobalTransTbl; } else { /* allocate a piece of memory to save the new translation table */ pNewTransTbl = (MMU_TRANS_TBL *) malloc (sizeof (MMU_TRANS_TBL)); /* if the memory can not allocated then return the NULL pointer */ if (pNewTransTbl == NULL) return (NULL); /* * initilialize the new translation table. * If the initialization falls then free the memory and return the NULL * pointer. */ if (mmuPpcTransTblInit (pNewTransTbl) == ERROR) { free ((char *) pNewTransTbl); return (NULL); } } /* return the new translation table created */ return (pNewTransTbl); }/******************************************************************************** mmuPpcTransTblInit - initialize a new translation table ** Initialize a new translation table. The level 1 table is copyed from the* global translation mmuPpcGlobalTransTbl, 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 mmuPpcTransTblInit ( MMU_TRANS_TBL * pNewTransTbl /* translation table to initialize */ ) { void * pPtegTable; pNewTransTbl->pteTableSize = mmuGlobalTransTbl.pteTableSize; pNewTransTbl->hTabMask = mmuGlobalTransTbl.hTabMask; pPtegTable = memalign (pNewTransTbl->pteTableSize, pNewTransTbl->pteTableSize); if (pPtegTable == NULL) return (ERROR); pNewTransTbl->hTabOrg = (u_int) pPtegTable ; memcpy ((void *) (pNewTransTbl->hTabOrg), (void *) (mmuGlobalTransTbl.hTabOrg), pNewTransTbl->pteTableSize); mmuPpcMemPagesWriteDisable (pNewTransTbl); return (OK); }/******************************************************************************** mmuPpcTransTblDelete - delete a translation table.* * This routine deletes a translation table.** RETURNS: OK always.*/LOCAL STATUS mmuPpcTransTblDelete ( MMU_TRANS_TBL * pTransTbl /* translation table to be deleted */ ) { /* free the PTEG table */ free ((void *) pTransTbl->hTabOrg); /* free the translation table data structure */ free (pTransTbl); return (OK); }/******************************************************************************** mmuPpcEnable - turn mmu on or off** RETURNS: OK*/LOCAL STATUS mmuPpcEnable ( BOOL enable /* TRUE to enable, FALSE to disable MMU */ ) { int lockKey; /* lock key for intUnlock() */ if (enable) { /* lock the interrupt */ lockKey = intLock (); if (mmuPpcSelected & MMU_INST) { mmuPpcAEnable (MMU_I_ADDR_TRANS); /* enable instruction MMU */ mmuPpcIEnabled = TRUE; /* tell I MMU is turned on */ /* test if the Instruction cache should be enabled too */ if (cacheIToEnable) cacheArchEnable (_INSTRUCTION_CACHE); /* enable the I cache */ } if (mmuPpcSelected & MMU_DATA) { mmuPpcAEnable (MMU_D_ADDR_TRANS); /* enable data MMU */ mmuPpcDEnabled = TRUE; /* tell D MMU is turned on */ /* test if the Data cache should be enabled too */ if (cacheDToEnable) cacheArchEnable (_DATA_CACHE); /* enable the D cache */ } intUnlock (lockKey); /* unlock the interrupt */ } else { lockKey = intLock (); /* lock the Interrupt */ if (mmuPpcSelected & MMU_INST) { /* * if the Instruction cache is enabled, then disable the * instruction cache before to disable the Instruction MMU. */ if (cacheIToEnable) cacheArchDisableFromMmu (_INSTRUCTION_CACHE); /* disable the Instruction MMU */ mmuPpcADisable (MMU_I_ADDR_TRANS); /* set the flag to tell that the Instruction MMU is disabled */ mmuPpcIEnabled = FALSE; } if (mmuPpcSelected & MMU_DATA) { /* * if the Data cache is enabled, then disable the Data cache * to disable the Data MMU. */ if (cacheDToEnable) cacheArchDisableFromMmu (_DATA_CACHE); /* disable the Data MMU */ mmuPpcADisable (MMU_D_ADDR_TRANS); /* set the flag to tell that the Data MMU is disabled */ mmuPpcDEnabled = FALSE; } intUnlock (lockKey); /* unlock the interrupt */ } return (OK); }/******************************************************************************** mmuPpcStateSet - set state of virtual memory page*** 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 cachable/notcachable* MMU_STATE_CACHEABLE_WRITETHROUGH* MMU_STATE_CACHEABLE_COPYBACK* MMU_STATE_MEM_COHERENCY MMU_STATE_MEM_COHERENCY_NOT* MMU_STATE_GUARDED MMU_STATE_GUARDED_NOT* MMU_STATE_NO_ACCESS* MMU_STATE_NO_EXECUTE*/LOCAL STATUS mmuPpcStateSet ( MMU_TRANS_TBL * pTransTbl, /* translation table */ void * effectiveAddr, /* page whose state to modify */ UINT stateMask, /* mask of which state bits to modify */ UINT state /* new state bit values */ ) { PTE * pPte; /* PTE address */ PTE pte; /* PTE value */ /* * Try to find in the PTEG table pointed to by the pTransTbl structure, * the PTE corresponding to the <effectiveAddr>. * If this PTE can not be found then return ERROR. */ if (mmuPpcPteGet (pTransTbl, effectiveAddr, &pPte) != OK) { errno = S_mmuLib_NO_DESCRIPTOR; return (ERROR); } /* * Check if the state to set page corresponding to <effectiveAddr> will * not set the cache in inhibited and writethrough mode. This mode is not * supported by the cache. */ if ((stateMask & MMU_STATE_MASK_CACHEABLE) && (state & MMU_STATE_CACHEABLE_NOT) && (state & MMU_STATE_CACHEABLE_WRITETHROUGH)) { return (ERROR); } /* load the value of the PTE pointed to by pPte to pte */ pte = *pPte; /* set or reset the VALID bit if requested */ pte.bytes.word0 = (pte.bytes.word0 & ~(stateMask & MMU_STATE_MASK_VALID)) | (state & stateMask & MMU_STATE_MASK_VALID); /* set or reset the WIMG bit if requested */ pte.bytes.word1 = (pte.bytes.word1 & ~(stateMask & MMU_STATE_MASK_WIMG_AND_WRITABLE)) | (state & stateMask & MMU_STATE_MASK_WIMG_AND_WRITABLE); /* update the PTE in the table */ mmuPpcPteUpdate (pPte, &pte); /* update the Translation Lookside Buffer */ mmuPpcTlbie (effectiveAddr); return (OK); }/******************************************************************************** mmuPpcStateGet - get state of virtual memory page**/LOCAL STATUS mmuPpcStateGet ( MMU_TRANS_TBL * pTransTbl, /* tranlation table */ void * effectiveAddr, /* page whose state we're querying */ UINT * state /* place to return state value */ ) { PTE * pPte; /* PTE address */ /* * Try to find the PTE corresponding to the <effectiveAddr> in the PTEG * table pointed to by the pTransTbl structure, * If this PTE can not be found then return ERROR. */ if (mmuPpcPteGet (pTransTbl, effectiveAddr, &pPte) != OK) { errno = S_mmuLib_NO_DESCRIPTOR; return (ERROR); } /* extract the state of the VALID and WIMG bit */ * state = pPte->bytes.word0 & MMU_STATE_MASK_VALID; * state |= pPte->bytes.word1 & MMU_STATE_MASK_WIMG_AND_WRITABLE; return (OK); }/******************************************************************************** mmuPpcPageMap - 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 mmuPpcPageMap ( MMU_TRANS_TBL * pTransTbl, /* translation table */ void * effectiveAddr, /* effective address */ void * physicalAddr /* physical address */ ) { PTE * pPte; /* PTE address */ PTE pte; /* PTE value */ PTEG * pPteg1; /* PTEG 1 address */ PTEG * pPteg2; /* PTEG 2 address */ UINT vsid; /* virtual segment ID */ UINT api; /* abbreviated page index */ UINT pteIndex; /* PTE index in a PTEG */ UINT hashLevel; /* hash table level */ if (mmuPpcPteGet (pTransTbl, effectiveAddr, &pPte) == OK) { pte = * pPte; } else { /* get the address of both PTEGs, VSID and API value */ mmuPpcPtegAddrGet (pTransTbl, effectiveAddr, &pPteg1, &pPteg2, &vsid, &api); pteIndex = 0; pPte = NULL; hashLevel = 0; /* * read the PTEs of the first group. If one of the PTE matchs * the expected PTE then extrats the physical address from the PTE * word 1 and exits the function with OK. If not, chechs the next PTE. * If no PTE matchs the expected PTE then read the second group. */ do { if (pPteg1->pte[pteIndex].field.v == FALSE) { pPte = &pPteg1->pte[pteIndex]; hashLevel = 0; break; } if (pPteg2->pte[pteIndex].field.v == FALSE) { pPte = &pPteg2->pte[pteIndex]; hashLevel = 1; } } while (++pteIndex < MMU_PTE_BY_PTEG); if (pPte == NULL) { errno = S_mmuLib_NO_DESCRIPTOR; return (ERROR); } pte.field.v = TRUE; /* entry valid */ pte.field.vsid = vsid; pte.field.h = hashLevel; pte.field.api = api; pte.field.r = 0; pte.field.c = 0; pte.field.wimg = 0; /* cache writethrough mode */ pte.field.pp = 2; /* read/write */ } pte.field.rpn = (u_int) physicalAddr >> MMU_PTE_RPN_SHIFT; mmuPpcPteUpdate (pPte, &pte); mmuPpcTlbie (effectiveAddr); return (OK); }/******************************************************************************** mmuPpcGlobalPageMap - map physical memory page to global virtual memory page** mmuPpcGlobalPageMap 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 mmuPpcGlobalPageMap ( void * effectiveAddr, /* effective address */ void * physicalAddr /* physical address */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -