Commit a67efff2 authored by Oleksandr Andrushchenko's avatar Oleksandr Andrushchenko Committed by Boris Ostrovsky
Browse files

xen-pciback: allow compiling on other archs than x86



Xen-pciback driver was designed to be built for x86 only. But it
can also be used by other architectures, e.g. Arm.

Currently PCI backend implements multiple functionalities at a time,
such as:
1. It is used as a database for assignable PCI devices, e.g. xl
   pci-assignable-{add|remove|list} manipulates that list. So, whenever
   the toolstack needs to know which PCI devices can be passed through
   it reads that from the relevant sysfs entries of the pciback.
2. It is used to hold the unbound PCI devices list, e.g. when passing
   through a PCI device it needs to be unbound from the relevant device
   driver and bound to pciback (strictly speaking it is not required
   that the device is bound to pciback, but pciback is again used as a
   database of the passed through PCI devices, so we can re-bind the
   devices back to their original drivers when guest domain shuts down)
3. Device reset for the devices being passed through
4. Para-virtualised use-cases support

The para-virtualised part of the driver is not always needed as some
architectures, e.g. Arm or x86 PVH Dom0, are not using backend-frontend
model for PCI device passthrough.

For such use-cases make the very first step in splitting the
xen-pciback driver into two parts: Xen PCI stub and PCI PV backend
drivers.

For that add new configuration options CONFIG_XEN_PCI_STUB and
CONFIG_XEN_PCIDEV_STUB, so the driver can be limited in its
functionality, e.g. no support for para-virtualised scenario.
x86 platform will continue using CONFIG_XEN_PCIDEV_BACKEND for the
fully featured backend driver.

Signed-off-by: default avatarOleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
Signed-off-by: default avatarAnastasiia Lukianenko <anastasiia_lukianenko@epam.com>
Reviewed-by: default avatarStefano Stabellini <sstabellini@kernel.org>
Reviewed-by: default avatarJuergen Gross <jgross@suse.com>
Link: https://lore.kernel.org/r/20211028143620.144936-1-andr2000@gmail.com


Signed-off-by: default avatarBoris Ostrovsky <boris.ostrovsky@oracle.com>
parent e453f872
Loading
Loading
Loading
Loading
+0 −19
Original line number Diff line number Diff line
@@ -22,25 +22,6 @@ static inline int __init pci_xen_initial_domain(void)
	return -1;
}
#endif
#ifdef CONFIG_XEN_DOM0
int xen_find_device_domain_owner(struct pci_dev *dev);
int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain);
int xen_unregister_device_domain_owner(struct pci_dev *dev);
#else
static inline int xen_find_device_domain_owner(struct pci_dev *dev)
{
	return -1;
}
static inline int xen_register_device_domain_owner(struct pci_dev *dev,
						   uint16_t domain)
{
	return -1;
}
static inline int xen_unregister_device_domain_owner(struct pci_dev *dev)
{
	return -1;
}
#endif

#if defined(CONFIG_PCI_MSI)
#if defined(CONFIG_PCI_XEN)
+1 −75
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@

#include <xen/features.h>
#include <xen/events.h>
#include <xen/pci.h>
#include <asm/xen/pci.h>
#include <asm/xen/cpuid.h>
#include <asm/apic.h>
@@ -585,78 +586,3 @@ int __init pci_xen_initial_domain(void)
}
#endif
#ifdef CONFIG_XEN_DOM0

struct xen_device_domain_owner {
	domid_t domain;
	struct pci_dev *dev;
	struct list_head list;
};

static DEFINE_SPINLOCK(dev_domain_list_spinlock);
static struct list_head dev_domain_list = LIST_HEAD_INIT(dev_domain_list);

static struct xen_device_domain_owner *find_device(struct pci_dev *dev)
{
	struct xen_device_domain_owner *owner;

	list_for_each_entry(owner, &dev_domain_list, list) {
		if (owner->dev == dev)
			return owner;
	}
	return NULL;
}

int xen_find_device_domain_owner(struct pci_dev *dev)
{
	struct xen_device_domain_owner *owner;
	int domain = -ENODEV;

	spin_lock(&dev_domain_list_spinlock);
	owner = find_device(dev);
	if (owner)
		domain = owner->domain;
	spin_unlock(&dev_domain_list_spinlock);
	return domain;
}
EXPORT_SYMBOL_GPL(xen_find_device_domain_owner);

int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain)
{
	struct xen_device_domain_owner *owner;

	owner = kzalloc(sizeof(struct xen_device_domain_owner), GFP_KERNEL);
	if (!owner)
		return -ENODEV;

	spin_lock(&dev_domain_list_spinlock);
	if (find_device(dev)) {
		spin_unlock(&dev_domain_list_spinlock);
		kfree(owner);
		return -EEXIST;
	}
	owner->domain = domain;
	owner->dev = dev;
	list_add_tail(&owner->list, &dev_domain_list);
	spin_unlock(&dev_domain_list_spinlock);
	return 0;
}
EXPORT_SYMBOL_GPL(xen_register_device_domain_owner);

int xen_unregister_device_domain_owner(struct pci_dev *dev)
{
	struct xen_device_domain_owner *owner;

	spin_lock(&dev_domain_list_spinlock);
	owner = find_device(dev);
	if (!owner) {
		spin_unlock(&dev_domain_list_spinlock);
		return -ENODEV;
	}
	list_del(&owner->list);
	spin_unlock(&dev_domain_list_spinlock);
	kfree(owner);
	return 0;
}
EXPORT_SYMBOL_GPL(xen_unregister_device_domain_owner);
#endif /* CONFIG_XEN_DOM0 */
+24 −0
Original line number Diff line number Diff line
@@ -181,10 +181,34 @@ config SWIOTLB_XEN
	select DMA_OPS
	select SWIOTLB

config XEN_PCI_STUB
	bool

config XEN_PCIDEV_STUB
	tristate "Xen PCI-device stub driver"
	depends on PCI && !X86 && XEN
	depends on XEN_BACKEND
	select XEN_PCI_STUB
	default m
	help
	  The PCI device stub driver provides limited version of the PCI
	  device backend driver without para-virtualized support for guests.
	  If you select this to be a module, you will need to make sure no
	  other driver has bound to the device(s) you want to make visible to
	  other guests.

	  The "hide" parameter (only applicable if backend driver is compiled
	  into the kernel) allows you to bind the PCI devices to this module
	  from the default device drivers. The argument is the list of PCI BDFs:
	  xen-pciback.hide=(03:00.0)(04:00.0)

	  If in doubt, say m.

config XEN_PCIDEV_BACKEND
	tristate "Xen PCI-device backend driver"
	depends on PCI && X86 && XEN
	depends on XEN_BACKEND
	select XEN_PCI_STUB
	default m
	help
	  The PCI device backend driver allows the kernel to export arbitrary
+1 −1
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@ obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o
obj-$(CONFIG_XEN_PVHVM_GUEST)		+= platform-pci.o
obj-$(CONFIG_SWIOTLB_XEN)		+= swiotlb-xen.o
obj-$(CONFIG_XEN_MCE_LOG)		+= mcelog.o
obj-$(CONFIG_XEN_PCIDEV_BACKEND)	+= xen-pciback/
obj-$(CONFIG_XEN_PCI_STUB)	        += xen-pciback/
obj-$(CONFIG_XEN_PRIVCMD)		+= xen-privcmd.o
obj-$(CONFIG_XEN_ACPI_PROCESSOR)	+= xen-acpi-processor.o
obj-$(CONFIG_XEN_EFI)			+= efi.o
+76 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include <linux/pci.h>
#include <linux/acpi.h>
#include <linux/pci-acpi.h>
#include <xen/pci.h>
#include <xen/xen.h>
#include <xen/interface/physdev.h>
#include <xen/interface/xen.h>
@@ -254,3 +255,78 @@ static int xen_mcfg_late(void)
	return 0;
}
#endif

#ifdef CONFIG_XEN_DOM0
struct xen_device_domain_owner {
	domid_t domain;
	struct pci_dev *dev;
	struct list_head list;
};

static DEFINE_SPINLOCK(dev_domain_list_spinlock);
static struct list_head dev_domain_list = LIST_HEAD_INIT(dev_domain_list);

static struct xen_device_domain_owner *find_device(struct pci_dev *dev)
{
	struct xen_device_domain_owner *owner;

	list_for_each_entry(owner, &dev_domain_list, list) {
		if (owner->dev == dev)
			return owner;
	}
	return NULL;
}

int xen_find_device_domain_owner(struct pci_dev *dev)
{
	struct xen_device_domain_owner *owner;
	int domain = -ENODEV;

	spin_lock(&dev_domain_list_spinlock);
	owner = find_device(dev);
	if (owner)
		domain = owner->domain;
	spin_unlock(&dev_domain_list_spinlock);
	return domain;
}
EXPORT_SYMBOL_GPL(xen_find_device_domain_owner);

int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain)
{
	struct xen_device_domain_owner *owner;

	owner = kzalloc(sizeof(struct xen_device_domain_owner), GFP_KERNEL);
	if (!owner)
		return -ENODEV;

	spin_lock(&dev_domain_list_spinlock);
	if (find_device(dev)) {
		spin_unlock(&dev_domain_list_spinlock);
		kfree(owner);
		return -EEXIST;
	}
	owner->domain = domain;
	owner->dev = dev;
	list_add_tail(&owner->list, &dev_domain_list);
	spin_unlock(&dev_domain_list_spinlock);
	return 0;
}
EXPORT_SYMBOL_GPL(xen_register_device_domain_owner);

int xen_unregister_device_domain_owner(struct pci_dev *dev)
{
	struct xen_device_domain_owner *owner;

	spin_lock(&dev_domain_list_spinlock);
	owner = find_device(dev);
	if (!owner) {
		spin_unlock(&dev_domain_list_spinlock);
		return -ENODEV;
	}
	list_del(&owner->list);
	spin_unlock(&dev_domain_list_spinlock);
	kfree(owner);
	return 0;
}
EXPORT_SYMBOL_GPL(xen_unregister_device_domain_owner);
#endif
Loading