[[smepmp]]
=== ext:smepmp[] Extension for PMP Enhancements for memory access and execution prevention in Machine mode

Being able to access the memory of a process running at a high privileged execution mode, such as the Supervisor or Machine mode, from a lower privileged mode such as the User mode, introduces an obvious attack vector since it allows for an attacker to perform privilege escalation, and tamper with the code and/or data of that process. A less obvious attack vector exists when the reverse happens, in which case an attacker instead of tampering with code and/or data that belong to a high-privileged process, can tamper with the memory of an unprivileged / less-privileged process and trick the high-privileged process to use or execute it.

Two mechanisms combine to prevent this attack vector.
The first one prevents the OS from accessing the memory of an unprivileged
process unless a specific code path is followed, and the second one prevents
the OS from executing the memory of an unprivileged process at all times.
RISC-V already includes support for the former through the ``sstatus.SUM`` bit,
and for the latter by always denying supervisor execution of virtual memory
pages marked with the U bit.

[NOTE]
====
Terms:

* *PMP Entry*: A pair of ``pmpcfg[i]`` / ``pmpaddr[i]`` registers.
* *PMP Rule*: The contents of a pmpcfg register and its associated pmpaddr register(s), that encode a valid protected physical memory region, where ``pmpcfg[i].A != OFF``, and if ``pmpcfg[i].A == TOR``, ``pmpaddr[i-1] < pmpaddr[i]``.
* *Ignored*: Any permissions set by a matching PMP rule are ignored, and _all_ accesses to the requested address range are allowed.
* *Enforced*: Only access types configured in the PMP rule matching the requested address range are allowed; failures will cause an access-fault exception.
* *Denied*: Any permissions set by a matching PMP rule are ignored, and _no_ accesses to the requested address range are allowed.; failures will cause an access-fault exception.
* *Locked*: A PMP rule/entry where the ``pmpcfg.L`` bit is set.
* *PMP reset*: A reset process where all PMP settings of the hart, including locked rules/settings, are re-initialized to a set of safe defaults, before releasing the hart (back) to the firmware / OS / application.
====

[[smepmp_threat]]
==== Threat model

The rationale that guided development of this extension is included in
Section <<smepmp_rationale>>.

[#norm:smepmp_no_mml_limit]#Without the Smepmp extension, it is not possible for a PMP rule to be *enforced* only on non-Machine modes and *denied* on Machine mode, in order to allow access to a memory region solely by less-privileged modes.# [#norm:smepmp_no_mml_behavior]#It is only possible to have a *locked* rule that will be *enforced* on all modes, or a rule that will be *enforced* on non-Machine modes and be *ignored* by Machine mode.# [#norm:smepmp_machine_unlimited]#So for any physical memory region which is not protected with a Locked rule, Machine mode has unlimited access, including the ability to execute it.#

[#norm:smepmp_attack_surface]#Without being able to protect less-privileged modes from Machine mode, it is not possible to prevent the mentioned attack vector.#  This becomes even more important for RISC-V than on other architectures, since implementations are allowed where a hart only has Machine and User modes available, so the whole OS will run on Machine mode instead of the non-existent Supervisor mode. In such implementations the attack surface is greatly increased, and the same kind of attacks performed on Supervisor mode and mitigated through the virtual-memory system, can be performed on Machine mode without any available mitigations. Even on implementations with Supervisor mode present attacks are still possible against the Firmware and/or the Secure Monitor running on Machine mode.

==== Smepmp Physical Memory Protection Rules

To address the threat model outlined in Section <<smepmp_threat>>, [#norm:mseccfg_fields_exist]#this
extension introduces the `RLB`, `MMWP`, and `MML` fields in the `mseccfg` CSR
and their associated rules.# See <<norm:mseccfg_enc_img>> for the detailed
specification of these fields and the corresponding rules.

[#norm:mml_truth_table]#The physical memory protection rules when `mseccfg.MML` is set to 1 are summarized in the truth table below.#

[cols="^1,^1,^1,^1,^3,^3",stripes=even,options="header"]
|===
4+|Bits on _pmpcfg_ register {set:cellbgcolor:green} 2+|Result
|L|R|W|X|M Mode|S/U Mode
|{set:cellbgcolor:!} 0|0|0|0 2+|Inaccessible region (Access Exception)
|0|0|0|1|Access Exception|Execute-only region
|0|0|1|0 2+|Shared data region: Read/write on M mode, read-only on S/U mode
|0|0|1|1 2+|Shared data region: Read/write for both M and S/U mode
|0|1|0|0|Access Exception|Read-only region
|0|1|0|1|Access Exception|Read/Execute region
|0|1|1|0|Access Exception|Read/Write region
|0|1|1|1|Access Exception|Read/Write/Execute region
|1|0|0|0 2+|Locked inaccessible region* (Access Exception)
|1|0|0|1|Locked Execute-only region*|Access Exception
|1|0|1|0 2+|Locked Shared code region: Execute only on both M and S/U mode.*
|1|0|1|1 2+|Locked Shared code region: Execute only on S/U mode, read/execute on M mode.*
|1|1|0|0|Locked Read-only region*|Access Exception
|1|1|0|1|Locked Read/Execute region*|Access Exception
|1|1|1|0|Locked Read/Write region*|Access Exception
|1|1|1|1 2+|Locked Shared data region: Read only on both M and S/U mode.*
|===

*: *Locked* rules cannot be removed or modified until a *PMP reset*, unless ``mseccfg.RLB`` is set.

A visual representation of these rules is as follows:

image::smepmp-visual-representation.png[]

==== Smepmp software discovery

[#norm:mseccfg_locking]#Since all fields defined in ``mseccfg`` as part of this extension are locked when set (``MMWP``/``MML``) or locked when cleared (``RLB``), software can't poll them for determining the presence of Smepmp.# [#norm:bootrom_discovery]#It is expected that BootROM will set ``mseccfg.MMWP`` and/or ``mseccfg.MML`` during early boot, before jumping to the firmware, so that the firmware will be able to determine the presence of Smepmp by reading ``mseccfg`` and checking the state of ``mseccfg.MMWP`` and ``mseccfg.MML``.#
