虚拟化(8)remoteproc(6)secure PIL on KVM
双标题的第一次,因为确实是两个知识点混到了一起
1.patch分析
1.1
https://lore.kernel.org/lkml/20241004212359.2263502-2-quic_mojha@quicinc.com/
为remoteproc加两个新属性:
1)iommu属性:remoteproc使用的输入输出管理单元
2)qcom,devmem:为非QHEE(高通专属的hypervisor)的系统涉及,比如KVM
背景说明:QHEE中,IOMMU由QHEE 管理/非QHEE中,IOMMU由KVM配置/remoteproc在启动前需要预先配置好内存 carveout 区域和设备资源权限/qcom,devmem 提供了这些设备内存区域的静态信息,供 boot firmware 使用
<device address> <physical address> <size> <iommu attributes>
1.2 qcom_map_unmap_carveout (carveout映射)
https://lore.kernel.org/lkml/20241004212359.2263502-3-quic_mojha@quicinc.com/
先区分一些概念
Carveout 是指在物理内存中预留的一块连续区域,专门供某些设备或处理器(如 ADSP、CDSP 等远程处理器)使用。
https://elixir.bootlin.com/linux/v6.17-rc1/source/arch/arm64/boot/dts/qcom/qcs615.dtsi#L3155
IOVA(Input/Output Virtual Address) 是设备访问内存时使用的虚拟地址,它是通过 IOMMU 映射到实际物理地址的。
/1.获取iova / 2.使用sid扩展iova / 3.调用iommu_map进行调用
远程处理器(如 ADSP)
↓
使用 IOVA
↓
IOMMU 映射
↓
转换为物理地址(将mem_phys和iova绑定在一起了,后续可以通过iova访问mem_phys)
↓
访问 carveout 区域(后续通过其他函数访问carveout)
1.3 qcom_map_devmem / qcom_unmap_devmem (devmem映射)
https://lore.kernel.org/lkml/20241004212359.2263502-4-quic_mojha@quicinc.com/
这里先介绍一下两个结构体,
qcom_devmem_info 就是把设备树里面的四个参数改成一个结构体,然后再混成一个数组
struct qcom_devmem_info {
u64 da; // 设备地址(IOVA)
u64 pa; // 物理地址
u32 len; // 映射长度
u32 flags; // IOMMU 权限标志(如 IOMMU_READ | IOMMU_WRITE)
};
struct qcom_devmem_table {
int num_entries;
struct qcom_devmem_info entries[0]; // 可变长度数组
};
设备树中的 qcom,devmem 属性
↓
解析为 qcom_devmem_table
↓
调用 qcom_map_devmem()
↓
每个条目:
IOVA = da (+ SID 高位)
PA = pa
LEN = len
FLAGS = flags
↓
iommu_map(domain, IOVA, PA, LEN, FLAGS)
↓
远程处理器可通过 IOVA 访问 PA
1.4 adsp_devmem_init (devmem提取)
https://lore.kernel.org/lkml/20241004212359.2263502-5-quic_mojha@quicinc.com/
设备树中定义:
qcom,devmem = <IOVA PA SIZE FLAGS>, <...>, ...
↓
驱动中调用:
adsp_devmem_init()
↓
构造:
struct qcom_devmem_table {
struct qcom_devmem_info entries[];
}
↓
调用:
qcom_map_devmem(rproc, devmem_table, use_sid, sid)
↓
完成 IOMMU 映射
1.5 https://lore.kernel.org/lkml/202410060641.ZedzhoKd-lkp@intel.com/
adsp_probe()
└── 设置 shm_bridge_needed = true
adsp_start()
├── 创建 SHM bridge(carveout)这个是来自于adsp_create_shmbridge函数,这个在adsp_start会直接调用
├── 分配 SHM bridge(metadata)这个是来自于qcom_scm_pas_init_image->qcom_mdt_pas_init->adsp_start
├── 调用 PAS SMC 接口
└── 清理 SHM bridge(carveout)
adsp_stop()
└── 清理 SHM bridge(carveout)
https://elixir.bootlin.com/linux/v6.6/source/drivers/remoteproc/qcom_q6v5_pas.c#L288
SHM bridge(Shared Memory Bridge)
是一种机制,用于将一块物理内存区域注册给 TrustZone(TZ),使其成为受保护的共享内存。它的主要作用是:让 TrustZone 能够安全访问该内存区域。
PAS(Peripheral Authentication Service)通过 SMC 调用将 metadata 和 curveout信息传给 TrustZone。
TrustZone 会验证这些信息,确保远程处理器启动的是合法镜像,并使用合法内存。
carveout 是remoteproc运行时使用的内存,供远程处理器运行时使用(代码、堆栈、数据等)
metadata 是启动时传递给 TrustZone 的参数信息,告诉 TrustZone 如何加载和认证远程处理器镜像
1.6 probe/start
probe中提取qcom,devmem
start中映射carveout 和 qcom, devmem
https://lore.kernel.org/lkml/20241004212359.2263502-7-quic_mojha@quicinc.com/
2.总结
✅ 启动流程 adsp_start() 调用 qcom_map_unmap_carveout() → 映射 carveout 调用 qcom_map_devmem() → 映射 devmem 调用 adsp_create_shmbridge() → 创建 SHM bridge 调用 qcom_scm_pas_auth_and_reset() → 启动 remoteproc 调用 adsp_delete_shmbridge() → 清理 SHM bridge ✅ 停止流程 adsp_stop() 调用 qcom_unmap_devmem() → 解除 devmem 映射 调用 qcom_map_unmap_carveout() → 解除 carveout 映射 ✅ 初始化流程 adsp_probe() 检查 iommus 属性 → 设置 has_iommu 和 sid 调用 adsp_devmem_init() → 解析 qcom,devmem 属性 设置 shm_bridge_needed = true#嵌入式##嵌入式软开##嵌入式笔面经分享#
qemu+kernel

美团公司福利 3017人发布