• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 #include "los_mpu.h"
32 #include "los_config.h"
33 #include "los_context.h"
34 
35 #if (LOSCFG_MPU_ENABLE == 1)
36 
37 #define SIZE_4G_BYTE        0x100000000
38 #define MPU_MAX_REGION_NUM  8
39 
40 STATIC UINT8 g_regionNumBeUsed[MPU_MAX_REGION_NUM] = {0};
41 
42 typedef enum {
43     MPU_AP_FORBID_USER_FORBID = 0x0, /* Privileged:No access      Unprivileged:No access */
44     MPU_AP_RW_USER_FORBID = 0x1,     /* Privileged:Read/Write     Unprivileged:No access */
45     MPU_AP_RW_USER_RO = 0x2,         /* Privileged:Read/Write     Unprivileged:Read-only */
46     MPU_AP_RW_USER_RW = 0x3,         /* Privileged:Read/Write     Unprivileged:Read/Write */
47     MPU_AP_NA_USER_NA = 0x4,         /* Privileged:UNPREDICTABLE  Unprivileged:UNPREDICTABLE */
48     MPU_AP_RO_USER_FORBID = 0x5,     /* Privileged:Read-only      Unprivileged:No access */
49     MPU_AP_RO_USER_RO = 0x6,         /* Privileged:Read-only      Unprivileged:Read-only */
50 } MpuApConfig;
51 
ArchMpuEnable(UINT32 defaultRegionEnable)52 VOID ArchMpuEnable(UINT32 defaultRegionEnable)
53 {
54     UINT32 intSave = ArchIntLock();
55     MPU->CTRL = (MPU_CTRL_ENABLE_Msk | ((defaultRegionEnable << MPU_CTRL_PRIVDEFENA_Pos) & MPU_CTRL_PRIVDEFENA_Msk));
56     SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
57     __DSB();
58     __ISB();
59     ArchIntRestore(intSave);
60 }
ArchMpuDisable(VOID)61 VOID ArchMpuDisable(VOID)
62 {
63     UINT32 intSave = ArchIntLock();
64     MPU->CTRL = 0;
65     __DSB();
66     __ISB();
67     ArchIntRestore(intSave);
68 }
69 
HalMpuRASRAddMemAttr(MPU_CFG_PARA * para,UINT32 * RASR)70 STATIC VOID HalMpuRASRAddMemAttr(MPU_CFG_PARA *para, UINT32 *RASR)
71 {
72     BOOL cachable = 0;
73     BOOL buffable = 0;
74     switch (para->memType) {
75         case MPU_MEM_ON_CHIP_ROM:
76         case MPU_MEM_ON_CHIP_RAM:
77             cachable = 1;
78             buffable = 0;
79             break;
80         case MPU_MEM_XIP_PSRAM:
81             cachable = 1;
82             buffable = 1;
83             break;
84         case MPU_MEM_XIP_NOR_FLASH:
85             cachable = 0;
86             buffable = 1;
87             break;
88         default:
89             break;
90     }
91     (*RASR) |= ((cachable << MPU_RASR_C_Pos) | (buffable << MPU_RASR_B_Pos));
92 }
93 
HalMpuEncodeSize(UINT64 size)94 STATIC UINT32 HalMpuEncodeSize(UINT64 size)
95 {
96     UINT32 encodeSize = 0;
97     if (size > SIZE_4G_BYTE) {
98         return 0;
99     }
100     if ((size & 0x1F) != 0) { /* size should aligned to 32 byte at least. */
101         return 0;
102     }
103     size = (size >> 2);
104     while (size != 0) {
105         if (((size & 1) != 0) && ((size & 0xFFFFFFFE) != 0)) { /* size != 2^x (5 <= x <= 32)  128B - 4GB */
106             return 0;
107         }
108         size = (size >> 1);
109         encodeSize++;
110     }
111     return encodeSize;
112 }
113 
HalMpuEncodeAP(MpuAccessPermission permission)114 STATIC UINT32 HalMpuEncodeAP(MpuAccessPermission permission)
115 {
116     UINT32 ap;
117     switch (permission) {
118         case MPU_RW_BY_PRIVILEGED_ONLY:
119             ap = MPU_AP_RW_USER_FORBID;
120             break;
121         case MPU_RW_ANY:
122             ap = MPU_AP_RW_USER_RW;
123             break;
124         case MPU_RO_BY_PRIVILEGED_ONLY:
125             ap = MPU_AP_RO_USER_FORBID;
126             break;
127         case MPU_RO_ANY:
128             ap = MPU_AP_RO_USER_RO;
129             break;
130         default:
131             ap = MPU_AP_RW_USER_RW;
132             break;
133     }
134     return ap;
135 }
136 
HalMpuGetRASR(UINT32 encodeSize,MPU_CFG_PARA * para)137 STATIC UINT32 HalMpuGetRASR(UINT32 encodeSize, MPU_CFG_PARA *para)
138 {
139     UINT32 RASR;
140     UINT32 ap;
141     ap = HalMpuEncodeAP(para->permission);
142     RASR = MPU_RASR_ENABLE_Msk;
143     RASR |= ((encodeSize << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk);
144     RASR |= ((ap << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | ((para->executable << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) |
145         ((para->shareability << MPU_RASR_S_Pos) & MPU_RASR_S_Msk);
146     HalMpuRASRAddMemAttr(para, &RASR);
147     return RASR;
148 }
149 
ArchMpuSetRegion(UINT32 regionId,MPU_CFG_PARA * para)150 UINT32 ArchMpuSetRegion(UINT32 regionId, MPU_CFG_PARA *para)
151 {
152     UINT32 RASR;
153     UINT32 RBAR;
154     UINT32 RNR;
155     UINT32 encodeSize;
156     UINT32 intSave;
157     UINT64 size;
158 
159     if ((regionId >= MPU_MAX_REGION_NUM) || (para == NULL)) {
160         return LOS_NOK;
161     }
162 
163     if ((MPU_TYPE_DREGION_Msk & MPU->TYPE) == 0) {
164         return LOS_NOK;
165     }
166 
167     RNR = regionId;
168     encodeSize = HalMpuEncodeSize(para->size);
169     if (encodeSize == 0) {
170         return LOS_NOK;
171     }
172     size = para->size - 1;              /* size aligned after encode check */
173     if ((para->baseAddr & size) != 0) { /* base addr should aligned to region size */
174         return LOS_NOK;
175     }
176     RBAR = para->baseAddr & MPU_RBAR_ADDR_Msk;
177     RASR = HalMpuGetRASR(encodeSize, para);
178     intSave = ArchIntLock();
179     if (g_regionNumBeUsed[regionId]) {
180         ArchIntRestore(intSave);
181         return LOS_NOK;
182     }
183     MPU->RNR = RNR;
184     MPU->RBAR = RBAR;
185     MPU->RASR = RASR;
186     __DSB();
187     __ISB();
188     g_regionNumBeUsed[regionId] = 1; /* Set mpu region used flag */
189     ArchIntRestore(intSave);
190     return LOS_OK;
191 }
192 
ArchMpuDisableRegion(UINT32 regionId)193 UINT32 ArchMpuDisableRegion(UINT32 regionId)
194 {
195     volatile UINT32 type;
196     UINT32 intSave;
197 
198     if (regionId >= MPU_MAX_REGION_NUM) {
199         return LOS_NOK;
200     }
201 
202     intSave = ArchIntLock();
203     if (!g_regionNumBeUsed[regionId]) {
204         ArchIntRestore(intSave);
205         return LOS_NOK;
206     }
207 
208     type = MPU->TYPE;
209     if ((MPU_TYPE_DREGION_Msk & type) != 0) {
210         MPU->RNR = regionId;
211         MPU->RASR = 0;
212         __DSB();
213         __ISB();
214     }
215     g_regionNumBeUsed[regionId] = 0; /* clear mpu region used flag */
216     ArchIntRestore(intSave);
217     return LOS_OK;
218 }
219 
ArchMpuUnusedRegionGet(VOID)220 INT32 ArchMpuUnusedRegionGet(VOID)
221 {
222     INT32 id;
223     UINT32 intSave = ArchIntLock();
224     for (id = 0; id < MPU_MAX_REGION_NUM; id++) {
225         if (!g_regionNumBeUsed[id]) {
226             break;
227         }
228     }
229     ArchIntRestore(intSave);
230 
231     if (id == MPU_MAX_REGION_NUM) {
232         return -1;
233     } else {
234         return id;
235     }
236 }
237 #endif
238