RISC-V 指令集特权架构

RISC-V 指令集手册

第二卷:特权架构

文档版本 20190608

前言

本文档介绍了 RISC-V 特权架构。此版本为 20190608-Priv-MSU-Ratified,表示已批准的 machine 和 supervisor 模块的指令集。

本文档包含以下版本的RISC-V ISA模块:

Module Version Status
Machine ISA 1.11 Ratified
Supervisor ISA 1.11 Ratified

本版本文档的变更包括:

  • 将 Machine 和 Supervisor 规范更改到 Ratified 状态。
  • 改进说明和注释。
  • 增加了有关虚拟机监控程序扩展的草案。
  • 规定哪些中断源保留供标准使用。
  • 分配了一些同步异常源供自定义使用。
  • 规定了同步异常的优先级顺序。
  • 添加了规范,即如果支持 A 扩展,则 xRET 指令可以清除 LR 保留,但不是必须的。
  • 无论 SUM 如何设置,虚拟内存系统不再允许超级用户(Supervisor)模式执行用户页面中的指令。
  • 强烈建议软件在全局范围内分配 ASID(地址空间 ID),以便将来的扩展可以全局化ASID,以提高性能和硬件灵活性。
  • SFENCE.VMA 语义已阐明。
  • 将 mstatus.MPP 字段设置为 WARL,而不是 WLRL
  • 将未使用的 xip 字段设置为 WPRI,而不是 WIRI
  • 将未使用的 misa 字段设置为 WLRL,而不是 WIRI
  • 将未使用的 pmpaddr 和 pmpcfg 字段设置为 WARL,而不是 WIRI
  • 要求系统中的所有 harts 都采用相同的 PTE-update 格式。
  • 纠正了编辑错误,该错误错误描述了在发生异常时写入 mstatus.xIE 的机制。
  • 描述了用于仿真未对齐 AMOs 的格式。
  • 在可变 IALIGN 的系统中规定了 misa 和 xepc 寄存器的行为。
  • 规定了向 misa 寄存器中写入自相矛盾的值的行为。
  • 定义了 mcountinhibit CSR 寄存器,该寄存器可停止性能计数器的递增以减少功耗。
  • 规定 PMP 区域的语义大于四个字节。
  • 规定跨 XLEN 修改 CSRs 的内容。
  • 将 PLIC 章节移至其自己的文档中。

译者注:

这里不是完整版指令集的翻译,只是我个人在学习 RISC-V 实现过程中目前了解到的部分内容。主要关注机器模式(M-mode)的实现部分内容。不完整的地方可查阅 RISC-V 基金会官方文档。

在试译过程中为了便于理解将 RISC-V 架构中有关于异常 (exception)、陷阱 (trap) 和中断 (interrupt)的描述做了一些简化。在 RISC-V 架构中,异常指在运行时发生的不寻常情况(包括地址异常、非法指令异常等),且同步处理;陷阱指正常运行的 hart 由另一个hart 条件引起的异常(包括系统 timer、ecall 和 ebreak 等),且同步的提升到特权模式;中断指由外部事件引发的异常(包括但不限于 TIM、GPIO 等外设引起的异常),且异步地提升到特权模式。但相较于 cpu 在正常运行时的状态来说,这三类情况从广义上来说都属于异常。所以本文中一般情况下所指的异常是比较广义上的异常,必要的地方会有区分。

第一章 介绍

本文档介绍了 RISC-V 特权体系结构,它涵盖了非特权 ISA 以外的 RISCV 系统的所有方面,包括特权指令以及运行操作系统和连接外部设备所需的其他功能。

1.1 RISC-V 特权软件堆栈术语

本节描述了我们用来描述 RISC-V 的各种可能的特权软件栈组件的术语。

下图显示了 RISC-V 架构可以支持的一些可能的软件栈。左侧显示了一个简单的系统,该系统仅支持在应用程序执行环境(AEE)上运行的单个应用程序。该应用程序以一个特定的应用程序二进制接口(ABI)来编码来运行。ABI 包括受支持的用户级 ISA+ 和一组与 AEE 进行交互的 ABI 调用。ABI 在应用程序中隐藏了 AEE 的详细信息,以便在实现 AEE 时具有更大的灵活性。相同的 ABI 可以在多个不同的主机 OS 上原生实现,也可以支持在具有不同本机 ISA 的机器上通过用户模式(U-mode)模拟环境来运行。

图片1.1

图1.1 支持各种特权执行形式的不同实现栈

中间配置显示了可以支持多个应用程序的多程序执行的常规操作系统(OS)。每个应用程序通过 ABI 与提供 AEE 的 OS 进行通信。就像应用程序接口通过 ABI 与 AEE 进行通信一样,RISC-V 操作系统也通过管理员二进制接口(SBI)与管理员执行环境(SEE)进行通信。一个 SBI 包括用户级和管理员级 ISA 以及一组 SBI 函数调用。在所有 SEE 实现中使用单个 SBI 可使单个 OS 二进制镜像在任何 SEE 上运行。SEE 可以是低端硬件平台中的简单引导加载程序和 BIOS 风格的 IO 系统,也可以是高端服务器中由管理程序提供的虚拟机,或者在体系结构模拟中可以是主机操作系统上的单薄转换层环境。


: 大多数管理员级别的 ISA 定义并未将 SBI 与执行环境和 / 或硬件平台分开,从而使虚拟化变得复杂,并带来了新的硬件平台。

最右边的配置显示了一个虚拟机监视器配置,其中单个虚拟机管理程序支持多个多任务 OS。每个 OS 都通过 SBI 与提供 SEE 的虚拟机管理程序进行通信。虚拟机管理程序使用虚拟层二进制接口(HBI)与虚拟层执行环境(HEE)通信,以将虚拟机管理程序与硬件平台的详细信息隔离开。


: ABI,SBI 和 HBI 仍在开发中,但是我们现在优先考虑对 Type-2 虚拟机管理程序的支持,其中 SBI 由 S 模式 OS 递归地提供。

RISC-V ISA 的硬件实现通常还需要特权 ISA 以外的其他特性来支持各种执行环境(AEE,SEE或HEE)。

1.2 特权等级

任何时候,RISC-V 硬件线程(hart)都以某种特权级别运行,该特权级别被编码为一个或多个 CSR(控制和状态寄存器)中的一种模式。 当前定义了三个 RISC-V 特权级别,如表1.1所示。

Level Encoding Name Abbreviation
0 00 User/Application U
1 01 Supervisor S
2 10 Reserved(Hypervisor) (H)
3 11 Machine M

表1.1 RISC-V 特权级别

特权级别用于在软件堆栈的不同组件之间提供保护,并且尝试执行当前特权模式不允许的操作将导致引发异常。 这些异常通常会导致进入底层执行环境的陷阱。


: 在描述中,我们尝试将编写代码的特权级别与运行代码的特权模式区分开,尽管两者通常是捆绑在一起的。例如,管理员级别的操作系统可以在具有三种特权模式的系统上以管理员模式运行,但是也可以在具有两种或多种特权模式的系统上的经典虚拟机监视器下以运行用户模式。在这两种情况下,都可以使用相同的管理员级别的操作系统二进制代码,将其编码为管理员级别的 SBI,因此期望能够使用管理员级别的特权指令和 CSR。在用户模式下运行访客 OS 时,所有具有管理员权限的操作都将被以较高特权级别运行的 SEE 捕获并模拟。

机器级别具有最高特权,并且是 RISC-V 硬件平台的唯一强制特权级别。在机器模式(M-mode)下运行的代码通常天生就受信任,因为它具有对机器实现的低级访问权限。M-mode 可以用来管理 RISC-V 上的安全执行环境。用户模式(U-mode)和超级用户模式(S-mode)分别用于常规应用程序和操作系统。

每个特权级别都有一组核心的特权 ISA 扩展,以及可选的扩展和变体。 例如,机器模式支持用于内存保护的可选标准扩展。

实现可以提供 1 到 3 种特权模式,以权衡减少隔离度以降低实现成本,如表1.2所示。

Number of levels Supported Modes Intended Usage
1 M Simple embedded systems
2 M,U Secure embedded systems
3 M,S,U Systems running Unix-like operating systems

表1.2 支持的特权模式组合。

所有硬件实现都必须提供 M-mode,因为这是唯一可以不受限制地访问整个计算机的模式。 最简单的 RISC-V 实现可能仅提供 M-mode,尽管这将无法防止错误或恶意的应用程序代码。

: 可选的 PMP功能的锁定特性,即使只实现 M-mode,可以提供一些有限的保护。

许多 RISC-V 实现也将至少支持用户模式(U-mode),以保护系统的其余部分免受应用程序代码的侵害。 可以添加管理员模式(S-mode),以在管理员级别的操作系统和 SEE 之间提供隔离。

Hart 通常以 U-mode 运行应用程序代码,直到某些异常(例如,管理员调用或计时器中断)强制将开关切换到异常处理程序,该异常处理程序通常以更高的特权模式运行。然后,hart 将执行异常处理程序,应用程序最终将在 U-mode 中原异常指令处或之后恢复执行。提高特权级别的 Traps 称为 vertical traps,而保持相同特权级别的 Traps 称为 horizontal traps。RISC-V 特权体系结构可将异常灵活路由到不同的特权层。


: horizontal traps 可以实现为 vertical traps,在较低特权模式下将控制权返回给 horizontal traps 处理程序。

1.3 调试模式

一个实现还可以包括一个调试模式,以支持片外调试和/或生产测试。调试模式(D-mode)可以被认为是一种额外的特权模式,其访问权限比 M-mode 更大。单独的调试规范建议描述了RISC-V hart 在调试模式下的操作。调试模式保留一些只能在 D-mode 下访问的 CSR 地址,并且还可能保留平台上物理地址空间的某些部分。

第二章 控制和状态寄存器(CSRs)

SYSTEM 主操作码用于编码 RISC-V ISA 中的所有特权指令。这些可分为两大类:控制和状态寄存器(CSRs)的原子操作(read-modify-write),以及所有其他特权指令。除了本手册第一卷中描述的用户级别状态外,一个实现还可以包含其他 CSRs,这些特权可以通过使用用户级别手册中描述的 CSR 指令的某些特权级别子集来访问。在本章中,我们规划出 CSR 地址空间。以下各章节根据特权级别描述了每个 CSRs 的功能,以及通常与特定特权级别紧密相关的其他特权指令。请注意,尽管 CSRs 和指令与一个特权级别相关联,但是它们也可以在所有更高的特权级别下访问。

2.1 CSR 地址映射规则

标准的 RISC-V ISA 留出 12 位编码空间(csr [11:0]),最多可存储 4096 个 CSRs。

按照惯例,CSR 地址的高 4 位(csr [11:8])用于根据权限级别对 CSRs 的读写可访问性进行编码,如表 2.1 所示。前两位(csr [11:10])指示寄存器是读/写(00、01 or 10)还是只读(11)。接下来的两位(csr [9:8])编码可以访问 CSR 的最低特权级别。


: CSR 地址约定使用 CSR 地址的高位来编码默认访问权限。这简化了硬件中的错误检查,并提供了更大的 CSR 空间,但确实限制了 CSR 到地址空间的映射。实现可能允许更高级别的特权捕获较低级别特权允许的 CSR 访问,以允许拦截这些访问。这个变化应该对特权较少的软件是明晰的。

尝试访问不存在的 CSR 会引发一个非法指令异常。尝试在没有适当特权级别的情况下访问 CSR 或写入只读寄存器也会引发非法指令异常。读/写寄存器可能还包含一些只读位,在这种情况下,对只读位的写操作将被忽略。

表 2.1 还列出了在标准用途和自定义用途之间分配CSR地址的约定。保留用于自定义用途的 CSR 地址不会在以后的标准扩展中重新定义。

机器模式标准读写 CSRs 0x7A0–0x7BF 保留供调试系统使用。在这些 CSRs 中,机器模式可访问 0x7A0-0x7AF,而调试模式仅可见 0x7B0-0x7BF。实现应在机器模式访问后一组寄存器时引发非法指令异常。


: 有效的虚拟化要求在虚拟化环境中尽可能多地在本机上运行指令,而任何特权访问都会 trap到虚拟机监视器[1]。如果将具有较低特权级别的只读 CSR 设为具有较高特权级别的读写,则它们将被映射到单独的 CSR 地址中。这样可以避免在允许低特权访问的同时引发 trap,同时仍然导致对非法访问的 trap。 当前,计数器是仅有的影子 CSRs。

2.2 CSR 寄存器清单

表 2.2–2.5 列出的 CSRs 寄存器是当前已分配了 CSR 地址的。timers,counters 和浮点 CSRs 是标准的用户级 CSRs,以及由 N 扩展添加的其他用户 trap 寄存器。其他寄存器由特权代码使用,如以下各章节所述。 请注意,并非所有实现都需要所有寄存器。

CSR Address Hex Use and Accessibility
[11:10] [9:8] [7:4]
User CSRs
00 00 XXXX 0x000-0x0FF Standard read/write
01 00 XXXX 0x400-0x4FF Standard read/write
10 00 XXXX 0x800-0x8FF Custom read/write
11 00 0XXX 0xC00-0xC7F Standard read-only
11 00 10XX 0xC80-0xCBF Standard read-only
11 00 11XX 0xCC0-0xCFF Custom read-only
Supervisor CSRs
00 01 XXXX 0x100-0x1FF Standard read/write
01 01 0XXX 0x500-0x57F Standard read/write
01 01 10XX 0x580-0x5BF Standard read/write
01 01 11XX 0x5C0-0x5FF Custom read/write
10 01 0XXX 0x900-0x97F Standard read/write
10 01 10XX 0x980-0x9BF Standard read/write
10 01 11XX 0x9C0-0x9FF Custom read/write
11 01 0XXX 0xD00-0xD7F Standard read-only
11 01 10XX 0xD80-0xDBF Standard read-only
11 01 11XX 0xDC0-0xDFF Custom read-only
Hypervisor CSRs
00 10 XXXX 0x200-0x2FF Standard read/write
01 10 0XXX 0x600-0x67F Standard read/write
01 10 10XX 0x680-0x6BF Standard read/write
01 10 11XX 0x6C0-0x6FF Custom read/write
10 10 0XXX 0xA00-0xA7F Standard read/write
10 10 10XX 0xA80-0xABF Standard read/write
10 10 11XX 0xAC0-0xAFF Custom read/write
11 10 0XXX 0xE00-0xE7F Standard read-only
11 10 10XX 0xE80-0xEBF Standard read-only
11 10 11XX 0xEC0-0xEFF Custom read-only
Machine CSRs
00 11 XXXX 0x300-0x3FF Standard read/write
01 11 0XXX 0x700-0x77F Standard read/write
01 11 100X 0x780-0x79F Standard read/write
01 11 1010 0x7A0-0x7AF Standard read/write debug CSRs
01 11 1011 0x7B0-0x7BF Debug-mode-only CSRs
01 11 11XX 0x7C0-0x7FF Custom read/write
10 11 0XXX 0xB00-0xB7F Standard read/write
10 11 10XX 0xB80-0xBBF Standard read/write
10 11 11XX 0xBC0-0xBFF Custom read/write
11 11 0XXX 0xF00-0xF7F Standard read-only
11 11 10XX 0xF80-0xFBF Standard read-only
11 11 11XX 0xFC0-0xFFF Custom read-only

表 2.1 RISC-V CSR地址范围的分配

sM7OiD.png

表 2.2 目前分配的 RISC-V 用户级 CSR 地址

sMHtyR.png

表 2.3 目前分配的 RISC-V 管理员级 CSR 地址

sMH7lj.png

表 2.4 目前分配的 RISC-V 机器级 CSR 地址。

sMbyNT.png

表 2.5 目前分配的 RISC-V 机器级 CSR 地址。

2.3 CSR 字段规范

以下定义和缩写用于指定 CSR 中字段的行为。

Reserved Writes Preserve Values, Reads Ignore Values (WPRI)(写保留原值,读忽略值)

一些完整的读/写字段保留供将来使用。 当将值写入同一寄存器的其他字段时,软件应忽略从这些字段读取的值,并应保留这些字段中保存的值。 为了向前兼容,不提供这些字段的实现时必须将其硬接线为零。 这些字段在寄存器描述中标记为 WPRI。

一些读/写 CSR 字段仅为可能的位编码的子集指定行为,而保留其他位编码。软件不应该向这样的字段写入任何合法值以外的内容,并且不应该假定读取将返回合法值,除非最后一次写入是合法值,或者由于另一次操作将寄存器设置为合法值,寄存器还没有被写入。这些字段在寄存器描述中标记为 WLRL。

如果指令试图将不支持的值写入 WLRL 字段,则允许实现,但不要求引发非法指令异常。 当最后一次写入具有非法值时,实现可以在读取WLRL字段时返回任意位模式,但是返回的值应确定性地取决于非法写入值和写入前的字段值。

一些读/写 CSR 字段仅针对位编码的子集定义,但允许写入任何值,同时保证每次读取时均返回合法值。 假设编写 CSR 没有其他副作用,则可以通过尝试写入所需的设置然后读取以查看是否保留该值来确定支持值的范围。 这些字段在寄存器说明中标记为 WARL。

在将不支持的值写入 WARL 字段时,实现不会引发异常。 当最后一次写入具有非法值时,实现可以在读取 WARL 字段时返回任何合法值,但是返回的合法值应确定性地取决于非法写入值和写入之前的字段值。

2.4 CSR 宽度调整

如果更改了 CSR 的宽度(例如,如第 3.1.6.2 节中所述,通过更改 MXLEN 或 UXLEN),则除非另有说明,否则新宽度CSR的可写字段和位是由先前宽度 CSR 确定的,就像通过以下算法确定一样:

  1. 将先前宽度的 CSR 的值复制到相同宽度的临时寄存器中。

  2. 对于先前宽度的CSR的只读位,临时寄存器中相同位置的位设置为零。

  3. 临时寄存器的宽度更改为新的宽度。 如果新宽度 W 窄于先前宽度,则保留临时寄存器的最低有效 W 位,并丢弃较高有效位。 如果新宽度比以前的宽度宽,则将临时寄存器零扩展到较宽的宽度。

  4. 新宽度 CSR 的每个可写字段都采用临时寄存器中相同位置的位值。

更改 CSR 的宽度不是对 CSR 的读取或写入,因此不会触发任何副作用。

第三章 机器级 ISA(Machine-Level ISA), 版本 1.1

本章介绍了机器模式(M-mode)下提供的机器级操作,该模式是 RISC-V 系统中的最高特权模式。M-mode 用于对硬件平台的低级别访问,并且是复位时进入的第一个模式。M-mode 也可以用来完成那些在硬件上直接实现太困难或太昂贵的功能。RISC-V 机器级 ISA 包含一个公共核心,该核心可以根据所支持的其他特权级别以及硬件实现的其他详细信息进行扩展。

3.1 Machine-Level CSRs (机器级 CSRs)

除了本节中描述的机器级 CSRs 外,M-mode 代码还可以访问较低特权级别的所有 CSRs。

3.1.1 机器指令集(ISA)寄存器: misa

misa CSR 是 WARL 读写寄存器,报告硬件(hart)支持的 ISA。该寄存器在任何实现中都必须是可读的,但是可以返回零值以指示未实现 misa 寄存器,这就需要通过一个单独的非标准机制确定 CPU 功能。

sMOvr9.png

图 3.1 机器 ISA 寄存器(misa)

MXL(机器 XLEN)字段编码本机基本整数 ISA 宽度,如表 3.1 所示。MXL 字段在支持多个基本 ISA 宽度的实现中可能是可写的。M-mode 下的有效 XLEN, MXLEN,由 MXL 的设置给出,如果 misa 为零,则有一个固定的值。重置时,MXL 字段始终设置为最广泛支持的 ISA 变种。

MXL XLEN
1 32
2 64
3 128

misa CSR 为 MXLEN 位宽。如果从 misa 读取的值不为零,该值的 MXL 字段总是表示当前的 MXLEN。如果对 misa 的写操作导致 MXLEN 发生更改,则 MXL 的位置将以新的宽度移动到 misa 的最高有效两位。


: 可以使用返回的 misa 值的符号上的分支,以及可能在符号上左移一个分支和第二个分支,来快速确定基本宽度。这些检查可以用汇编代码编写,而无需知道机器的寄存器宽度(XLEN)。 基本宽度由 XLEN = 2^(MXL + 4) 给出。 如果 misa 为零,则可以通过将立即数 4 放置在一个寄存器中,然后一次将寄存器左移 31位来找到基本宽度。如果在一次移位后为零,则该机器为 RV32。 如果两次移位后为零,则机器为 RV64,否则为 RV128。

Extensions 字段对标准扩展的存在进行编码,每个字母都有一个比特(bit 0 编码扩展名“ A” 存在,bit 1 编码扩展名“ B” 存在,直到 bit 25 编码“ Z”)。RV32I,RV64I,RV128I 基本 ISA 的“ I”位置 1,而 RV32E 的“ E”位置 1。Extensions 字段是 WARL 字段,可以包含可写位,其中实现允许修改支持的 ISA。重置时,“Extensions ”字段应包含支持的扩展名的最大集合,并且如果两者均可用,则 “I” 应该被选择而不是 E 。

RV128I 基本 ISA 尚未冻结,尽管本规范的其余大部分有望应用于 RV128,但这个版本的文档仅关注 RV32 和 RV64。

“ G” 位用作转义符,以允许扩展到更大的标准扩展名空间。


: G 用于指示 IMAFD 组合,因此在 misa CSR 中是多余的,因此我们保留该位以指示存在其他标准扩展。

如果分别支持用户和管理员模式,则将设置“ U”和“ S”位。

如果存在任何非标准扩展名,则将设置“ X”位。


: misa CSR 将 CPU 功能的基本目录暴露给机器模式代码。可以在机器模式中通过探测其他机器寄存器,并检查系统中的其他 ROM 存储器,作为引导过程的一部分来获得更多的信息。 我们要求较低特权级别执行环境调用,而不是读取 CPU 寄存器来确定每个特权级别可用的功能。这使虚拟化层可以更改在任何级别观察到的 ISA,并支持更丰富的命令界面,而不会增加硬件设计的负担。

“ E”位是只读的。 除非将 misa 硬连线为零,否则“ E”位始终读取为“ I”位的补码(补集?)。同时支持 RV32E 和 RV32I 的实现可以通过清除“ I”位来选择 RV32E。

sQmQJO.png

表 3.2 misa 中 Extensions 字段的编码。 保留供将来使用的所有位在读取时必须返回零。

如果 ISA 功能 x 取决于 ISA 功能 y,则尝试启用功能 x 但禁用功能 y 会导致两个功能都被禁用。 例如,设置 “ F” = 0 和 “ D” = 1 会导致同时清除“ F”和“ D”。

一个实现可能会对两个或多个 misa 字段的集合设置施加其他约束,在这种情况下,它们将共同充当单个 WARL 字段。 尝试写入不受支持的组合会导致将这些位设置为某些受支持的组合。

写 misa 可能会增加 IALIGN,例如,通过禁用 C 扩展。如果要写入 misa 的指令增加了 IALIGN,而后一条指令的地址未按 IALIGN 位对齐,则将抑制对 misa 的写入,从而使 misa 保持不变。

3.1.2 机器厂商 ID 寄存器: mvendorid

mvendorid CSR 是一个 32 位只读寄存器,提供核心提供者的 JEDEC 制造商 ID。该寄存器在任何实现中都必须是可读的,但是可以返回 0 值指示该字段未实现或这是非商业实现。

sQn1A0.png

图3.2 Vendor ID 寄存器(mvendorid)

JEDEC 制造商 ID 通常编码为单字节连续的 0x7f 代码的序列,以不等于 0x7f 的单字节 ID 终止,并且在每个字节的最高有效位中带有奇校验位。mvendorid 在 Bank 字段中编码单字节的连续代码,并在 Offset 字段中编码最后一个字节,丢弃奇偶校验位。例如,JEDEC 制造商ID 0x7f 0x7f 0x7f 0x7f 0x7f 0x7f 0x7f 0x7f 0x7f 0x7f 0x7f 0x7f 0x8a(十二个连续代码,后跟 0x8a)将在 mvendorid 字段中编码为 0x60a。


: 以前,供应商 ID 是 RISC-V 基金会分配的编号,但这与 JEDEC 在维护制造商 ID 标准方面的工作重复。 在撰写本文时,向 JEDEC 注册制造商 ID 的一次性费用为 500 美元。

3.1.3 机器架构 ID 寄存器: marchid

marchid CSR 是 MXLEN 位的只读寄存器,用于编码 hart 的基本微体系结构。该寄存器在任何实现中都必须是可读的,但是可以返回 0 值以指示未实现该字段。 mvendorid 和 marchid 的组合应该唯一地标识所实现的 hart 微体系结构的类型。

sQMCnJ.png

图 3.3 机器架构 ID 寄存器(marchid)

开源项目体系结构 IDs 由 RISC-V 基金会全局分配,并且具有非零体系结构 IDs,其中最高有效位(MSB)为零。商业体系结构 IDs 由每个商业供应商独立分配,但是必须设置 MSB,并且在其余 MXLEN-1 位中不能包含零。


: *

3.1.4 机器实现 ID 寄存器: mimpid

3.1.5 Hart ID 寄存器: mhartid

3.1.6 机器状态寄存器:mstatus

mstatus 寄存器是一个 MXLEN 位读/写寄存器,其格式在 RV32 上的如图 3.6 和在 RV64 如图 3.7 所示。mstatus 寄存器跟踪并控制 hart 的当前操作状态。 mstatus 寄存器的受限视图分别在 S 级和 U 级 ISA 中显示为 sstatus 和 ustatus 寄存器。

sQINkD.png

图 3.6 RV32下机器模式状态寄存器 (mstatus)

sQIUte.png

图 3.7 RV64 下机器模式状态寄存器 (mstatus)

3.1.6.1 mstatus 寄存器中的特权和全局中断使能栈

为每种特权模式提供了全局中断使能位 MIE,SIE 和 UIE。这些位主要用于保证当前特权模式下中断处理程序的原子性。


: 全局 xIE 位位于 mstatus 的低位,因此可以通过一条 CSR 指令自动设置或清除它们。

当 hart 在 x 特权模式中执行时,当 xIE = 1 时中断被全局启用,当 xIE = 0 时中断被全局禁用。无论低特权模式的全局 wIE 位如何设置,w < x,较低特权模式的中断总是会全局禁用。无论高特权模式的全局 yIE 位如何设置,y > x,始终会全局启用高特权模式的中断。特权级别较高的代码可以使用单独的每个中断启用位来禁用选定的较高级别的特权模式中断,然后再将控制权移交给较低级别的特权模式。


: 较高特权模式 y 可以在将控制权移交给较低特权模式之前禁用其所有中断,但这将是不寻常的,因为它将仅留下同步异常 (trap),不可屏蔽的中断或重置以重新获得对 hart 的控制。

为了支持异常 (traps) 嵌套,每个 x 特权模式都有一个两级的堆栈,其中包括中断使能位和特权模式。xPIE 保留异常之前活动的中断使能位的值,而 xPP 保留先前的特权模式。xPP 字段最多只能保留 x 的特权模式,因此 MPP 为 2 位宽,SPP 为 1 位宽,UPP 隐式为 0。当异常从特权模式 y 进入特权模式 x 时,xPIE 设置为 xIE 的值; xIE 设置为 0;并且 xPP 设置为 y。


: 对于低特权模式,任何异常(同步或者异步)通常都以更高的特权模式进行,进入时禁用中断。更高级别的 trap 处理程序要么为 trap 提供服务,然后使用堆栈的信息返回,要么(如果没有立即返回到被中断的上下文)在重新启用中断之前保存特权堆栈,因此每个堆栈只需要一个入口。

MRET,SRET 或 URET 指令分别用于从 M-mode,S-mode 或 U-mode 的异常返回。当执行 xRET 指令时,假设 xPP 保持值 y,则 xIE 设置为 xPIE; 特权模式更改为 y; xPIE 设置为 1; 并且 xPP 设置为 U(如果不支持用户模式,则为 M)。

xPP 字段是 WARL 字段,只能包含 x 特权模式 和任何低于 x 的已实现特权模式。 如果未实现 x 特权模式,则必须将 xPP 硬接线为 0。


: M-mode 软件可以通过将特权模式写入 MPP 然后将其读回来确定是否实现了特权模式。 如果机器仅提供 U 和 M 模式,则仅需要单个硬件存储位即可表示 MPP 中的 00 或 11。

用户级中断是可选的扩展,并已分配 ISA 扩展字母 N。 如果省略了用户级中断,则 UIE 和 UPIE 位被硬接线为零。对于所有其他受支持的 x 特权模式,不得对 xIE 和 xPIE 进行硬接线。


: 用户级中断的主要目的是支持仅包含 M-mode 和 U-mode 的安全嵌入式系统,但也可以在运行类 Unix 操作系统的系统中支持的用户级中断,以支持用户级异常处理。

3.1.6.2 mstatus 寄存器中基本 ISA 控制

对于 RV64 系统,SXL 和 UXL 字段是 WARL 字段,分别控制 S-mode 和 U-mode 的 XLEN 值。这些字段的编码与 misa 的 MXL 字段相同,如表 3.1 所示。 S-mode 和 U-mode 下的有效 XLEN 分别称为 SXLEN 和 UXLEN。

对于 RV32 系统,SXL 和 UXL 字段不存在,并且 SXLEN = 32 和 UXLEN = 32。

对于 RV64 系统,如果不支持 S-mode,则 SXL 硬接线为零。 否则,它是一个 WARL 字段,对 SXLEN 的当前值进行编码。 特别地,该实现可以硬连线 SXL,使得 SXLEN = MXLEN。

对于 RV64 系统,如果不支持 U-mode,则 UXL 硬接线为零。 否则,它是一个 WARL 字段,对 UXLEN 的当前值进行编码。 特别地,该实现可以硬编码 UXL,使得 UXLEN = MXLEN 或 UXLEN = SXLEN。

只要在任何模式下将 XLEN 的值设置为小于支持的最大 XLEN 的值,所有操作都必须忽略配置的 XLEN 上方的源操作数寄存器位,并且必须对结果进行符号扩展以填充目标寄存器中整个支持的最大 XLEN。

如果 MXLEN 从 32 更改为更宽的宽度,则 mstatus 字段 SXL 和 UXL 中的每个(如果未硬接线为强制值)将获得与最大支持宽度对应的值,该宽度不比新 MXLEN 宽。

3.1.6.3 mstatus 寄存器中内存特权

3.1.6.4 mstatus 寄存器中虚拟化支持

3.1.6.5 mstatus 寄存器中扩展上下文状态(Extension Context Status)

支持大量扩展是 RISC-V 的主要目标之一,因此,我们定义了一个标准接口,以允许不变的特权模式代码(尤其是管理员级别的 OS)支持任意的用户模式状态扩展。

FS [1:0] WARL字段和XS [1:0]只读字段分别用于通过设置和跟踪浮点单元和任何其他用户模式扩展的当前状态来减少上下文保存和还原的成本。

3.1.7 机器异常向量(Trap-Vector)基地址寄存器: mtvec

mtvec 寄存器是 MXLEN 位的读/写寄存器,用于保存异常向量配置, 由向量基址(BASE)和向量模式(MODE)组成。

image-20210111141718084

图 3.8 机器异常向量基地址寄存器 (mtvec)

mtvec 寄存器必须始终实现,但可以包含硬连线的只读值。 如果 mtvec 是可写的,则寄存器可能保存的一组值可能因实现而异。 BASE 字段中的值必须始终在 4 字节边界上对齐,并且 MODE 设置可能会对 BASE 字段中的值施加其他对齐约束。


: 我们在实现 trap 向量基址时具有相当大的灵活性。 一方面,我们不希望负担大量状态位给底层实现带来负担,但另一方面,我们希望为更大的系统提供灵活性。

s37vLj.png

表 3.5 mtvec MODE 字段编码

表 3.5 中显示了 MODE 字段的编码。 当 MODE = Direct 时,所有进入机器模式的 trap 都会导致将 pc 设置为 BASE 字段中的地址。当 MODE = Vectored 时,进入机器模式的所有同步异常都将 pc 设置为 BASE 字段中的地址,而中断将 pc 设置为 BASE 字段中的地址加上四倍的中断 cause 编号。例如,机器模式计时器中断导致将 PC 设置为 BASE + 0x1c(请参阅表 3.6)。


: 启用向量中断后,与用户模式软件中断相对应的中断 cause 0 被向量到与同步异常相同的位置。 由于用户模式软件中断被禁用或委托给特权较少的模式,因此在实践中不会出现这种歧义。

对于不同的模式,实现可能具有不同的对齐约束。 特别的是,MODE = Vectored 可能比 MODE = Direct 更严格的对齐约束。

3.1.8 机器异常(Trap)委托寄存器:(medeleg and mideleg)

3.1.9 机器中断寄存器:(mip 和 mie)

mip 寄存器是 MXLEN 位读/写寄存器,包含有关挂起的中断的信息,而 mie 是对应的 MXLEN 位读/写寄存器,包含中断使能位。通过该 CSR 地址只能写入 mip 中的低特权软件中断(USIP,SSIP),定时器中断(UTIP,STIP)和外部中断(UEIP,SEIP)所对应的位; 其余位是只读的。


: 机器级中断寄存器处理一些根中断源,为简单起见,这些中断源被分配了固定的服务优先级,而单独的外部中断控制器可以对更大的一组中断实施更复杂的优先级排序方案,然后将这些中断混和到机器级 中断源。

mip 和 mie 寄存器的受限视图分别以 sip / sie 和 uip / uie 寄存器的形式出现在 S-mode 和 U-mode 下。 如果通过在 mideleg 寄存器中设置一个位将中断委托给 x 特权模式,则该中断在 x ip 寄存器中可见,并且可以使用 x ie 寄存器屏蔽。否则,x ip 和 x ie 中的相应位呈现硬连接为零。

sGp4Dx.png

图 3.11 机器中断挂起寄存器

MTIP,STIP,UTIP 位对应于机器级,管理员级和用户级的定时器中断。MTIP 位是只读的,可通过写入内存映射的机器模式定时器比较寄存器来清除。UTIP 和 STIP 位可以由 M-mode 软件写入,以将计时器中断传递到较低的特权级别。 用户和管理员层软件可以分别通过调用 AEE 和 SEE 来清除 UTIP 和 STIP 位。

sG9jW4.png

图 3.12 机器中断使能寄存器

有一个单独的定时器中断使能位,分别称为 MTIE,STIE 和 UTIE,分别用于 M 模式,S 模式和 U 模式定时器中断使能。

每个较低的权限级别都有一个单独的软件挂起中断位( SSIP、USIP ), CSR 访问本地 hart 上运行的代码可以在相关的权限级别或任何更高的权限级别上读写该位。机器级别的 MSIP 位是通过访问内存映射的控制寄存器来写入的,远程 harts 使用这些寄存器来提供机器模式的处理器间中断。较低特权级别的处理器间中断是通过特定于实现的机制来实现的,例如,通过对 AEE 或 SEE 的调用,这可能最终导致对接收方 hart 的机器模式写操作是 MSIP 位。 hart 可以使用相同的内存映射控制寄存器写入自己的 MSIP 位。

mie CSR 中的 MSIE,SSIE 和 USIE 字段分别启用M模式软件中断,S 模式软件中断和 U 模式软件中断。


: 当以适当的模式运行时,我们仅允许 hart 直接写入自己的 SSIP 或 USIP 位,因为其他 hart 可能会被虚拟化,并可能被更高的特权级别调度。因此,我们依靠对 AEE 和 SEE 的调用来提供处理器间中断。机器模式的 hart 不是虚拟化的,可以通过设置它们的 MSIP 位直接中断其他 hart,通常根据平台规范使用未缓存的 I/O 写入内存映射控制寄存器。

mip 中的 MEIP 字段是一个只读位,指示机器模式外部中断正在处理中。 MEIP 由特定于平台的中断控制器设置和清除。 设置时,mie 中的 MEIE 字段启用机器外部中断。

mip 中的 SEIP 字段包含单个读写位。 SEIP 可由 M 模式软件编写,以指示 S 模式外部中断正在处理。 此外,平台级别的中断控制器可能会生成主管级别的外部中断。 软件可写位的逻辑或与来自外部中断控制器的信号用于生成对管理程序的外部中断。 当使用 CSRRW,CSRRS 或 CSRRC 指令读取 SEIP 位时,在第一个目标寄存器中返回的值包含软件可写位的逻辑或,以及来自中断控制器的中断信号。 但是,在 CSRRS 或 CSRRC 指令的读-修改-写序列中使用的值只是软件可写 SEIP 位,而忽略了来自外部中断控制器的中断值。

3.1.10 机器时间寄存器:(mtime 和 mtimecmp)

3.1.11 硬件性能监控器

3.1.12 计数器使能寄存器:([m|s]counteren)

3.1.13 机器计数器禁止 CSR 寄存器:(mcountinhibit)

3.1.14 机器暂存寄存器:(mscratch)

3.1.15 机器异常程序计数器:(mepc) ——指向发生异常PC地址

3.1.16 机器异常源寄存器:(mcause)——(异常源 or 中断号 or 异常种类?)

3.1.17 机器异常值寄存器:(mtval)

3.2 机器模式(M-mode)特权指令

3.2.1 环境调用和断点:(ECALL 和 EBREAK)

3.2.2 异常返回指令(Trap-return)

3.2.3 等待中断指令:(WFI)

3.3 复位(Reset)

3.4 不可屏蔽中断(NMI)

3.5 物理内存特性(PMA)

3.5.1 主内存对 I/O 设备和空白区域

3.5.2 PMAs 支持的访问类型

3.5.3 PMAs 的原子操作

3.5.4 PMAs 内存排序操作

3.5.5 PMAs 的一致性和可缓存性

3.5.6 PMAs 幂等性

3.6 物理内存保护(PMP)

为了支持安全处理和遏制故障,最好是限制在 hart 上运行的软件所能访问的物理地址。一个可选的物理内存保护(PMP)单元提供每个 hart 的机器模式控制寄存器,允许为每个物理内存区域指定物理内存访问权限(读、写、执行)。PMP 值与第 3.5 节中描述的 PMA 检查并行检查。

PMP 访问控制设置的粒度是特定于平台的,平台内的粒度可能因物理内存区域而异,但标准 PMP 编码支持小到四个字节的区域。某些区域的权限可以是硬连接的。例如,某些区域可能仅在机器模式下可见,但在较低的权限层中不可见。


: 平台对物理内存保护的需求差异很大,一些平台可能提供其他 PMP 结构,以补充或替代本节中描述的方案。

当 hart 在 S 或 U 模式下运行时,PMP 检查适用于所有访问;当 mstatus 寄存器中设置 MPRV 位且 mstatus 寄存器中的 MPP 字段包含 S 或 U 时,PMP 检查适用于加载和存储。PMP 检查也适用于页表访问,以进行虚拟地址转换,有效特权模式为 S。可选地,PMP 检查可额外应用于 M 模式访问,在这种情况下,PMP 寄存器本身被锁定,因此即使是 M 模式软件也无法在没有系统重置的情况下更改它们。实际上,PMP 可以向 S 模式和 U 模式授予权限,默认情况下 S 模式和 U 模式没有权限,并且可以从 M 模式撤销权限,M 模式默认情况下具有完全权限。

PMP 冲突总是精确地捕获在处理器上。

3.6.1 CSRs 的物理内存保护寄存器(PMP CSR)

PMP 条目由一个 8 位配置寄存器和一个 MXLEN 位地址寄存器描述。某些 PMP 设置还使用与前面的 PMP 条目关联的地址寄存器。最多支持 16 个 PMP 条目。如果实施了任何 PMP 条目,则必须实施所有 PMP CSR,但所有 PMP CSR 字段均为 WARL,并且可能硬连线为零。PMP CSR 仅适用于 M 模式。

PMP 配置寄存器被密集地打包到 CSRs 中,以最小化上下文切换时间。对于 RV32,四个 CSRs pmpcfg0–pmpcfg3 为 16 个 PMP 条目保留配置 pmp0cfg–pmp15cfg,如图 3.24 所示。对于 RV64,pmpcfg0 和 pmpcfg2 保留 16 个 PMP 条目的配置,如图 3.25 所示;pmpcfg1 和 pmpcfg3 是非法的。


: RV64 系统使用 pmpcfg2 而不是 pmpcfg1 来保存 PMP 条目 8–15 的配置。这种设计降低了支持多个 MXLEN 值的成本,因为 RV32 和 RV64 的 PMP 条目 8–11 的配置都出现在 pmpcfg2[31:0] 中。

Ia85GV.png

IaGheH.png

PMP 地址寄存器是名为 pmpaddr0–pmpaddr15 的 CSR。每个 PMP 地址寄存器对 RV32 的 34 位物理地址的 33–2 位进行编码,如图 3.26 所示。对于 RV64,每个 PMP 地址寄存器对 56 位物理地址的位 55–2 进行编码,如图 3.27 所示。并非所有物理地址位都可以实现,因此 pmpaddr 寄存器是 WARL。


: 第 4.3 节中描述的基于 Sv32 页的虚拟内存方案支持 RV32 的 34 位物理地址,因此 PMP 方案必须支持比 RV32 的 XLEN 更宽的地址。第 4.4 节和第 4.5 节中描述的基于 Sv39 和 Sv48 页的虚拟内存方案支持 56 位物理地址空间,因此 RV64 PMP 地址寄存器施加相同的限制。

图 3.28 显示了 PMP 配置寄存器的布局。设置时,R、W 和 X 位分别表示 PMP 条目允许读取、写入和指令执行。当这些位之一清除时,相应的访问类型被拒绝。R=0 和 W=1 的组合留作将来使用。其余两个字段 A 和 L 将在以下部分中介绍。

IaNlcV.png

IaN0c6.png

试图从没有执行权限的 PMP 区域获取指令会引发获取访问异常。如果在没有读取权限的情况下尝试执行有效地址位于 PMP 区域内的 load 或 load 保留指令,则会引发加载访问异常。如果在没有写入权限的情况下,尝试执行有效地址位于 PMP 区域内的存储、存储条件(无论是否成功)或 AMO 指令,则会引发存储访问异常。

如果更改了 MXLEN,则 pmpxcfg 字段的内容将保留,但会出现在由 MXLEN 的新设置规定的 pmpcfgy CSR 中。例如,当 MXLEN 从 64 更改为 32 时,pmp4cfg 从 pmpcfg0[39:32] 移动到 pmpcfg1[7:0]。pmpaddr CSR 遵循第 2.4 节中描述的通常 CSR 宽度调制规则。

地址匹配

PMP 条目的配置寄存器中的 A 字段对关联 PMP 地址寄存器的地址匹配模式进行编码。该字段的编码如表 3.9 所示。当 A=0 时,此 PMP 条目被禁用,并且不匹配任何地址。支持另外两种地址匹配模式:自然对齐的二次幂区域(NAPOT),包括自然对齐的四字节区域(NA4)的特例;和任意范围的上边界(TOR)。这些模式支持四字节粒度。

IaNzuT.png

NAPOT 范围利用相关地址寄存器的低位对范围大小进行编码,如表 3.10 所示。

IaUIR1.png

如果选择 TOR,则相关地址寄存器构成地址范围的顶部,前面的 PMP 地址寄存器构成地址范围的底部。如果 PMP 条目 i 的 A 字段设置为 TOR,则该条目与任何地址 y 匹配,从而 pmpaddr i−1 ≤ y < pmpaddr i。如果 PMP 条目 0 的 A 字段设置为 TOR,则下限使用 0,因此它匹配任何地址 y < pmpaddr 0。

尽管 PMP 机制支持小到四个字节的区域,但平台可能会指定更粗糙的 PMP 区域。通常,PMP 粒度为 2G+2 字节,并且在所有 PMP 区域中必须相同。当 G≥1、NA4 模式不可选择。当 G≥2 且设置了pmpcfgi.A[1],即模式为 NAPOT,然后位 pmpaddr i[G-2:0] 读取为所有。当 G≥1 和 pmpcfg i.A[1] 清除,即模式为 OFF 或 TOR,则位pmpaddr i[G-1:0] 读取为全零。位 pmpaddr i[G-1:0] 不影响 TOR 地址匹配逻辑。虽然更改 pmpcfg i.A[1] 会影响从 pmpaddr i 读取的值,但不会影响存储在该寄存器中的基础值,特别是,当 pmpcfg i.A 从 NAPOT 更改为 TOR/OFF,然后再更改回 NAPOT 时,pmpaddr i[G-1] 保留其原始值。


: 软件可以通过将 0 写入 pmp0cfg ,然后将所有的写入 pmpaddr0,然后读回 pmpaddr0 来确定 PMP 粒度。如果 G 是最低有效位集的索引,则 PMP 粒度为 2G+2 字节。

如果当前 XLEN 大于 MXLEN,为了地址匹配,PMP 地址寄存器从 MXLEN 零扩展到 XLEN 位。

锁定和特权模式

L 位表示 PMP 条目已锁定,即忽略对配置寄存器和相关地址寄存器的写入。锁定的 PMP 条目只能在系统重置时解锁。如果 PMP 条目 i 被锁定,则将忽略对 pmpicfg 和 pmpaddri 的写入。此外,如果将 pmpicfg.A 设置为 TOR,则将忽略对 pmpaddri-1 的写入。

除了锁定 PMP 条目外,L 位还指示在 M 模式访问上是否强制执行 R/W/X 权限。当设置 L 位时,所有特权模式都强制执行这些权限。当 L 位清除时,任何与 PMP 条目匹配的 M 模式访问都将成功;R/W/X 权限仅适用于 S 和 U 模式。

优先级和匹配逻辑

PMP 条目按静态优先级排列。与访问的任何字节相匹配的编号最低的 PMP 条目确定访问是成功还是失败。匹配的 PMP 条目必须匹配访问的所有字节,否则访问失败,与 L、R、W 和 X 位无关。例如,如果将 PMP 条目配置为匹配四字节范围 0xC–0xF,则对范围 0x8–0xF 的 8 字节访问将失败,前提是 PMP 条目是匹配这些地址的最高优先级条目。

如果 PMP 条目与访问的所有字节匹配,则 L、R、W 和 X 位确定访问是否成功。如果L位清除且访问权限模式为 M,则访问成功。否则,如果设置了 L 位或访问的特权模式为 S 或 U,则仅当设置了与访问类型对应的 R、W 或 X 位时,访问才会成功。

如果没有与 M 模式访问匹配的 PMP 条目,则访问成功。如果没有 PMP 条目匹配 S 模式或 U 模式访问,但至少实现了一个 PMP 条目,则访问失败。

失败的访问将生成加载、存储或指令访问异常。请注意,一条指令可能会生成多个访问,这些访问可能不是相互原子的。如果一条指令生成的至少一次访问失败,则会生成访问异常,尽管该指令生成的其他访问可能会成功,并产生明显的副作用。值得注意的是,引用虚拟内存的指令被分解为多个访问。

在某些实现中,未对齐的加载、存储和指令获取也可能分解为多个访问,其中一些可能在访问异常发生之前成功。特别是,即使另一部分未通过 PMP 检查,通过 PMP 检查的未对齐存储的一部分也可能变得可见。对于比 XLEN 位宽的浮点存储(例如,RV32D 中的 FSD 指令),即使存储地址自然对齐,也可能表现出相同的行为。

3.6.2 物理内存保护和分页

物理内存保护机制旨在与第 4 章中描述的基于页面的虚拟内存系统组成。启用分页时,访问虚拟内存的指令可能导致多个物理内存访问,包括对页表的隐式引用。PMP 检查适用于所有这些访问。隐式页表访问的有效特权模式是 S。

使用虚拟内存的实现允许推测性地执行地址转换,并且比显式虚拟内存访问所需的时间更早。可以在地址转换和显式虚拟内存访问之间的任意点检查结果物理地址的 PMP 设置。因此,当修改 PMP 设置的方式影响保存页表的物理内存或页表指向的物理内存时,M 模式软件必须将 PMP 设置与虚拟内存系统同步。这是通过在写入 PMP CSR 后执行 rs1=x0 和 rs2=x0 的 SFENCE.VMA 指令来实现的。

如果未实现基于页的虚拟内存,或者禁用了基于页的虚拟内存,则内存访问会同步检查 PMP 设置,因此不需要 Fence。

赞赏一下吧~ 还可以关注公众号订阅最新内容啊

0%