OPTEE虚拟化

前言

本文主要介绍OPTEE的虚拟化(Virtualization)技术,翻译自官方文档:Virtualization — OP-TEE documentation documentation (optee.readthedocs.io)


一、配置

虚拟化支持通过CFG_VIRTUALIZATION配置选项启用。启用此选项后,如果没有兼容的虚拟机管理程序,OP-TEE 将无法工作。这是因为虚拟机监控程序应先发送具有虚拟机 ID OPTEE_SMC_VM_CREATED SMC,然后才能从客户端接收任何标准 SMC。

CFG_VIRT_GUEST_COUNT控制支持的最大 VM 数。由于 OP-TEE 的可用内存大小有限,因此增加此计数将减少一个 VM 可用的内存量。由于我们希望 VM 是独立的,因此 OP-TEE 将可用内存分成相等的部分分配给每个 VM,因此一个 VM 不会消耗所有内存并导致其他 VM 出现 DoS。

二、虚拟机管理程序的要求

如前所述,虚拟机管理程序应该了解从虚拟来宾到 OP-TEE 的 OP-TEE 和 SMC。这是兼容虚拟机管理程序应执行的操作列表:

1、创建新的支持 OP-TEE 的虚拟机时,虚拟机监控程序应通过 SMC OPTEE_SMC_VM_CREATED通知 OP-TEE。a1 参数应包含虚拟机 ID。ID 0 定义为 HYP_CLNT_ID 并为虚拟机管理程序本身保留。

2、销毁支持 OP-TEE 的虚拟机时,虚拟机监控程序应停止所有 VCPU(这将确保 OP-TEE 没有该虚拟机的活动线程),并使用与 OPTEE_SMC_VM_CREATED 相同的参数发送 SMC OPTEE_SMC_VM_DESTROYED。

3、任何 SMC 到 OP-TEE 都应在 a7 参数中具有虚拟机 ID。如果调用源自虚拟机监控程序或在调用中传递OPTEE_SMC_VM_CREATED VM ID,则HYP_CLNT_ID此操作。

4、虚拟机监控程序应为所有 SMC 执行 IPA<->PA 地址转换。这包括 a1-a6 寄存器和内存中命令缓冲区中的参数。

5、虚拟机监控程序应固定虚拟机与 OP-TEE 共享的内存页。这意味着,虚拟机监控程序应确保固定页面将驻留在原始 PA 中,因为它与 OP-TEE 共享。此外,它仍应属于共享它的 VM。例如,虚拟机监控程序不应交换此页面、将所有权转移到另一个 VM、将其与 VM 地址空间取消映射等。

6、当然,虚拟机管理程序应该正确处理 OP-TEE 协议,因此对于任何 VM,它都应该看起来像是直接使用 OP-TEE。

三、局限性

虚拟化支持处于实验状态,它有一些局限性,用户应该注意。

1、平台支持

仅支持 Armv8 架构。没有硬性限制,但目前特定于 Armv7 的代码(如 MMU 或线程操作)对虚拟化一无所知。目前只有一个平台经过测试,那就是QEMU-V8(又名qemu,模拟Arm Versatile Express和Armv8架构)。对Rcar Gen3的支持应该很快就会添加。

2、静态虚拟机客户机计数和内存分配

目前,用户应配置最大来宾数。OP-TEE 会将内存拆分为相等的块,因此每个 VM 将具有相同的内存量。例如,如果 TA 有 6MB,则可以将 CFG_VIRT_GUEST_COUNT 设置为 3,并且每个 VM 最多可以使用 2MB,即使没有其他 VM 正在运行也是如此。当您知道 VM 的确切数量和角色时,这对于嵌入式设置是可以的,但对于服务器应用程序来说可能不方便。此外,无法为给定 VM 配置可用的内存量。每个 VM 实例将具有完全相同的内存量。

3、共享硬件资源和 PTA

目前,只有可由多个虚拟机同时使用的硬件是串行控制台,用于日志记录。硬件加密加速器、安全存储设备(例如直接从 OP-TEE 访问的外部闪存)等设备目前不受支持。驱动程序应先具有虚拟化感知能力,然后才能与虚拟化扩展一起使用。

每个 VM 都有自己的 PTA 状态,这在大多数情况下是一件好事。但是,如果希望 PTA 具有在 VM 之间共享的某种全局状态,则需要相应地编写 PTA。

4、与“正常”模式不兼容

使用 CFG_VIRTUALIZATION=y 构建的 OP-TEE 如果没有虚拟机管理程序将无法工作,因为在执行任何标准 SMC 之前,必须调用OPTEE_SMC_VM_CREATED。如果要频繁地在虚拟化和非虚拟化环境之间切换,这可能会很不方便。另一方面,这在生产环境中没什么大不了的。可以为此采取简单的解决方法:如果 OP-TEE 在OPTEE_SMC_VM_CREATED之前收到标准 SMC,它会隐式创建 VM 上下文并将其用于所有后续调用。

5、实现细节

OP-TEE作为一个整体可以分为两个实体。让我们称它们为“纽带(nexus)”和 TEE。Nexus是OP-TEE的核心部分,负责低级事务:SMC处理,内存管理,线程创建等。TEE 是完成实际工作的部分:处理请求、加载 TA、执行它们等。因此,很自然地有一个结点实例和多个 TEE 实例,每个注册的 VM 一个 TEE 实例。这可以显式或隐式完成。

显式方法是在某种结构中移动 TEE 状态,并使所有代码访问此结构的字段。类似于 linux 内核中的结构task_struct和当前。然后,可以轻松地为每个 VM 实例分配此类结构。但这种方法基本上需要重写所有OP-TEE代码。

隐式方法是为 TEE/VM 实例存储内存部分。所以内存布局可以看起来像这样:

+-------------------------------------------------+
|           Nexus: .nex_bss, .nex_data, ...       |
+-------------------------------------------------+
|                   TEE states                    |
|                                                 |
| VM1 TEE state | VM 2 TEE state | VM 3 TEE state |
| .bss, .data   | .bss, .data    | .bss, .data,   |
+-------------------------------------------------+

此方法不需要更改 TEE 代码,并且需要对结点代码进行一些更改。因此,Nexus状态位于单独的部分(.nex_data,.nex_bss,.nex_nozi,.nex_heap和其他)中,并且始终被映射。

TEE 状态驻留在标准部分(如 .data、.bss、.heap 等)。每个注册的虚拟机都有一组单独的此部分,Nexus仅在收到来自相应虚拟机的调用时映射它们。

由于 Nexus 和 TEE 具有单独的堆,bget 分配器被扩展为处理多个“上下文”。malloc(), free() 与朋友在一个上下文中工作。添加了nex_malloc()(和其他nex_函数)。它们使用不同的上下文,因此现在Nexus可以使用单独的堆,该堆始终映射到OP-TEE地址空间。禁用虚拟化支持时,所有这些nex_函数都定义为指向标准的 malloc() 对应项。

为了在运行时更改内存映射,我们在 MMU 代码中添加了一个名为“partition”的新实体,该实体由结构mmu_partition定义。它保存有关所有页表的信息,因此整个MMU映射可以通过一次写入TTBR寄存器进行切换。

存在默认分区,当没有活动 VM 上下文时,它会保持 MMU 状态,因此不会映射 TEE 状态。当 OP-TEE 收到OPTEE_SMC_VM_CREATED调用时,它会将默认分区复制到新分区中,然后使用 TEE 数据映射部分。这是通过 virtualization.c 中的 prepare_memory_map() 函数完成的。

当 OP-TEE 收到 STD 调用时,它会检查提供的虚拟机 ID 是否有效,然后激活相应的 MMU 分区,以便 TEE 代码可以访问自己的数据。这基本上就是虚拟化支持的工作方式。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

趣多多代言人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值