虚拟化(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 文章被收录于专栏

qemu+kernel

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务