@@ -875,11 +875,23 @@ EXPORT_SYMBOL_GPL(vfio_device_get_from_dev);
875
875
static struct vfio_device * vfio_device_get_from_name (struct vfio_group * group ,
876
876
char * buf )
877
877
{
878
- struct vfio_device * it , * device = NULL ;
878
+ struct vfio_device * it , * device = ERR_PTR ( - ENODEV ) ;
879
879
880
880
mutex_lock (& group -> device_lock );
881
881
list_for_each_entry (it , & group -> device_list , group_next ) {
882
- if (!strcmp (dev_name (it -> dev ), buf )) {
882
+ int ret ;
883
+
884
+ if (it -> ops -> match ) {
885
+ ret = it -> ops -> match (it -> device_data , buf );
886
+ if (ret < 0 ) {
887
+ device = ERR_PTR (ret );
888
+ break ;
889
+ }
890
+ } else {
891
+ ret = !strcmp (dev_name (it -> dev ), buf );
892
+ }
893
+
894
+ if (ret ) {
883
895
device = it ;
884
896
vfio_device_get (device );
885
897
break ;
@@ -1430,8 +1442,8 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
1430
1442
return - EPERM ;
1431
1443
1432
1444
device = vfio_device_get_from_name (group , buf );
1433
- if (! device )
1434
- return - ENODEV ;
1445
+ if (IS_ERR ( device ) )
1446
+ return PTR_ERR ( device ) ;
1435
1447
1436
1448
ret = device -> ops -> open (device -> device_data );
1437
1449
if (ret ) {
@@ -1720,6 +1732,44 @@ struct vfio_group *vfio_group_get_external_user(struct file *filep)
1720
1732
}
1721
1733
EXPORT_SYMBOL_GPL (vfio_group_get_external_user );
1722
1734
1735
+ /**
1736
+ * External user API, exported by symbols to be linked dynamically.
1737
+ * The external user passes in a device pointer
1738
+ * to verify that:
1739
+ * - A VFIO group is assiciated with the device;
1740
+ * - IOMMU is set for the group.
1741
+ * If both checks passed, vfio_group_get_external_user_from_dev()
1742
+ * increments the container user counter to prevent the VFIO group
1743
+ * from disposal before external user exits and returns the pointer
1744
+ * to the VFIO group.
1745
+ *
1746
+ * When the external user finishes using the VFIO group, it calls
1747
+ * vfio_group_put_external_user() to release the VFIO group and
1748
+ * decrement the container user counter.
1749
+ *
1750
+ * @dev [in] : device
1751
+ * Return error PTR or pointer to VFIO group.
1752
+ */
1753
+
1754
+ struct vfio_group * vfio_group_get_external_user_from_dev (struct device * dev )
1755
+ {
1756
+ struct vfio_group * group ;
1757
+ int ret ;
1758
+
1759
+ group = vfio_group_get_from_dev (dev );
1760
+ if (!group )
1761
+ return ERR_PTR (- ENODEV );
1762
+
1763
+ ret = vfio_group_add_container_user (group );
1764
+ if (ret ) {
1765
+ vfio_group_put (group );
1766
+ return ERR_PTR (ret );
1767
+ }
1768
+
1769
+ return group ;
1770
+ }
1771
+ EXPORT_SYMBOL_GPL (vfio_group_get_external_user_from_dev );
1772
+
1723
1773
void vfio_group_put_external_user (struct vfio_group * group )
1724
1774
{
1725
1775
vfio_group_try_dissolve_container (group );
@@ -1961,6 +2011,146 @@ int vfio_unpin_pages(struct device *dev, unsigned long *user_pfn, int npage)
1961
2011
}
1962
2012
EXPORT_SYMBOL (vfio_unpin_pages );
1963
2013
2014
+ /*
2015
+ * Pin a set of guest IOVA PFNs and return their associated host PFNs for a
2016
+ * VFIO group.
2017
+ *
2018
+ * The caller needs to call vfio_group_get_external_user() or
2019
+ * vfio_group_get_external_user_from_dev() prior to calling this interface,
2020
+ * so as to prevent the VFIO group from disposal in the middle of the call.
2021
+ * But it can keep the reference to the VFIO group for several calls into
2022
+ * this interface.
2023
+ * After finishing using of the VFIO group, the caller needs to release the
2024
+ * VFIO group by calling vfio_group_put_external_user().
2025
+ *
2026
+ * @group [in] : VFIO group
2027
+ * @user_iova_pfn [in] : array of user/guest IOVA PFNs to be pinned.
2028
+ * @npage [in] : count of elements in user_iova_pfn array.
2029
+ * This count should not be greater
2030
+ * VFIO_PIN_PAGES_MAX_ENTRIES.
2031
+ * @prot [in] : protection flags
2032
+ * @phys_pfn [out] : array of host PFNs
2033
+ * Return error or number of pages pinned.
2034
+ */
2035
+ int vfio_group_pin_pages (struct vfio_group * group ,
2036
+ unsigned long * user_iova_pfn , int npage ,
2037
+ int prot , unsigned long * phys_pfn )
2038
+ {
2039
+ struct vfio_container * container ;
2040
+ struct vfio_iommu_driver * driver ;
2041
+ int ret ;
2042
+
2043
+ if (!group || !user_iova_pfn || !phys_pfn || !npage )
2044
+ return - EINVAL ;
2045
+
2046
+ if (npage > VFIO_PIN_PAGES_MAX_ENTRIES )
2047
+ return - E2BIG ;
2048
+
2049
+ container = group -> container ;
2050
+ driver = container -> iommu_driver ;
2051
+ if (likely (driver && driver -> ops -> pin_pages ))
2052
+ ret = driver -> ops -> pin_pages (container -> iommu_data ,
2053
+ user_iova_pfn , npage ,
2054
+ prot , phys_pfn );
2055
+ else
2056
+ ret = - ENOTTY ;
2057
+
2058
+ return ret ;
2059
+ }
2060
+ EXPORT_SYMBOL (vfio_group_pin_pages );
2061
+
2062
+ /*
2063
+ * Unpin a set of guest IOVA PFNs for a VFIO group.
2064
+ *
2065
+ * The caller needs to call vfio_group_get_external_user() or
2066
+ * vfio_group_get_external_user_from_dev() prior to calling this interface,
2067
+ * so as to prevent the VFIO group from disposal in the middle of the call.
2068
+ * But it can keep the reference to the VFIO group for several calls into
2069
+ * this interface.
2070
+ * After finishing using of the VFIO group, the caller needs to release the
2071
+ * VFIO group by calling vfio_group_put_external_user().
2072
+ *
2073
+ * @group [in] : vfio group
2074
+ * @user_iova_pfn [in] : array of user/guest IOVA PFNs to be unpinned.
2075
+ * @npage [in] : count of elements in user_iova_pfn array.
2076
+ * This count should not be greater than
2077
+ * VFIO_PIN_PAGES_MAX_ENTRIES.
2078
+ * Return error or number of pages unpinned.
2079
+ */
2080
+ int vfio_group_unpin_pages (struct vfio_group * group ,
2081
+ unsigned long * user_iova_pfn , int npage )
2082
+ {
2083
+ struct vfio_container * container ;
2084
+ struct vfio_iommu_driver * driver ;
2085
+ int ret ;
2086
+
2087
+ if (!group || !user_iova_pfn || !npage )
2088
+ return - EINVAL ;
2089
+
2090
+ if (npage > VFIO_PIN_PAGES_MAX_ENTRIES )
2091
+ return - E2BIG ;
2092
+
2093
+ container = group -> container ;
2094
+ driver = container -> iommu_driver ;
2095
+ if (likely (driver && driver -> ops -> unpin_pages ))
2096
+ ret = driver -> ops -> unpin_pages (container -> iommu_data ,
2097
+ user_iova_pfn , npage );
2098
+ else
2099
+ ret = - ENOTTY ;
2100
+
2101
+ return ret ;
2102
+ }
2103
+ EXPORT_SYMBOL (vfio_group_unpin_pages );
2104
+
2105
+
2106
+ /*
2107
+ * This interface allows the CPUs to perform some sort of virtual DMA on
2108
+ * behalf of the device.
2109
+ *
2110
+ * CPUs read/write from/into a range of IOVAs pointing to user space memory
2111
+ * into/from a kernel buffer.
2112
+ *
2113
+ * As the read/write of user space memory is conducted via the CPUs and is
2114
+ * not a real device DMA, it is not necessary to pin the user space memory.
2115
+ *
2116
+ * The caller needs to call vfio_group_get_external_user() or
2117
+ * vfio_group_get_external_user_from_dev() prior to calling this interface,
2118
+ * so as to prevent the VFIO group from disposal in the middle of the call.
2119
+ * But it can keep the reference to the VFIO group for several calls into
2120
+ * this interface.
2121
+ * After finishing using of the VFIO group, the caller needs to release the
2122
+ * VFIO group by calling vfio_group_put_external_user().
2123
+ *
2124
+ * @group [in] : VFIO group
2125
+ * @user_iova [in] : base IOVA of a user space buffer
2126
+ * @data [in] : pointer to kernel buffer
2127
+ * @len [in] : kernel buffer length
2128
+ * @write : indicate read or write
2129
+ * Return error code on failure or 0 on success.
2130
+ */
2131
+ int vfio_dma_rw (struct vfio_group * group , dma_addr_t user_iova ,
2132
+ void * data , size_t len , bool write )
2133
+ {
2134
+ struct vfio_container * container ;
2135
+ struct vfio_iommu_driver * driver ;
2136
+ int ret = 0 ;
2137
+
2138
+ if (!group || !data || len <= 0 )
2139
+ return - EINVAL ;
2140
+
2141
+ container = group -> container ;
2142
+ driver = container -> iommu_driver ;
2143
+
2144
+ if (likely (driver && driver -> ops -> dma_rw ))
2145
+ ret = driver -> ops -> dma_rw (container -> iommu_data ,
2146
+ user_iova , data , len , write );
2147
+ else
2148
+ ret = - ENOTTY ;
2149
+
2150
+ return ret ;
2151
+ }
2152
+ EXPORT_SYMBOL (vfio_dma_rw );
2153
+
1964
2154
static int vfio_register_iommu_notifier (struct vfio_group * group ,
1965
2155
unsigned long * events ,
1966
2156
struct notifier_block * nb )
0 commit comments