Skip to content

Commit 44abdd1

Browse files
nicolincawilliam
authored andcommitted
vfio: Pass in starting IOVA to vfio_pin/unpin_pages API
The vfio_pin/unpin_pages() so far accepted arrays of PFNs of user IOVA. Among all three callers, there was only one caller possibly passing in a non-contiguous PFN list, which is now ensured to have contiguous PFN inputs too. Pass in the starting address with "iova" alone to simplify things, so callers no longer need to maintain a PFN list or to pin/unpin one page at a time. This also allows VFIO to use more efficient implementations of pin/unpin_pages. For now, also update vfio_iommu_type1 to fit this new parameter too, while keeping its input intact (being user_iova) since we don't want to spend too much effort swapping its parameters and local variables at that level. Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Reviewed-by: Tony Krowiak <akrowiak@linux.ibm.com> Acked-by: Eric Farman <farman@linux.ibm.com> Tested-by: Terrence Xu <terrence.xu@intel.com> Tested-by: Eric Farman <farman@linux.ibm.com> Signed-off-by: Nicolin Chen <nicolinc@nvidia.com> Link: https://lore.kernel.org/r/20220723020256.30081-6-nicolinc@nvidia.com Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
1 parent cfedb3d commit 44abdd1

File tree

8 files changed

+37
-49
lines changed

8 files changed

+37
-49
lines changed

Documentation/driver-api/vfio-mediated-device.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,10 +262,10 @@ Translation APIs for Mediated Devices
262262
The following APIs are provided for translating user pfn to host pfn in a VFIO
263263
driver::
264264

265-
int vfio_pin_pages(struct vfio_device *device, unsigned long *user_pfn,
265+
int vfio_pin_pages(struct vfio_device *device, dma_addr_t iova,
266266
int npage, int prot, unsigned long *phys_pfn);
267267

268-
void vfio_unpin_pages(struct vfio_device *device, unsigned long *user_pfn,
268+
void vfio_unpin_pages(struct vfio_device *device, dma_addr_t iova,
269269
int npage);
270270

271271
These functions call back into the back-end IOMMU module by using the pin_pages

drivers/gpu/drm/i915/gvt/kvmgt.c

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -231,14 +231,8 @@ static void intel_gvt_cleanup_vgpu_type_groups(struct intel_gvt *gvt)
231231
static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
232232
unsigned long size)
233233
{
234-
int total_pages = DIV_ROUND_UP(size, PAGE_SIZE);
235-
int npage;
236-
237-
for (npage = 0; npage < total_pages; npage++) {
238-
unsigned long cur_gfn = gfn + npage;
239-
240-
vfio_unpin_pages(&vgpu->vfio_device, &cur_gfn, 1);
241-
}
234+
vfio_unpin_pages(&vgpu->vfio_device, gfn << PAGE_SHIFT,
235+
DIV_ROUND_UP(size, PAGE_SIZE));
242236
}
243237

244238
/* Pin a normal or compound guest page for dma. */
@@ -255,14 +249,14 @@ static int gvt_pin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
255249
* on stack to hold pfns.
256250
*/
257251
for (npage = 0; npage < total_pages; npage++) {
258-
unsigned long cur_gfn = gfn + npage;
252+
dma_addr_t cur_iova = (gfn + npage) << PAGE_SHIFT;
259253
unsigned long pfn;
260254

261-
ret = vfio_pin_pages(&vgpu->vfio_device, &cur_gfn, 1,
255+
ret = vfio_pin_pages(&vgpu->vfio_device, cur_iova, 1,
262256
IOMMU_READ | IOMMU_WRITE, &pfn);
263257
if (ret != 1) {
264-
gvt_vgpu_err("vfio_pin_pages failed for gfn 0x%lx, ret %d\n",
265-
cur_gfn, ret);
258+
gvt_vgpu_err("vfio_pin_pages failed for iova %pad, ret %d\n",
259+
&cur_iova, ret);
266260
goto err;
267261
}
268262

drivers/s390/cio/vfio_ccw_cp.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ static void pfn_array_unpin(struct pfn_array *pa,
114114
continue;
115115
}
116116

117-
vfio_unpin_pages(vdev, first, npage);
117+
vfio_unpin_pages(vdev, *first << PAGE_SHIFT, npage);
118118
unpinned += npage;
119119
npage = 1;
120120
}
@@ -146,7 +146,7 @@ static int pfn_array_pin(struct pfn_array *pa, struct vfio_device *vdev)
146146
continue;
147147
}
148148

149-
ret = vfio_pin_pages(vdev, first, npage,
149+
ret = vfio_pin_pages(vdev, *first << PAGE_SHIFT, npage,
150150
IOMMU_READ | IOMMU_WRITE,
151151
&pa->pa_pfn[pinned]);
152152
if (ret < 0) {

drivers/s390/crypto/vfio_ap_ops.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ static void vfio_ap_free_aqic_resources(struct vfio_ap_queue *q)
124124
q->saved_isc = VFIO_AP_ISC_INVALID;
125125
}
126126
if (q->saved_pfn && !WARN_ON(!q->matrix_mdev)) {
127-
vfio_unpin_pages(&q->matrix_mdev->vdev, &q->saved_pfn, 1);
127+
vfio_unpin_pages(&q->matrix_mdev->vdev, q->saved_pfn << PAGE_SHIFT, 1);
128128
q->saved_pfn = 0;
129129
}
130130
}
@@ -258,7 +258,7 @@ static struct ap_queue_status vfio_ap_irq_enable(struct vfio_ap_queue *q,
258258
return status;
259259
}
260260

261-
ret = vfio_pin_pages(&q->matrix_mdev->vdev, &g_pfn, 1,
261+
ret = vfio_pin_pages(&q->matrix_mdev->vdev, g_pfn << PAGE_SHIFT, 1,
262262
IOMMU_READ | IOMMU_WRITE, &h_pfn);
263263
switch (ret) {
264264
case 1:
@@ -301,7 +301,7 @@ static struct ap_queue_status vfio_ap_irq_enable(struct vfio_ap_queue *q,
301301
break;
302302
case AP_RESPONSE_OTHERWISE_CHANGED:
303303
/* We could not modify IRQ setings: clear new configuration */
304-
vfio_unpin_pages(&q->matrix_mdev->vdev, &g_pfn, 1);
304+
vfio_unpin_pages(&q->matrix_mdev->vdev, g_pfn << PAGE_SHIFT, 1);
305305
kvm_s390_gisc_unregister(kvm, isc);
306306
break;
307307
default:
@@ -1232,9 +1232,8 @@ static void vfio_ap_mdev_dma_unmap(struct vfio_device *vdev, u64 iova,
12321232
{
12331233
struct ap_matrix_mdev *matrix_mdev =
12341234
container_of(vdev, struct ap_matrix_mdev, vdev);
1235-
unsigned long g_pfn = iova >> PAGE_SHIFT;
12361235

1237-
vfio_unpin_pages(&matrix_mdev->vdev, &g_pfn, 1);
1236+
vfio_unpin_pages(&matrix_mdev->vdev, iova, 1);
12381237
}
12391238

12401239
/**

drivers/vfio/vfio.c

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1934,26 +1934,25 @@ int vfio_set_irqs_validate_and_prepare(struct vfio_irq_set *hdr, int num_irqs,
19341934
EXPORT_SYMBOL(vfio_set_irqs_validate_and_prepare);
19351935

19361936
/*
1937-
* Pin a set of guest PFNs and return their associated host PFNs for local
1937+
* Pin contiguous user pages and return their associated host pages for local
19381938
* domain only.
19391939
* @device [in] : device
1940-
* @user_pfn [in]: array of user/guest PFNs to be pinned.
1941-
* @npage [in] : count of elements in user_pfn array. This count should not
1942-
* be greater VFIO_PIN_PAGES_MAX_ENTRIES.
1940+
* @iova [in] : starting IOVA of user pages to be pinned.
1941+
* @npage [in] : count of pages to be pinned. This count should not
1942+
* be greater than VFIO_PIN_PAGES_MAX_ENTRIES.
19431943
* @prot [in] : protection flags
19441944
* @phys_pfn[out]: array of host PFNs
19451945
* Return error or number of pages pinned.
19461946
*/
1947-
int vfio_pin_pages(struct vfio_device *device, unsigned long *user_pfn,
1947+
int vfio_pin_pages(struct vfio_device *device, dma_addr_t iova,
19481948
int npage, int prot, unsigned long *phys_pfn)
19491949
{
19501950
struct vfio_container *container;
19511951
struct vfio_group *group = device->group;
19521952
struct vfio_iommu_driver *driver;
19531953
int ret;
19541954

1955-
if (!user_pfn || !phys_pfn || !npage ||
1956-
!vfio_assert_device_open(device))
1955+
if (!phys_pfn || !npage || !vfio_assert_device_open(device))
19571956
return -EINVAL;
19581957

19591958
if (npage > VFIO_PIN_PAGES_MAX_ENTRIES)
@@ -1967,7 +1966,7 @@ int vfio_pin_pages(struct vfio_device *device, unsigned long *user_pfn,
19671966
driver = container->iommu_driver;
19681967
if (likely(driver && driver->ops->pin_pages))
19691968
ret = driver->ops->pin_pages(container->iommu_data,
1970-
group->iommu_group, user_pfn,
1969+
group->iommu_group, iova,
19711970
npage, prot, phys_pfn);
19721971
else
19731972
ret = -ENOTTY;
@@ -1977,15 +1976,13 @@ int vfio_pin_pages(struct vfio_device *device, unsigned long *user_pfn,
19771976
EXPORT_SYMBOL(vfio_pin_pages);
19781977

19791978
/*
1980-
* Unpin set of host PFNs for local domain only.
1979+
* Unpin contiguous host pages for local domain only.
19811980
* @device [in] : device
1982-
* @user_pfn [in]: array of user/guest PFNs to be unpinned. Number of user/guest
1983-
* PFNs should not be greater than VFIO_PIN_PAGES_MAX_ENTRIES.
1984-
* @npage [in] : count of elements in user_pfn array. This count should not
1981+
* @iova [in] : starting address of user pages to be unpinned.
1982+
* @npage [in] : count of pages to be unpinned. This count should not
19851983
* be greater than VFIO_PIN_PAGES_MAX_ENTRIES.
19861984
*/
1987-
void vfio_unpin_pages(struct vfio_device *device, unsigned long *user_pfn,
1988-
int npage)
1985+
void vfio_unpin_pages(struct vfio_device *device, dma_addr_t iova, int npage)
19891986
{
19901987
struct vfio_container *container;
19911988
struct vfio_iommu_driver *driver;
@@ -2000,7 +1997,7 @@ void vfio_unpin_pages(struct vfio_device *device, unsigned long *user_pfn,
20001997
container = device->group->container;
20011998
driver = container->iommu_driver;
20021999

2003-
driver->ops->unpin_pages(container->iommu_data, user_pfn, npage);
2000+
driver->ops->unpin_pages(container->iommu_data, iova, npage);
20042001
}
20052002
EXPORT_SYMBOL(vfio_unpin_pages);
20062003

drivers/vfio/vfio.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@ struct vfio_iommu_driver_ops {
5050
struct iommu_group *group);
5151
int (*pin_pages)(void *iommu_data,
5252
struct iommu_group *group,
53-
unsigned long *user_pfn,
53+
dma_addr_t user_iova,
5454
int npage, int prot,
5555
unsigned long *phys_pfn);
5656
void (*unpin_pages)(void *iommu_data,
57-
unsigned long *user_pfn, int npage);
57+
dma_addr_t user_iova, int npage);
5858
void (*register_device)(void *iommu_data,
5959
struct vfio_device *vdev);
6060
void (*unregister_device)(void *iommu_data,

drivers/vfio/vfio_iommu_type1.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -829,7 +829,7 @@ static int vfio_unpin_page_external(struct vfio_dma *dma, dma_addr_t iova,
829829

830830
static int vfio_iommu_type1_pin_pages(void *iommu_data,
831831
struct iommu_group *iommu_group,
832-
unsigned long *user_pfn,
832+
dma_addr_t user_iova,
833833
int npage, int prot,
834834
unsigned long *phys_pfn)
835835
{
@@ -841,7 +841,7 @@ static int vfio_iommu_type1_pin_pages(void *iommu_data,
841841
bool do_accounting;
842842
dma_addr_t iova;
843843

844-
if (!iommu || !user_pfn || !phys_pfn)
844+
if (!iommu || !phys_pfn)
845845
return -EINVAL;
846846

847847
/* Supported for v2 version only */
@@ -857,7 +857,7 @@ static int vfio_iommu_type1_pin_pages(void *iommu_data,
857857
again:
858858
if (iommu->vaddr_invalid_count) {
859859
for (i = 0; i < npage; i++) {
860-
iova = user_pfn[i] << PAGE_SHIFT;
860+
iova = user_iova + PAGE_SIZE * i;
861861
ret = vfio_find_dma_valid(iommu, iova, PAGE_SIZE, &dma);
862862
if (ret < 0)
863863
goto pin_done;
@@ -882,7 +882,7 @@ static int vfio_iommu_type1_pin_pages(void *iommu_data,
882882
for (i = 0; i < npage; i++) {
883883
struct vfio_pfn *vpfn;
884884

885-
iova = user_pfn[i] << PAGE_SHIFT;
885+
iova = user_iova + PAGE_SIZE * i;
886886
dma = vfio_find_dma(iommu, iova, PAGE_SIZE);
887887
if (!dma) {
888888
ret = -EINVAL;
@@ -939,7 +939,7 @@ static int vfio_iommu_type1_pin_pages(void *iommu_data,
939939
for (j = 0; j < i; j++) {
940940
dma_addr_t iova;
941941

942-
iova = user_pfn[j] << PAGE_SHIFT;
942+
iova = user_iova + PAGE_SIZE * j;
943943
dma = vfio_find_dma(iommu, iova, PAGE_SIZE);
944944
vfio_unpin_page_external(dma, iova, do_accounting);
945945
phys_pfn[j] = 0;
@@ -950,7 +950,7 @@ static int vfio_iommu_type1_pin_pages(void *iommu_data,
950950
}
951951

952952
static void vfio_iommu_type1_unpin_pages(void *iommu_data,
953-
unsigned long *user_pfn, int npage)
953+
dma_addr_t user_iova, int npage)
954954
{
955955
struct vfio_iommu *iommu = iommu_data;
956956
bool do_accounting;
@@ -964,10 +964,9 @@ static void vfio_iommu_type1_unpin_pages(void *iommu_data,
964964

965965
do_accounting = list_empty(&iommu->domain_list);
966966
for (i = 0; i < npage; i++) {
967+
dma_addr_t iova = user_iova + PAGE_SIZE * i;
967968
struct vfio_dma *dma;
968-
dma_addr_t iova;
969969

970-
iova = user_pfn[i] << PAGE_SHIFT;
971970
dma = vfio_find_dma(iommu, iova, PAGE_SIZE);
972971
if (!dma)
973972
break;

include/linux/vfio.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,9 @@ bool vfio_file_has_dev(struct file *file, struct vfio_device *device);
161161

162162
#define VFIO_PIN_PAGES_MAX_ENTRIES (PAGE_SIZE/sizeof(unsigned long))
163163

164-
int vfio_pin_pages(struct vfio_device *device, unsigned long *user_pfn,
164+
int vfio_pin_pages(struct vfio_device *device, dma_addr_t iova,
165165
int npage, int prot, unsigned long *phys_pfn);
166-
void vfio_unpin_pages(struct vfio_device *device, unsigned long *user_pfn,
167-
int npage);
166+
void vfio_unpin_pages(struct vfio_device *device, dma_addr_t iova, int npage);
168167
int vfio_dma_rw(struct vfio_device *device, dma_addr_t user_iova,
169168
void *data, size_t len, bool write);
170169

0 commit comments

Comments
 (0)