?? mmu440lib.c
字號(hào):
/* mmu440Lib.c - mmu library for PowerPC 440 series *//* Copyright 2001-2003 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01e,30jan03,jtp SPR 85792 support caching by allowing no selected MMUs01d,02jan03,jtp SPR 82770 move mmuPpcSelected to mmuArchVars.c01c,08may02,pch fix copy/paste error in previous checkin: this is a 440, not a 405.01b,25apr02,pch SPR 74926: don't connect to unused vector01a,17apr02,jtp written.*//*DESCRIPTION:mmu440Lib.c provides the architecture dependent routines that directlycontrol the memory management unit for the PowerPC 440 series. Itprovides routines that are called by the higher level architectureindependent routines in vmLib.c or vmBaseLib.c.The PPC440 is a BookE Specification processor. BookE Memory ManagementUnits (MMU) are always on, and cannot be turned off. The PPC440GPcontains a cache of 64 virtual-to-physical page mappings in aTranslation Lookaside Buffer (TLB) cache. Each cache entry can beaddressed with a TLB Entry index.Lower-numbered TLB indexes are used to set up a static mapping ofmemory. Typically large blocks of memory (256MB chunks) are mapped viaeach static TLB entry. The lowest TLB entries set the Translation Space(TS) field of the TLB entries to 0. These entries are used when the MSRregister IS and/or DS fields are set to '0', and are used to emulateconventional 'real mode' access. In the bootrom, romInit.s isresponsible for initializing a bare-bones static mapping.Once booted, a description of the desired static TLB mappings is passedin to mmu440LibInit, and it reinitializes the static TLB entries,overwriting the ones established by romInit. A few of these entries havethe TS field set to 1, for use when the vmLib is 'enabled', and are usedto map program addresses to physical addresses that cannot be expressedin a 32 bit pointer. Once initialized, these lower-numbered TLB entriesare largely left unperturbed by the mmu440Lib.Higher-numbered TLB indexes are used by the 440 MMU library todynamically map memory. The minimum usable TLB index is defined by theBSP and passed in as an argument to mmu440LibInit during systeminitialization. All the pages mapped by this library set the TS(Translation Space) field of the TLB entries to 1. These entries areused when the MSR IS and/or DS fields are set to '1'. The blocks ofmemory mapped are 4KB (MMU_PAGE_SIZE) in size. As a result, the TLBcache entries can only map a small fraction of the available programaddress space and the TLB Miss handler recycles them as needed in around-robin fashion.This implementation supports the use of multiple program address spaces.TLB Entries with a TID field of 0 (causing them to match all programaddress spaces) are used for the static mapping. TLB Entries withnon-zero TID fields are used for dynamic mapping. The global transtable (used for the kernel's initial vm context) uses a TID of 2, andsubsequent trans tables are given a copy of the global trans table's L1table as they are created.Cache library interaction: The Book E specification and the PPC440GPimplementation do not provide a means to set global cache enable/disablewithout manipulating individual TLB entries. Therefore, as in thePPC60X series kernels, changes to the cacheability of individual blocksand pages of memory are deferred to this MMU library: enabling the cacherequires the MMU library.Furthermore, since cacheability is controlled by a single pair of bits(W, I) on a per-TLB basis, the cacheability of instructions versus datawithin the same virtual address mapping cannot be independentlycontrolled. In the PPC440 the selections for data and instruction cacheenablement and mode must be identical.Lastly, the MMU library may be configured but neither I nor D MMUselected for enablement. This permits the MMU libary to set up thestatic TLB mappings and enable the cache on them, but it does notmake use of the dynamic TLB entries. This may be desired for someapplications.For more details on the 440's cache implementation, see cache440ALib.s.*//* 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/mmu440Lib.h"/* defines *//* typedefs *//* * The MMUCR register is important for TLB entry search, read and write: * * Search: sts and stid fields are used by tlbsx instruction. * Read: stid field is set by a tlbre 0 instruction * Write: stid field is used by tlbwe 0 instruction */typedef union { struct { UINT32 rsvd1:7; UINT32 swoa:1; /* Store W/O Allocate */ UINT32 rsvd2:1; UINT32 u1te:1; /* U1 Transient Enable */ UINT32 u2swoae:1; /* U2 Store W/O Allocate Enable */ UINT32 rsvd3:1; UINT32 dulxe:1; /* Data Cache Unlock Exc Enable */ UINT32 iulxe:1; /* Instr Cache Unlock Exc Enable */ UINT32 rsvd4:1; UINT32 sts:1; /* Search Translation Space */ UINT32 rsvd5:8; UINT32 stid:8; /* Search Translation ID */ } field; UINT32 word; } MMUCR_REG;/* 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 int mmuPpcTlbSearch (void * effAddr);IMPORT void mmuPpcTlbWriteEntryWord0 (UINT32 index, UINT32 word0);IMPORT void mmuPpcTlbWriteEntryWord1 (UINT32 index, UINT32 word1);IMPORT void mmuPpcTlbWriteEntryWord2 (UINT32 index, UINT32 word2);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 cache440ToEnable;STATUS cache440Enable (CACHE_TYPE cache);IMPORT STATUS cacheArchFlush(CACHE_TYPE cache, void *address, size_t bytes);IMPORT UINT32 mmuPpcSelected; /* mmu type selected *//* 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 */ /* * 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];/* * TLB replacement counter: mmuPpcTlbNext is used by the page fill exception * handler. We use a round-robin strategy to determine which TLB entry to * replace. mmuPpcTlbMin provides a minimum value, so that assigned Tlbs are * selected from mmuPpcTlbMin up to mmuPpcTlbMax. */UINT32 mmuPpcTlbNext;UINT32 mmuPpcTlbMin;UINT32 mmuPpcTlbMax;#ifdef DEBUG_MISS_HANDLERUINT32 mmuPpcITlbMisses;UINT32 mmuPpcITlbMissArray[256];UINT32 mmuPpcDTlbMisses;UINT32 mmuPpcDTlbMissArray[256];UINT32 mmuPpcITlbErrors;UINT32 mmuPpcDTlbErrors;#endif /* DEBUG_MISS_HANDLER *//* * pointer to array of static TLB entries, used mostly in conjunction * with the cache library to enable/disable caching */TLB_ENTRY_DESC *mmu440StaticTlbArray;/* 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} };/* forward declarations */LOCAL MMU_TRANS_TBL * mmu440TransTblCreate ();LOCAL STATUS mmu440TransTblDelete (MMU_TRANS_TBL *transTbl);LOCAL STATUS mmu440Enable (BOOL enable);LOCAL STATUS mmu440StateSet (MMU_TRANS_TBL *transTbl, void *pageAddr, UINT stateMask, UINT state);LOCAL STATUS mmu440StateGet (MMU_TRANS_TBL *transTbl, void *pageAddr, UINT *state);LOCAL STATUS mmu440PageMap (MMU_TRANS_TBL *transTbl, void * virtualAddress, void *physPage);LOCAL STATUS mmu440GlobalPageMap (void * virtualAddress, void * physPage);LOCAL STATUS mmu440Translate (MMU_TRANS_TBL * transTbl, void * virtAddress, void ** physAddress);LOCAL void mmu440CurrentSet (MMU_TRANS_TBL * transTbl);LOCAL STATUS mmu440TransTblInit (MMU_TRANS_TBL * pNewTransTbl);LOCAL LEVEL_1_DESC * mmu440Lvl1DescAddrGet (MMU_TRANS_TBL * pTransTbl, void * effectiveAddr);LOCAL STATUS mmu440Lvl2DescAddrGet (MMU_TRANS_TBL * pTransTbl, void * effectiveAddr, LEVEL_2_DESC ** ppLvl2Desc);LOCAL void mmu440Lvl1DescUpdate (LEVEL_1_DESC * pLvl1Desc, LEVEL_1_DESC lvl1Desc);LOCAL STATUS mmu440Lvl1DescInit (MMU_TRANS_TBL * pTransTbl, LEVEL_1_DESC * pLvl1Desc, void * effectiveAddr);LOCAL void mmu440Lvl2DescUpdate (LEVEL_2_DESC * pLvl2Desc, LEVEL_2_DESC lvl2Desc);LOCAL BOOL mmu440IsOn (int mmuType);LOCAL UINT8 mmu440PidAlloc (MMU_TRANS_TBL *transTbl);LOCAL void mmu440PidFree (UINT8 pid);LOCAL void mmu440Tlbie (MMU_TRANS_TBL *pTransTbl, void * effAddr);LOCAL void mmu440TlbDynamicInvalidate (void);LOCAL void mmu440TlbStaticInit (int numDescs, TLB_ENTRY_DESC * pTlbDesc, BOOL cacheAllow);/* locals (need forward declarations) */LOCAL MMU_LIB_FUNCS mmuLibFuncsLocal = { mmu440LibInit, mmu440TransTblCreate, mmu440TransTblDelete, mmu440Enable, mmu440StateSet, mmu440StateGet, mmu440PageMap, mmu440GlobalPageMap, mmu440Translate, mmu440CurrentSet };/******************************************************************************** mmu440LibInit - 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 mmu440Lib is allowed to use* for dynamic page mapping.** RETURNS: OK, or ERROR if <mmuType> is incorrect or memory allocation* failed.*/STATUS mmu440LibInit ( 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 */ ) { /* save the Data and/or Instruction MMU selected */ mmuPpcSelected = mmuType; /* set up the static TLB entries with caching off */ mmu440TlbStaticInit(staticTlbNum, pStaticTlbDesc, FALSE); /* initialize the TLB replacement counter to the minimum tlb index */ mmuPpcTlbMin = staticTlbNum; mmuPpcTlbMax = N_TLB_ENTRIES; mmuPpcTlbNext = mmuPpcTlbMin; mmu440StaticTlbArray = pStaticTlbDesc; /* 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, "440 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, "440 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)); /* create the global translation table */ mmuGlobalTransTbl = mmu440TransTblCreate(); if (mmuGlobalTransTbl == NULL) { strcpy(sysExcMsg, "440 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); mmu440TlbDynamicInvalidate(); /* 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; /* if caching turnon was delayed until mmu inited, do it now */ if (cache440ToEnable == TRUE) { cache440Enable(0); cache440ToEnable = FALSE; } return (OK); }#if FALSE/******************************************************************************** mmu440MemPagesWriteEnable - write enable the memory holding PTEs** Each translation table has a linked list of physical pages that contain its* table and page descriptors. Before you can write into any descriptor, you* must write enable the page it is contained in. This routine enables all the* pages used by a given translation table.**/LOCAL STATUS mmu440MemPagesWriteEnable ( MMU_TRANS_TBL * pTransTbl /* Translation table to enable */ ) {
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -