基于opensbi为quard_star创建domain
1. Opensbi之domain机制
OpenSBI(Open Source Supervisor Binary Interface)的 domain 机制是一种用于管理和隔离不同软件实体(例如操作系统、虚拟机)的机制。它提供了一种在系统中划分资源和权限的方法,以确保软件实体之间的相互隔离和安全性。
在 OpenSBI 中,domain 是一种逻辑上的实体,它代表了一个软件实体,可以是一个操作系统、一个虚拟机或其他一些执行环境。每个 domain 都有自己的一组资源和权限,包括处理器(Hart)、内存、设备和中断等。domain 之间是相互隔离的,它们不能直接访问或干扰彼此的资源。
OpenSBI 的 domain 机制通过以下方式实现:
- Domain ID:每个 domain 都有一个唯一的标识符,称为 Domain ID。它用于区分不同的 domain。
- Hart Mask:OpenSBI 使用 Hart Mask 来表示哪些处理器属于特定的 domain。Hart Mask 是一个位图,每个位代表一个处理器,可以将相应的位设置为 1 表示该处理器属于某个 domain。
- SBI 接口:OpenSBI 提供了一组 SBI(Supervisor Binary Interface)接口,用于 domain 之间的通信和资源管理。这些接口包括中断处理、内存管理、设备访问等,可以由 domain 使用来请求和管理资源。
通过 domain 机制,OpenSBI 可以实现不同软件实体的隔离和安全性。每个 domain 只能访问自己被授权的资源,并且不能越权访问其他 domain 的资源。这样可以确保系统的稳定性和安全性,并支持多个软件实体在同一硬件平台上共存和运行。
在opensbi的doc目录下的domain_support.md
文档介绍了如何使用设备树来基于opensbi来划分domain,在文档中提到默认情况下,所有的 HART 都被分配给 ROOT domain
。OpenSBI 平台支持可以通过平台特定的回调函数提供 HART 到 domain 实例的分配。同时也可以使用设备树来定义domain
,文档中举了一个设备树的例子如下:
chosen { |
在这份设备树中需要定义如下三个节点:
Domain Configuration Node
这里就是要定义compatible = “opensbi,domain,config”;
Domain Memory Region Node
这里是定义和内存相关的节点,域内存区域设备树节点的属性如下:
- compatible(必选)- 域内存区域的兼容字符串。该设备树属性的值应为 “opensbi,domain,memregion”。
- base(必选)- 域内存区域的基地址。该设备树属性应为2^order对齐的64位地址(即两个设备树单元)。
- order(必选)- 域内存区域的阶数。该设备树属性应为32位值(即一个设备树单元),取值范围为 3 <= order <= __riscv_xlen。
- mmio(可选)- 一个布尔标志,表示域内存区域是否为内存映射I/O(MMIO)区域。
- devices(可选)- 设备列表,其中包含属于此域内存区域的设备设备树节点的句柄。
Domain Instance Node
compatible
(必选)-:域实例的兼容字符串。该设备树属性的值应为 “opensbi,domain,instance”。possible-harts
(可选)- 域实例的CPU设备树节点句柄列表。该列表表示域实例的可能HART集合。regions
(可选)- 域实例的域内存区域设备树节点句柄和访问权限列表。每个列表条目都是一个设备树节点句柄和访问权限的对。访问权限以32位掩码表示,具有可读(BIT[0])、可写(BIT[1])、可执行(BIT[2])和M模式(BIT[3])的位。boot-hart
(可选)- 引导域实例的HART的设备树节点句柄。如果将冷启动HART分配给域实例,则忽略此设备树属性,并假定冷启动HART是域实例的引导HART。next-arg1
(可选)- 域实例的64位下一个引导阶段arg1。如果此设备树属性不可用且未将冷启动HART分配给域实例,则使用默认值0x0。如果此设备树属性不可用且将冷启动HART分配给域实例,则使用冷启动HART的下一个引导阶段arg1作为默认值。next-addr
(可选)- 域实例的64位下一个引导阶段地址。如果此设备树属性不可用且未将冷启动HART分配给域实例,则使用默认值0x0。如果此设备树属性不可用且将冷启动HART分配给域实例,则使用冷启动HART的下一个引导阶段地址作为默认值。next-mode
(可选)- 域实例的32位下一个引导阶段模式。该设备树属性的可能值为:0x1(s模式)和0x0(u模式)。如果此设备树属性不可用且未将冷启动HART分配给域实例,则使用默认值0x1。如果此设备树属性不可用且将冷启动HART分配给域实例,则使用冷启动HART的下一个引导阶段模式作为默认值。system-reset-allowed
(可选)- 一个布尔标志,表示是否允许域实例进行系统复位。
2. 为quard_star划分domain
2.1 修改quard_star设备树
chosen { |
可以看见为quard_star
划分了两个domain
,一个为trusted-domain
,使用了cpu7,下级程序的起始地址为0xb0000000
,模式为U
模式,这个domain
可以用来运行类似freertos
的实时操作系统;一个domain为untrusted-domain
,这个domain
使用了cpu0~cpu6
,用于运行linux
系统,下级程序的起始地址为0x82000000
2.2 编写domain测试代码
在quard_star目录下新建一个trusted_domain
的文件夹,在此文件夹下新建link.lds
和startup.s
两个文件。
timer@DESKTOP-JI9EVEH:~/quard-star/trusted_domain$ ls |
link.lds
如下,这里需要注意的是运行起始地址和设备树中的保持一致,即:0xb0000000
OUTPUT_ARCH( "riscv" ) |
startup.s
如下:
.section .text |
这里需要注意的是串口的输出地址为0x10002000
,即UART2
的地址,和设备树中tuart
的地址保持一致
这里需要生成trusted_domain
的固件并将其加载到0xb0000000
处执行,所以先修改build.sh
先编译生成trusted_domain.bin
编译trusted_domain |
然后合成fw.bin
,新增一行如下:
将trusted_domain.bin
写入到了地址偏移为:0x400000
的地方,下一步就要将固件加载到0xb0000000
,因此还需要修改一下boot下的start.s
,修改如下:
//load trusted_fw.bin |
2.3 测试
run.sh
修改:
SHELL_FOLDER=$(cd "$(dirname "$0")";pwd) |
用DEFAULT_VC
来指定了qemu显示的分辨率,这个分辨率我随便设置的,还需要新增三个-serial
选项让qemu输出三个串口终端,运行结果如下:
所以现在的内存布局如下: