IOMMU可以将连续的虚拟地址映射到不连续的多个物理内存片段,这部分功能于MMU类似,对于没有IOMMU的情况,设备访问的物理空间必须是连续的,IOMMU可有效的解决这个问题 2.2IOMMU工作原理 前面简单介绍了IOMMU的映射功能,下面讲述IOMMU到底如何实现映射的,为便于分析,这里先不考虑虚拟化的场景,以下图为例,阐述工作原理。 IOMMU...
intcontainer,group,device,i;structvfio_group_statusgroup_status={.argsz=sizeof(group_status)};structvfio_iommu_type1_infoiommu_info={.argsz=sizeof(iommu_info)};structvfio_iommu_type1_dma_mapdma_map={.argsz=sizeof(dma_map)};structvfio_device_infodevice_info={.argsz=sizeof(device_info)...
基于这几点来看VFIO的DMA重映射就比较清晰,首先从VFIO设备的初始化开始,在获取设备信息之前会先获取到设备所属的group和Container,并调用VFIO_SET_IOMMU完成container和IOMMU的绑定,并attach由VFIO管理的所有设备。此外注意到这里的 pci_device_iommu_address_space 函数,意思是qemu为设备dma注册了一段专门的地址空间,这...
IOMMU是一个硬件单元,它可以把设备的IO地址映射成虚拟地址,为设备提供页表映射,设备通过IOMMU将数据直接DMA写到用户空间。 Device是指要操作的硬件设备,这里的设备需要从IOMMU拓扑的角度来看。如果device是一个硬件拓扑上是独立那么这个设备构成了一个IOMMU group。如果多个设备在硬件是互联的,需要相互访问数据,那么这些设...
structvfio_iommu_type1_dma_mapdma_map={ .argsz =sizeof(dma_map) }; structvfio_device_infodevice_info={ .argsz =sizeof(device_info) }; /* Create a new container */ container = open("/dev/vfio/vfio", O_RDWR); if(ioctl(container, VFIO_GET_API_VERSION) != VFIO_API_VERSION) ...
那些不安全的 DMA 用红色箭头显示。 这就是为什么我们需要在来宾中使用 vIOMMU来加强保护 使用案例 1:使用 vIOMMU 进行访客设备分配 为了保护来宾内存免受恶意分配设备的影响,我们可以在来宾中拥有 vIOMMU,就像主机 IOMMU 对主机所做的那样。上图中,唯一的区别是我们引入了 guest vIOMMU 来做 DMA 保护。 这样,...
VFIO_IOMMU_MAP_DMA:指定设备端看到的IO地址到进程的虚拟地址之间的映射 第二个层面,group的操作是通过打开/dev/vifo/<group_id>文件, 对其执行ioctl操作,主要的操作有: VFIO_GROUP_GET_STATUS:获取group 的状态信息 VFIO_GROUP_SET_CONTAINER:设置group 和container 之间的绑定关系 ...
ioctl(container, VFIO_IOMMU_MAP_DMA, &dma_map); 很明显,这个概念空间包括container和group两个概念,vfio_container是访问的上下文,vfio_group是vfio对iommu_group的表述。 [vfio_iommu_type1.c] 1staticlongvfio_iommu_type1_ioctl(void*iommu_data,2unsignedintcmd, unsignedlongarg)3{4structvfio_iommu *iom...
用VFIO_IOMMU_MAP_DMA将此IOMMU group的DMA地址映射至进程虚拟地址空间 逻辑 VFIO设备实现层与Linux设备模型紧密相连,当前,VFIO中仅有针对PCI的设备实现层(实现在vfio-pci模块中)。设备实现层的作用与普通设备驱动的作用类似。普通设备驱动向上穿过若干抽象层,最终以Linux里广为人知的抽象设备(网络设备,块设备等等)展现...
struct vfio_iommu_type1_dma_map map; uint32_t mask = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE; minsz = offsetofend(struct vfio_iommu_type1_dma_map, size); if (copy_from_user(&map, (void __user *)arg, minsz)) ...