Understanding Memory Protection Units

Why MPUs are so critical and how to implement them.

popularity

Let’s talk about the various security measures we take to protect our homes. We use locks, install security cameras to detect any suspicious activities, etc., all to safeguard our loved ones and valuable possessions. In similar sense, the tiny microcontrollers inside our devices have protection units (PU) that safeguard the precious resource: memory.

One of the most important types of protection units is the memory protection unit (MPU).  

What are MPUs?

An MPU is a programmable hardware unit that acts as a gatekeeper of memory. It enables the user to divide the memory into different regions and set memory access permissions (privileged access only or full access, etc.) and memory attributes to each of these regions.  

The number of definable regions varies based on implementation.  The MPU in  Arm Cortex-M4/M7 and M0+ CPU in TRAVEO T2G supports up to 8 programmable regions, and each region defined can further be divided into 8 equal subregions. This increases the granularity of the implemented protection. We will refer to Arm implementation of MPU in this blog.

What’s the difference from other protection units?

The MPU is implemented as part of the CPU core. This means MPU memory regions and the attributes configured are unique to that core. The MPU takes the highest priority over other types of PUs. We will now look into what memory attributes and access permissions we can configure.

What are those memory access permissions and attributes?

Following are the different types of memory attributes that are defined for an MPU protected memory region:

  1. Execute never (XN):

If enabled, any instruction fetch from the memory region would result in a memory access fault.

  1. Data access permission (AP):

It defines the data access permissions of a privileged or user software in the core. That is, if a read or write access by a user or privileged software is allowed.

  1. Shareable (S), Cacheable (C), Bufferable (B):

It is used to allow if any fetched instruction or data can be cached or sent to buffer units or if it can be shared between multiple processors. Along with the field called Type Extension (TEX), the region memory access attributes can be programmed correctly to support different types of memory.

  1. Sub region disable (SRD):

It is used to divide the memory region into 8 sub-regions and define each as enabled or disabled.

The above attributes are part of the region attributes and size (MPU_RASR) register. Along with other MPU registers namely MPU_Type, MPU_Control, MPU_Region number, MPU_Base address, an MPU can be configured for a memory region. For more details about these registers and their bit structure refer to the Arm architecture reference manual (section B3.5.4).  Now that we know what to set, we will see how to set an MPU.

How to setup the MPU?

Ashwin_Kumar_0-1697018135081.png

Fig. 1: MPU setup flow

The steps involved in setting up MPU for ‘i’ different memory regions is explained below. Figure 1 shows the MPU setup as a flowchart. 

  1. We first check for the following two conditions:
    1. Check if the processor/core we are using supports MPU by observing the register MPU->TYPE is not equal to 0.
    2. Check if the number of MPU regions to be configured (CFG_SIZE) is less than or equal to maximum number of MPU regions that is supported (MAX_MPU_NUM).

If both conditions are TRUE then go to next step. Else break out and report as error.

  1. Disable MPU before configuration (MPU_CTRL = 0).
  2. Initialize counter value i = 0
  3. Check if i is less than MAX_MPU_NUM, if TRUE goto step 5. Else goto step 9
  4. Check if i is less than CFG_SIZE. If TRUE goto step 6. Else goto step 7
  5. Select the region number i to be protected. Configure the MPU region number i with the base address and the necessary memory attributes. Now goto step 8
  6. Disable the unused MPU by configuring the base address and its attributes with value 0.
  7. Update the counter value i by 1 and goto step 4
  8. Enable the MPU to apply them over the respective memory regions

Now we know what to set in and how to set an MPU. In the following section we will see the various use cases of MPUs.

Some use cases of MPUs

Following are some of the widely used applications of MPUs to make our system more robust and secure:

  1. To define SRAM as read-only to protect important data from corruption.
  2. Preventing unprivileged tasks from accessing critical memory resources.
  3. To isolate stack space allocated for different applications thus preventing corruption of other stack spaces.

In conclusion, MPUs play a crucial role in ensuring security and integrity of memory resources making it a vital topic to understand and build our systems with security.  In the upcoming blogs we will discuss more about the other protection units.



Leave a Reply


(Note: This name will be displayed publicly)