Re: [PATCH v3 10/19] iommufd: Add IOMMU_HWPT_GET_DIRTY_IOVA

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 13/10/2023 17:22, Jason Gunthorpe wrote:
> On Sat, Sep 23, 2023 at 02:25:02AM +0100, Joao Martins wrote:
> 
>> +int iommufd_check_iova_range(struct iommufd_ioas *ioas,
>> +			     struct iommufd_dirty_data *bitmap)
>> +{
>> +	unsigned long pgshift, npages;
>> +	size_t iommu_pgsize;
>> +	int rc = -EINVAL;
>> +
>> +	pgshift = __ffs(bitmap->page_size);
>> +	npages = bitmap->length >> pgshift;
>> +
>> +	if (!npages || (npages > ULONG_MAX))
>> +		return rc;
>> +
>> +	iommu_pgsize = 1 << __ffs(ioas->iopt.iova_alignment);
> 
> iova_alignment is not a bitmask, it is the alignment itself, so is
> redundant.
> 
Yes, let me remove it

>> +	/* allow only smallest supported pgsize */
>> +	if (bitmap->page_size != iommu_pgsize)
>> +		return rc;
> 
> != is smallest?
> 
> Why are we restricting this anyhow? I thought the iova bitmap stuff
> did all the adaptation automatically?
> 
yes, it does

> I can sort of see restricting the start/stop iova
>

There's no fundamental reason to restricting it; I am probably just too obsessed
with making the most granular tracking, but I shouldn't restrict the user to
track at some other page granularity

> 
>> +	if (bitmap->iova & (iommu_pgsize - 1))
>> +		return rc;
>> +
>> +	if (!bitmap->length || bitmap->length & (iommu_pgsize - 1))
>> +		return rc;
>> +
>> +	return 0;
>> +}
> 
>> --- a/drivers/iommu/iommufd/main.c
>> +++ b/drivers/iommu/iommufd/main.c
>> @@ -316,6 +316,7 @@ union ucmd_buffer {
>>  	struct iommu_option option;
>>  	struct iommu_vfio_ioas vfio_ioas;
>>  	struct iommu_hwpt_set_dirty set_dirty;
>> +	struct iommu_hwpt_get_dirty_iova get_dirty_iova;
>>  #ifdef CONFIG_IOMMUFD_TEST
>>  	struct iommu_test_cmd test;
>>  #endif
>> @@ -361,6 +362,8 @@ static const struct iommufd_ioctl_op iommufd_ioctl_ops[] = {
>>  		 __reserved),
>>  	IOCTL_OP(IOMMU_HWPT_SET_DIRTY, iommufd_hwpt_set_dirty,
>>  		 struct iommu_hwpt_set_dirty, __reserved),
>> +	IOCTL_OP(IOMMU_HWPT_GET_DIRTY_IOVA, iommufd_hwpt_get_dirty_iova,
>> +		 struct iommu_hwpt_get_dirty_iova, bitmap.data),
> 
> Also keep sorted
> 
OK

>>  #ifdef CONFIG_IOMMUFD_TEST
>>  	IOCTL_OP(IOMMU_TEST_CMD, iommufd_test, struct iommu_test_cmd, last),
>>  #endif
>> diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h
>> index 37079e72d243..b35b7d0c4be0 100644
>> --- a/include/uapi/linux/iommufd.h
>> +++ b/include/uapi/linux/iommufd.h
>> @@ -48,6 +48,7 @@ enum {
>>  	IOMMUFD_CMD_HWPT_ALLOC,
>>  	IOMMUFD_CMD_GET_HW_INFO,
>>  	IOMMUFD_CMD_HWPT_SET_DIRTY,
>> +	IOMMUFD_CMD_HWPT_GET_DIRTY_IOVA,
>>  };
>>  
>>  /**
>> @@ -481,4 +482,39 @@ struct iommu_hwpt_set_dirty {
>>  	__u32 __reserved;
>>  };
>>  #define IOMMU_HWPT_SET_DIRTY _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HWPT_SET_DIRTY)
>> +
>> +/**
>> + * struct iommufd_dirty_bitmap - Dirty IOVA tracking bitmap
>> + * @iova: base IOVA of the bitmap
>> + * @length: IOVA size
>> + * @page_size: page size granularity of each bit in the bitmap
>> + * @data: bitmap where to set the dirty bits. The bitmap bits each
>> + * represent a page_size which you deviate from an arbitrary iova.
>> + * Checking a given IOVA is dirty:
>> + *
>> + *  data[(iova / page_size) / 64] & (1ULL << (iova % 64))
>> + */
>> +struct iommufd_dirty_data {
>> +	__aligned_u64 iova;
>> +	__aligned_u64 length;
>> +	__aligned_u64 page_size;
>> +	__aligned_u64 *data;
>> +};
> 
> Is there a reason to add this struct? Does something else use it?
> 
I was just reducing how much data I really need to pass around so consolidated
all that into a struct representing the bitmap data considering (...)

>> +/**
>> + * struct iommu_hwpt_get_dirty_iova - ioctl(IOMMU_HWPT_GET_DIRTY_IOVA)
>> + * @size: sizeof(struct iommu_hwpt_get_dirty_iova)
>> + * @hwpt_id: HW pagetable ID that represents the IOMMU domain.
>> + * @flags: Flags to control dirty tracking status.
>> + * @bitmap: Bitmap of the range of IOVA to read out
>> + */
>> +struct iommu_hwpt_get_dirty_iova {
>> +	__u32 size;
>> +	__u32 hwpt_id;
>> +	__u32 flags;
>> +	__u32 __reserved;
>> +	struct iommufd_dirty_data bitmap;
> 
> vs inlining here?
> 
> I see you are passing it around the internal API, but that could
> easily pass the whole command too

I use it for the read_and_clear_dirty_data (and it's input validation). Kinda
weird to do:

	iommu_read_and_clear(domain, flags, cmd)

Considering none of those functions pass command data around. If you prefer with
passing the whole command then I can go at it;



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux