vfio: powerpc/spapr: Support Dynamic DMA windows
This adds create/remove window ioctls to create and remove DMA windows. sPAPR defines a Dynamic DMA windows capability which allows para-virtualized guests to create additional DMA windows on a PCI bus. The existing linux kernels use this new window to map the entire guest memory and switch to the direct DMA operations saving time on map/unmap requests which would normally happen in a big amounts. This adds 2 ioctl handlers - VFIO_IOMMU_SPAPR_TCE_CREATE and VFIO_IOMMU_SPAPR_TCE_REMOVE - to create and remove windows. Up to 2 windows are supported now by the hardware and by this driver. This changes VFIO_IOMMU_SPAPR_TCE_GET_INFO handler to return additional information such as a number of supported windows and maximum number levels of TCE tables. DDW is added as a capability, not as a SPAPR TCE IOMMU v2 unique feature as we still want to support v2 on platforms which cannot do DDW for the sake of TCE acceleration in KVM (coming soon). Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> [aw: for the vfio related changes] Acked-by: Alex Williamson <alex.williamson@redhat.com> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
		
					parent
					
						
							
								2157e7b82f
							
						
					
				
			
			
				commit
				
					
						e633bc86a9
					
				
			
		
					 4 changed files with 273 additions and 5 deletions
				
			
		|  | @ -444,6 +444,23 @@ struct vfio_iommu_type1_dma_unmap { | |||
| 
 | ||||
| /* -------- Additional API for SPAPR TCE (Server POWERPC) IOMMU -------- */ | ||||
| 
 | ||||
| /*
 | ||||
|  * The SPAPR TCE DDW info struct provides the information about | ||||
|  * the details of Dynamic DMA window capability. | ||||
|  * | ||||
|  * @pgsizes contains a page size bitmask, 4K/64K/16M are supported. | ||||
|  * @max_dynamic_windows_supported tells the maximum number of windows | ||||
|  * which the platform can create. | ||||
|  * @levels tells the maximum number of levels in multi-level IOMMU tables; | ||||
|  * this allows splitting a table into smaller chunks which reduces | ||||
|  * the amount of physically contiguous memory required for the table. | ||||
|  */ | ||||
| struct vfio_iommu_spapr_tce_ddw_info { | ||||
| 	__u64 pgsizes;			/* Bitmap of supported page sizes */ | ||||
| 	__u32 max_dynamic_windows_supported; | ||||
| 	__u32 levels; | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * The SPAPR TCE info struct provides the information about the PCI bus | ||||
|  * address ranges available for DMA, these values are programmed into | ||||
|  | @ -454,14 +471,17 @@ struct vfio_iommu_type1_dma_unmap { | |||
|  * addresses too so the window works as a filter rather than an offset | ||||
|  * for IOVA addresses. | ||||
|  * | ||||
|  * A flag will need to be added if other page sizes are supported, | ||||
|  * so as defined here, it is always 4k. | ||||
|  * Flags supported: | ||||
|  * - VFIO_IOMMU_SPAPR_INFO_DDW: informs the userspace that dynamic DMA windows | ||||
|  *   (DDW) support is present. @ddw is only supported when DDW is present. | ||||
|  */ | ||||
| struct vfio_iommu_spapr_tce_info { | ||||
| 	__u32 argsz; | ||||
| 	__u32 flags;			/* reserved for future use */ | ||||
| 	__u32 flags; | ||||
| #define VFIO_IOMMU_SPAPR_INFO_DDW	(1 << 0)	/* DDW supported */ | ||||
| 	__u32 dma32_window_start;	/* 32 bit window start (bytes) */ | ||||
| 	__u32 dma32_window_size;	/* 32 bit window size (bytes) */ | ||||
| 	struct vfio_iommu_spapr_tce_ddw_info ddw; | ||||
| }; | ||||
| 
 | ||||
| #define VFIO_IOMMU_SPAPR_TCE_GET_INFO	_IO(VFIO_TYPE, VFIO_BASE + 12) | ||||
|  | @ -534,6 +554,41 @@ struct vfio_iommu_spapr_register_memory { | |||
|  */ | ||||
| #define VFIO_IOMMU_SPAPR_UNREGISTER_MEMORY	_IO(VFIO_TYPE, VFIO_BASE + 18) | ||||
| 
 | ||||
| /**
 | ||||
|  * VFIO_IOMMU_SPAPR_TCE_CREATE - _IOWR(VFIO_TYPE, VFIO_BASE + 19, struct vfio_iommu_spapr_tce_create) | ||||
|  * | ||||
|  * Creates an additional TCE table and programs it (sets a new DMA window) | ||||
|  * to every IOMMU group in the container. It receives page shift, window | ||||
|  * size and number of levels in the TCE table being created. | ||||
|  * | ||||
|  * It allocates and returns an offset on a PCI bus of the new DMA window. | ||||
|  */ | ||||
| struct vfio_iommu_spapr_tce_create { | ||||
| 	__u32 argsz; | ||||
| 	__u32 flags; | ||||
| 	/* in */ | ||||
| 	__u32 page_shift; | ||||
| 	__u64 window_size; | ||||
| 	__u32 levels; | ||||
| 	/* out */ | ||||
| 	__u64 start_addr; | ||||
| }; | ||||
| #define VFIO_IOMMU_SPAPR_TCE_CREATE	_IO(VFIO_TYPE, VFIO_BASE + 19) | ||||
| 
 | ||||
| /**
 | ||||
|  * VFIO_IOMMU_SPAPR_TCE_REMOVE - _IOW(VFIO_TYPE, VFIO_BASE + 20, struct vfio_iommu_spapr_tce_remove) | ||||
|  * | ||||
|  * Unprograms a TCE table from all groups in the container and destroys it. | ||||
|  * It receives a PCI bus offset as a window id. | ||||
|  */ | ||||
| struct vfio_iommu_spapr_tce_remove { | ||||
| 	__u32 argsz; | ||||
| 	__u32 flags; | ||||
| 	/* in */ | ||||
| 	__u64 start_addr; | ||||
| }; | ||||
| #define VFIO_IOMMU_SPAPR_TCE_REMOVE	_IO(VFIO_TYPE, VFIO_BASE + 20) | ||||
| 
 | ||||
| /* ***************************************************************** */ | ||||
| 
 | ||||
| #endif /* _UAPIVFIO_H */ | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Alexey Kardashevskiy
				Alexey Kardashevskiy