📄 mmush7750lib.c
字号:
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 & SH7750_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 & SH7750_PHYS_MASK) | ((UINT32)transTbl->vUpperTbl & ~SH7750_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 mmuUTLBDumpOp () { UINT32 a[64][2]; /* (64-entry) * (v_addr | p_addr) */ UINT32 ent; int i; for (ent = 0; ent < 64; ent++) { a[ent][0] = *(UINT32 *)(0xf6000000 | (ent << 8)); a[ent][1] = *(UINT32 *)(0xf7000000 | (ent << 8)); } quick_sort (a, 64); for (i = 0; i < 64; i++) { char s[4]; switch (a[i][1] & 0x00000090) { case 0x00000000: strcpy (s, "1k"); break; case 0x00000010: strcpy (s, "4k"); break; case 0x00000080: strcpy (s, "64k"); break; case 0x00000090: strcpy (s, "1M"); break; } printf ("va: 0x%08x -> pa: 0x%08x %s %s %s %s %s %s %s\n", a[i][0] & 0xfffffc00, a[i][1] & 0x1ffffc00, 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] & 0x00000001 ? "WT" : "CB", s); } }LOCAL void mmuITLBDumpOp () { UINT32 a[4][2]; /* (4-entry) * (v_addr | p_addr) */ UINT32 ent; int i; for (ent = 0; ent < 4; ent++) { a[ent][0] = *(UINT32 *)(0xf2000000 | (ent << 8)); a[ent][1] = *(UINT32 *)(0xf3000000 | (ent << 8)); } quick_sort (a, 4); for (i = 0; i < 4; i++) { char s[4]; switch (a[i][1] & 0x00000090) { case 0x00000000: strcpy (s, "1k"); break; case 0x00000010: strcpy (s, "4k"); break; case 0x00000080: strcpy (s, "64k"); break; case 0x00000090: strcpy (s, "1M"); break; } printf ("va: 0x%08x -> pa: 0x%08x %s %s %s %s %s %s %s\n", a[i][0] & 0xfffffc00, a[i][1] & 0x1ffffc00, 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] & 0x00000001 ? "WT" : "CB", s); } }void mmuUTLBDump () { UINT32 pfunc = ((UINT32)mmuUTLBDumpOp & SH7750_PHYS_MASK) | SH7750_P2_BASE; (* (VOIDFUNCPTR)pfunc)(); }void mmuITLBDump () { UINT32 pfunc = ((UINT32)mmuITLBDumpOp & SH7750_PHYS_MASK) | SH7750_P2_BASE; (* (VOIDFUNCPTR)pfunc)(); }void mmuTLBFlushTestAll () { mmuOn (0); mmuTLBFlush (ENTIRE_TLB); mmuUTLBDump (); mmuOn (1); }void mmuTLBFlushTest (int v_addr) { mmuOn (0); mmuTLBFlush (v_addr); mmuUTLBDump (); mmuOn (1); }#endif /* MMU_DEBUG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -