Abstract: MemoryProtection Unit (MPU) maps memory into a series of memory regions, and defines the dimensions, sizes, access rights, and memory familiarity of these memory regions.
This article is shared by Huawei cloud community “Hongmeng light kernel M core source code analysis series 16 MPU memory protection unit”, author: zhushy.
The Memory Protection Unit (MPU) maps Memory into a series of Memory areas and defines the dimensions, sizes, access permissions, and Memory familiarity of these Memory areas. The MPU supports independent attribute Settings for each memory region, allowing the memory region to be heavy and exporting memory attributes. Detailed information about the MPU can refer to the official site data, such as document location is: the corresponding architecture (M3 developer.arm.com/documentati… .
In hongmeng light kernel, MPU is used for overflow detection of task stack. This paper mainly analyzes the source code of hongmeng light kernel MPU module. The source code in this article, using the OpenHarmonyLitEOS-M kernel as an example, is available on the open source site gitee.com/openharmony… To obtain. Kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel kernel
MPU enumerations, structure definitions, and common macro definitions
1.1 MPU enumeration and structure definition
In the file kernel\arch\include\los_mpu.h define the mpU-related structures. (1) in definition MPU access memory area, about access to visit the website developer.arm.com/documentati… In particular, learn more about Table 4.47.ap encoding from the above page. (2) defines whether the MPU’s attribute enumeration is executable, (3) defines whether the MPU memory region can share attribute enumeration, (4) defines the memory region’s type attribute enumeration, and (5) defines the structure used to define the MPU memory region.
⑴ typedef enum {MPU_RW_BY_PRIVILEGED_ONLY = 0, MPU_RW_ANY = 1, MPU_RO_BY_PRIVILEGED_ONLY = 2, MPU_RO_ANY = 3, } MpuAccessPermission; ⑵ typedef enum {MPU_EXECUTABLE = 0, MPU_NON_EXECUTABLE = 1,} MpuExecutable; Typedef enum {MPU_NO_SHARE = 0, MPU_SHARE = 1,} MpuShareability; ⑷ ⑷ typedef enum {MPU_MEM_ON_CHIP_ROM = 0, MPU_MEM_ON_CHIP_RAM = 1, MPU_MEM_XIP_PSRAM = 2, MPU_MEM_XIP_NOR_FLASH = 3, MPU_MEM_SHARE_MEM = 4, } MpuMemType; ⑸ typedef struct {UINT32 baseAddr; UINT64 size; /* armv7 size == 2^x (5 <= x <= 32) 128B - 4GB */ MpuAccessPermission permission; MpuExecutable executable; MpuShareability shareability; MpuMemType memType; } MPU_CFG_PARA;Copy the code
1.2 MPU macro
Some macro definitions for MPU peripherals have HALDrivers definitions, such as for cortex-M4, the location is Drivers\CMSIS\Core\Include\core_cm4.h. MPU structures are defined as follows, detailed information about the MPU register can access developer.arm.com/documentati… , view Table 4.38. MPU registers summary on the page. The individual registers of the MPU will be covered in the code below.
#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) #define MPU_BASE (SCS_BASE + 0x0D90UL) /*! < Memory Protection Unit */ #define MPU ((MPU_Type *) MPU_BASE ) /*! < Memory Protection Unit */ #endifCopy the code
In addition, the MPU supports eight memory regions. The kernel\arch\arm\cortex-m4\ GCC \los_mpu.c file defines the following macros:
#define MPU_MAX_REGION_NUM 8
Copy the code
2. Common MPU operations
Common MPU operation functions include MPUHalMpuEnable and MPUHalMpuDisable, HalMpuSetRegion, and MPUHalMpuDisable. The specified memory region HalMpuDisableRegion and the unused memory region id HalMpuUnusedRegionGet are disabled.
2.1 can make MPU
HalMpuEnable This function enables the MPU function. At (1), the MPU Control Register is operated, and the MPU can be enabled by assigning the relevant bit bits of the Register. Suggestions about the register read developer.arm.com/documentati… . The code at (2) enables a MemoryFault exception. Then execute the data synchronization barrier __DSB() and instruction synchronization barrier __ISB(), detailed can refer to ARM DMB,DSB,ISB and other instructions.
VOID HalMpuEnable(UINT32 defaultRegionEnable) { UINT32 intSave = HalIntLock(); (1) MPU - > CTRL = (MPU_CTRL_ENABLE_Msk | ((defaultRegionEnable < < MPU_CTRL_PRIVDEFENA_Pos) & MPU_CTRL_PRIVDEFENA_Msk)); 2 SCB - > SHCSR | = SCB_SHCSR_MEMFAULTENA_Msk; __DSB(); __ISB(); HalIntRestore(intSave); }Copy the code
2.2 the fail MPU
The HalMpuDisable code is simple and disables THE MPU function by setting the MPU control register to 0.
VOID HalMpuDisable(VOID)
{
UINT32 intSave = HalIntLock();
MPU->CTRL = 0;
__DSB();
__ISB();
HalIntRestore(intSave);
}
Copy the code
2.3 Disabling the specified memory area HalMpuDisableRegion
After the HalMpuDisableRegion function is executed, the specified memory area is not MPU protected. The parameter validity is verified in 1. The unused MPU memory region (2) cannot be disabled. (3) obtain the type of the MPU registers, detailed access developer.arm.com/documentati… .
(4) When the Number of MPU dataregions is not empty, execute ⑸ code to update the MPU Region Number Register to the specified memory Region Number. Detailed information is available developer.arm.com/documentati… . Then execute [6] in code update MPU memory area properties and size Register (MPU Region Attribute andSize Register), can refer to detailed developer.arm.com/documentati… . Where ⑺ sets the locale number specified in the global variable array to 0.
UINT32 HalMpuDisableRegion(UINT32 regionId) { volatile UINT32 type; UINT32 intSave; ⑴ if (regionId >= MPU_MAX_REGION_NUM) {return LOS_NOK; } intSave = HalIntLock(); 2 the if (! g_regionNumBeUsed[regionId]) { HalIntRestore(intSave); return LOS_NOK; } ⑶ type = MPU-> type; ⑷ if ((MPU_TYPE_DREGION_Msk & type)! {⑸ MPU->RNR = regionId; [6] MPU - > RASR = 0; __DSB(); __ISB(); } ⑺ g_regionNumBeUsed[regionId] = 0; /* clear mpu region used flag */ HalIntRestore(intSave); return LOS_OK; }Copy the code
2.4 Setting the memory area attribute HalMpuSetRegion
The HalMpuSetRegion function sets the properties of the specified memory region. (1) Verify the validity of parameters. (2) if the number of data memory regions represented in the MPU register is 0, the embedded region cannot be set, and LOS_NOK is returned directly. The HalMpuEncodeSize function is called at ⑶ to get the encoding size based on the actual size value of the memory region, which is then assigned to the MPU property and the size bit of the size register. (4) Return LOS_NOK if the size of the memory region is not aligned with the size of the memory region.
5] calculation Base address register data, the Base address register (MPU Region Base AddressRegister), can visit developer.arm.com/documentati… Learn more. ⑹ calculates the values of the properties and size registers. If the specified memory area is used, LOS_NOK is returned. ⑻ set the MPU – related register and mark the memory area as used. The code is as follows:
UINT32 HalMpuSetRegion(UINT32 regionId, MPU_CFG_PARA *para) { UINT32 RASR; UINT32 RBAR; UINT32 RNR; UINT32 encodeSize; UINT32 intSave; UINT64 size; (1) if ((regionId > = MPU_MAX_REGION_NUM) | | (para = = NULL) {return LOS_NOK; } ⑵ if ((MPU_TYPE_DREGION_Msk & MPU->TYPE) == 0) {return LOS_NOK; } RNR = regionId; (3) encodeSize = HalMpuEncodeSize (para - > size); if (encodeSize == 0) { return LOS_NOK; } ⑷ ⑷ size = 4; /* size aligned after encode check */ if ((para->baseAddr & size) ! = 0) { /* base addr should aligned to region size */ return LOS_NOK; } ⑸ RBAR = para->baseAddr & MPU_RBAR_ADDR_Msk; ⑹ RASR = HalMpuGetRASR(encodeSize, para); intSave = HalIntLock(); ⑺ if (g_regionNumBeUsed[regionId]) {HalIntRestore(intSave); return LOS_NOK; } ⑻ MPU->RNR = RNR; MPU->RBAR = RBAR; MPU->RASR = RASR; __DSB(); __ISB(); g_regionNumBeUsed[regionId] = 1; /* Set mpu region used flag */ HalIntRestore(intSave); return LOS_OK; }Copy the code
2.4.1 HalMpuEncodeSize Obtains the size attribute based on the actual size of the memory area
The HalMpuEncodeSize function obtains the size attribute value according to the actual size of the memory area, and the corresponding calculation formula is as follows: (Regionsize in bytes) = 2^(SIZE+1). For details, visit Table 4.44. Example SIZE field values 32bytes corresponds to 4,1KB corresponds to 5,… ,4GB corresponds to 31.
(1) indicates that the size of the memory area cannot be larger than 4GB, and then determines whether to align the memory with 32 bytes. (3) For each step to the right, the size property increases by 1.
STATIC UINT32 HalMpuEncodeSize(UINT64 size) { UINT32 encodeSize = 0; ⑴ if (size > SIZE_4G_BYTE) {return 0; } if ((size & 0x1F) ! = 0) { /* size should aligned to 32 byte at least. */ return 0; } ⑵ = (size >> 2); while (size ! = 0) { if (((size & 1) ! = 0) && ((size & 0xFFFFFFFE) ! = 0)) { /* size ! = 2^x (5 <= x <= 32) 128B - 4GB */ return 0; } ⑶ size = (size >> 1); encodeSize++; } return encodeSize; }Copy the code
2.4.2 HalMpuGetRASR calculates the property and size register values based on the size property value and configuration parameters
HalMpuGetRASR computes the values of the property and size registers based on the size property value and configuration parameters. ⑴ calculates AP (ACCESS permission) according to the configured ACCESS permission, then calculates the value of the property and size register, and finally performs ⑶ to assign the value to the register.
STATIC UINT32 HalMpuEncodeAP(MpuAccessPermission permission) { UINT32 ap; switch (permission) { case MPU_RW_BY_PRIVILEGED_ONLY: ap = MPU_AP_RW_USER_FORBID; break; case MPU_RW_ANY: ap = MPU_AP_RW_USER_RW; break; case MPU_RO_BY_PRIVILEGED_ONLY: ap = MPU_AP_RO_USER_FORBID; break; case MPU_RO_ANY: ap = MPU_AP_RO_USER_RO; break; default: ap = MPU_AP_RW_USER_RW; break; } return ap; } STATIC VOID HalMpuRASRAddMemAttr(MPU_CFG_PARA *para, UINT32 *RASR) { BOOL cachable = 0; BOOL buffable = 0; switch (para->memType) { case MPU_MEM_ON_CHIP_ROM: case MPU_MEM_ON_CHIP_RAM: cachable = 1; buffable = 0; break; case MPU_MEM_XIP_PSRAM: cachable = 1; buffable = 1; break; case MPU_MEM_XIP_NOR_FLASH: cachable = 0; buffable = 1; break; default: break; } (*RASR) |= ((cachable << MPU_RASR_C_Pos) | (buffable << MPU_RASR_B_Pos)); } STATIC UINT32 HalMpuGetRASR(UINT32 encodeSize, MPU_CFG_PARA *para) { UINT32 RASR; UINT32 ap; (1) the ap = HalMpuEncodeAP (para - > permission). RASR = MPU_RASR_ENABLE_Msk; RASR |= ((encodeSize << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk); RASR |= ((ap << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | ((para->executable << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | ((para->shareability << MPU_RASR_S_Pos) & MPU_RASR_S_Msk); (3) HalMpuRASRAddMemAttr (para, & RASR); return RASR; }Copy the code
Click to follow, the first time to learn about Huawei cloud fresh technology ~