Architecture
Architecture
Overview
The purpose of Miralis is to virtualize firmware. In a standard RISC-V deployment, the firmware runs in M-mode, below the OS:
┌──────────────┐
U-mode │ User App │
├──────────────┤
S-mode │ OS │
├──────────────┤
M-mode │ Firmware │
└──────────────┘
Because M-mode is all-powerful, it has absolute control over the OS, including reading and modifying its data. The traditional purpose of the firmware is the manage the SoC, that is initializing and configuring all devices, manage power, monitor temperature and device health, etc... In addition, the firmware is increasingly used for security-critical features, such as enforcing isolation. For instance, on Arm the firmware (EL3 on that architecture) is responsible for enforcing the security guarantees of confidential VMs (see Arm CCA extension).
We end-up in a situation where the firmware has two roles: to manage the physical board, and to enforce security policies. Unfortunately those two roles are in tension: hardware manufacturers tend to ship opaque firmware blob to manage proprietary hardware, while security require measured and open-source software to allow scrutiny.
The purpose of Miralis is decouple those two functions: on one hand it can support opaque firmware for managing the board, and on the other it can enforce security by isolating the OS. The way Miralis achieve this is through firmware virtualization. At a high level, a deployment on top of Miralis looks like this:
┌──────────────┐ ┌────────────┐
U-mode │ User App │ │ Firmware │
├──────────────┤ └────────────┘
S-mode │ OS │
├──────────────┴──────────────┐
M-mode │ Miralis │
└─────────────────────────────┘
Miralis itself runs in M-mode in the place where one would usually find the firmware. But because the hardware still requires a firmware to function properly, Miralis actually runs the firmware in U-mode and virtualizes all privileged operations, such as interacting with M-mode registers. At the same time, Miralis allows running a standard OS like it usually would, in S-mode. The OS can call into the firmware, and miralis will take care of forwarding those calls appropriately. That way, Miralis manages to keep all the firmware functionalities, but can enforce strong security guarantees, such as ensuring that the firmware can never access the OS memory.
PMP Virtualization
One of the main aspect of OS virtualization is MMU (Memory Management Unit) virtualization. The MMU can be virtualized using either pure software shadow page tables, or using hardware assisted 2-level page tables.
In the case of Miralis we have no such concerns, because M-mode doesn't have access to an MMU (S-mode does, but Miralis doesn't need to virtualize it). Instead, M-mode has access to PMP (Physical Memory Protection) registers, which falls under the category of MPU (Memory Protection Unit) often found in embedded micro-controllers. Miralis needs to protect its own memory using PMP while still exposing PMP to the firmware to protect itself from the OS. For that purpose Miralis needs to virtualize and multiplex the physical PMP registers.
PMP registers form an ordered list of physical memory ranges with attached access rights. The first entry that matches a given address determines the access rights for that particular load or store. For more details regarding PMP, please refer to the RISC-V privileged specification.
Miralis split PMP registers in four groups, as depicted bellow with the example of 8 physical PMP registers:
┌─────────┐ ─┐
│ PMP 0 │ │
├─────────┤ │ For Miralis use
│ PMP 1 │ │
├─────────┤ ─┤
│ 0 │ │ Null entry