1 /* 2 * Based on linux/arch/arm/mm/nommu.c 3 * 4 * ARM PMSAv7 supporting functions. 5 */ 6 7 #include <linux/bitops.h> 8 #include <linux/memblock.h> 9 #include <linux/string.h> 10 11 #include <asm/cacheflush.h> 12 #include <asm/cp15.h> 13 #include <asm/cputype.h> 14 #include <asm/mpu.h> 15 #include <asm/sections.h> 16 17 #include "mm.h" 18 19 struct region { 20 phys_addr_t base; 21 phys_addr_t size; 22 unsigned long subreg; 23 }; 24 25 static struct region __initdata mem[MPU_MAX_REGIONS]; 26 #ifdef CONFIG_XIP_KERNEL 27 static struct region __initdata xip[MPU_MAX_REGIONS]; 28 #endif 29 30 static unsigned int __initdata mpu_min_region_order; 31 static unsigned int __initdata mpu_max_regions; 32 33 static int __init __mpu_min_region_order(void); 34 static int __init __mpu_max_regions(void); 35 36 #ifndef CONFIG_CPU_V7M 37 38 #define DRBAR __ACCESS_CP15(c6, 0, c1, 0) 39 #define IRBAR __ACCESS_CP15(c6, 0, c1, 1) 40 #define DRSR __ACCESS_CP15(c6, 0, c1, 2) 41 #define IRSR __ACCESS_CP15(c6, 0, c1, 3) 42 #define DRACR __ACCESS_CP15(c6, 0, c1, 4) 43 #define IRACR __ACCESS_CP15(c6, 0, c1, 5) 44 #define RNGNR __ACCESS_CP15(c6, 0, c2, 0) 45 46 /* Region number */ 47 static inline void rgnr_write(u32 v) 48 { 49 write_sysreg(v, RNGNR); 50 } 51 52 /* Data-side / unified region attributes */ 53 54 /* Region access control register */ 55 static inline void dracr_write(u32 v) 56 { 57 write_sysreg(v, DRACR); 58 } 59 60 /* Region size register */ 61 static inline void drsr_write(u32 v) 62 { 63 write_sysreg(v, DRSR); 64 } 65 66 /* Region base address register */ 67 static inline void drbar_write(u32 v) 68 { 69 write_sysreg(v, DRBAR); 70 } 71 72 static inline u32 drbar_read(void) 73 { 74 return read_sysreg(DRBAR); 75 } 76 /* Optional instruction-side region attributes */ 77 78 /* I-side Region access control register */ 79 static inline void iracr_write(u32 v) 80 { 81 write_sysreg(v, IRACR); 82 } 83 84 /* I-side Region size register */ 85 static inline void irsr_write(u32 v) 86 { 87 write_sysreg(v, IRSR); 88 } 89 90 /* I-side Region base address register */ 91 static inline void irbar_write(u32 v) 92 { 93 write_sysreg(v, IRBAR); 94 } 95 96 static inline u32 irbar_read(void) 97 { 98 return read_sysreg(IRBAR); 99 } 100 101 #else 102 103 static inline void rgnr_write(u32 v) 104 { 105 writel_relaxed(v, BASEADDR_V7M_SCB + PMSAv7_RNR); 106 } 107 108 /* Data-side / unified region attributes */ 109 110 /* Region access control register */ 111 static inline void dracr_write(u32 v) 112 { 113 u32 rsr = readl_relaxed(BASEADDR_V7M_SCB + PMSAv7_RASR) & GENMASK(15, 0); 114 115 writel_relaxed((v << 16) | rsr, BASEADDR_V7M_SCB + PMSAv7_RASR); 116 } 117 118 /* Region size register */ 119 static inline void drsr_write(u32 v) 120 { 121 u32 racr = readl_relaxed(BASEADDR_V7M_SCB + PMSAv7_RASR) & GENMASK(31, 16); 122 123 writel_relaxed(v | racr, BASEADDR_V7M_SCB + PMSAv7_RASR); 124 } 125 126 /* Region base address register */ 127 static inline void drbar_write(u32 v) 128 { 129 writel_relaxed(v, BASEADDR_V7M_SCB + PMSAv7_RBAR); 130 } 131 132 static inline u32 drbar_read(void) 133 { 134 return readl_relaxed(BASEADDR_V7M_SCB + PMSAv7_RBAR); 135 } 136 137 /* ARMv7-M only supports a unified MPU, so I-side operations are nop */ 138 139 static inline void iracr_write(u32 v) {} 140 static inline void irsr_write(u32 v) {} 141 static inline void irbar_write(u32 v) {} 142 static inline unsigned long irbar_read(void) {return 0;} 143 144 #endif 145 146 static bool __init try_split_region(phys_addr_t base, phys_addr_t size, struct region *region) 147 { 148 unsigned long subreg, bslots, sslots; 149 phys_addr_t abase = base & ~(size - 1); 150 phys_addr_t asize = base + size - abase; 151 phys_addr_t p2size = 1 << __fls(asize); 152 phys_addr_t bdiff, sdiff; 153 154 if (p2size != asize) 155 p2size *= 2; 156 157 bdiff = base - abase; 158 sdiff = p2size - asize; 159 subreg = p2size / PMSAv7_NR_SUBREGS; 160 161 if ((bdiff % subreg) || (sdiff % subreg)) 162 return false; 163 164 bslots = bdiff / subreg; 165 sslots = sdiff / subreg; 166 167 if (bslots || sslots) { 168 int i; 169 170 if (subreg < PMSAv7_MIN_SUBREG_SIZE) 171 return false; 172 173 if (bslots + sslots > PMSAv7_NR_SUBREGS) 174 return false; 175 176 for (i = 0; i < bslots; i++) 177 _set_bit(i, ®ion->subreg); 178 179 for (i = 1; i <= sslots; i++) 180 _set_bit(PMSAv7_NR_SUBREGS - i, ®ion->subreg); 181 } 182 183 region->base = abase; 184 region->size = p2size; 185 186 return true; 187 } 188 189 static int __init allocate_region(phys_addr_t base, phys_addr_t size, 190 unsigned int limit, struct region *regions) 191 { 192 int count = 0; 193 phys_addr_t diff = size; 194 int attempts = MPU_MAX_REGIONS; 195 196 while (diff) { 197 /* Try cover region as is (maybe with help of subregions) */ 198 if (try_split_region(base, size, ®ions[count])) { 199 count++; 200 base += size; 201 diff -= size; 202 size = diff; 203 } else { 204 /* 205 * Maximum aligned region might overflow phys_addr_t 206 * if "base" is 0. Hence we keep everything below 4G 207 * until we take the smaller of the aligned region 208 * size ("asize") and rounded region size ("p2size"), 209 * one of which is guaranteed to be smaller than the 210 * maximum physical address. 211 */ 212 phys_addr_t asize = (base - 1) ^ base; 213 phys_addr_t p2size = (1 << __fls(diff)) - 1; 214 215 size = asize < p2size ? asize + 1 : p2size + 1; 216 } 217 218 if (count > limit) 219 break; 220 221 if (!attempts) 222 break; 223 224 attempts--; 225 } 226 227 return count; 228 } 229 230 /* MPU initialisation functions */ 231 void __init pmsav7_adjust_lowmem_bounds(void) 232 { 233 phys_addr_t specified_mem_size = 0, total_mem_size = 0; 234 phys_addr_t mem_start; 235 phys_addr_t mem_end; 236 phys_addr_t reg_start, reg_end; 237 unsigned int mem_max_regions; 238 int num; 239 u64 i; 240 241 /* Free-up PMSAv7_PROBE_REGION */ 242 mpu_min_region_order = __mpu_min_region_order(); 243 244 /* How many regions are supported */ 245 mpu_max_regions = __mpu_max_regions(); 246 247 mem_max_regions = min((unsigned int)MPU_MAX_REGIONS, mpu_max_regions); 248 249 /* We need to keep one slot for background region */ 250 mem_max_regions--; 251 252 #ifndef CONFIG_CPU_V7M 253 /* ... and one for vectors */ 254 mem_max_regions--; 255 #endif 256 257 #ifdef CONFIG_XIP_KERNEL 258 /* plus some regions to cover XIP ROM */ 259 num = allocate_region(CONFIG_XIP_PHYS_ADDR, __pa(_exiprom) - CONFIG_XIP_PHYS_ADDR, 260 mem_max_regions, xip); 261 262 mem_max_regions -= num; 263 #endif 264 265 for_each_mem_range(i, ®_start, ®_end) { 266 if (i == 0) { 267 phys_addr_t phys_offset = PHYS_OFFSET; 268 269 /* 270 * Initially only use memory continuous from 271 * PHYS_OFFSET */ 272 if (reg_start != phys_offset) 273 panic("First memory bank must be contiguous from PHYS_OFFSET"); 274 275 mem_start = reg_start; 276 mem_end = reg_end; 277 specified_mem_size = mem_end - mem_start; 278 } else { 279 /* 280 * memblock auto merges contiguous blocks, remove 281 * all blocks afterwards in one go (we can't remove 282 * blocks separately while iterating) 283 */ 284 pr_notice("Ignoring RAM after %pa, memory at %pa ignored\n", 285 &mem_end, ®_start); 286 memblock_remove(reg_start, 0 - reg_start); 287 break; 288 } 289 } 290 291 memset(mem, 0, sizeof(mem)); 292 num = allocate_region(mem_start, specified_mem_size, mem_max_regions, mem); 293 294 for (i = 0; i < num; i++) { 295 unsigned long subreg = mem[i].size / PMSAv7_NR_SUBREGS; 296 297 total_mem_size += mem[i].size - subreg * hweight_long(mem[i].subreg); 298 299 pr_debug("MPU: base %pa size %pa disable subregions: %*pbl\n", 300 &mem[i].base, &mem[i].size, PMSAv7_NR_SUBREGS, &mem[i].subreg); 301 } 302 303 if (total_mem_size != specified_mem_size) { 304 pr_warn("Truncating memory from %pa to %pa (MPU region constraints)", 305 &specified_mem_size, &total_mem_size); 306 memblock_remove(mem_start + total_mem_size, 307 specified_mem_size - total_mem_size); 308 } 309 } 310 311 static int __init __mpu_max_regions(void) 312 { 313 /* 314 * We don't support a different number of I/D side regions so if we 315 * have separate instruction and data memory maps then return 316 * whichever side has a smaller number of supported regions. 317 */ 318 u32 dregions, iregions, mpuir; 319 320 mpuir = read_cpuid_mputype(); 321 322 dregions = iregions = (mpuir & MPUIR_DREGION_SZMASK) >> MPUIR_DREGION; 323 324 /* Check for separate d-side and i-side memory maps */ 325 if (mpuir & MPUIR_nU) 326 iregions = (mpuir & MPUIR_IREGION_SZMASK) >> MPUIR_IREGION; 327 328 /* Use the smallest of the two maxima */ 329 return min(dregions, iregions); 330 } 331 332 static int __init mpu_iside_independent(void) 333 { 334 /* MPUIR.nU specifies whether there is *not* a unified memory map */ 335 return read_cpuid_mputype() & MPUIR_nU; 336 } 337 338 static int __init __mpu_min_region_order(void) 339 { 340 u32 drbar_result, irbar_result; 341 342 /* We've kept a region free for this probing */ 343 rgnr_write(PMSAv7_PROBE_REGION); 344 isb(); 345 /* 346 * As per ARM ARM, write 0xFFFFFFFC to DRBAR to find the minimum 347 * region order 348 */ 349 drbar_write(0xFFFFFFFC); 350 drbar_result = irbar_result = drbar_read(); 351 drbar_write(0x0); 352 /* If the MPU is non-unified, we use the larger of the two minima*/ 353 if (mpu_iside_independent()) { 354 irbar_write(0xFFFFFFFC); 355 irbar_result = irbar_read(); 356 irbar_write(0x0); 357 } 358 isb(); /* Ensure that MPU region operations have completed */ 359 /* Return whichever result is larger */ 360 361 return __ffs(max(drbar_result, irbar_result)); 362 } 363 364 static int __init mpu_setup_region(unsigned int number, phys_addr_t start, 365 unsigned int size_order, unsigned int properties, 366 unsigned int subregions, bool need_flush) 367 { 368 u32 size_data; 369 370 /* We kept a region free for probing resolution of MPU regions*/ 371 if (number > mpu_max_regions 372 || number >= MPU_MAX_REGIONS) 373 return -ENOENT; 374 375 if (size_order > 32) 376 return -ENOMEM; 377 378 if (size_order < mpu_min_region_order) 379 return -ENOMEM; 380 381 /* Writing N to bits 5:1 (RSR_SZ) specifies region size 2^N+1 */ 382 size_data = ((size_order - 1) << PMSAv7_RSR_SZ) | 1 << PMSAv7_RSR_EN; 383 size_data |= subregions << PMSAv7_RSR_SD; 384 385 if (need_flush) 386 flush_cache_all(); 387 388 dsb(); /* Ensure all previous data accesses occur with old mappings */ 389 rgnr_write(number); 390 isb(); 391 drbar_write(start); 392 dracr_write(properties); 393 isb(); /* Propagate properties before enabling region */ 394 drsr_write(size_data); 395 396 /* Check for independent I-side registers */ 397 if (mpu_iside_independent()) { 398 irbar_write(start); 399 iracr_write(properties); 400 isb(); 401 irsr_write(size_data); 402 } 403 isb(); 404 405 /* Store region info (we treat i/d side the same, so only store d) */ 406 mpu_rgn_info.rgns[number].dracr = properties; 407 mpu_rgn_info.rgns[number].drbar = start; 408 mpu_rgn_info.rgns[number].drsr = size_data; 409 410 mpu_rgn_info.used++; 411 412 return 0; 413 } 414 415 /* 416 * Set up default MPU regions, doing nothing if there is no MPU 417 */ 418 void __init pmsav7_setup(void) 419 { 420 int i, region = 0, err = 0; 421 422 /* Setup MPU (order is important) */ 423 424 /* Background */ 425 err |= mpu_setup_region(region++, 0, 32, 426 PMSAv7_ACR_XN | PMSAv7_RGN_STRONGLY_ORDERED | PMSAv7_AP_PL1RW_PL0RW, 427 0, false); 428 429 #ifdef CONFIG_XIP_KERNEL 430 /* ROM */ 431 for (i = 0; i < ARRAY_SIZE(xip); i++) { 432 /* 433 * In case we overwrite RAM region we set earlier in 434 * head-nommu.S (which is cachable) all subsequent 435 * data access till we setup RAM bellow would be done 436 * with BG region (which is uncachable), thus we need 437 * to clean and invalidate cache. 438 */ 439 bool need_flush = region == PMSAv7_RAM_REGION; 440 441 if (!xip[i].size) 442 continue; 443 444 err |= mpu_setup_region(region++, xip[i].base, ilog2(xip[i].size), 445 PMSAv7_AP_PL1RO_PL0NA | PMSAv7_RGN_NORMAL, 446 xip[i].subreg, need_flush); 447 } 448 #endif 449 450 /* RAM */ 451 for (i = 0; i < ARRAY_SIZE(mem); i++) { 452 if (!mem[i].size) 453 continue; 454 455 err |= mpu_setup_region(region++, mem[i].base, ilog2(mem[i].size), 456 PMSAv7_AP_PL1RW_PL0RW | PMSAv7_RGN_NORMAL, 457 mem[i].subreg, false); 458 } 459 460 /* Vectors */ 461 #ifndef CONFIG_CPU_V7M 462 err |= mpu_setup_region(region++, vectors_base, ilog2(2 * PAGE_SIZE), 463 PMSAv7_AP_PL1RW_PL0NA | PMSAv7_RGN_NORMAL, 464 0, false); 465 #endif 466 if (err) { 467 panic("MPU region initialization failure! %d", err); 468 } else { 469 pr_info("Using ARMv7 PMSA Compliant MPU. " 470 "Region independence: %s, Used %d of %d regions\n", 471 mpu_iside_independent() ? "Yes" : "No", 472 mpu_rgn_info.used, mpu_max_regions); 473 } 474 } 475