从virtio看iommu和DMA的关系

本文探讨了在物理机和虚拟机环境中,为何开启iommu以及VIRTIO_F_ACCESS_PLATFORM的重要性。在设备直通时,物理机开启iommu防止了DMA冲突。iommu的开启对前端驱动的影响主要在于DMA地址映射。虚拟机支持iommu通常用于安全场景,如vhost-user。vfio驱动并不强制要求iommu。在裸金属启动虚拟机时,需要配置iommu并启用VIRTIO_F_ACCESS_PLATFORM以保证DMA正确性。
摘要由CSDN通过智能技术生成

这篇文章主要从virtio和ADMA的角度讲述一下iommu中的一些逻辑。

做虚拟化或者网络的人对virtio,iommu或者DMA这些概念都不陌生,但是其中的关联却又有很多人不是很明白,比如在裸金属或物理机上支持虚拟机或安全容器需要开启iommu,那虚拟机前端不支持VIRTIO_F_ACCESS_PLATFORM是否有影响呢?这里就是把iommu和viommu搞混了。又比如物理机开启或关闭iommu对应virtio设备的处理逻辑有什么影响?这篇文章主要就是把这些问题讨论清楚。

问题1:如果使用设备直通方式在物理机上启动虚拟机,为什么需要物理机开启iommu?

这个问题比较简单,物理机开启iommu主要是为了避免直通给虚拟机A的外设DMA到虚拟机B的内存,所以不直接使用hpa,而使用iova(gpa)进行DMA,这样每个虚拟机用自己的iova,iommu确保其转换后之会访问自己对应的内存。

问题2:iommu是否开启对前端驱动的处理逻辑有什么影响?

我们知道开启iommu后,设备发起DMA操作会经过如下图流程,根据TLP中的bdf找到应对的context entry进行地址转换。那么对于前端的驱动软件处理行为有什么差异呢?

(免费订阅,永久学习)学习地址: Dpdk/网络协议栈/vpp/OvS/DDos/NFV/虚拟化/高性能专家-学习视频教程-腾讯课堂

更多DPDK相关学习资料有需要的可以自行报名学习,免费订阅,永久学习,或点击这里加qun免费
领取,关注我持续更新哦! ! 

其实,iommu对于驱动软硬的影响主要是在进行DMA操作或者说进行DMA地址映射时使用的地址差异(直接使用物理地址还是iova)。 我们以ixgbe的发送函数ixgbe_tx_map为例:

  1. static void ixgbe_tx_map(struct ixgbe_ring *tx_ring,

  2. struct ixgbe_tx_buffer *first,

  3. const u8 hdr_len)

  4. {

  5. //...

  6. dma = dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE);

  7. for (frag = &skb_shinfo(skb)->frags[0];; frag++) {

  8. tx_desc->read.buffer_addr = cpu_to_le64(dma);

  9. while (unlikely(size > IXGBE_MAX_DATA_PER_TXD)) {

  10. i++;

  11. tx_desc++;

  12. tx_desc->read.buffer_addr = cpu_to_le64(dma);

  13. }

  14. //...

  15. }

核心逻辑就是先把skb的地址做一下dma map,然后让硬件可以直接dma这段数据,其具体后续调用过程如下图:

之前iommu文章中介绍过在intel环境iommu初始化会把pci bus的iommu ops设置成intel_dma_ops,所以map_page函数{BANNED}最佳终会调用到intel_map_page。

l __intel_map_single

  1. static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr,

  2. size_t size, int dir, u64 dma_mask)

  3. {

  4. struct dmar_domain *domain;

  5. phys_addr_t start_paddr;

  6. unsigned long iova_pfn;

  7. int prot = 0;

  8. int ret;

  9. struct intel_iommu *iommu;

  10. unsigned long paddr_pfn = paddr >> PAGE_SHIFT;

  11. BUG_ON(dir == DMA_NONE);

  12. if (iommu_no_mapping(dev))

  13. return paddr;

  14. domain = get_valid_domain_for_dev(dev);

  15. if (!domain)

  16. return 0;

  17. iommu = domain_get_iommu(domain);

  18. size = aligned_nrpages(paddr, si

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值