diff mbox series

[v4,30/41] vfio/iommufd: Add support for iova_ranges

Message ID 20231102071302.1818071-31-zhenzhong.duan@intel.com
State New
Headers show
Series vfio: Adopt iommufd | expand

Commit Message

Duan, Zhenzhong Nov. 2, 2023, 7:12 a.m. UTC
Some vIOMMU such as virtio-iommu use iova ranges from host side to
setup reserved ranges for passthrough device, so that guest will not
use an iova range beyond host support.

Use an uAPI of IOMMUFD to get iova ranges of host side and pass to
vIOMMU just like the legacy backend.

Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
---
v4: fix build error in 32bit fedora

 hw/vfio/iommufd.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

Comments

Cédric Le Goater Nov. 6, 2023, 5:19 p.m. UTC | #1
On 11/2/23 08:12, Zhenzhong Duan wrote:
> Some vIOMMU such as virtio-iommu use iova ranges from host side to
> setup reserved ranges for passthrough device, so that guest will not
> use an iova range beyond host support.
> 
> Use an uAPI of IOMMUFD to get iova ranges of host side and pass to
> vIOMMU just like the legacy backend.
> 
> Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
> ---
> v4: fix build error in 32bit fedora
> 
>   hw/vfio/iommufd.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 47 insertions(+)
> 
> diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c
> index 1bb55ca2c4..22f02f92a9 100644
> --- a/hw/vfio/iommufd.c
> +++ b/hw/vfio/iommufd.c
> @@ -341,6 +341,52 @@ static int iommufd_ram_block_discard_disable(bool state)
>       return ram_block_uncoordinated_discard_disable(state);
>   }
>   
> +static int vfio_get_info_iova_range(VFIOIOMMUFDContainer *container,
> +                                    uint32_t ioas_id)
> +{
> +    VFIOContainerBase *bcontainer = &container->bcontainer;
> +    struct iommu_ioas_iova_ranges *info;
> +    struct iommu_iova_range *iova_ranges;
> +    int ret, sz, fd = container->be->fd;
> +
> +    info = g_malloc0(sizeof(*info));
> +    info->size = sizeof(*info);
> +    info->ioas_id = ioas_id;
> +
> +    ret = ioctl(fd, IOMMU_IOAS_IOVA_RANGES, info);
> +    if (ret && errno != EMSGSIZE) {
> +        goto error;
> +    }
> +
> +    sz = info->num_iovas * sizeof(struct iommu_iova_range);
> +    info = g_realloc(info, sizeof(*info) + sz);
> +    info->allowed_iovas = (uintptr_t)(info + 1);
> +
> +    ret = ioctl(fd, IOMMU_IOAS_IOVA_RANGES, info);
> +    if (ret) {
> +        goto error;
> +    }
> +
> +    iova_ranges = (struct iommu_iova_range *)info->allowed_iovas;

iova_ranges = (struct iommu_iova_range *)(uintptr_t)info->allowed_iovas;

Thanks,

C.


> +
> +    for (int i = 0; i < info->num_iovas; i++) {
> +        Range *range = g_new(Range, 1);
> +
> +        range_set_bounds(range, iova_ranges[i].start, iova_ranges[i].last);
> +        bcontainer->iova_ranges =
> +            range_list_insert(bcontainer->iova_ranges, range);
> +    }
> +
> +    g_free(info);
> +    return 0;
> +
> +error:
> +    ret = -errno;
> +    g_free(info);
> +    error_report("vfio/iommufd: Cannot get iova ranges: %m");
> +    return ret;
> +}
> +
>   static int iommufd_attach_device(const char *name, VFIODevice *vbasedev,
>                                    AddressSpace *as, Error **errp)
>   {
> @@ -418,6 +464,7 @@ static int iommufd_attach_device(const char *name, VFIODevice *vbasedev,
>       }
>   
>       bcontainer->pgsizes = qemu_real_host_page_size();
> +    vfio_get_info_iova_range(container, ioas_id);
>   
>       bcontainer->listener = vfio_memory_listener;
>       memory_listener_register(&bcontainer->listener, bcontainer->space->as);
Duan, Zhenzhong Nov. 7, 2023, 3:07 a.m. UTC | #2
>-----Original Message-----
>From: Cédric Le Goater <clg@redhat.com>
>Sent: Tuesday, November 7, 2023 1:19 AM
>Subject: Re: [PATCH v4 30/41] vfio/iommufd: Add support for iova_ranges
>
>On 11/2/23 08:12, Zhenzhong Duan wrote:
>> Some vIOMMU such as virtio-iommu use iova ranges from host side to
>> setup reserved ranges for passthrough device, so that guest will not
>> use an iova range beyond host support.
>>
>> Use an uAPI of IOMMUFD to get iova ranges of host side and pass to
>> vIOMMU just like the legacy backend.
>>
>> Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
>> ---
>> v4: fix build error in 32bit fedora
>>
>>   hw/vfio/iommufd.c | 47
>+++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 47 insertions(+)
>>
>> diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c
>> index 1bb55ca2c4..22f02f92a9 100644
>> --- a/hw/vfio/iommufd.c
>> +++ b/hw/vfio/iommufd.c
>> @@ -341,6 +341,52 @@ static int iommufd_ram_block_discard_disable(bool
>state)
>>       return ram_block_uncoordinated_discard_disable(state);
>>   }
>>
>> +static int vfio_get_info_iova_range(VFIOIOMMUFDContainer *container,
>> +                                    uint32_t ioas_id)
>> +{
>> +    VFIOContainerBase *bcontainer = &container->bcontainer;
>> +    struct iommu_ioas_iova_ranges *info;
>> +    struct iommu_iova_range *iova_ranges;
>> +    int ret, sz, fd = container->be->fd;
>> +
>> +    info = g_malloc0(sizeof(*info));
>> +    info->size = sizeof(*info);
>> +    info->ioas_id = ioas_id;
>> +
>> +    ret = ioctl(fd, IOMMU_IOAS_IOVA_RANGES, info);
>> +    if (ret && errno != EMSGSIZE) {
>> +        goto error;
>> +    }
>> +
>> +    sz = info->num_iovas * sizeof(struct iommu_iova_range);
>> +    info = g_realloc(info, sizeof(*info) + sz);
>> +    info->allowed_iovas = (uintptr_t)(info + 1);
>> +
>> +    ret = ioctl(fd, IOMMU_IOAS_IOVA_RANGES, info);
>> +    if (ret) {
>> +        goto error;
>> +    }
>> +
>> +    iova_ranges = (struct iommu_iova_range *)info->allowed_iovas;
>
>iova_ranges = (struct iommu_iova_range *)(uintptr_t)info->allowed_iovas;

Will fix, thanks for point out.

BRs.
Zhenzhong
diff mbox series

Patch

diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c
index 1bb55ca2c4..22f02f92a9 100644
--- a/hw/vfio/iommufd.c
+++ b/hw/vfio/iommufd.c
@@ -341,6 +341,52 @@  static int iommufd_ram_block_discard_disable(bool state)
     return ram_block_uncoordinated_discard_disable(state);
 }
 
+static int vfio_get_info_iova_range(VFIOIOMMUFDContainer *container,
+                                    uint32_t ioas_id)
+{
+    VFIOContainerBase *bcontainer = &container->bcontainer;
+    struct iommu_ioas_iova_ranges *info;
+    struct iommu_iova_range *iova_ranges;
+    int ret, sz, fd = container->be->fd;
+
+    info = g_malloc0(sizeof(*info));
+    info->size = sizeof(*info);
+    info->ioas_id = ioas_id;
+
+    ret = ioctl(fd, IOMMU_IOAS_IOVA_RANGES, info);
+    if (ret && errno != EMSGSIZE) {
+        goto error;
+    }
+
+    sz = info->num_iovas * sizeof(struct iommu_iova_range);
+    info = g_realloc(info, sizeof(*info) + sz);
+    info->allowed_iovas = (uintptr_t)(info + 1);
+
+    ret = ioctl(fd, IOMMU_IOAS_IOVA_RANGES, info);
+    if (ret) {
+        goto error;
+    }
+
+    iova_ranges = (struct iommu_iova_range *)info->allowed_iovas;
+
+    for (int i = 0; i < info->num_iovas; i++) {
+        Range *range = g_new(Range, 1);
+
+        range_set_bounds(range, iova_ranges[i].start, iova_ranges[i].last);
+        bcontainer->iova_ranges =
+            range_list_insert(bcontainer->iova_ranges, range);
+    }
+
+    g_free(info);
+    return 0;
+
+error:
+    ret = -errno;
+    g_free(info);
+    error_report("vfio/iommufd: Cannot get iova ranges: %m");
+    return ret;
+}
+
 static int iommufd_attach_device(const char *name, VFIODevice *vbasedev,
                                  AddressSpace *as, Error **errp)
 {
@@ -418,6 +464,7 @@  static int iommufd_attach_device(const char *name, VFIODevice *vbasedev,
     }
 
     bcontainer->pgsizes = qemu_real_host_page_size();
+    vfio_get_info_iova_range(container, ioas_id);
 
     bcontainer->listener = vfio_memory_listener;
     memory_listener_register(&bcontainer->listener, bcontainer->space->as);