We walk the XenStore keys to see if there is a matching PCI device
that is assigned to a non-privileged PV domain (that uses the pciback module).
If so,
we extract the domain id and use that for to map the IPI for the MSI
to the correct guest.
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
---
drivers/xen/events.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 51 insertions(+), 2 deletions(-)
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index d3c267f..41772d5 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -45,6 +45,7 @@
#include <xen/interface/xen.h>
#include <xen/interface/event_channel.h>
+#include <xen/xenbus.h>
#include "../pci/msi.h"
/*
@@ -92,6 +93,7 @@ struct irq_info
unsigned short nr;
unsigned char vector;
unsigned char flags;
+ domid_t domid;
} pirq;
} u;
};
@@ -148,7 +150,8 @@ static struct irq_info mk_pirq_info(unsigned short evtchn,
unsigned short pirq, unsigned short vector)
{
return (struct irq_info) { .type = IRQT_PIRQ, .evtchn = evtchn,
- .cpu = 0, .u.pirq = { .nr = pirq, .vector = vector } };
+ .cpu = 0, .u.pirq =
+ { .nr = pirq, .vector = vector, .domid = DOMID_SELF } };
}
/*
@@ -595,7 +598,7 @@ int xen_destroy_irq(int irq)
goto out;
unmap_irq.pirq = info->u.pirq.nr;
- unmap_irq.domid = DOMID_SELF;
+ unmap_irq.domid = info->u.pirq.domid;
rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq);
if (rc) {
printk(KERN_WARNING "unmap irq failed %d\n", rc);
@@ -610,6 +613,43 @@ out:
spin_unlock(&irq_mapping_update_lock);
return rc;
}
+#define XS_PCI_SEARCH "/local/domain/0/backend/pci/"
+#define XS_PCI_SEARCH_LEN 28
+
+static int get_domid_for_dev(char *nodename, char *path, char *val, void *data)
+{
+ struct pci_dev *dev = (struct pci_dev *)data;
+
+ /* We are looking for:
+ * CB inv[/local/domain/0/backend/pci/3/0/dev-1]=0000:00:14.5 */
+
+ if (!dev || !pci_name(dev))
+ return -ENODEV;
+
+ if (strncmp(nodename, XS_PCI_SEARCH, XS_PCI_SEARCH_LEN) == 0)
+ {
+ if (strncmp(path, "dev", 3) == 0) {
+ char *name = NULL;
+ unsigned int domid;
+
+ /* The val contains: 0000:00:14.5 */
+ if (strcmp(val, pci_name(dev)) != 0)
+ return 0;
+
+ /* From here on, extract the Domain ID */
+ name = strstr(nodename, "pci/");
+ if (!name)
+ return 0;
+
+ if (sscanf(name, "pci/%u", &domid) != 1)
+ return 0;
+
+ dev_dbg(&dev->dev,"Assigned to domain %u.\n", domid);
+ return domid;
+ }
+ }
+ return 0;
+}
int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type)
{
@@ -620,6 +660,12 @@ int xen_create_msi_irq(struct pci_dev *dev, struct
msi_desc *msidesc, int type)
int pos;
u32 table_offset, bir;
+ /* Walk the XenStore keys to see if the device is assigned to any
+ * domain. If so, extract the domain id. */
+ domid = rc = xenbus_walk( "/local/domain/0", get_domid_for_dev, dev);
+ if (domid <= 0)
+ domid = DOMID_SELF;
+
memset(&map_irq, 0, sizeof(map_irq));
map_irq.domid = domid;
map_irq.type = MAP_PIRQ_TYPE_MSI;
@@ -658,6 +704,9 @@ int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc
*msidesc, int type)
}
irq_info[irq] = mk_pirq_info(0, map_irq.pirq, map_irq.index);
+ if (domid)
+ irq_info[irq].u.pirq.domid = domid;
+
set_irq_chip_and_handler_name(irq, &xen_pirq_chip,
handle_level_irq,
(type == PCI_CAP_ID_MSIX) ? "msi-x":"msi");
--
1.6.2.5
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|