1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdbool.h> 18 #include <stdint.h> 19 20 #include <bl.h> 21 #include <cpu.h> 22 #include <mpu.h> 23 #include <platform.h> 24 25 #include <plat/cmsis.h> 26 27 #define MPU_REG_DEFAULT 0 28 #define MPU_REG_ROM 1 29 #define MPU_REG_RAM 2 30 #define MPU_REG_PERIPH 3 31 #define MPU_REG_PRIV_PERIPH 4 32 33 #define MPU_RASR_S 0x00040000 34 #define MPU_RASR_C 0x00020000 35 #define MPU_RASR_B 0x00010000 36 37 /* region type */ 38 #define MPU_TYPE_SRAM (MPU_RASR_S | MPU_RASR_C) 39 #define MPU_TYPE_FLASH (MPU_RASR_C) 40 #define MPU_TYPE_PERIPH (MPU_RASR_S | MPU_RASR_B) 41 42 /* region execute priviledges */ 43 #define MPU_BIT_XN (1UL << 28) /* no execute */ 44 45 /* region access priviledges */ 46 #define MPU_NA (0UL << 24) /* S: no access U: no access */ 47 #define MPU_U_NA_S_RW (1UL << 24) /* S: RW U: no access */ 48 #define MPU_U_RO_S_RW (2UL << 24) /* S: RW U: RO */ 49 #define MPU_RW (3UL << 24) /* S: RW U: RW */ 50 #define MPU_U_NA_S_RO (5UL << 24) /* S: RO U: no access */ 51 #define MPU_U_RO_S_RO (6UL << 24) /* S: RO U: RO */ 52 53 /* subregion disable (not used so all zeroes) */ 54 #define MPU_SRD_BITS 0x0000UL 55 #define MPU_BIT_ENABLE 1UL 56 57 /* these define rom */ 58 extern uint8_t __shared_end[]; 59 extern uint8_t __ram_start[]; 60 extern uint8_t __ram_end[]; 61 62 void MemoryManagemntFault_Handler(void); 63 void __attribute__((naked)) MemoryManagemntFault_Handler(void) 64 { 65 asm volatile( 66 "mov r0, #3 \n" 67 "b cpuCommonFaultCode \n" 68 ); 69 } 70 71 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 */ 72 { 73 uint32_t proposedStart, lenVal = 1; 74 uint64_t len, proposedLen, intState; 75 76 if (start > end) 77 return false; 78 else 79 len = end - start + UINT64_C(1); 80 81 /* expand until it works */ 82 do { 83 proposedStart = start &~ ((UINT64_C(1) << lenVal) - 1); 84 proposedLen = start + len - proposedStart; 85 if (proposedLen < 32) 86 proposedLen = 32; 87 lenVal = (proposedLen & (proposedLen - UINT64_C(1))) ? 64 - __builtin_clzll(proposedLen) : 63 - __builtin_clzll(proposedLen); 88 89 } while (proposedStart & ((UINT64_C(1) << lenVal) - UINT64_C(1))); 90 91 /* minimum size: 32 bytes */ 92 if (lenVal < 5) 93 lenVal = 5; 94 95 intState = cpuIntsOff(); 96 asm volatile("dsb\nisb"); 97 98 MPU->RNR = regionNo; 99 MPU->RASR = 0; /* disable region before changing it */ 100 MPU->RBAR = proposedStart; 101 MPU->RASR = MPU_SRD_BITS | MPU_BIT_ENABLE | attrs | ((lenVal-1) << 1); 102 103 asm volatile("dsb\nisb"); 104 cpuIntsRestore(intState); 105 106 return true; 107 } 108 109 static void mpuCfgRom(bool allowSvcWrite) 110 { 111 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)); 112 } 113 114 static void mpuCfgRam(bool allowSvcExecute) 115 { 116 mpuRegionCfg(MPU_REG_RAM, (uint32_t)&__ram_start, (uint32_t)&__ram_end - 1, MPU_TYPE_SRAM | MPU_RW | (allowSvcExecute ? 0 : MPU_BIT_XN)); 117 } 118 119 120 void mpuStart(void) 121 { 122 MPU->CTRL = 0x00; // disable MPU 123 124 /* 0x00000000 - 0xFFFFFFFF */ 125 mpuRegionCfg(MPU_REG_DEFAULT, 0, 0xFFFFFFFF, MPU_NA | MPU_BIT_XN); 126 127 mpuCfgRom(false); 128 mpuCfgRam(false); 129 130 /* 0x40000000 - 0x4003FFFF */ 131 mpuRegionCfg(MPU_REG_PERIPH, 0x40000000, 0x4003FFFF, MPU_TYPE_PERIPH | MPU_U_NA_S_RW | MPU_BIT_XN); 132 133 /* 0xE0000000 - 0xE00FFFFF */ 134 mpuRegionCfg(MPU_REG_PRIV_PERIPH, 0xE0000000, 0xE00FFFFF, MPU_TYPE_PERIPH | MPU_U_NA_S_RW | MPU_BIT_XN); 135 136 //MPU on, even during faults, supervisor default: allow, user default: default deny 137 MPU->CTRL = MPU_CTRL_ENABLE_Msk | MPU_CTRL_HFNMIENA_Msk | MPU_CTRL_PRIVDEFENA_Msk; 138 SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; 139 } 140 141 void mpuAllowRamExecution(bool allowSvcExecute) 142 { 143 mpuCfgRam(allowSvcExecute); 144 } 145 146 void mpuAllowRomWrite(bool allowSvcWrite) 147 { 148 mpuCfgRom(allowSvcWrite); 149 } 150 151 void mpuShow() 152 { 153 int i, regions = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos; 154 uint32_t addr, rasr; 155 uint8_t ap; 156 bool xn; 157 char *s, *u; 158 159 osLog(LOG_INFO, "MPU: %d HFNMIENA: %d PRIVDEFENA: %d\n", 160 !!(MPU->CTRL & MPU_CTRL_ENABLE_Msk), 161 !!(MPU->CTRL & MPU_CTRL_HFNMIENA_Msk), 162 !!(MPU->CTRL & MPU_CTRL_PRIVDEFENA_Msk)); 163 for (i=0; i<regions; i++) { 164 MPU->RNR = i; 165 addr = MPU->RBAR & MPU_RBAR_ADDR_Msk; 166 rasr = MPU->RASR; 167 xn = rasr & MPU_RASR_XN_Msk; 168 ap = (rasr & MPU_RASR_AP_Msk) >> MPU_RASR_AP_Pos; 169 if (ap == 0) { 170 s = "---"; 171 } else if (ap == 1 || ap == 2 || ap == 3) { 172 if (xn) 173 s = "RW-"; 174 else 175 s = "RWX"; 176 } else if (ap == 5 || ap == 6 || ap == 7) { 177 if (xn) 178 s = "R--"; 179 else 180 s = "R-X"; 181 } else { 182 s = "???"; 183 } 184 if (ap == 0 || ap == 1 || ap == 5) { 185 u = "---"; 186 } else if (ap == 3) { 187 if (xn) 188 u = "RW-"; 189 else 190 u = "RWX"; 191 } else if (ap == 2 || ap == 6 || ap == 7) { 192 if (xn) 193 u = "R--"; 194 else 195 u = "R-X"; 196 } else { 197 u = "???"; 198 } 199 osLog(LOG_INFO, 200 "%d: %c %08lx-%08lx S: %s U: %s TEX: %ld %c%c%c %02lx\n", 201 i, (rasr & MPU_RASR_ENABLE_Msk) ? 'E' : 'D', 202 addr, 203 addr + (1 << (((rasr & MPU_RASR_SIZE_Msk) >> MPU_RASR_SIZE_Pos) + 1))-1, 204 s, u, 205 (rasr & MPU_RASR_TEX_Msk) >> MPU_RASR_TEX_Pos, 206 (rasr & MPU_RASR_S_Msk) ? 'S' : ' ', 207 (rasr & MPU_RASR_C_Msk) ? 'C' : ' ', 208 (rasr & MPU_RASR_B_Msk) ? 'B' : ' ', 209 (rasr & MPU_RASR_SRD_Msk) >> MPU_RASR_SRD_Pos); 210 } 211 } 212