forked from mirrors/linux
		
	 58ccf0190d
			
		
	
	
		58ccf0190d
		
	
	
	
	
		
			
			The new facility adds a bunch of wrappers that abstract how an IOVA range
is represented in a bitmap that is granulated by a given page_size. So it
translates all the lifting of dealing with user pointers into its
corresponding kernel addresses backing said user memory into doing finally
the (non-atomic) bitmap ops to change various bits.
The formula for the bitmap is:
   data[(iova / page_size) / 64] & (1ULL << (iova % 64))
Where 64 is the number of bits in a unsigned long (depending on arch)
It introduces an IOVA iterator that uses a windowing scheme to minimize the
pinning overhead, as opposed to pinning it on demand 4K at a time. Assuming
a 4K kernel page and 4K requested page size, we can use a single kernel
page to hold 512 page pointers, mapping 2M of bitmap, representing 64G of
IOVA space.
An example usage of these helpers for a given @base_iova, @page_size,
@length and __user @data:
   bitmap = iova_bitmap_alloc(base_iova, page_size, length, data);
   if (IS_ERR(bitmap))
       return -ENOMEM;
   ret = iova_bitmap_for_each(bitmap, arg, dirty_reporter_fn);
   iova_bitmap_free(bitmap);
Each iteration of the @dirty_reporter_fn is called with a unique @iova
and @length argument, indicating the current range available through the
iova_bitmap. The @dirty_reporter_fn uses iova_bitmap_set() to mark dirty
areas (@iova_length) within that provided range, as following:
   iova_bitmap_set(bitmap, iova, iova_length);
The facility is intended to be used for user bitmaps representing dirtied
IOVAs by IOMMU (via IOMMUFD) and PCI Devices (via vfio-pci).
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Yishai Hadas <yishaih@nvidia.com>
Link: https://lore.kernel.org/r/20220908183448.195262-5-yishaih@nvidia.com
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
		
	
			
		
			
				
	
	
		
			26 lines
		
	
	
	
		
			771 B
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			26 lines
		
	
	
	
		
			771 B
		
	
	
	
		
			C
		
	
	
	
	
	
| /* SPDX-License-Identifier: GPL-2.0 */
 | |
| /*
 | |
|  * Copyright (c) 2022, Oracle and/or its affiliates.
 | |
|  * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved
 | |
|  */
 | |
| #ifndef _IOVA_BITMAP_H_
 | |
| #define _IOVA_BITMAP_H_
 | |
| 
 | |
| #include <linux/types.h>
 | |
| 
 | |
| struct iova_bitmap;
 | |
| 
 | |
| typedef int (*iova_bitmap_fn_t)(struct iova_bitmap *bitmap,
 | |
| 				unsigned long iova, size_t length,
 | |
| 				void *opaque);
 | |
| 
 | |
| struct iova_bitmap *iova_bitmap_alloc(unsigned long iova, size_t length,
 | |
| 				      unsigned long page_size,
 | |
| 				      u64 __user *data);
 | |
| void iova_bitmap_free(struct iova_bitmap *bitmap);
 | |
| int iova_bitmap_for_each(struct iova_bitmap *bitmap, void *opaque,
 | |
| 			 iova_bitmap_fn_t fn);
 | |
| void iova_bitmap_set(struct iova_bitmap *bitmap,
 | |
| 		     unsigned long iova, size_t length);
 | |
| 
 | |
| #endif
 |