Skip to content

Commit 2fb732b

Browse files
committed
Merge tag 'vfio-v5.7-rc1' of git://github.com/awilliam/linux-vfio
Pull VFIO updates from Alex Williamson: - vfio-pci SR-IOV support (Alex Williamson) - vfio DMA read/write interface (Yan Zhao) - Fix vfio-platform erroneous IRQ error log (Eric Auger) - Fix shared ATSD support for NVLink on POWER (Sam Bobroff) - Fix init error without CONFIG_IOMMU_DMA (Andre Przywara) * tag 'vfio-v5.7-rc1' of git://github.com/awilliam/linux-vfio: vfio: Ignore -ENODEV when getting MSI cookie vfio-pci/nvlink2: Allow fallback to ibm,mmio-atsd[0] vfio/pci: Cleanup .probe() exit paths vfio/pci: Remove dev_fmt definition vfio/pci: Add sriov_configure support vfio: Introduce VFIO_DEVICE_FEATURE ioctl and first user vfio/pci: Introduce VF token vfio/pci: Implement match ops vfio: Include optional device match in vfio_device_ops callbacks vfio: avoid inefficient operations on VFIO group in vfio_pin/unpin_pages vfio: introduce vfio_dma_rw to read/write a range of IOVAs vfio: allow external user to get vfio group from device vfio: platform: Switch to platform_get_irq_optional()
2 parents ad0bf4e + f44efca commit 2fb732b

File tree

8 files changed

+710
-32
lines changed

8 files changed

+710
-32
lines changed

drivers/vfio/pci/vfio_pci.c

Lines changed: 366 additions & 24 deletions
Large diffs are not rendered by default.

drivers/vfio/pci/vfio_pci_nvlink2.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -422,8 +422,14 @@ int vfio_pci_ibm_npu2_init(struct vfio_pci_device *vdev)
422422

423423
if (of_property_read_u64_index(hose->dn, "ibm,mmio-atsd", nvlink_index,
424424
&mmio_atsd)) {
425-
dev_warn(&vdev->pdev->dev, "No available ATSD found\n");
426-
mmio_atsd = 0;
425+
if (of_property_read_u64_index(hose->dn, "ibm,mmio-atsd", 0,
426+
&mmio_atsd)) {
427+
dev_warn(&vdev->pdev->dev, "No available ATSD found\n");
428+
mmio_atsd = 0;
429+
} else {
430+
dev_warn(&vdev->pdev->dev,
431+
"Using fallback ibm,mmio-atsd[0] for ATSD.\n");
432+
}
427433
}
428434

429435
if (of_property_read_u64(npu_node, "ibm,device-tgt-addr", &tgt)) {

drivers/vfio/pci/vfio_pci_private.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include <linux/pci.h>
1313
#include <linux/irqbypass.h>
1414
#include <linux/types.h>
15+
#include <linux/uuid.h>
16+
#include <linux/notifier.h>
1517

1618
#ifndef VFIO_PCI_PRIVATE_H
1719
#define VFIO_PCI_PRIVATE_H
@@ -84,6 +86,12 @@ struct vfio_pci_reflck {
8486
struct mutex lock;
8587
};
8688

89+
struct vfio_pci_vf_token {
90+
struct mutex lock;
91+
uuid_t uuid;
92+
int users;
93+
};
94+
8795
struct vfio_pci_device {
8896
struct pci_dev *pdev;
8997
void __iomem *barmap[PCI_STD_NUM_BARS];
@@ -122,6 +130,8 @@ struct vfio_pci_device {
122130
struct list_head dummy_resources_list;
123131
struct mutex ioeventfds_lock;
124132
struct list_head ioeventfds_list;
133+
struct vfio_pci_vf_token *vf_token;
134+
struct notifier_block nb;
125135
};
126136

127137
#define is_intx(vdev) (vdev->irq_type == VFIO_PCI_INTX_IRQ_INDEX)

drivers/vfio/platform/vfio_platform.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ static int get_platform_irq(struct vfio_platform_device *vdev, int i)
4444
{
4545
struct platform_device *pdev = (struct platform_device *) vdev->opaque;
4646

47-
return platform_get_irq(pdev, i);
47+
return platform_get_irq_optional(pdev, i);
4848
}
4949

5050
static int vfio_platform_probe(struct platform_device *pdev)

drivers/vfio/vfio.c

Lines changed: 194 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -875,11 +875,23 @@ EXPORT_SYMBOL_GPL(vfio_device_get_from_dev);
875875
static struct vfio_device *vfio_device_get_from_name(struct vfio_group *group,
876876
char *buf)
877877
{
878-
struct vfio_device *it, *device = NULL;
878+
struct vfio_device *it, *device = ERR_PTR(-ENODEV);
879879

880880
mutex_lock(&group->device_lock);
881881
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) {
883895
device = it;
884896
vfio_device_get(device);
885897
break;
@@ -1430,8 +1442,8 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
14301442
return -EPERM;
14311443

14321444
device = vfio_device_get_from_name(group, buf);
1433-
if (!device)
1434-
return -ENODEV;
1445+
if (IS_ERR(device))
1446+
return PTR_ERR(device);
14351447

14361448
ret = device->ops->open(device->device_data);
14371449
if (ret) {
@@ -1720,6 +1732,44 @@ struct vfio_group *vfio_group_get_external_user(struct file *filep)
17201732
}
17211733
EXPORT_SYMBOL_GPL(vfio_group_get_external_user);
17221734

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+
17231773
void vfio_group_put_external_user(struct vfio_group *group)
17241774
{
17251775
vfio_group_try_dissolve_container(group);
@@ -1961,6 +2011,146 @@ int vfio_unpin_pages(struct device *dev, unsigned long *user_pfn, int npage)
19612011
}
19622012
EXPORT_SYMBOL(vfio_unpin_pages);
19632013

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+
19642154
static int vfio_register_iommu_notifier(struct vfio_group *group,
19652155
unsigned long *events,
19662156
struct notifier_block *nb)

drivers/vfio/vfio_iommu_type1.c

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <linux/iommu.h>
2828
#include <linux/module.h>
2929
#include <linux/mm.h>
30+
#include <linux/mmu_context.h>
3031
#include <linux/rbtree.h>
3132
#include <linux/sched/signal.h>
3233
#include <linux/sched/mm.h>
@@ -1786,7 +1787,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
17861787

17871788
if (resv_msi) {
17881789
ret = iommu_get_msi_cookie(domain->domain, resv_msi_base);
1789-
if (ret)
1790+
if (ret && ret != -ENODEV)
17901791
goto out_detach;
17911792
}
17921793

@@ -2305,6 +2306,80 @@ static int vfio_iommu_type1_unregister_notifier(void *iommu_data,
23052306
return blocking_notifier_chain_unregister(&iommu->notifier, nb);
23062307
}
23072308

2309+
static int vfio_iommu_type1_dma_rw_chunk(struct vfio_iommu *iommu,
2310+
dma_addr_t user_iova, void *data,
2311+
size_t count, bool write,
2312+
size_t *copied)
2313+
{
2314+
struct mm_struct *mm;
2315+
unsigned long vaddr;
2316+
struct vfio_dma *dma;
2317+
bool kthread = current->mm == NULL;
2318+
size_t offset;
2319+
2320+
*copied = 0;
2321+
2322+
dma = vfio_find_dma(iommu, user_iova, 1);
2323+
if (!dma)
2324+
return -EINVAL;
2325+
2326+
if ((write && !(dma->prot & IOMMU_WRITE)) ||
2327+
!(dma->prot & IOMMU_READ))
2328+
return -EPERM;
2329+
2330+
mm = get_task_mm(dma->task);
2331+
2332+
if (!mm)
2333+
return -EPERM;
2334+
2335+
if (kthread)
2336+
use_mm(mm);
2337+
else if (current->mm != mm)
2338+
goto out;
2339+
2340+
offset = user_iova - dma->iova;
2341+
2342+
if (count > dma->size - offset)
2343+
count = dma->size - offset;
2344+
2345+
vaddr = dma->vaddr + offset;
2346+
2347+
if (write)
2348+
*copied = __copy_to_user((void __user *)vaddr, data,
2349+
count) ? 0 : count;
2350+
else
2351+
*copied = __copy_from_user(data, (void __user *)vaddr,
2352+
count) ? 0 : count;
2353+
if (kthread)
2354+
unuse_mm(mm);
2355+
out:
2356+
mmput(mm);
2357+
return *copied ? 0 : -EFAULT;
2358+
}
2359+
2360+
static int vfio_iommu_type1_dma_rw(void *iommu_data, dma_addr_t user_iova,
2361+
void *data, size_t count, bool write)
2362+
{
2363+
struct vfio_iommu *iommu = iommu_data;
2364+
int ret = 0;
2365+
size_t done;
2366+
2367+
mutex_lock(&iommu->lock);
2368+
while (count > 0) {
2369+
ret = vfio_iommu_type1_dma_rw_chunk(iommu, user_iova, data,
2370+
count, write, &done);
2371+
if (ret)
2372+
break;
2373+
2374+
count -= done;
2375+
data += done;
2376+
user_iova += done;
2377+
}
2378+
2379+
mutex_unlock(&iommu->lock);
2380+
return ret;
2381+
}
2382+
23082383
static const struct vfio_iommu_driver_ops vfio_iommu_driver_ops_type1 = {
23092384
.name = "vfio-iommu-type1",
23102385
.owner = THIS_MODULE,
@@ -2317,6 +2392,7 @@ static const struct vfio_iommu_driver_ops vfio_iommu_driver_ops_type1 = {
23172392
.unpin_pages = vfio_iommu_type1_unpin_pages,
23182393
.register_notifier = vfio_iommu_type1_register_notifier,
23192394
.unregister_notifier = vfio_iommu_type1_unregister_notifier,
2395+
.dma_rw = vfio_iommu_type1_dma_rw,
23202396
};
23212397

23222398
static int __init vfio_iommu_type1_init(void)

0 commit comments

Comments
 (0)