In this session, we'll look at the security extension, the Armv8-M processors with the main extension. We'll start with an overview and then we'll break down to look at three big topics: memory configuration, how to make function calls, and how that's supported in the tool chain. Finally, we'll look at exceptions and interrupts. By the end of this session, you should be able to describe the need for secure and non-secure partitioning, describe the key difference in the programmer's model with and without the security extension, describe the instructions used to call between secure and non-secure code, and the architectural and hardware features that support this. You'll know how to partition secure and non-secure memory regions using CMSIS-Core, and also build secure applications and libraries using a CMSE-compliant compiler tool. You'll be able to describe how the exception handling mechanism behaves when the security extension is configured and you'll know how to target configurable interrupts and exceptions as secure or non-secure. Let's begin with introducing some terminology. The feature we'll be looking at in the architecture is called the security extension. But it's often branded as TrustZone. You may have seen references to TrustZone in Arm processes for quite a while. The TrustZone security extension is available in both the A class and the M class architecture. To differentiate between the two, we talked about Arm TrustZone for Armv8-M or Arm TrustZone for Armv8-A. The concept is very similar between the two, but the implementation that we have in TrustZone for Armv8-M is optimized for microcontroller use cases. The basic principle though, is to take some highly trusted software which has access to more system resources and provide it a secure execution space to run in and then protect that trusted code from access and interference from non-trusted code. To do this, the security extension provides isolated secure memory for code and data, and a special secure execution state to run that secure code. From earlier sessions, you should be familiar with the Armv8-M programmer's model. We have two execution modes: handler mode, which is always considered to be privileged and is mainly used for handling exceptions, and thread mode, which can either be privileged, or unprivileged, and is used to run application threads. Each of these modes can select which that pointer it's using. Handler mode always uses the main stack pointer or MSP, thread mode can choose between the MSP or the process stack pointer, the PSP. When we add in the security extension, we add another degree of freedom so thread mode or handler mode now exists in one or two states; the non-secure state and the secure state. This is also where I introduce this concept of register banking. You'll see that the MSP now contains an underscore NS or underscore S suffix. This is because we have two instances of this register now which are selected based on the current security state. We'll use this register bank in concept for a few other registers. I will explain it in more detail in a few slides time. Having the thread and handler mode replicated between the security states means that we can use the same conceptual breakdown in both security states. We can now have non secure interrupt handlers running a non-secure handler mode, and secure interrupt handlers running in secure handler mode. We can have secure and non-secure threads running in the appropriate thread mode. In the introduction, I said that the point of TrustZone is to isolate trusted code from the rest of the code in your system. But for it to be useful, we need to allow some interaction between the two systems. Usually, non secure code can make calls into the secure code to use its resources. For instance, to access secure peripherals or to make use of encryption keys, which are stored in secure memory. In TrustZone for Armv8-M, these calls can be made at a function boundary. Effectively, we have a special variance of the branch instruction, which can also change the security state of the processor. To ensure security is maintained though, only a subset of the non-secure code is callable from non-secure. The entry points into the secure state are limited. A nice feature is that your non-secure code doesn't need to know it's making a function call into the secure state. From the non-secure points of view, it looks like a regular library call. If you're familiar with TrustZone for Armv8-A, this is the first major difference. In the TrustZone for Armv8-A, security state changes can only occur on an exception boundary. That effectively makes a secure function call into a system call with the overhead that implies. To maintain the performance and programming model we expect in the microcontrollers TrustZone for Armv8-M differs. Secure function calls are now function calls. There is still a slightly higher overhead, but not the overhead of a system call. Briefly introduced the concept of register banking. This is where you have two instances of a register and we select between them based on the current security state. As we can see from the screen, most of the registers are common between the security states. The general purpose registers and the floating point registers, if we have that extension, are common between the two security states. This means unless we take some action, a secure value in R0 will still be visible to non-secure code if we don't change the value of R0 at the same time as changing security state. In later slides, we'll see how we can manage this. R13 is the alias we use to access the currently selected stack pointer. Because as we saw earlier, stack pointer registers are banked between security states, this is the first instance of register banking we'll see. From earlier sessions, you should be familiar with the special purpose registers such as the control register. These are banked by security: the control register, the exception masking registers, PRIMASK, BASEPRI and FAULTMASK are banked as other stack pointer limit registers : MSPLIM and PSPLIM. Non-secure code can only ever access the non-secure version of these registers. Secure code can choose which instance of the register to access. It can access both the secure and non-secure instances. To enable this, the specification of the MRS and MSR instruction has been improved. As we can see from the slide, we now have the ability to specify we want to access the non-secure instance of the register by applying the underscore NS suffix to the register name. We can see from a secure state, if we access the control register, that will access the secure instance of the control register. If we try and access CONTROL_NS, that will access the non-secure instance of the control register.