RMM,即 Realm 管理监视器。管理 Realm 机密虚拟机,同时做为了机密虚拟机和虚拟机管理者之间沟通的桥梁。
RMM 代码获取方法:
mkdir cca-v4 cd cca-v4 repo init -u https://git.codelinaro.org/linaro/dcap/op-tee-4.2.0/manifest.git -b cca/v4 -m sbsa_cca.xml repo sync -j8 --no-clone-bundle
RMM 代码框架
在 cca-v4
的根目录下,可以看到 rmm
目录,为 RMM
项目的主目录。目录结构如下:
|- cmake
|- configs
|- docs
|- drivers
|- ext
|- lib
|- plat
|- runtime
|- toolchain
|- tools
lib
文件夹中有相关的库功能实现,例如 GIC
的实现。runtime
文件夹中就是 RMM
的运行时代码。我们再看看 runtime
文件目录:
|- core
|- include
|- rmi
|- rsi
|- tests
core
:一些……include
:相关头文件rmi
:rmi
接口相关代码的实现rsi
:rsi
接口相关代码的实现tests
:一些测试文件
我们重点关注 core
/ rmi
/ rsi
文件夹中的代码。
REC_ENTER
从非安全环境 (NS) 中进入 Realm,需要调用 RMI_REC_ENTER
。搜索 REC_ENTER
关键字,得到了以下内容:
第一条搜索内容就很有意义。我们在 core/handler.c
代码中找到了 smc_handler
结构体。该结构体定义了绝大多数 RMI
接口功能的处理函数。REC_ENTER
的处理函数是 smc_rec_enter
。
在 rmi/run.c
文件中,我们找到了 smc_rec_enter
的原型。该函数体现出了 REC
进入和退出的一个完整周期:
- 清空
RecExit
结构体。 - 获取
RecEnter
中的信息。 - 检查 Realm 的状态。
- 检查 GIC 的状态,并将 GIC 的状态拷贝到
RecEnter
中。 - 检查之前的处理异常时模拟的结果。
- 调用
rec_run_loop
函数。 - 此时 REC 已经退出,将 GIC 信息拷贝到
RecExit
中。
rec_run_loop
是一个关键点。在此之前,是在检查进入 REC
前的相关条件是否符合要求;在此之后,就是保存 GIC 的相关信息。我们再 core/run.c
文件中找到了 rec_run_loop
的原型。该函数涉及到 REC 上下文相关的处理:
-
保存 NS 的上下文。
-
恢复 Realm 的上下文。
-
进行一些 attest 相关操作。
-
进入一个循环体。
- 检查时钟状态。如果计时器时间达到,就直接退出循环体。
- 激活 REC 相关事件。
- 保存 RMM 的
cptr_el2
寄存器,恢复 Realm 的cptr_el2
寄存器。 - 恢复 Realm 的密钥。
- 调用
run_realm
,参数是 REC 的通用寄存器堆。 - 保存 Realm 的密钥。
- 恢复 RMM 的密钥。
- 保存 Realm 的
cptr_el2
寄存器,恢复 RMM 的cptr_el2
寄存器。 - 检查 Realm 退出的原因,决定是否继续执行循环体。
-
反馈 Realm 的时钟状态。
-
保存 Realm 的上下文。
-
恢复 NS 的上下文。
几个比较重要的点,时钟的检查,Realm 的上下文的保存与恢复,run_realm
函数以及检查 Realm 退出原因。
Realm 的上下文
RMM 分别调用 save_realm_state
以及 restore_realm_state
函数保存和恢复 Realm 的上下文。两个函数均在 core/run.c
文件中。我们以 save_realm_state
为例子,会涉及到以下过程:
- 调用
save_sysreg_state
保存系统寄存器至 REC 中。 - 将
elr_el2
的值保存到 REC 的 PC 中。 - 将
spsr_el2
的值保存到 REC 的 pstate 中。 - 保存 GIC 信息到 REC 中。
- 对 PMU 一些内容进行处理。
此处比较关键的内容就是 save_sysreg_state
函数。同样也在 core/run.c
文件中,找到了这个函数。函数内容基本都是赋值语句,将读取到的 sysreg 的值存储到相应的 REC 寄存器中。这些寄存器就有我们比较关注的寄存器,例如 ttbr
,vbar
等。这个函数可以证明,整个 REC 就一套 sysreg。
对于时钟和 Realm 退出检查的内容,会在后面的博客讲述。