📄 mmulib.c
字号:
mask2 = 0xFFFFFFFF << ((region + 1) * 2); cpr &= (cpr & ~mask1); cpr |= ((cpr & mask2) >> 1); /* clear out the definitions for the highest numbered region */ regs[MPU_NUM_REGIONS - 1].bits = 0; ccr &= ~(1 << (MPU_NUM_REGIONS - 1)); wbcr &= ~(1 << (MPU_NUM_REGIONS - 1)); ccr &= ~(MMU_STATE_VALID << ((MPU_NUM_REGIONS - 1) * 2)); /* put the new values into the registers */ mmuPrrSet (regs); mmuCcrSet (ccr); mmuWbcrSet (wbcr); mmuPrSet (cpr); return; } /* mmuDeleteRegion() *//******************************************************************************** mmuStateGetRegion - get state of a memory region (ARM)** This routine extracts the state information for a region and returns* it as the "architecture-specific state".** No locking is performed during this routine. If the region* definitions are changed during the execution of this routine, an* incorrect state can be returned.** RETURNS: the (architecture-specific) state.*/LOCAL UINT32 mmuStateGetRegion ( int region /* the region number */ ) { UINT32 regState; /* Get C bit from Cache Control register */ regState = (mmuCcrGet () << (7 - region)) & MMU_STATE_CACHE_BIT; /* Get WB bit from Write Buffer Control Register */ regState |= ((mmuWbcrGet () << (7 - region)) >> 1) & MMU_STATE_BUFFERABLE; /* Get AP bits from Protection register */ regState |= (mmuPrGet () >> (region * 2)) & MMU_STATE_VALID; return regState; } /* mmuStateGetRegion() *//******************************************************************************** mmuRegionModify - modify a memory region (ARM)** This routine modifies the definition of a region.** The MPU must be disabled while this routine is called.** RETURNS: N/A.*/LOCAL void mmuRegionModify ( MPU_REGION_REG * regs, /* the Protection Region Registers */ int region, /* the region number */ UINT32 addr, /* start address */ UINT32 size, /* size of region */ UINT32 state, /* (architecture-dependent) state to set */ UINT32 stateMask /* (architecture-dependent) state mask */ ) { UINT32 val; MMU_LOG_MSG (MMU_DEBUG_MPU, "regionModify: region= 0x%X, addr= 0x%X, size= 0x%X, state= 0x%X, stateMask= 0x%X\n", region, addr, size, state, stateMask, 0); /* Create region definition in regs array. Mark it as active */ if (size != MMU_ENTIRE_SPACE) regs[region].bits = (addr & MPU_REGION_BASE_MASK) | 0x01 | ((ffsLsb (size) - 2) << 1); else regs[region].bits = MPU_REGION_SIZE_MAX | 0x01; /* write region definitions back to MPU Protection Region Registers. */ mmuPrrSet (regs); /* * If modifying validity, get protection register, change it * and set it back. */ if ((stateMask & MMU_STATE_MASK_VALID) != 0) { val = mmuPrGet(); val &= ~((state & MMU_STATE_VALID) << (region * 2)); val |= (state & MMU_STATE_VALID) << (region * 2); mmuPrSet(val); } /* If modifying cacheable status, set cache control and WB control regs */ if ((stateMask & MMU_STATE_MASK_CACHEABLE) != 0) { val = mmuCcrGet(); if ((state & MMU_STATE_CACHE_BIT) != 0) { val |= (1 << region); } else { val &= ~(1<< region); } mmuCcrSet (val); val = mmuWbcrGet(); if ((state & MMU_STATE_BUFFERABLE) != 0) { val |= (1 << region); } else { val &= ~(1<< region); } mmuWbcrSet (val); } return; } /* mmuRegionModify() *//******************************************************************************** mmuRegionCreate - create a new memory region (ARM)** This routine creates the definition of a region.** The MPU must be disabled while this routine is called.** RETURNS: N/A.*/LOCAL STATUS mmuRegionCreate ( MPU_REGION_REG * regs, /* the Protection Region Registers */ UINT32 addr, /* start address */ UINT32 size, /* size of region */ UINT32 state, /* (architecture-dependent) state to set */ UINT32 stateMask /* (architecture-dependent) state mask*/ ) { int i; MMU_LOG_MSG (MMU_DEBUG_MPU, "regionCreate: addr = 0x%X, size = 0x%X, state=%x, stateMask=%x\n", addr, size, state, stateMask, 0, 0); /* Find the first free free region, starting from the lowest priority. */ for (i = 0; i < MPU_NUM_REGIONS; i++) { if (regs[i].fields.enable == 0) { /* then region is free; modify region */ mmuRegionModify(regs, i, addr, size, state, stateMask); break; } } if (i == MPU_NUM_REGIONS) { /* then there was no free region */ errno = S_vmLib_NO_FREE_REGIONS; return ERROR; } return OK; }/******************************************************************************** mmuStateSetRegion - set state of memory region (ARM)** mmuStateSetRegion is used to modify the state for the given region.* The following states are provided:** MMU_STATE_VALID MMU_STATE_VALID_NOT valid/invalid* MMU_STATE_CACHEABLE MMU_STATE_CACHEABLE_NOT cacheable/not cacheable** These may be OR'd together in the state parameter. Additionally, masks* are provided so that only specific states may be set:** MMU_STATE_MASK_VALID* MMU_STATE_MASK_CACEHABLE** These may be OR'd together in the stateMask parameter.** Accesses to a region marked as invalid will result in a bus error.** RETURNS: OK or ERROR if cannot set state of or create the region.*/LOCAL STATUS mmuStateSetRegion ( MMU_TRANS_TBL * transTbl, /* translation table */ void * startAddr, /* start address of region */ UINT stateMask, /* mask of which state bits to modify */ UINT state, /* new state bit values */ UINT size /* size of region */ ) {#define MPU_MATCH_OTHER 1#define MPU_MATCH_SUBSET 2#define MPU_MATCH_EXACT 3 int oldIntLev = 0; /* keep compiler quiet */ int i; UINT32 regBase, regSize; int match = MPU_MATCH_OTHER, match2 = MPU_MATCH_OTHER; int region1 = -1, region2 = -1; UINT32 addr = (UINT32) startAddr; STATUS ret = OK; /* * Obviously, if the entire address space has been specified, the * start address should be 0! */ if (size == MMU_ENTIRE_SPACE) { if (addr != 0) { errno = S_vmLib_NOT_PAGE_ALIGNED; return ERROR; } } else { /* check size is an exact power of two */ if (ffsMsb(size) != ffsLsb (size)) { errno = S_vmLib_NOT_PAGE_ALIGNED; return ERROR; } /* check start address is appropriately aligned for size */ if ((addr % size) != 0) { errno = S_vmLib_NOT_PAGE_ALIGNED; return ERROR; } } /* modify the MPU with all interrupts locked out including FIQs */ MMU_UNLOCK (oldIntLev); /* Get the Protection Region Registers (region address definitions) */ mmuPrrGet (transTbl->regs); /* * Search all current regions for an exact address match, or a * region that is a superset of the region requested. Also look for a * second match. Search from highest numbered (highest priority) * region downwards. */ for (i = (MPU_NUM_REGIONS - 1); i >= 0; i--) { if ((transTbl->regs[i].bits & 0x01) != 0) { /* region is enabled, extract start and size of region */ MMU_LOG_MSG (MMU_DEBUG_MPU, "check enabled region %d\n", i, 0, 0, 0, 0, 0); regBase = transTbl->regs[i].bits & MPU_REGION_BASE_MASK; regSize = (transTbl->regs[i].bits & MPU_REGION_SIZE_MASK) >> 1; if (regSize == (MPU_REGION_SIZE_MAX >> 1)) regSize = MMU_ENTIRE_SPACE; else regSize = 1 << (regSize + 1); if (((regBase <= addr) && ((regBase + regSize) > addr)) || (regSize == MMU_ENTIRE_SPACE)) { /* address starts within this region; is this second match? */ MMU_LOG_MSG (MMU_DEBUG_MPU, "address 0x%X within region %X size 0x%X, regBase = 0x%X, regSize = , 0x%X\n", addr, i, size, regBase, regSize, 0); if (region1 == -1) { /* not found first match yet */ region1 = i; MMU_LOG_MSG (MMU_DEBUG_MPU, "setting region1 = %d\n", i, 0, 0, 0, 0, 0); if ((regBase == addr) && (regSize == size)) { match = MPU_MATCH_EXACT; MMU_LOG_MSG (MMU_DEBUG_MPU, "setting MATCH_EXACT\n", 0, 0, 0, 0, 0, 0); } else if (((regBase + regSize) >= (addr + size)) || (regSize == MMU_ENTIRE_SPACE)) { MMU_LOG_MSG (MMU_DEBUG_MPU,"setting MATCH_SUBSET\n", 0, 0, 0, 0, 0, 0); match = MPU_MATCH_SUBSET; } else { MMU_LOG_MSG (MMU_DEBUG_MPU, "setting MATCH_OTHER\n", 0, 0, 0, 0, 0, 0); match = MPU_MATCH_OTHER; } } else { if (region2 == -1) { MMU_LOG_MSG (MMU_DEBUG_MPU, "setting region2 = %d\n", i, 0, 0, 0, 0, 0); region2 = i; if (((regBase == addr) && (regSize == size)) || ((regBase + regSize) >= (addr + size)) || (regSize == MMU_ENTIRE_SPACE)) match2 = MPU_MATCH_SUBSET; else match2 = MPU_MATCH_OTHER; break; } } } /* endif within region */ } /* endif region enabled */ } /* endfor all regions */ MMU_LOG_MSG (MMU_DEBUG_MPU, "end of checks, region1 = %d, region2 = %d, match=%d\n", region1, region2, match, 0, 0, 0); if ((region1 != -1) && (match == MPU_MATCH_SUBSET)) { /* * Requested region is a subset of first matching region. If * state matches, nothing to do, else create new region. */ MMU_LOG_MSG (MMU_DEBUG_MPU, "subset match\n", 0, 0, 0, 0, 0, 0); if (state != mmuStateGetRegion (region1)) { /* state does not match existing region */ ret = mmuRegionCreate (transTbl->regs, addr, size, state, stateMask); } } else { MMU_LOG_MSG (MMU_DEBUG_MPU, "else 1\n", 0, 0, 0, 0, 0, 0); if ((region1 == -1) || (match == MPU_MATCH_OTHER)) { /* * Either the address start specified is not present within any * currently defined region or the region specified overlaps a * current region. Take simple approach and create a new region * for the request. */ MMU_LOG_MSG (MMU_DEBUG_MPU, "no match, region1 = %d, region2 = %d, match=%d\n", region1,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -