IOMMU/SMMUV3代码分析(1)SMMU设备的分配

        对于SMMUV3驱动,它以platform device驱动加载,而SMMU设备为platform device,根据platform设备驱动模型,当两者匹配时,会触发SMMUV3驱动的probe函数。

        本节将介绍SMMU如何作为platform device被分配以及识别。

1. IORT中SMMUV3结点

        SMMU设备在IORT表中被定义,它定义了SMMU设备的资源、特性以及SPI中断等。IORT描述了用ACPI描述IO设备拓扑,其中SMMUV3结点定义如下所示:

        

        上面表示SMMUV3结点格式,定义了NODE长度,ID映射的数目等。SMMUV3相关的内容如下所示:

 

 其中:(1)Base Address定义了SMMU在基地址;

(2)SMMU相关的标志,定义如下:COHACC Override可以覆盖掉SMMU_IDR0.COHACC;HTTU Override可以覆盖掉SMMU_IDR0.HTTU;Proximity Domain Valid设置为1时Proximity Domain有效。

(3)VATOS address: VATOS基地址,若为0表示不支持;

(4)Model:目前定义的值为各厂商workaround用,保留部分作将来使用;

(5)Event/PRI/Gerr/Sync:分别为支持SPI时的GSIV中断号;

(6)Proximity Domain: SMMUV3设备所在的NUMA NODE;

(7)DeviceID Mapping index: 指向ITS group;

2. SMMU设备的分配和识别

        对于SMMUV3设备,在ACPI初始化时会遍历IORT结点,并将SMMUV3结点生成platform设备,对该platform设备作相关设置,并最终将其加入到系统中。

2.1 函数acpi_iort_init()

        函数acpi_iort_init()获取IORT表,并根据IORT表初始化SMMUV3所对应的platform device。

2.2 函数iort_init_platform_devices()

         其中函数iort_init_platform_devices()执行如下:

  1. 对每个IORT结点进行处理,若IORT结点为RC结点且父结点为SMMUV3时,使能AC
  2. 获取dev cfg,当前仅SMMUV3/SMMU/PMCG结点存在设备配置,分别定义在iort_arm_smmu_v3_cfg/iort_arm_smmu_cfg/iort_arm_pmcg_v3_cfg
  3. 分配fwnode_handle,并设置;
  4. 分配platform device,作设置,并将加入到系统中;

2.3 函数iort_add_platform_device()

        对于函数iort_add_platform_device(),作如下详细分析:

        对于SMMUV3结点,其定义iommu_arm_smmu_v3_cfg,其中:

(1)dev_set_proximity = arm_smmu_v3_set_proximity

        根据IORT表SMMUV3结点中proximity domain域设置设备所对应的node;

(2)dev_count_resources = arm_smmu_v3_count_resources

        根据IORT表SMMUV3结点中的event_gsiv/pri_gsiv/gerr_gsiv/sync_gsiv域(SPI中断)确定资源的数目。

(3)dev_init_resources = arm_smmu_v3_init_resources

        添加MEMORY资源,同时根据定义SPI中断情况申请中断。

(4)dev_dma_configure = arm_smmu_v3_dma_configure

        获取DMA范围和大小。

        对于该函数用的其他的函数调用,为对platform device的操作:

(1)platform_device_alloc()分配platform device;

(2)Platform_device_add_resources()为platform device增加资源(内存,以及可能SPI中断);

(3)Platform_device_add_data()为platform device添加数据;

(4)Platform_device_add()将platform device添加到系统中;

至此SMMU结点作为platform device被分配和识别,并添加到系统中。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个使用SMMU的例子: ``` #include <linux/iommu.h> static struct iommu_domain *smmu_domain; static int smmu_probe(struct platform_device *pdev) { /* 初始化SMMU */ smmu_domain = iommu_domain_alloc(&platform_bus_type); if (!smmu_domain) { dev_err(&pdev->dev, "Failed to allocate SMMU domain\n"); return -ENOMEM; } /* 添加设备SMMU域中 */ if (iommu_attach_device(smmu_domain, &pdev->dev)) { dev_err(&pdev->dev, "Failed to attach device to SMMU domain\n"); iommu_domain_free(smmu_domain); return -ENODEV; } return 0; } static int smmu_remove(struct platform_device *pdev) { /* 从SMMU域中移除设备 */ iommu_detach_device(smmu_domain, &pdev->dev); /* 释放SMMU域 */ iommu_domain_free(smmu_domain); return 0; } static const struct of_device_id smmu_of_match[] = { { .compatible = "arm,mmu-500" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, smmu_of_match); static struct platform_driver smmu_driver = { .probe = smmu_probe, .remove = smmu_remove, .driver = { .name = "smmu", .of_match_table = smmu_of_match, }, }; module_platform_driver(smmu_driver); ``` 这个代码片段是一个SMMU驱动程序的框架,它通过调用`iommu_domain_alloc()`函数分配一个SMMU域,然后通过调用`iommu_attach_device()`函数将设备添加到SMMU域中。当设备被移除时,它会调用`iommu_detach_device()`函数将设备SMMU域中移除,并释放SMMU域。 在实际的驱动程序中,还需要为SMMU设备提供具体的操作函数,如`iommu_ops`结构体中的`map()`、`unmap()`、`flush_iotlb_all()`等。这些函数将被SMMU核心调用以执行特定的操作。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值