212 lines
6.4 KiB
C
212 lines
6.4 KiB
C
/*
|
|
* Copyright (C) 2016 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
#include <bl.h>
|
|
#include <cpu.h>
|
|
#include <mpu.h>
|
|
#include <platform.h>
|
|
|
|
#include <plat/cmsis.h>
|
|
|
|
#define MPU_REG_DEFAULT 0
|
|
#define MPU_REG_ROM 1
|
|
#define MPU_REG_RAM 2
|
|
#define MPU_REG_PERIPH 3
|
|
#define MPU_REG_PRIV_PERIPH 4
|
|
|
|
#define MPU_RASR_S 0x00040000
|
|
#define MPU_RASR_C 0x00020000
|
|
#define MPU_RASR_B 0x00010000
|
|
|
|
/* region type */
|
|
#define MPU_TYPE_SRAM (MPU_RASR_S | MPU_RASR_C)
|
|
#define MPU_TYPE_FLASH (MPU_RASR_C)
|
|
#define MPU_TYPE_PERIPH (MPU_RASR_S | MPU_RASR_B)
|
|
|
|
/* region execute priviledges */
|
|
#define MPU_BIT_XN (1UL << 28) /* no execute */
|
|
|
|
/* region access priviledges */
|
|
#define MPU_NA (0UL << 24) /* S: no access U: no access */
|
|
#define MPU_U_NA_S_RW (1UL << 24) /* S: RW U: no access */
|
|
#define MPU_U_RO_S_RW (2UL << 24) /* S: RW U: RO */
|
|
#define MPU_RW (3UL << 24) /* S: RW U: RW */
|
|
#define MPU_U_NA_S_RO (5UL << 24) /* S: RO U: no access */
|
|
#define MPU_U_RO_S_RO (6UL << 24) /* S: RO U: RO */
|
|
|
|
/* subregion disable (not used so all zeroes) */
|
|
#define MPU_SRD_BITS 0x0000UL
|
|
#define MPU_BIT_ENABLE 1UL
|
|
|
|
/* these define rom */
|
|
extern uint8_t __shared_end[];
|
|
extern uint8_t __ram_start[];
|
|
extern uint8_t __ram_end[];
|
|
|
|
void MemoryManagemntFault_Handler(void);
|
|
void __attribute__((naked)) MemoryManagemntFault_Handler(void)
|
|
{
|
|
asm volatile(
|
|
"mov r0, #3 \n"
|
|
"b cpuCommonFaultCode \n"
|
|
);
|
|
}
|
|
|
|
static bool mpuRegionCfg(uint32_t regionNo, uint32_t start, uint32_t end, uint32_t attrs) /* region will be rounded to acceptable boundaries (32B minimum, self-aligned) by GROWTH */
|
|
{
|
|
uint32_t proposedStart, lenVal = 1;
|
|
uint64_t len, proposedLen, intState;
|
|
|
|
if (start > end)
|
|
return false;
|
|
else
|
|
len = end - start + UINT64_C(1);
|
|
|
|
/* expand until it works */
|
|
do {
|
|
proposedStart = start &~ ((UINT64_C(1) << lenVal) - 1);
|
|
proposedLen = start + len - proposedStart;
|
|
if (proposedLen < 32)
|
|
proposedLen = 32;
|
|
lenVal = (proposedLen & (proposedLen - UINT64_C(1))) ? 64 - __builtin_clzll(proposedLen) : 63 - __builtin_clzll(proposedLen);
|
|
|
|
} while (proposedStart & ((UINT64_C(1) << lenVal) - UINT64_C(1)));
|
|
|
|
/* minimum size: 32 bytes */
|
|
if (lenVal < 5)
|
|
lenVal = 5;
|
|
|
|
intState = cpuIntsOff();
|
|
asm volatile("dsb\nisb");
|
|
|
|
MPU->RNR = regionNo;
|
|
MPU->RASR = 0; /* disable region before changing it */
|
|
MPU->RBAR = proposedStart;
|
|
MPU->RASR = MPU_SRD_BITS | MPU_BIT_ENABLE | attrs | ((lenVal-1) << 1);
|
|
|
|
asm volatile("dsb\nisb");
|
|
cpuIntsRestore(intState);
|
|
|
|
return true;
|
|
}
|
|
|
|
static void mpuCfgRom(bool allowSvcWrite)
|
|
{
|
|
mpuRegionCfg(MPU_REG_ROM, (uint32_t)&BL, (uint32_t)&__shared_end - 1, MPU_TYPE_FLASH | (allowSvcWrite ? MPU_U_RO_S_RW : MPU_U_RO_S_RO));
|
|
}
|
|
|
|
static void mpuCfgRam(bool allowSvcExecute)
|
|
{
|
|
mpuRegionCfg(MPU_REG_RAM, (uint32_t)&__ram_start, (uint32_t)&__ram_end - 1, MPU_TYPE_SRAM | MPU_RW | (allowSvcExecute ? 0 : MPU_BIT_XN));
|
|
}
|
|
|
|
|
|
void mpuStart(void)
|
|
{
|
|
MPU->CTRL = 0x00; // disable MPU
|
|
|
|
/* 0x00000000 - 0xFFFFFFFF */
|
|
mpuRegionCfg(MPU_REG_DEFAULT, 0, 0xFFFFFFFF, MPU_NA | MPU_BIT_XN);
|
|
|
|
mpuCfgRom(false);
|
|
mpuCfgRam(false);
|
|
|
|
/* 0x40000000 - 0x4003FFFF */
|
|
mpuRegionCfg(MPU_REG_PERIPH, 0x40000000, 0x4003FFFF, MPU_TYPE_PERIPH | MPU_U_NA_S_RW | MPU_BIT_XN);
|
|
|
|
/* 0xE0000000 - 0xE00FFFFF */
|
|
mpuRegionCfg(MPU_REG_PRIV_PERIPH, 0xE0000000, 0xE00FFFFF, MPU_TYPE_PERIPH | MPU_U_NA_S_RW | MPU_BIT_XN);
|
|
|
|
//MPU on, even during faults, supervisor default: allow, user default: default deny
|
|
MPU->CTRL = MPU_CTRL_ENABLE_Msk | MPU_CTRL_HFNMIENA_Msk | MPU_CTRL_PRIVDEFENA_Msk;
|
|
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
|
|
}
|
|
|
|
void mpuAllowRamExecution(bool allowSvcExecute)
|
|
{
|
|
mpuCfgRam(allowSvcExecute);
|
|
}
|
|
|
|
void mpuAllowRomWrite(bool allowSvcWrite)
|
|
{
|
|
mpuCfgRom(allowSvcWrite);
|
|
}
|
|
|
|
void mpuShow()
|
|
{
|
|
int i, regions = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
|
|
uint32_t addr, rasr;
|
|
uint8_t ap;
|
|
bool xn;
|
|
char *s, *u;
|
|
|
|
osLog(LOG_INFO, "MPU: %d HFNMIENA: %d PRIVDEFENA: %d\n",
|
|
!!(MPU->CTRL & MPU_CTRL_ENABLE_Msk),
|
|
!!(MPU->CTRL & MPU_CTRL_HFNMIENA_Msk),
|
|
!!(MPU->CTRL & MPU_CTRL_PRIVDEFENA_Msk));
|
|
for (i=0; i<regions; i++) {
|
|
MPU->RNR = i;
|
|
addr = MPU->RBAR & MPU_RBAR_ADDR_Msk;
|
|
rasr = MPU->RASR;
|
|
xn = rasr & MPU_RASR_XN_Msk;
|
|
ap = (rasr & MPU_RASR_AP_Msk) >> MPU_RASR_AP_Pos;
|
|
if (ap == 0) {
|
|
s = "---";
|
|
} else if (ap == 1 || ap == 2 || ap == 3) {
|
|
if (xn)
|
|
s = "RW-";
|
|
else
|
|
s = "RWX";
|
|
} else if (ap == 5 || ap == 6 || ap == 7) {
|
|
if (xn)
|
|
s = "R--";
|
|
else
|
|
s = "R-X";
|
|
} else {
|
|
s = "???";
|
|
}
|
|
if (ap == 0 || ap == 1 || ap == 5) {
|
|
u = "---";
|
|
} else if (ap == 3) {
|
|
if (xn)
|
|
u = "RW-";
|
|
else
|
|
u = "RWX";
|
|
} else if (ap == 2 || ap == 6 || ap == 7) {
|
|
if (xn)
|
|
u = "R--";
|
|
else
|
|
u = "R-X";
|
|
} else {
|
|
u = "???";
|
|
}
|
|
osLog(LOG_INFO,
|
|
"%d: %c %08lx-%08lx S: %s U: %s TEX: %ld %c%c%c %02lx\n",
|
|
i, (rasr & MPU_RASR_ENABLE_Msk) ? 'E' : 'D',
|
|
addr,
|
|
addr + (1 << (((rasr & MPU_RASR_SIZE_Msk) >> MPU_RASR_SIZE_Pos) + 1))-1,
|
|
s, u,
|
|
(rasr & MPU_RASR_TEX_Msk) >> MPU_RASR_TEX_Pos,
|
|
(rasr & MPU_RASR_S_Msk) ? 'S' : ' ',
|
|
(rasr & MPU_RASR_C_Msk) ? 'C' : ' ',
|
|
(rasr & MPU_RASR_B_Msk) ? 'B' : ' ',
|
|
(rasr & MPU_RASR_SRD_Msk) >> MPU_RASR_SRD_Pos);
|
|
}
|
|
}
|