114986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi/* 214986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * Copyright (C) 2016 The Android Open Source Project 314986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * 414986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * Licensed under the Apache License, Version 2.0 (the "License"); 514986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * you may not use this file except in compliance with the License. 614986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * You may obtain a copy of the License at 714986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * 814986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * http://www.apache.org/licenses/LICENSE-2.0 914986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * 1014986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * Unless required by applicable law or agreed to in writing, software 1114986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * distributed under the License is distributed on an "AS IS" BASIS, 1214986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1314986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * See the License for the specific language governing permissions and 1414986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * limitations under the License. 1514986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi */ 1614986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi 175a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg#include <stdbool.h> 185a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg#include <stdint.h> 19bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov 20bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov#include <bl.h> 21659f9df90838b00bff8fd94985c357db57d1c8b5Dmitry Grinberg#include <cpu.h> 22bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov#include <mpu.h> 23bf34a2b6e59688feefe63537e6d378b9de71fb8cAlexey Polyudov#include <platform.h> 245a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 255a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinbergstruct CortexMpu { 265a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg volatile uint32_t CTRL; 275a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg volatile uint32_t RNR; 285a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg volatile uint32_t RBAR; 295a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg volatile uint32_t RASR; 305a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg}; 315a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 325a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg#define MPU ((struct CortexMpu*)0xE000ED94UL) 335a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 34c4a6f4ca4298e1af237cc9b990aeadb21ec9ad63Dmitry Grinberg#define MPU_REG_ROM 0 35c4a6f4ca4298e1af237cc9b990aeadb21ec9ad63Dmitry Grinberg#define MPU_REG_RAM 1 36c4a6f4ca4298e1af237cc9b990aeadb21ec9ad63Dmitry Grinberg#define MPU_REG_NULL_PAGE 2 375a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 385a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 395a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg/* region type */ 405a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg#define MPU_TYPE_DEVICE (0x10UL << 16) 415a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg#define MPU_TYPE_MEMORY (0x0FUL << 16) 425a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 435a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg/* region execute priviledges */ 445a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg#define MPU_BIT_XN (1UL << 28) /* no execute */ 455a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 46c4a6f4ca4298e1af237cc9b990aeadb21ec9ad63Dmitry Grinberg/* region access priviledges */ 475a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg#define MPU_NA (0UL << 24) /* S: no access U: no access */ 485a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg#define MPU_U_NA_S_RW (1UL << 24) /* S: RW U: no access */ 495a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg#define MPU_U_RO_S_RW (2UL << 24) /* S: RW U: RO */ 505a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg#define MPU_RW (3UL << 24) /* S: RW U: RW */ 515a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg#define MPU_U_NA_S_RO (5UL << 24) /* S: RO U: no access */ 525a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg#define MPU_U_RO_S_RO (6UL << 24) /* S: RO U: RO */ 535a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 545a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg/* subregion mask (not used so all ones) */ 555a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg#define MPU_SRD_BITS 0xFF00UL 565a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg#define MPU_BIT_ENABLE 1UL 575a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 585a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg/* these define rom */ 595a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinbergextern uint8_t __shared_end[]; 605a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinbergextern uint8_t __ram_start[]; 615a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinbergextern uint8_t __ram_end[]; 625a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 635a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinbergstatic void mpuRegionCfg(uint32_t regionNo, uint32_t start, uint32_t len, uint32_t attrs) /* region will be rounded to acceptable boundaries (32B minimum, self-aligned) by GROWTH */ 645a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg{ 655a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg uint32_t proposedStart, proposedLen, lenVal = 1; 665a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg uint64_t intState; 675a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 685a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg /* expand until it works */ 695a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg do { 705a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg /* special case 4GB region */ 715a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg if (lenVal == 32) { 725a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg proposedStart = 0; 735a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg break; 745a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg } 755a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 765a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg proposedStart = start &~ ((1ULL << lenVal) - 1); 775a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg proposedLen = start + len - proposedStart; 785a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg if (proposedLen < 32) 795a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg proposedLen = 32; 805a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg lenVal = (proposedLen & (proposedLen - 1)) ? 32 - __builtin_clz(proposedLen) : 31 - __builtin_clz(proposedLen); 815a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 825a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg } while (proposedStart & ((1ULL << lenVal) - 1)); 835a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 84659f9df90838b00bff8fd94985c357db57d1c8b5Dmitry Grinberg intState = cpuIntsOff(); 855a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg asm volatile("dsb\nisb"); 865a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 875a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg MPU->RNR = regionNo; 885a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg MPU->RASR = 0; /* disable region before changing it */ 895a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg MPU->RBAR = proposedStart; 905a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg MPU->RASR = MPU_SRD_BITS | MPU_BIT_ENABLE | attrs | (lenVal << 1); 915a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 925a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg asm volatile("dsb\nisb"); 93659f9df90838b00bff8fd94985c357db57d1c8b5Dmitry Grinberg cpuIntsRestore(intState); 945a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg} 955a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 965a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinbergstatic void mpuCfgRom(bool allowSvcWrite) 975a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg{ 98c4a6f4ca4298e1af237cc9b990aeadb21ec9ad63Dmitry Grinberg mpuRegionCfg(MPU_REG_ROM, (uint32_t)&BL, __shared_end - (uint8_t*)&BL, MPU_TYPE_MEMORY | (allowSvcWrite ? MPU_U_RO_S_RW : MPU_U_RO_S_RO)); 995a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg} 1005a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 1015a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinbergstatic void mpuCfgRam(bool allowSvcExecute) 1025a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg{ 103c4a6f4ca4298e1af237cc9b990aeadb21ec9ad63Dmitry Grinberg mpuRegionCfg(MPU_REG_RAM, (uint32_t)&__ram_start, __ram_end - __ram_start, MPU_TYPE_MEMORY | MPU_RW | (allowSvcExecute ? 0 : MPU_BIT_XN)); 1045a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg} 1055a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 1065a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 1075a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinbergvoid mpuStart(void) 1085a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg{ 109c4a6f4ca4298e1af237cc9b990aeadb21ec9ad63Dmitry Grinberg MPU->CTRL = 0x07; //MPU on, even during faults, supervisor default: allow, user default: default deny 1105a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 1115a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg mpuCfgRom(false); 1125a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg mpuCfgRam(false); 113c4a6f4ca4298e1af237cc9b990aeadb21ec9ad63Dmitry Grinberg mpuRegionCfg(MPU_REG_NULL_PAGE, 0, 4096, MPU_TYPE_MEMORY | MPU_NA | MPU_BIT_XN); 1145a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg} 1155a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 1165a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinbergvoid mpuAllowRamExecution(bool allowSvcExecute) 1175a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg{ 1185a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg mpuCfgRam(allowSvcExecute); 1195a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg} 1205a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 1215a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinbergvoid mpuAllowRomWrite(bool allowSvcWrite) 1225a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg{ 1235a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg mpuCfgRom(allowSvcWrite); 1245a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg} 1255a17a7a8ed94b23a59d6bac6ff6d94e5ca976205Dmitry Grinberg 126