LINUX ASID/VMID 编程接口

提问

一般来说,我们使用ASID来标识进程的ID, 使用VMID来标识虚拟机ID,那么具体CPU/加速器/PCIe发起的一次操作,如何从硬件角度识别,并透传到后续模块呢?即如何标识不同的流?软硬件的编程接口是如何配合的?

CPU视角

ASID

首先,站在CPU视角,CPU通过TTBR0/TTBR1来控制不同EL等级下的内存域。当CPU下发操作的时候,通过访问地址的VA,确定当前应该使用TTBR0还是TTBR1:

简而言之,换做Linux,TTBR0管用户态,TTBR1管内核态(包括EL2),无论哪个level的TTBR寄存器,基本的组成形式如下:

其中寄存器域63-48合计16个bit标识ASID(这里存在一个卷绕的问题,内核巧妙的进行了处理)。

通过TTBR寄存器,可以识别不同的进程使用的页表,也就是说页表信息跟随进程绑定,我们在内核的task_struct里面可以看到这一点:

struct task_struct {
	...
  struct mm_struct                *mm;
	struct mm_struct                *active_mm;
	...
}

在进程切换的时候,我们可以看到ASID的切换:

因此ASID通过页表,TTBR,task_struct全部串联起来。

VMID

如果在虚拟化场景,多个虚拟机之间的ASID可能存在一样的情况,这个时候,系统主要通过VMID区分两者。

在ARM SPEC中,VMID主要设置于:

那么多个虚拟机之间的流怎么区分呢?

虚拟化场景下,CPU发出的请求是需要通过VA->IPA->PA的过程,在VA->IPA 的时候不需要关心VMID,因为此时在虚拟机内部,当IPA到PA的时候,就需要通过VTTBR获取VMID,从而标识这条流的ASID以及VMID。

因此VMID只有在虚拟机切换的时候会需要进行装载,因此在内核代码中,我们可以看到:

__kvm_vcpu_run->__kvm_vcpu_run_vhe->__load_guest_stage2

因此,Linux将ASID跟task_struct进程绑定,VMID跟kvm_vcpu 虚拟机绑定,完成了CPU 侧的stream id的编程。

【文章福利】小编推荐自己的Linux内核技术交流群: 【977878001】整理一些个人觉得比较好得学习书籍、视频资料;进群私聊群管理领取 内核资料包(含视频教程、电子书、实战项目及代码)

内核资料直通车:Linux内核源码技术学习路线+视频教程代码资料

学习直通车:Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈

IO视角

IO视角其实与CPU非常一致,可以将PCIe设备当成一个CPU来处理,传统的DMA编程模型下,如果CPU填充PCIe的是PA,此时SMMU要么是关闭,要么是直接透传。

在关闭的情况下,设备发出的请求是没有携带标识的(除非在出口处做了处理),在透传的情况下,相当于进行了stage1的转换。

在SMMU的spec中,使用了类似ASID以及VMID的标识来区分不同等级的流,即STREAMID,SUBSTREAMID(PCIe体系中,命名为RequesterID和PASID)。

当只进行了一级的转换,只需要给转换的流携带STREAMID即可,而SUBSTREAMID在stage2的时候使用,目前看到的场景,仅在虚拟化中使用SVA可能会使用到。

pasid同样在结构体mm_struct中定义:

那么在虚拟机中的设备如何绑定某个进程的呢?(因为SVM跟进程相关,不同进程使用的地址空间不一样)

首先,进程 DMA前会通过bind,将进程地址空间跟设备绑定起来:

其次,会通sva_bind分配一个pasid给对应的进程:

注意,iommu_bond这个结构并不对外, 用iommu_sva_bind_device/unbind接口时,函数参数都是mm_struct(进程地址空间)。使用SVA的设备可以把一个设备的一些资源和一个进程地址空间绑定,这种绑定关系是灵活的,比如可以一个设备上的不同资源和不用的进程地址空间绑定(bond 1, bond 2),还可以同一个设备上的资源都绑定在一个进程的地址空间上(bond 3,bond 4)。从进程地址空间的角度看,一个进程地址空间可能和多个设备资源绑定。iommu_bond指的就是一个绑定,io_mm指的是绑定了外设资源的一个进程地址空间。io_pgtables是指内核dma接口申请内存的页表。

___________________________
             |  IOMMU domain A           |
             |  ________________         |
             | |  IOMMU group   |        +------- io_pgtables
             | |                |        |
             | |   dev 00:00.0 ----+------- bond 1 --- io_mm X
             | |________________|   \    |
             |                       '----- bond 2 ---.
             |___________________________|             \
              ___________________________               \
             |  IOMMU domain B           |             io_mm Y
             |  ________________         |             / /
             | |  IOMMU group   |        |            / /
             | |                |        |           / /
             | |   dev 00:01.0 ------------ bond 3 -' /
             | |   dev 00:01.1 ------------ bond 4 --'
             | |________________|        |
             |                           +------- io_pgtables
             |___________________________|

                                PASID tables
                                 of domain A
                              .->+--------+
                             / 0 |        |-------> io_pgtable
                            /    +--------+
            Device tables  /   1 |        |-------> pgd X
              +--------+  /      +--------+
      00:00.0 |      A |-'     2 |        |--.
              +--------+         +--------+   \
              :        :       3 |        |    \
              +--------+         +--------+     --> pgd Y
      00:01.0 |      B |--.                    /
              +--------+   \                  |
      00:01.1 |      B |----+   PASID tables  |
              +--------+     \   of domain B  |
                              '->+--------+   |
                               0 |        |-- | --> io_pgtable
                                 +--------+   |
                               1 |        |   |
                                 +--------+   |
                               2 |        |---'
                                 +--------+
                               3 |        |
                                 +--------+

需要使用SVA特性的社区驱动在调用上面的接口后,可以建立起静态的数据结构。

至此,所有关系都已经建立完成。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值