Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions arch/x86/include/asm/xen/hypercall.h
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,12 @@ HYPERVISOR_xenpmu_op(unsigned int op, void *arg)
return _hypercall2(int, xenpmu_op, op, arg);
}

static inline long
HYPERVISOR_iommu_op(unsigned int subop, void *arg)
{
return _hypercall2(int, iommu_op, subop, arg);
}

static inline int
HYPERVISOR_dm_op(
domid_t dom, unsigned int nr_bufs, struct xen_dm_op_buf *bufs)
Expand Down
19 changes: 18 additions & 1 deletion arch/x86/pci/xen.c
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,24 @@ static void xen_teardown_msi_irqs(struct pci_dev *dev)

static void xen_pv_teardown_msi_irqs(struct pci_dev *dev)
{
if (dev->msix_enabled)
struct msi_desc *desc;
bool msix = false;

/*
* pci_disable_msix() clears msix_enabled in pci_msix_shutdown() before
* freeing the irqs brings us here, so it cannot say which of the two
* the device was using. Ask a descriptor instead: getting this wrong
* leaves the backend with MSI-X still enabled on the real device, and
* the next attempt to enable it fails with -EALREADY.
*
* The descriptor lock is already held by pci_disable_msix().
*/
msi_for_each_desc(desc, &dev->dev, MSI_DESC_ALL) {
msix = desc->pci.msi_attrib.is_msix;
break;
}

if (msix)
xen_pci_frontend_disable_msix(dev);
else
xen_pci_frontend_disable_msi(dev);
Expand Down
12 changes: 12 additions & 0 deletions drivers/iommu/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,18 @@ config VIRTIO_IOMMU

Say Y here if you intend to run this kernel as a guest.

config XEN_IOMMU
bool "Xen IOMMU driver"
depends on XEN
select IOMMU_API
select IOMMU_IO_PGTABLE
help
Xen PV-IOMMU driver.

Say Y here if you intend to run this kernel under Xen, either as
Dom0 or as a guest whose passed-through devices come through
vPCI.

config SPRD_IOMMU
tristate "Unisoc IOMMU Support"
depends on ARCH_SPRD || COMPILE_TEST
Expand Down
2 changes: 2 additions & 0 deletions drivers/iommu/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ obj-$(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) += io-pgtable-arm-v7s.o
obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE_KUNIT_TEST) += io-pgtable-arm-selftests.o
obj-$(CONFIG_IOMMU_IO_PGTABLE_DART) += io-pgtable-dart.o
obj-$(CONFIG_XEN_IOMMU) += io-pgtable-xen.o
obj-$(CONFIG_IOMMU_IOVA) += iova.o
obj-$(CONFIG_OF_IOMMU) += of_iommu.o
obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
Expand All @@ -38,3 +39,4 @@ obj-$(CONFIG_SPRD_IOMMU) += sprd-iommu.o
obj-$(CONFIG_APPLE_DART) += apple-dart.o
obj-$(CONFIG_VSI_IOMMU) += vsi-iommu.o
obj-$(CONFIG_IOMMU_DEBUG_PAGEALLOC) += iommu-debug-pagealloc.o
obj-$(CONFIG_XEN_IOMMU) += xen-iommu.o
14 changes: 13 additions & 1 deletion drivers/iommu/dma-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include <linux/of_iommu.h>
#include <linux/pci.h>
#include <linux/pci-p2pdma.h>

#include "iommu-priv.h"
#include <linux/scatterlist.h>
#include <linux/spinlock.h>
#include <linux/swiotlb.h>
Expand Down Expand Up @@ -559,7 +561,17 @@ static int iova_reserve_iommu_regions(struct device *dev,
LIST_HEAD(resv_regions);
int ret = 0;

if (dev_is_pci(dev)) {
/*
* A PCI host bridge's windows are reserved so that an IOVA cannot
* collide with an address the bridge would route to MMIO. Under a
* paravirtual IOMMU the IOVA space belongs to the hypervisor and is not
* the bridge's address space at all, and the windows a Xen guest sees
* are invented -- pcifront hands out iomem_resource itself, and a PVH
* guest with no host bridge _CRS gets Linux's catch-all default. There
* is nothing meaningful to reserve, and reserving it leaves no usable
* IOVA space whatsoever.
*/
if (dev_is_pci(dev) && !xen_iommu_manages_iova(dev)) {
ret = iova_reserve_pci_windows(to_pci_dev(dev), iovad);
if (ret)
return ret;
Expand Down
Loading