📄 mmush7700lib.c
字号:
if (mmuPteGet (transTbl, v_addr, &pPte) != OK) return ERROR; /* modify the pte with mmu turned off and interrupts locked out */ key = intLock (); mmuATTRSet (pPte, stateMask, state, v_addr); intUnlock (key); 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, void *v_addr, void *p_addr /* physical address */ ) { int key; PTE *pPte; if (mmuPteGet (transTbl, v_addr, &pPte) != OK) { /* build the translation table for the virtual address */ if (mmuVirtualPageCreate (transTbl, v_addr) != OK) return ERROR; if (mmuPteGet (transTbl, v_addr, &pPte) != OK) return ERROR; } key = intLock (); mmuPPNSet (pPte, p_addr, v_addr); intUnlock (key); 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 *v_addr, void *p_addr ) { return (mmuPageMap (&mmuGlobalTransTbl, v_addr, p_addr)); }/******************************************************************************** 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, void *v_addr, void **p_addr /* put physical address here */ ) { PTE *pPhys; if (mmuPteGet (transTbl, v_addr, &pPhys) != OK) { errno = S_mmuLib_NO_DESCRIPTOR; return ERROR; } if (pPhys->pte.l.fields.valid == 0) { errno = S_mmuLib_INVALID_DESCRIPTOR; return ERROR; } *p_addr = (void *)((pPhys->pte.l.fields.ppn << 10) + ((UINT32)v_addr & PAGE_OFFSET_MASK)); return OK; }/******************************************************************************** mmuPteGet - get the pte for a given page** mmuPteGet traverses a translation table and returns the (physical) address* of the pte for the given virtual address.** RETURNS: OK or ERROR if there is no virtual space for the given address */LOCAL STATUS mmuPteGet ( MMU_TRANS_TBL *transTbl, void *v_addr, PTE **result /* return result here */ ) { PTE *lowerPtr = &transTbl->vUpperTbl [(UINT)v_addr / PAGE_BLOCK_SIZE]; PTE *pa_LowTbl = (PTE *)(lowerPtr->pte.td.adrs); int index; if ((UINT)pa_LowTbl == 0xffffffff) return ERROR; index = ((UINT)v_addr >> BITS_PAGE_OFFSET) & (LOWER_TBL_SIZE - 1); *result = &pa_LowTbl [index]; return OK; }/******************************************************************************** mmuCurrentSet - change active translation table** mmuCurrentSet is used to change the virtual memory context. Load the TTB* (translation table base) register with the given translation table.*/LOCAL void mmuCurrentSet ( MMU_TRANS_TBL *transTbl /* new active tranlation table */ ) { int key; static BOOL firstTime = TRUE; if (firstTime) { mmuTblWriteDisable (&mmuGlobalTransTbl); mmuTblWriteDisable (transTbl); firstTime = FALSE; } key = intLock (); /* LOCK INTERRUPTS */ mmuTTBSet ((PTE *)(((UINT32)transTbl->vUpperTbl & SH7700_PHYS_MASK) | mmuTransTblSpace)); mmuCurrentTransTbl = transTbl; intUnlock (key); /* UNLOCK INTERRUPTS */ }/******************************************************************************** mmuTblWriteDisable - 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.** NOTE: This routine is called from mmuCurrentSet() only.*/LOCAL void mmuTblWriteDisable ( MMU_TRANS_TBL *transTbl ) { int i; for (i = 0; i < UPPER_TBL_SIZE; i++) { UINT32 p_addr = (UINT32)transTbl->vUpperTbl[i].pte.td.adrs; if (p_addr != 0xffffffff) mmuStateSet (transTbl, (void *)((p_addr & SH7700_PHYS_MASK) | ((UINT32)transTbl->vUpperTbl & ~SH7700_PHYS_MASK)), MMU_STATE_MASK_WRITABLE | MMU_STATE_MASK_CACHEABLE, MMU_STATE_WRITABLE_NOT | MMU_STATE_CACHEABLE_NOT); } mmuStateSet (transTbl, transTbl->vUpperTbl, MMU_STATE_MASK_WRITABLE | MMU_STATE_MASK_CACHEABLE, MMU_STATE_WRITABLE_NOT | MMU_STATE_CACHEABLE_NOT); }/******************************************************************************** mmuPageAlloc - allocate a page of physical memory**/LOCAL char *mmuPageAlloc ( MMU_TRANS_TBL *transTbl ) { char *v_page; int i; if ((v_page = (char *)lstGet (&transTbl->memFreePageList)) == NULL) { v_page = memPartAlignedAlloc (mmuPageSource, /* partId */ mmuPageSize * mmuNumPagesInFreeList, /* bytes */ mmuPageSize); /* alignment */ if (v_page == NULL) return NULL; if (transTbl->memBlocksUsedIndex >= transTbl->memBlocksUsedSize) { void *newArray; /* realloc the array */ transTbl->memBlocksUsedSize *= 2; newArray = realloc (transTbl->memBlocksUsedArray, sizeof(void *) * transTbl->memBlocksUsedSize); if (newArray == NULL) { transTbl->memBlocksUsedSize /= 2; return NULL; } transTbl->memBlocksUsedArray = (void **)newArray; } transTbl->memBlocksUsedArray [transTbl->memBlocksUsedIndex++] = (void *)v_page; for (i = 0; i < mmuNumPagesInFreeList; i++, v_page += mmuPageSize) lstAdd (&transTbl->memFreePageList, (NODE *)v_page); v_page = (char *)lstGet (&transTbl->memFreePageList); } return v_page; }#undef MMU_DEBUG#ifdef MMU_DEBUG/******************************************************************************** mmuTLBDump - dump TLB contents** NOMANUAL*/LOCAL int partition (UINT32 a[][2], int l, int r) { int i, j, pivot; UINT32 t; i = l - 1; j = r; pivot = a[r][0]; for (;;) { while (a[++i][0] < pivot) ; while (i < --j && pivot < a[j][0]) ; if (i >= j) break; t = a[i][0]; a[i][0] = a[j][0]; a[j][0] = t; t = a[i][1]; a[i][1] = a[j][1]; a[j][1] = t; } t = a[i][0]; a[i][0] = a[r][0]; a[r][0] = t; t = a[i][1]; a[i][1] = a[r][1]; a[r][1] = t; return i; }LOCAL void quick_sort_1 (UINT32 a[][2], int l, int r) { int v; if (l >= r) return; v = partition (a, l, r); quick_sort_1 (a, l, v - 1); /* sort left partial array */ quick_sort_1 (a, v + 1, r); /* sort right partial array */ }LOCAL void quick_sort (UINT32 a[][2], int n) { quick_sort_1 (a, 0, n - 1); }#include "stdio.h"LOCAL void mmuTLBDumpOp () { UINT32 a[128][2]; /* (32-entry * 4-way) * (v_addr | p_addr) */ UINT32 ent; int i; for (ent = 0; ent < 32; ent++) { int way; for (way = 0; way < 4; way++) { UINT32 aa = *(UINT32 *)(0xf2000000 | (ent << 12) | (way << 8)); UINT32 da = *(UINT32 *)(0xf3000000 | (ent << 12) | (way << 8)); a[ent * 4 + way][0] = (aa & 0xfffe0fff) | (ent << 12); /* va */ a[ent * 4 + way][1] = da; /* pa */ } } quick_sort (a, 128); for (i = 0; i < 128; i++) { printf ("va: 0x%08x -> pa: 0x%08x %s %s %s %s %s %s\n", a[i][0] & 0xfffff000, a[i][1] & 0xfffffc00, a[i][1] & 0x00000100 ? "V+" : "V-", a[i][1] & 0x00000020 ? "W+" : "W-", a[i][1] & 0x00000008 ? "C+" : "C-", a[i][1] & 0x00000004 ? "D+" : "D-", a[i][1] & 0x00000002 ? "S+" : "S-", a[i][1] & 0x00000010 ? "4k" : "1k"); } }void mmuTLBDump () { UINT32 pfunc = ((UINT32)mmuTLBDumpOp & SH7700_PHYS_MASK) | SH7700_P2_BASE; (* (VOIDFUNCPTR)pfunc)(); }void mmuTLBFlushTestAll () { mmuOn (0); mmuTLBFlush (ENTIRE_TLB); mmuTLBDump (); mmuOn (1); }void mmuTLBFlushTest (int v_addr) { mmuOn (0); mmuTLBFlush (v_addr); mmuTLBDump (); mmuOn (1); }#endif /* MMU_DEBUG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -