📄 mmui86lib.c
字号:
* mismatch in virtual/physical address space, or the called out function's * disapearance. It is guaranteed that this code is in physical memory. */#define MMU_ON() \ do { int tempReg; WRS_ASM ("movl %%cr0,%0; orl $0x80010000,%0; \ movl %0,%%cr0; jmp 0f; 0:" : "=r" (tempReg) : : "memory"); } while (0)#define MMU_OFF() \ do { int tempReg; WRS_ASM ("movl %%cr0,%0; andl $0x7ffeffff,%0; \ movl %0,%%cr0; jmp 0f; 0:" : "=r" (tempReg) : : "memory"); } while (0)#define MMU_UNLOCK(wasEnabled, oldLevel) \ do { if (((wasEnabled) = mmuI86Enabled) == TRUE) \ {INT_LOCK (oldLevel); MMU_OFF (); } \ } while (0)#define MMU_LOCK(wasEnabled, oldLevel) \ do { if ((wasEnabled) == TRUE) \ {MMU_ON (); INT_UNLOCK (oldLevel);} \ } while (0)/* inline version of mmuI86TLBFlush() */#define MMU_TLB_FLUSH() \ do { int tempReg; WRS_ASM ("pushfl; cli; movl %%cr3,%0; \ movl %0,%%cr3; jmp 0f; 0: popfl; " : "=r" (tempReg) : : "memory"); \ } while (0)/******************************************************************************** mmuI86LibInit - 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.** RETURNS: OK if no error, ERROR otherwise** ERRNO: S_mmuLib_INVALID_PAGE_SIZE*/STATUS mmuI86LibInit ( int pageSize /* system pageSize (must be 4096 for i86) */ ) { PTE *pDirectoryTable; int i; /* 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; /* we assume a 4096 byte page size */ if (pageSize != PAGE_SIZE) { errno = S_mmuLib_INVALID_PAGE_SIZE; return (ERROR); } mmuI86Enabled = FALSE; mmuPageSize = pageSize; /* allocate the global page block array to keep track of which parts * of virtual memory are handled by the global translation tables. * Allocate on page boundry so we can write protect it. */ globalPageBlock = (BOOL *) memalign (pageSize, pageSize); bzero ((char *) globalPageBlock, 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 */ /* allocate a page to hold the directory table */ mmuGlobalTransTbl.pDirectoryTable = pDirectoryTable = (PTE *) memalign (pageSize, pageSize); if (pDirectoryTable == NULL) return (ERROR); /* invalidate all the directory table entries */ for (i = 0; i < (PAGE_SIZE / sizeof(PTE)) ;i++) { pDirectoryTable[i].field.present = 0; pDirectoryTable[i].field.rw = 0; pDirectoryTable[i].field.us = 0; pDirectoryTable[i].field.pwt = 0; pDirectoryTable[i].field.pcd = 0; pDirectoryTable[i].field.access = 0; pDirectoryTable[i].field.dirty = 0; pDirectoryTable[i].field.zero = 0; pDirectoryTable[i].field.avail = 0; pDirectoryTable[i].field.page = -1; } 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 *pTransTbl, /* translation table */ void *virtAddr, /* virtual address */ PTE **result /* result is returned here */ ) { PTE *pDte; PTE *pPageTable; pDte = &pTransTbl->pDirectoryTable [(UINT) virtAddr >> DIRECTORY_INDEX]; pPageTable = (PTE *) (pDte->bits & PTE_TO_ADDR); if ((UINT) pPageTable == 0xfffff000) return (ERROR); *result = &pPageTable[((UINT) virtAddr & TABLE_BITS) >> TABLE_INDEX]; return (OK); }/******************************************************************************** mmuTransTblCreate - create a new translation table.** create a i86 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 directory 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 for directory table.*/LOCAL STATUS mmuTransTblInit ( MMU_TRANS_TBL *newTransTbl /* translation table to be inited */ ) { FAST PTE *pDirectoryTable; /* allocate a page to hold the directory table */ newTransTbl->pDirectoryTable = pDirectoryTable = (PTE *) memalign (mmuPageSize, mmuPageSize); if (pDirectoryTable == NULL) return (ERROR); /* copy the directory table from mmuGlobalTransTbl, * so we get the global virtual memory */ bcopy ((char *) mmuGlobalTransTbl.pDirectoryTable, (char *) pDirectoryTable, mmuPageSize); /* write protect virtual memory pointing to the the directory table in * the global translation table to insure that it can't be corrupted */ mmuStateSet (&mmuGlobalTransTbl, (void *) pDirectoryTable, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE_NOT); return (OK); }/******************************************************************************** mmuTransTblDelete - delete a translation table.* * mmuTransTblDelete deallocates all the memory used to store the translation* table entries. It does not deallocate physical pages mapped into the* virtual memory space.** RETURNS: OK**/LOCAL STATUS mmuTransTblDelete ( MMU_TRANS_TBL *transTbl /* translation table to be deleted */ ) { FAST int i; FAST PTE *pDte = transTbl->pDirectoryTable; FAST PTE *pPageTable; /* write enable the physical page containing the directory table */ mmuStateSet (&mmuGlobalTransTbl, transTbl->pDirectoryTable, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE); /* deallocate only non-global page blocks */ for (i = 0; i < (PAGE_SIZE / sizeof(PTE)); i++, pDte++) if ((pDte->field.present == 1) && !globalPageBlock[i]) { pPageTable = (PTE *) (pDte->bits & PTE_TO_ADDR); mmuStateSet (&mmuGlobalTransTbl, pPageTable, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE); free (pPageTable); } /* free the page holding the directory table */ free (transTbl->pDirectoryTable); /* free the translation table data structure */ free (transTbl); return (OK); }/******************************************************************************** mmuVirtualPageCreate - set up translation tables for a virtual page** simply check if there's already a page table that has a* pte for the given virtual page. If there isn't, create one.** RETURNS OK or ERROR if couldn't allocate space for a page table.*/LOCAL STATUS mmuVirtualPageCreate ( MMU_TRANS_TBL *thisTbl, /* translation table */ void *virtPageAddr /* virtual addr to create */ ) { PTE *pDte; FAST PTE *pPageTable; FAST UINT i; PTE *dummy; if (mmuPteGet (thisTbl, virtPageAddr, &dummy) == OK) return (OK); pPageTable = (PTE *) memalign (mmuPageSize, mmuPageSize); if (pPageTable == NULL) return (ERROR); /* invalidate every page in the new page block */ for (i = 0; i < (PAGE_SIZE / sizeof(PTE)); i++) { pPageTable[i].field.present = 0; pPageTable[i].field.rw = 0; pPageTable[i].field.us = 0; pPageTable[i].field.pwt = 0; pPageTable[i].field.pcd = 0; pPageTable[i].field.access = 0; pPageTable[i].field.dirty = 0; pPageTable[i].field.zero = 0; pPageTable[i].field.avail = 0; pPageTable[i].field.page = -1; } /* write protect the new physical page containing the pte's for this new page block */ mmuStateSet (&mmuGlobalTransTbl, pPageTable, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE_NOT); /* unlock the physical page containing the directory table, so we can modify it */ mmuStateSet (&mmuGlobalTransTbl, thisTbl->pDirectoryTable, MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE); pDte = &thisTbl->pDirectoryTable [(UINT) virtPageAddr >> DIRECTORY_INDEX];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -