Skip to content

Commit 2fae6bb

Browse files
Jiqian Chenjgross1
authored andcommitted
xen/privcmd: Add new syscall to get gsi from dev
On PVH dom0, when passthrough a device to domU, QEMU and xl tools want to use gsi number to do pirq mapping, see QEMU code xen_pt_realize->xc_physdev_map_pirq, and xl code pci_add_dm_done->xc_physdev_map_pirq, but in current codes, the gsi number is got from file /sys/bus/pci/devices/<sbdf>/irq, that is wrong, because irq is not equal with gsi, they are in different spaces, so pirq mapping fails. And in current linux codes, there is no method to get gsi for userspace. For above purpose, record gsi of pcistub devices when init pcistub and add a new syscall into privcmd to let userspace can get gsi when they have a need. Signed-off-by: Jiqian Chen <[email protected]> Signed-off-by: Huang Rui <[email protected]> Signed-off-by: Jiqian Chen <[email protected]> Reviewed-by: Stefano Stabellini <[email protected]> Message-ID: <[email protected]> Signed-off-by: Juergen Gross <[email protected]>
1 parent b166b8a commit 2fae6bb

File tree

5 files changed

+84
-3
lines changed

5 files changed

+84
-3
lines changed

drivers/xen/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ config XEN_SCSI_BACKEND
261261
config XEN_PRIVCMD
262262
tristate "Xen hypercall passthrough driver"
263263
depends on XEN
264+
imply CONFIG_XEN_PCIDEV_BACKEND
264265
default m
265266
help
266267
The hypercall passthrough driver allows privileged user programs to

drivers/xen/privcmd.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@
4646
#include <xen/page.h>
4747
#include <xen/xen-ops.h>
4848
#include <xen/balloon.h>
49+
#ifdef CONFIG_XEN_ACPI
50+
#include <xen/acpi.h>
51+
#endif
4952

5053
#include "privcmd.h"
5154

@@ -844,6 +847,31 @@ static long privcmd_ioctl_mmap_resource(struct file *file,
844847
return rc;
845848
}
846849

850+
static long privcmd_ioctl_pcidev_get_gsi(struct file *file, void __user *udata)
851+
{
852+
#if defined(CONFIG_XEN_ACPI)
853+
int rc = -EINVAL;
854+
struct privcmd_pcidev_get_gsi kdata;
855+
856+
if (copy_from_user(&kdata, udata, sizeof(kdata)))
857+
return -EFAULT;
858+
859+
if (IS_REACHABLE(CONFIG_XEN_PCIDEV_BACKEND))
860+
rc = pcistub_get_gsi_from_sbdf(kdata.sbdf);
861+
862+
if (rc < 0)
863+
return rc;
864+
865+
kdata.gsi = rc;
866+
if (copy_to_user(udata, &kdata, sizeof(kdata)))
867+
return -EFAULT;
868+
869+
return 0;
870+
#else
871+
return -EINVAL;
872+
#endif
873+
}
874+
847875
#ifdef CONFIG_XEN_PRIVCMD_EVENTFD
848876
/* Irqfd support */
849877
static struct workqueue_struct *irqfd_cleanup_wq;
@@ -1543,6 +1571,10 @@ static long privcmd_ioctl(struct file *file,
15431571
ret = privcmd_ioctl_ioeventfd(file, udata);
15441572
break;
15451573

1574+
case IOCTL_PRIVCMD_PCIDEV_GET_GSI:
1575+
ret = privcmd_ioctl_pcidev_get_gsi(file, udata);
1576+
break;
1577+
15461578
default:
15471579
break;
15481580
}

drivers/xen/xen-pciback/pci_stub.c

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ struct pcistub_device {
5656

5757
struct pci_dev *dev;
5858
struct xen_pcibk_device *pdev;/* non-NULL if struct pci_dev is in use */
59+
#ifdef CONFIG_XEN_ACPI
60+
int gsi;
61+
#endif
5962
};
6063

6164
/* Access to pcistub_devices & seized_devices lists and the initialize_devices
@@ -88,6 +91,9 @@ static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev)
8891

8992
kref_init(&psdev->kref);
9093
spin_lock_init(&psdev->lock);
94+
#ifdef CONFIG_XEN_ACPI
95+
psdev->gsi = -1;
96+
#endif
9197

9298
return psdev;
9399
}
@@ -220,6 +226,25 @@ static struct pci_dev *pcistub_device_get_pci_dev(struct xen_pcibk_device *pdev,
220226
return pci_dev;
221227
}
222228

229+
#ifdef CONFIG_XEN_ACPI
230+
int pcistub_get_gsi_from_sbdf(unsigned int sbdf)
231+
{
232+
struct pcistub_device *psdev;
233+
int domain = (sbdf >> 16) & 0xffff;
234+
int bus = PCI_BUS_NUM(sbdf);
235+
int slot = PCI_SLOT(sbdf);
236+
int func = PCI_FUNC(sbdf);
237+
238+
psdev = pcistub_device_find(domain, bus, slot, func);
239+
240+
if (!psdev)
241+
return -ENODEV;
242+
243+
return psdev->gsi;
244+
}
245+
EXPORT_SYMBOL_GPL(pcistub_get_gsi_from_sbdf);
246+
#endif
247+
223248
struct pci_dev *pcistub_get_pci_dev_by_slot(struct xen_pcibk_device *pdev,
224249
int domain, int bus,
225250
int slot, int func)
@@ -367,14 +392,20 @@ static int pcistub_match(struct pci_dev *dev)
367392
return found;
368393
}
369394

370-
static int pcistub_init_device(struct pci_dev *dev)
395+
static int pcistub_init_device(struct pcistub_device *psdev)
371396
{
372397
struct xen_pcibk_dev_data *dev_data;
398+
struct pci_dev *dev;
373399
#ifdef CONFIG_XEN_ACPI
374400
int gsi, trigger, polarity;
375401
#endif
376402
int err = 0;
377403

404+
if (!psdev)
405+
return -EINVAL;
406+
407+
dev = psdev->dev;
408+
378409
dev_dbg(&dev->dev, "initializing...\n");
379410

380411
/* The PCI backend is not intended to be a module (or to work with
@@ -452,6 +483,7 @@ static int pcistub_init_device(struct pci_dev *dev)
452483
err = xen_pvh_setup_gsi(gsi, trigger, polarity);
453484
if (err)
454485
goto config_release;
486+
psdev->gsi = gsi;
455487
}
456488
#endif
457489

@@ -494,7 +526,7 @@ static int __init pcistub_init_devices_late(void)
494526

495527
spin_unlock_irqrestore(&pcistub_devices_lock, flags);
496528

497-
err = pcistub_init_device(psdev->dev);
529+
err = pcistub_init_device(psdev);
498530
if (err) {
499531
dev_err(&psdev->dev->dev,
500532
"error %d initializing device\n", err);
@@ -564,7 +596,7 @@ static int pcistub_seize(struct pci_dev *dev,
564596
spin_unlock_irqrestore(&pcistub_devices_lock, flags);
565597

566598
/* don't want irqs disabled when calling pcistub_init_device */
567-
err = pcistub_init_device(psdev->dev);
599+
err = pcistub_init_device(psdev);
568600

569601
spin_lock_irqsave(&pcistub_devices_lock, flags);
570602

include/uapi/xen/privcmd.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ struct privcmd_ioeventfd {
126126
__u8 pad[2];
127127
};
128128

129+
struct privcmd_pcidev_get_gsi {
130+
__u32 sbdf;
131+
__u32 gsi;
132+
};
133+
129134
/*
130135
* @cmd: IOCTL_PRIVCMD_HYPERCALL
131136
* @arg: &privcmd_hypercall_t
@@ -157,5 +162,7 @@ struct privcmd_ioeventfd {
157162
_IOW('P', 8, struct privcmd_irqfd)
158163
#define IOCTL_PRIVCMD_IOEVENTFD \
159164
_IOW('P', 9, struct privcmd_ioeventfd)
165+
#define IOCTL_PRIVCMD_PCIDEV_GET_GSI \
166+
_IOC(_IOC_NONE, 'P', 10, sizeof(struct privcmd_pcidev_get_gsi))
160167

161168
#endif /* __LINUX_PUBLIC_PRIVCMD_H__ */

include/xen/acpi.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,13 @@ static inline int xen_acpi_get_gsi_info(struct pci_dev *dev,
9191
}
9292
#endif
9393

94+
#ifdef CONFIG_XEN_PCI_STUB
95+
int pcistub_get_gsi_from_sbdf(unsigned int sbdf);
96+
#else
97+
static inline int pcistub_get_gsi_from_sbdf(unsigned int sbdf)
98+
{
99+
return -1;
100+
}
101+
#endif
102+
94103
#endif /* _XEN_ACPI_H */

0 commit comments

Comments
 (0)