📄 mmu405lib.c
字号:
MMU_TRANS_TBL * pTransTbl /* new active tranlation table */ ) { FAST int lockKey; /* intLock lock key */ static BOOL firstTime = TRUE; /* first time call flag */ if (firstTime) { /* * write protect all the pages containing the descriptors allocated for * the global translation table. Need to do this because when this * memory is allocated, the global translation table doesn't exist yet. */ mmu405MemPagesWriteDisable (&mmuGlobalTransTbl); mmu405MemPagesWriteDisable (pTransTbl); firstTime = FALSE; } lockKey = intLock (); /* * save the PID value in the PID register via * mmuPpcPidSet(). If one or both MMUs are turned on then disable * the MMU, set the PID register and re-enable the MMU. */ if (mmu405IsOn (MMU_INST) || mmu405IsOn (MMU_DATA)) { mmu405Enable (FALSE); /* disable the MMU */ mmuPpcPidSet (pTransTbl->pid); mmu405Enable (TRUE); /* re-enable the MMU */ } else mmuPpcPidSet (pTransTbl->pid); intUnlock (lockKey); }/********************************************************************************* mmu405Lvl2DescAddrGet - get the address of a level 2 Desciptor* * This routine finds the address of a level 2 desciptor corresponding to the* <effectiveAddr> in the translation table pointed to by <pTransTbl> structure.* If a matching level 2 Descriptor exists, the routine save the level 2* desciptor address at the address pointed to by <ppLvl2Desc>.* If any level 2 Descriptor matching the <effectiveAddr> is not found then* the function return ERROR.** RETURNS: OK or ERROR.*/LOCAL STATUS mmu405Lvl2DescAddrGet ( MMU_TRANS_TBL * pTransTbl, /* translation table */ void * effectiveAddr, /* effective address */ LEVEL_2_DESC ** ppLvl2Desc /* where to save the lvl 2 desc addr */ ) { LEVEL_1_DESC * pLvl1Desc; /* level 1 descriptor address */ LEVEL_2_DESC * pLvl2Desc; /* level 2 descriptor address */ EFFECTIVE_ADDR effAddr; /* effective address */ /* get address of the level 1 descriptor */ pLvl1Desc = mmu405Lvl1DescAddrGet (pTransTbl, effectiveAddr); /* * check the valid bit. If the level 1 descriptor is not valid than * the level 2 descriptor doesn't exist. In this case return ERROR. */ if (!pLvl1Desc->field.v) return (ERROR); effAddr.effAddr = effectiveAddr; /* * save the level 2 descriptor address at the address * pointed to by <ppLvl2Desc>. */ pLvl2Desc = (LEVEL_2_DESC *) (pLvl1Desc->field.l2ba << 2); * ppLvl2Desc = pLvl2Desc + effAddr.field.l2index; return (OK); } /********************************************************************************* mmu405Lvl1DescAddrGet - get the address of a level 1 descriptor ** This function returns the address of the level 1 descriptor corresponding* to the effective address pointed to by <effectiveAddr>. ** RETRUNS: always the address of the level 1 descriptor**/LOCAL LEVEL_1_DESC * mmu405Lvl1DescAddrGet ( MMU_TRANS_TBL * pTransTbl, /* translation table */ void * effectiveAddr /* effective address */ ) { EFFECTIVE_ADDR effAddr; effAddr = * ((EFFECTIVE_ADDR *) &effectiveAddr); /* * build the Level 1 descriptor address corresponding to the effective * address pointed to by <effectiveAddr>. */ return ( pTransTbl->l1TblPtr.pL1Desc + effAddr.field.l1index ); }/********************************************************************************* mmu405Lvl1DescUpdate - update a level 1 descriptor ** This function updates a level 1 desciptor. The addess of the level 1* descriptor is handled by <pLvl1Desc> and the new value of the level 1* descriptor by <lvl1Desc>.** RETURNS: N/A*/LOCAL void mmu405Lvl1DescUpdate ( LEVEL_1_DESC * pLvl1Desc, /* Level 1 descriptor address */ LEVEL_1_DESC lvl1Desc /* Level 1 descriptor */ ) { UINT32 key; if (mmu405IsOn (MMU_INST) || mmu405IsOn (MMU_DATA)) { key = intLock(); /* lock interrupt */ mmu405Enable (FALSE); /* disable the mmu */ pLvl1Desc->l1desc = lvl1Desc.l1desc; /* update the descriptor */ mmu405Enable (TRUE); /* enable the MMU */ intUnlock(key); /* re-enable interrupt */ } else pLvl1Desc->l1desc = lvl1Desc.l1desc; /* update the descriptor */ }/********************************************************************************* mmu405Lvl2DescUpdate - update a level 2 descriptor ** This function updates a level 2 desciptor. The addess of the level 2* descriptor is handled by <pLvl2Desc> and the new value of the level 2* descriptor by <lvl2Desc>.** RETURNS: N/A*/LOCAL void mmu405Lvl2DescUpdate ( LEVEL_2_DESC * pLvl2Desc, /* Level 2 descriptor address */ LEVEL_2_DESC lvl2Desc /* Level 2 descriptor */ ) { UINT32 key; if (mmu405IsOn (MMU_INST) || mmu405IsOn (MMU_DATA)) { key = intLock(); /* lock interrupt */ mmu405Enable (FALSE); /* disable the mmu */ *pLvl2Desc = lvl2Desc; /* update the descriptor */ mmu405Enable (TRUE); /* enable the MMU */ intUnlock(key); /* re-enable interrupt */ } else *pLvl2Desc = lvl2Desc; /* update the descriptor */ }/********************************************************************************* mmu405IsOn - return the state of the MMU** This function returns TRUE if the MMU selected by <mmuType> is on.** RETURNS: TRUE or FALSE**/LOCAL BOOL mmu405IsOn ( int mmuType /* MMU type to return the state of */ ) { switch (mmuType) { case MMU_INST: /* Instruction MMU to test */ return (vxMsrGet () & _PPC_MSR_IR); break; case MMU_DATA: /* Data MMU to test */ return (vxMsrGet () & _PPC_MSR_DR); break; default: /* default value */ return (FALSE); } }/********************************************************************************* mmu405GetNewPid - get a free PID for use with a new address map from * mmuAddrMapArray, and set the address map element* to point to MMU_TRANS_TBL pointer.** NOTE: For MMU library internal use only** RETURNS: index of free array element or 0.*/UINT8 mmu405GetNewPid (MMU_TRANS_TBL *transTbl) { int i; for (i = 1; i < MMU_ADDR_MAP_ARRAY_SIZE; i++) if (mmuAddrMapArray [i] == MMU_ADDR_MAP_ARRAY_INV) { mmuAddrMapArray [i] = transTbl; return i; } return 0; }/********************************************************************************* mmu405FreePid - Free (mark as invalid) the pid entry** NOTE: For MMU library internal use only**/void mmu405FreePid (UINT8 pid) { mmuAddrMapArray [pid] = MMU_ADDR_MAP_ARRAY_INV; }/********************************************************************************* mmu405Tlbie - Invalidate tlb entry for the specified effective addr** NOTE: For MMU library internal use only. This function switches the current* address map to the one pointed to by pTransTbl and then restores it back.**/void mmu405Tlbie ( MMU_TRANS_TBL * pTransTbl, /* tranlation table */ void * effAddr /* EA to invalidate in tlb */ ) { UINT32 index; UINT32 tlbhi; UINT32 oldPid; /* save old PID */ oldPid = mmuPpcPidGet (); /* set PID to the one for pTransTbl */ if (oldPid != pTransTbl->pid) mmuPpcPidSet (pTransTbl->pid); if ((index = mmuPpcTlbSearch (effAddr)) != -1) { /* read current entry (hi part) */ tlbhi = mmuPpcTlbReadEntryHi (index); /* clear valid bit */ tlbhi &= ~MMU_STATE_VALID; /* write back entry */ mmuPpcTlbWriteEntryHi (index, tlbhi); } /* restore old PID */ if (oldPid != pTransTbl->pid) mmuPpcPidSet (oldPid); }/********************************************************************************* mmu405Show - show the level 1 and 2 desciptor for and effective address** NOTE: For MMU library debug only */void mmu405Show ( MMU_TRANS_TBL * pTransTbl, /* translation table */ void * effectiveAddr /* effective address */ ) { LEVEL_1_DESC * pLvl1Desc; /* level 1 descriptor address */ LEVEL_2_DESC * pLvl2Desc; /* level 2 descriptor address */ /* get the level 1 descriptor address */ pLvl1Desc = mmu405Lvl1DescAddrGet (pTransTbl, effectiveAddr); printf ("Level 1:\n"); printf ("l2ba = 0x%x\n", pLvl1Desc->field.l2ba); printf ("v = %d\n", pLvl1Desc->field.v); if (mmu405Lvl2DescAddrGet (pTransTbl, effectiveAddr, &pLvl2Desc) != OK) return ; printf ("\n\n"); printf ("Level 2:\n"); printf ("epn = 0x%x\n", pLvl2Desc->field.epn); printf ("size = 0x%x\n", pLvl2Desc->field.size); printf ("v = %d\n", pLvl2Desc->field.v); printf ("e = %d\n", pLvl2Desc->field.e); printf ("u0 = %d\n", pLvl2Desc->field.u0); printf ("\n"); printf ("rpn = 0x%x\n", pLvl2Desc->field.rpn); printf ("ex = %d\n", pLvl2Desc->field.ex); printf ("wr = %d\n", pLvl2Desc->field.wr); printf ("zsel = 0x%x\n", pLvl2Desc->field.zsel); printf ("w = %d\n", pLvl2Desc->field.w); printf ("i = %d\n", pLvl2Desc->field.i); printf ("m = %d\n", pLvl2Desc->field.m); printf ("g = %d\n", pLvl2Desc->field.g); }/******************************************************************************** mmu405TlbShow - List the contents of the TLB Entry registers** RETURNS: nothing*/void mmu405TlbShow () { int ix; UINT32 tlbhi, tlblo; for (ix=0; ix<64; ix++) { tlbhi = mmuPpcTlbReadEntryHi (ix); tlblo = mmuPpcTlbReadEntryLo (ix); printf ("TLB at index %d : %x %x\n", ix, tlbhi, tlblo); } }#ifdef DEBUG_MISS_HANDLER/******************************************************************************** mmu405MetricsShow - Show Miss Handler metrics for debugging** OPTIONS:* 0 or 3 for I-MMU and D-MMU (long)* 1 for I-MMU only (long)* 2 for D-MMU only (long)* 4 or 7 for all metrics (short)* 5 for I-MMU only (short)* 6 for D-MMU only (short)** RETURNS: nothing*/void mmu405MetricsShow ( UINT32 option ) { int i; /* index into miss array */ int firsttime; UINT32 effAdrs; /* effective address from miss array */ if (option == 0) option = 3; if (option == 4) option = 7; if (option & 1) { printf ("I-MMU: %d misses, %d errors.", mmuPpcITlbMisses, mmuPpcITlbErrors); if ((option & 4) == 0) { if (mmuPpcITlbMisses > 0) printf(" recent misses:"); i = (int)mmuPpcITlbMisses - 256; i = max(0, i); for (firsttime=1; i < mmuPpcITlbMisses; i++) { if (i % 8 == 0 || firsttime) { printf("\n %3d ", i); firsttime = 0; } effAdrs = mmuPpcITlbMissArray[i % 256] & 0xfffffc00; printf(" %8x", effAdrs); } } printf("\n"); } if (option & 2) { printf ("D-MMU: %d misses, %d errors.", mmuPpcDTlbMisses, mmuPpcDTlbErrors); if ((option & 4) == 0) { if (mmuPpcDTlbMisses > 0) printf(" recent misses:"); i = (int)mmuPpcDTlbMisses - 256; i = max(0, i); for (firsttime=1; i < mmuPpcDTlbMisses; i++) { if (i % 8 == 0 || firsttime) { printf("\n %3d ", i); firsttime=0; } effAdrs = mmuPpcDTlbMissArray[i % 256] & 0xfffffc00; printf(" %8x", effAdrs); } } printf("\n"); } }#endif /* DEBUG_MISS_HANDLER */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -