Skip to content

Commit a67efff

Browse files
Oleksandr Andrushchenkobostrovs
authored andcommitted
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: Oleksandr Andrushchenko <[email protected]> Signed-off-by: Anastasiia Lukianenko <[email protected]> Reviewed-by: Stefano Stabellini <[email protected]> Reviewed-by: Juergen Gross <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Boris Ostrovsky <[email protected]>
1 parent e453f87 commit a67efff

File tree

11 files changed

+156
-100
lines changed

11 files changed

+156
-100
lines changed

arch/x86/include/asm/xen/pci.h

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,6 @@ static inline int __init pci_xen_initial_domain(void)
2222
return -1;
2323
}
2424
#endif
25-
#ifdef CONFIG_XEN_DOM0
26-
int xen_find_device_domain_owner(struct pci_dev *dev);
27-
int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain);
28-
int xen_unregister_device_domain_owner(struct pci_dev *dev);
29-
#else
30-
static inline int xen_find_device_domain_owner(struct pci_dev *dev)
31-
{
32-
return -1;
33-
}
34-
static inline int xen_register_device_domain_owner(struct pci_dev *dev,
35-
uint16_t domain)
36-
{
37-
return -1;
38-
}
39-
static inline int xen_unregister_device_domain_owner(struct pci_dev *dev)
40-
{
41-
return -1;
42-
}
43-
#endif
4425

4526
#if defined(CONFIG_PCI_MSI)
4627
#if defined(CONFIG_PCI_XEN)

arch/x86/pci/xen.c

Lines changed: 1 addition & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include <xen/features.h>
2525
#include <xen/events.h>
26+
#include <xen/pci.h>
2627
#include <asm/xen/pci.h>
2728
#include <asm/xen/cpuid.h>
2829
#include <asm/apic.h>
@@ -585,78 +586,3 @@ int __init pci_xen_initial_domain(void)
585586
}
586587
#endif
587588

588-
#ifdef CONFIG_XEN_DOM0
589-
590-
struct xen_device_domain_owner {
591-
domid_t domain;
592-
struct pci_dev *dev;
593-
struct list_head list;
594-
};
595-
596-
static DEFINE_SPINLOCK(dev_domain_list_spinlock);
597-
static struct list_head dev_domain_list = LIST_HEAD_INIT(dev_domain_list);
598-
599-
static struct xen_device_domain_owner *find_device(struct pci_dev *dev)
600-
{
601-
struct xen_device_domain_owner *owner;
602-
603-
list_for_each_entry(owner, &dev_domain_list, list) {
604-
if (owner->dev == dev)
605-
return owner;
606-
}
607-
return NULL;
608-
}
609-
610-
int xen_find_device_domain_owner(struct pci_dev *dev)
611-
{
612-
struct xen_device_domain_owner *owner;
613-
int domain = -ENODEV;
614-
615-
spin_lock(&dev_domain_list_spinlock);
616-
owner = find_device(dev);
617-
if (owner)
618-
domain = owner->domain;
619-
spin_unlock(&dev_domain_list_spinlock);
620-
return domain;
621-
}
622-
EXPORT_SYMBOL_GPL(xen_find_device_domain_owner);
623-
624-
int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain)
625-
{
626-
struct xen_device_domain_owner *owner;
627-
628-
owner = kzalloc(sizeof(struct xen_device_domain_owner), GFP_KERNEL);
629-
if (!owner)
630-
return -ENODEV;
631-
632-
spin_lock(&dev_domain_list_spinlock);
633-
if (find_device(dev)) {
634-
spin_unlock(&dev_domain_list_spinlock);
635-
kfree(owner);
636-
return -EEXIST;
637-
}
638-
owner->domain = domain;
639-
owner->dev = dev;
640-
list_add_tail(&owner->list, &dev_domain_list);
641-
spin_unlock(&dev_domain_list_spinlock);
642-
return 0;
643-
}
644-
EXPORT_SYMBOL_GPL(xen_register_device_domain_owner);
645-
646-
int xen_unregister_device_domain_owner(struct pci_dev *dev)
647-
{
648-
struct xen_device_domain_owner *owner;
649-
650-
spin_lock(&dev_domain_list_spinlock);
651-
owner = find_device(dev);
652-
if (!owner) {
653-
spin_unlock(&dev_domain_list_spinlock);
654-
return -ENODEV;
655-
}
656-
list_del(&owner->list);
657-
spin_unlock(&dev_domain_list_spinlock);
658-
kfree(owner);
659-
return 0;
660-
}
661-
EXPORT_SYMBOL_GPL(xen_unregister_device_domain_owner);
662-
#endif /* CONFIG_XEN_DOM0 */

drivers/xen/Kconfig

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,34 @@ config SWIOTLB_XEN
181181
select DMA_OPS
182182
select SWIOTLB
183183

184+
config XEN_PCI_STUB
185+
bool
186+
187+
config XEN_PCIDEV_STUB
188+
tristate "Xen PCI-device stub driver"
189+
depends on PCI && !X86 && XEN
190+
depends on XEN_BACKEND
191+
select XEN_PCI_STUB
192+
default m
193+
help
194+
The PCI device stub driver provides limited version of the PCI
195+
device backend driver without para-virtualized support for guests.
196+
If you select this to be a module, you will need to make sure no
197+
other driver has bound to the device(s) you want to make visible to
198+
other guests.
199+
200+
The "hide" parameter (only applicable if backend driver is compiled
201+
into the kernel) allows you to bind the PCI devices to this module
202+
from the default device drivers. The argument is the list of PCI BDFs:
203+
xen-pciback.hide=(03:00.0)(04:00.0)
204+
205+
If in doubt, say m.
206+
184207
config XEN_PCIDEV_BACKEND
185208
tristate "Xen PCI-device backend driver"
186209
depends on PCI && X86 && XEN
187210
depends on XEN_BACKEND
211+
select XEN_PCI_STUB
188212
default m
189213
help
190214
The PCI device backend driver allows the kernel to export arbitrary

drivers/xen/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o
2424
obj-$(CONFIG_XEN_PVHVM_GUEST) += platform-pci.o
2525
obj-$(CONFIG_SWIOTLB_XEN) += swiotlb-xen.o
2626
obj-$(CONFIG_XEN_MCE_LOG) += mcelog.o
27-
obj-$(CONFIG_XEN_PCIDEV_BACKEND) += xen-pciback/
27+
obj-$(CONFIG_XEN_PCI_STUB) += xen-pciback/
2828
obj-$(CONFIG_XEN_PRIVCMD) += xen-privcmd.o
2929
obj-$(CONFIG_XEN_ACPI_PROCESSOR) += xen-acpi-processor.o
3030
obj-$(CONFIG_XEN_EFI) += efi.o

drivers/xen/pci.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/pci.h>
99
#include <linux/acpi.h>
1010
#include <linux/pci-acpi.h>
11+
#include <xen/pci.h>
1112
#include <xen/xen.h>
1213
#include <xen/interface/physdev.h>
1314
#include <xen/interface/xen.h>
@@ -254,3 +255,78 @@ static int xen_mcfg_late(void)
254255
return 0;
255256
}
256257
#endif
258+
259+
#ifdef CONFIG_XEN_DOM0
260+
struct xen_device_domain_owner {
261+
domid_t domain;
262+
struct pci_dev *dev;
263+
struct list_head list;
264+
};
265+
266+
static DEFINE_SPINLOCK(dev_domain_list_spinlock);
267+
static struct list_head dev_domain_list = LIST_HEAD_INIT(dev_domain_list);
268+
269+
static struct xen_device_domain_owner *find_device(struct pci_dev *dev)
270+
{
271+
struct xen_device_domain_owner *owner;
272+
273+
list_for_each_entry(owner, &dev_domain_list, list) {
274+
if (owner->dev == dev)
275+
return owner;
276+
}
277+
return NULL;
278+
}
279+
280+
int xen_find_device_domain_owner(struct pci_dev *dev)
281+
{
282+
struct xen_device_domain_owner *owner;
283+
int domain = -ENODEV;
284+
285+
spin_lock(&dev_domain_list_spinlock);
286+
owner = find_device(dev);
287+
if (owner)
288+
domain = owner->domain;
289+
spin_unlock(&dev_domain_list_spinlock);
290+
return domain;
291+
}
292+
EXPORT_SYMBOL_GPL(xen_find_device_domain_owner);
293+
294+
int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain)
295+
{
296+
struct xen_device_domain_owner *owner;
297+
298+
owner = kzalloc(sizeof(struct xen_device_domain_owner), GFP_KERNEL);
299+
if (!owner)
300+
return -ENODEV;
301+
302+
spin_lock(&dev_domain_list_spinlock);
303+
if (find_device(dev)) {
304+
spin_unlock(&dev_domain_list_spinlock);
305+
kfree(owner);
306+
return -EEXIST;
307+
}
308+
owner->domain = domain;
309+
owner->dev = dev;
310+
list_add_tail(&owner->list, &dev_domain_list);
311+
spin_unlock(&dev_domain_list_spinlock);
312+
return 0;
313+
}
314+
EXPORT_SYMBOL_GPL(xen_register_device_domain_owner);
315+
316+
int xen_unregister_device_domain_owner(struct pci_dev *dev)
317+
{
318+
struct xen_device_domain_owner *owner;
319+
320+
spin_lock(&dev_domain_list_spinlock);
321+
owner = find_device(dev);
322+
if (!owner) {
323+
spin_unlock(&dev_domain_list_spinlock);
324+
return -ENODEV;
325+
}
326+
list_del(&owner->list);
327+
spin_unlock(&dev_domain_list_spinlock);
328+
kfree(owner);
329+
return 0;
330+
}
331+
EXPORT_SYMBOL_GPL(xen_unregister_device_domain_owner);
332+
#endif

drivers/xen/xen-pciback/Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# SPDX-License-Identifier: GPL-2.0
2+
3+
# N.B. The below cannot be expressed with a single line using
4+
# CONFIG_XEN_PCI_STUB as it always remains in "y" state,
5+
# thus preventing the driver to be built as a module.
6+
# Please note, that CONFIG_XEN_PCIDEV_BACKEND and
7+
# CONFIG_XEN_PCIDEV_STUB are mutually exclusive.
28
obj-$(CONFIG_XEN_PCIDEV_BACKEND) += xen-pciback.o
9+
obj-$(CONFIG_XEN_PCIDEV_STUB) += xen-pciback.o
310

411
xen-pciback-y := pci_stub.o pciback_ops.o xenbus.o
512
xen-pciback-y += conf_space.o conf_space_header.o \

drivers/xen/xen-pciback/conf_space_header.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,12 @@ static void *bar_init(struct pci_dev *dev, int offset)
236236
else {
237237
pos = (offset - PCI_BASE_ADDRESS_0) / 4;
238238
if (pos && (res[pos - 1].flags & IORESOURCE_MEM_64)) {
239-
bar->val = res[pos - 1].start >> 32;
240-
bar->len_val = -resource_size(&res[pos - 1]) >> 32;
239+
/*
240+
* Use ">> 16 >> 16" instead of direct ">> 32" shift
241+
* to avoid warnings on 32-bit architectures.
242+
*/
243+
bar->val = res[pos - 1].start >> 16 >> 16;
244+
bar->len_val = -resource_size(&res[pos - 1]) >> 16 >> 16;
241245
return bar;
242246
}
243247
}

drivers/xen/xen-pciback/pci_stub.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
#include <linux/sched.h>
2020
#include <linux/atomic.h>
2121
#include <xen/events.h>
22-
#include <asm/xen/pci.h>
22+
#include <xen/pci.h>
23+
#include <xen/xen.h>
2324
#include <asm/xen/hypervisor.h>
2425
#include <xen/interface/physdev.h>
2526
#include "pciback.h"

drivers/xen/xen-pciback/pciback.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ struct pci_dev *pcistub_get_pci_dev(struct xen_pcibk_device *pdev,
7171
struct pci_dev *dev);
7272
void pcistub_put_pci_dev(struct pci_dev *dev);
7373

74+
static inline bool xen_pcibk_pv_support(void)
75+
{
76+
return IS_ENABLED(CONFIG_XEN_PCIDEV_BACKEND);
77+
}
78+
7479
/* Ensure a device is turned off or reset */
7580
void xen_pcibk_reset_device(struct pci_dev *pdev);
7681

drivers/xen/xen-pciback/xenbus.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include <linux/workqueue.h>
1515
#include <xen/xenbus.h>
1616
#include <xen/events.h>
17-
#include <asm/xen/pci.h>
17+
#include <xen/pci.h>
1818
#include "pciback.h"
1919

2020
#define INVALID_EVTCHN_IRQ (-1)
@@ -743,6 +743,9 @@ const struct xen_pcibk_backend *__read_mostly xen_pcibk_backend;
743743

744744
int __init xen_pcibk_xenbus_register(void)
745745
{
746+
if (!xen_pcibk_pv_support())
747+
return 0;
748+
746749
xen_pcibk_backend = &xen_pcibk_vpci_backend;
747750
if (passthrough)
748751
xen_pcibk_backend = &xen_pcibk_passthrough_backend;
@@ -752,5 +755,6 @@ int __init xen_pcibk_xenbus_register(void)
752755

753756
void __exit xen_pcibk_xenbus_unregister(void)
754757
{
755-
xenbus_unregister_driver(&xen_pcibk_driver);
758+
if (xen_pcibk_pv_support())
759+
xenbus_unregister_driver(&xen_pcibk_driver);
756760
}

0 commit comments

Comments
 (0)