📄 mmue500lib.c
字号:
/* mmuE500Lib.c - mmu library for PowerPC e500Core series *//* Copyright 2001-2002 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01d,30jul03,dtr Removing some gloabals no longer required.01c,07jan03,dtr Adding static TLB entry support.01b,02dec02,dtr Adding cache support.01a,05nov02,pcs Remove debug sim_printf*//*DESCRIPTION:*//* includes */#include "vxWorks.h"#include "cacheLib.h"#include "errno.h"#include "intLib.h"#include "stdlib.h"#include "stdio.h"#include "string.h"#include "vmLib.h"#include "sysLib.h"#include "private/memPartLibP.h"#include "private/vmLibP.h"#include "arch/ppc/excPpcLib.h"#include "arch/ppc/vxPpcLib.h"#include "arch/ppc/mmuArchVars.h"#include "arch/ppc/mmuE500Lib.h"/* defines *//* typedefs *//* externals */IMPORT void mmuPpcPidSet (UINT8 pid);IMPORT UINT32 mmuPpcPidGet (void);IMPORT void mmuPpcMmucrSet (UINT32 pid);IMPORT UINT32 mmuPpcMmucrGet (void);IMPORT UINT32 mmuPpcTlbReadEntryWord0 (UINT32 index);IMPORT UINT32 mmuPpcTlbReadEntryWord1 (UINT32 index);IMPORT UINT32 mmuPpcTlbReadEntryWord2 (UINT32 index);IMPORT void mmuPpcTlbWriteEntryWord0 (UINT32 word0);IMPORT void mmuPpcTlbWriteEntryWord1 (UINT32 word1);IMPORT void mmuPpcTlbWriteEntryWord2 (UINT32 word2);IMPORT void mmuPpcTlbWriteExecute(UINT32 mas0reg);IMPORT int mmuPpcE500Tlbie (MMU_TRANS_TBL *pTransTbl,void * effAddr);IMPORT void mmuPpcAEnable ();IMPORT void mmuPpcADisable ();IMPORT void mmuPpcInstTlbMissHandler();IMPORT void mmuPpcDataTlbMissHandler();IMPORT STATE_TRANS_TUPLE * mmuStateTransArray;IMPORT int mmuStateTransArraySize;IMPORT MMU_LIB_FUNCS mmuLibFuncs;IMPORT int mmuPageBlockSize;IMPORT BOOL cacheIToEnable;IMPORT BOOL cacheDToEnable;IMPORT STATUS cacheArchEnable (CACHE_TYPE cache);IMPORT STATUS cacheArchFlush(CACHE_TYPE cache, void *address, size_t bytes);IMPORT STATUS cacheArchDisableFromMmu (CACHE_TYPE cache);IMPORT void mmuE500TlbDynamicInvalidate();IMPORT void mmuE500TlbStaticInvalidate();/* globals *//* * a translation table to hold the descriptors for the global transparent * translation of physical to virtual memory */MMU_TRANS_TBL * mmuGlobalTransTbl; /* global translation table */ TLB_ENTRY_DESC *mmuE500StaticTlbArray;/* * An array of 256 translation table pointers is allocated to store up to 255 * (entry 0 unused) unique address maps. This array is indexed by the PID * value. A value of -1 denotes an unused entry. */MMU_TRANS_TBL * mmuAddrMapArray [MMU_ADDR_MAP_ARRAY_SIZE];/* locals *//* * This table is used to map vmLib per-page mapping attributes to * the architecture-specific values stored in the TLB. Omission of * a vmLib attribute combination implies that that combination is not * supported in the architecture-specific MMU library. */LOCAL STATE_TRANS_TUPLE mmuStateTransArrayLocal [] = { {VM_STATE_MASK_VALID, MMU_STATE_MASK_VALID, VM_STATE_VALID, MMU_STATE_VALID}, {VM_STATE_MASK_VALID, MMU_STATE_MASK_VALID, VM_STATE_VALID_NOT, MMU_STATE_VALID_NOT}, {VM_STATE_MASK_WRITABLE, MMU_STATE_MASK_WRITABLE, VM_STATE_WRITABLE, MMU_STATE_WRITABLE}, {VM_STATE_MASK_WRITABLE, MMU_STATE_MASK_WRITABLE, VM_STATE_WRITABLE_NOT, MMU_STATE_WRITABLE_NOT}, {VM_STATE_MASK_CACHEABLE, MMU_STATE_MASK_CACHEABLE, VM_STATE_CACHEABLE, MMU_STATE_CACHEABLE}, {VM_STATE_MASK_CACHEABLE, MMU_STATE_MASK_CACHEABLE, VM_STATE_CACHEABLE_NOT, MMU_STATE_CACHEABLE_NOT}, {VM_STATE_MASK_CACHEABLE, MMU_STATE_MASK_CACHEABLE, VM_STATE_CACHEABLE_WRITETHROUGH, MMU_STATE_CACHEABLE_WRITETHROUGH}, {VM_STATE_MASK_GUARDED, MMU_STATE_MASK_GUARDED, VM_STATE_GUARDED, MMU_STATE_GUARDED}, {VM_STATE_MASK_GUARDED, MMU_STATE_MASK_GUARDED, VM_STATE_GUARDED_NOT, MMU_STATE_GUARDED_NOT} };LOCAL UINT32 mmuE500Selected; /* mmu type selected *//* forward declarations */LOCAL MMU_TRANS_TBL * mmuE500TransTblCreate ();LOCAL STATUS mmuE500TransTblDelete (MMU_TRANS_TBL *transTbl);LOCAL STATUS mmuE500Enable (BOOL enable);LOCAL STATUS mmuE500StateSet (MMU_TRANS_TBL *transTbl, void *pageAddr, UINT stateMask, UINT state);LOCAL STATUS mmuE500StateGet (MMU_TRANS_TBL *transTbl, void *pageAddr, UINT *state);LOCAL STATUS mmuE500PageMap (MMU_TRANS_TBL *transTbl, void * virtualAddress, void *physPage);LOCAL STATUS mmuE500GlobalPageMap (void * virtualAddress, void * physPage);LOCAL STATUS mmuE500Translate (MMU_TRANS_TBL * transTbl, void * virtAddress, void ** physAddress);LOCAL void mmuE500CurrentSet (MMU_TRANS_TBL * transTbl);LOCAL STATUS mmuE500TransTblInit (MMU_TRANS_TBL * pNewTransTbl);LOCAL LEVEL_1_DESC * mmuE500Lvl1DescAddrGet (MMU_TRANS_TBL * pTransTbl, void * effectiveAddr);LOCAL STATUS mmuE500Lvl2DescAddrGet (MMU_TRANS_TBL * pTransTbl, void * effectiveAddr, LEVEL_2_DESC ** ppLvl2Desc);LOCAL void mmuE500Lvl1DescUpdate (LEVEL_1_DESC * pLvl1Desc, LEVEL_1_DESC lvl1Desc);LOCAL STATUS mmuE500Lvl1DescInit (MMU_TRANS_TBL * pTransTbl, LEVEL_1_DESC * pLvl1Desc, void * effectiveAddr);LOCAL void mmuE500Lvl2DescUpdate (LEVEL_2_DESC * pLvl2Desc, LEVEL_2_DESC lvl2Desc);LOCAL BOOL mmuE500IsOn (int mmuType);LOCAL UINT8 mmuE500PidAlloc (MMU_TRANS_TBL *transTbl);LOCAL void mmuE500PidFree (UINT8 pid);LOCAL void mmuE500MemPagesWriteDisable ( MMU_TRANS_TBL * pTransTbl); void mmuE500TlbStaticInit (int numDescs, TLB_ENTRY_DESC *pTlbDesc, BOOL cacheAllow);/* locals (need forward declarations) */LOCAL MMU_LIB_FUNCS mmuLibFuncsLocal = { mmuE500LibInit, mmuE500TransTblCreate, mmuE500TransTblDelete, mmuE500Enable, mmuE500StateSet, mmuE500StateGet, mmuE500PageMap, mmuE500GlobalPageMap, mmuE500Translate, mmuE500CurrentSet };/******************************************************************************** mmuE500LibInit - MMU library initialization** This routine initializes data structures used to store mmu page tables* so that subsequent page mapping operations can be performed, and so that* the TLB miss handler exceptions can consult the data structures with* meaningful results.** The staticTlbNum argument specifies how many static TLB entries are* defined in the pStaticTlbDesc array. TLB indices lower than* staticTlbNum are used for static page mapping. staticTlbNum also* specifies the lowest TLB index that the mmuE500Lib is allowed to use* for dynamic page mapping.** RETURNS: OK, or ERROR if <mmuType> is incorrect or memory allocation* failed.*/STATUS mmuE500LibInit ( int mmuType, /* data and/or instr. MMU to init */ int staticTlbNum, /* number of static TLB Entries */ TLB_ENTRY_DESC * pStaticTlbDesc /* array of static TLB descriptions */ ) { /* check if the MMU type to initialize is coherent */ if (!(mmuType & MMU_INST) && !(mmuType & MMU_DATA)) { /* * too soon in boot process to print a string, so store one in the * exception message area. */ strcpy(sysExcMsg, "e500 MMU config failed: either enable I or D MMU, " "or remove MMU support\n"); return (ERROR); } /* save the Data and/or Instruction MMU selected */ mmuE500Selected = mmuType; /* initialize the exception table: * At the exception offset, we put a branch instruction (0x48000002) * OR'ed with the address of the TLB miss handler. */ if (mmuType & MMU_INST) { if ((UINT32)mmuPpcInstTlbMissHandler > 0x03fffffc) { strcpy(sysExcMsg, "e500 MMU config failed: TLB miss handler " "is too far from the vector table\n"); return (ERROR); } * (int *) _EXC_OFF_INST_MISS = 0x48000002 | (((int) mmuPpcInstTlbMissHandler) & 0x03fffffc); CACHE_TEXT_UPDATE((void *)_EXC_OFF_INST_MISS, sizeof(int)); } if (mmuType & MMU_DATA) { if ((UINT32)mmuPpcDataTlbMissHandler > 0x03fffffc) { strcpy(sysExcMsg, "e500 MMU config failed: TLB miss handler " "is too far from the vector table\n"); return (ERROR); } * (int *) _EXC_OFF_DATA_MISS = 0x48000002 | (((int) mmuPpcDataTlbMissHandler) & 0x03fffffc); CACHE_TEXT_UPDATE((void *)_EXC_OFF_DATA_MISS, sizeof(int)); } /* initialize the address map array: a value of -1 denotes an unused element. */ memset ((void *) mmuAddrMapArray, (int)MMU_ADDR_MAP_ARRAY_INV, sizeof (mmuAddrMapArray)); /* Remove old CAM TLB1 entries, leave TLB0 entries as required for mem access*/ mmuE500TlbStaticInvalidate(); /* Just CAMS TLBSEL = 1 */ /* set up the static TLB entries with caching on */ mmuE500TlbStaticInit(staticTlbNum, pStaticTlbDesc, TRUE); /* create the global translation table */ mmuGlobalTransTbl = mmuE500TransTblCreate(); if (mmuGlobalTransTbl == NULL) { strcpy(sysExcMsg, "e500 MMU config failed: could not allocate " "global trans table\n"); return (ERROR); } /* initialize the PID register (it won't be accessed until MSR[IS,DS] * gets set later) and invalidate all dynamic TLB entries */ mmuPpcPidSet (mmuGlobalTransTbl->pid); /* initialize the data objects that are shared with vmLib.c */ mmuStateTransArray = &mmuStateTransArrayLocal [0]; mmuStateTransArraySize = sizeof (mmuStateTransArrayLocal) / sizeof (STATE_TRANS_TUPLE); mmuLibFuncs = mmuLibFuncsLocal; mmuPageBlockSize = MMU_PAGE_SIZE; /* Invalidate all dynamic TLB entries before MMU is enabled */ mmuE500TlbDynamicInvalidate(); return (OK); }/******************************************************************************** mmuE500TransTblCreate - create a new translation table.** RETURNS: address of new object or NULL if allocation failed.*/LOCAL MMU_TRANS_TBL * mmuE500TransTblCreate (void) { MMU_TRANS_TBL * pNewTransTbl; /* new translation table */ /* 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); } /* get a free PID for the new translation table */ pNewTransTbl->pid = mmuE500PidAlloc (pNewTransTbl); if (pNewTransTbl->pid == 0) /* no free PIDs ! */ { free ((char *) pNewTransTbl); return (NULL); } /* * initialize the new translation table. * If the initialization fails then free the memory and return the NULL * pointer. */ if (mmuE500TransTblInit (pNewTransTbl) == ERROR) { free ((char *) pNewTransTbl); return (NULL); } /* return the new translation table created */ return (pNewTransTbl); }/******************************************************************************** mmuE500TransTblInit - initialize a new translation table** Initialize a new translation table. The level 1 table is copied 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.*/LOCAL STATUS mmuE500TransTblInit ( MMU_TRANS_TBL * pNewTransTbl /* translation table to initialize */ ) { /* * Allocate memory space for a new Level 1 descriptor table. This memory * needs to be page aligned because, we write protect all the page tables * later, and we don't want other variables sharing a page with the page * table itself. */ pNewTransTbl->l1TblPtr.pL1Desc = (LEVEL_1_DESC *) memalign (MMU_PAGE_SIZE, MMU_PAGE_SIZE); /* if the memory cannot be allocated then return ERROR */ if (pNewTransTbl->l1TblPtr.pL1Desc == NULL) return (ERROR); /* invalidate all entries in the table */ memset ((void *) pNewTransTbl->l1TblPtr.pL1Desc, 0x00, MMU_PAGE_SIZE); if (mmuGlobalTransTbl != NULL) { /* copy the global level 1 descriptor table to the new table */ memcpy ((void *) pNewTransTbl->l1TblPtr.pL1Desc, (void *) mmuGlobalTransTbl->l1TblPtr.pL1Desc, MMU_PAGE_SIZE); } /* In AE, would page protect the new L1 descriptor table here */ return (OK); }/******************************************************************************** mmuE500TransTblDelete - delete a translation table.** This routine deletes a translation table.** RETURNS: OK always.*/LOCAL STATUS mmuE500TransTblDelete ( MMU_TRANS_TBL * pTransTbl /* translation table to be deleted */ ) { LEVEL_1_DESC lvl1Desc; /* level 1 descriptor */ UINT32 ix; /* free the PID element for this translation table */ mmuE500PidFree (pTransTbl->pid); /* free level 2 page tables */ for (ix = 0 ; ix < MMU_LVL_2_DESC_NB; ix++) { lvl1Desc = * (pTransTbl->l1TblPtr.pL1Desc + ix); if (lvl1Desc.field.v) free ((void *) (lvl1Desc.l1desc & MMU_LVL_1_L2BA_MSK)); } /* free the level 1 table */ free ((void *) pTransTbl->l1TblPtr.pL1Desc); return (OK); }/******************************************************************************** mmuE500Enable - turn mmu on or off** On the PPCE500, the MMU is always on, so turning it off is a misnomer.* Instead, this function changes the MSR[IS,DS] values, which change which TLB* entries match -- either the static ones that emulate 'real mode', or the ones* that provide dynamic mmu page mapping.** RETURNS: OK*/LOCAL STATUS mmuE500Enable ( BOOL enable /* TRUE to enable, FALSE to disable MMU */ ) { int lockKey; /* lock key for intUnlock() */ /* lock the interrupt */ lockKey = intLock (); if (enable) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -