---
hw/pci.c | 6 +++++
xen-all.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 76 insertions(+), 0 deletions(-)
diff --git a/hw/pci.c b/hw/pci.c
index bf046bf..4df4449 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -31,6 +31,7 @@
#include "loader.h"
#include "range.h"
#include "qmp-commands.h"
+#include "xen.h"
//#define DEBUG_PCI
#ifdef DEBUG_PCI
@@ -764,6 +765,11 @@ static PCIDevice *do_pci_register_device(PCIDevice
*pci_dev, PCIBus *bus,
pci_dev->devfn = devfn;
pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
pci_dev->irq_state = 0;
+
+ if (xen_enabled()&& xen_register_pcidev(pci_dev)) {
+ return NULL;
+ }
+
pci_config_alloc(pci_dev);
pci_config_set_vendor_id(pci_dev->config, pc->vendor_id);
diff --git a/xen-all.c b/xen-all.c
index 366bafe..2f5405c 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -107,6 +107,76 @@ void xen_piix3_set_irq(void *opaque, int irq_num, int
level)
irq_num& 3, level);
}
+static uint32_t str_to_bdf(const char *str)
+{
+ /* We assume that bdf is valid */
+ char *buf;
+ uint32_t bdf;
+ uint32_t tmp;
+
+ bdf = strtol(str,&buf, 16);
+ buf++;
+
+ str = buf;
+ tmp = strtol(str,&buf, 16);
+ bdf = (bdf<< 16) | (tmp<< 11);
+ buf++;
+
+ str = buf;
+ tmp = strtol(str,&buf, 16);
+ bdf = bdf | (tmp<< 8);
+
+ return bdf;
+}
+
+int xen_register_pcidev(PCIDevice *pci_dev)
+{
+ struct xs_handle *xs = NULL;
+ uint32_t bdf = 0;
+ uint32_t allowed_bdf = 0;
+ char **dir;
+ char path[50];
+ unsigned int nb;
+ unsigned int i;
+ unsigned int len;
+ char *str;
+ int rc = 0;
+
+
+ /* Fix : missing bus id to be more generic */
+ bdf |= pci_dev->devfn<< 8;
+
+ xs = xs_open(0);
+ if (!xs) {
+ fprintf(stderr, "pci_register: Unable to open xenstore\n");
+ return 1;
+ }
+
+ snprintf(path, sizeof (path), "/local/domain/%u/image/dms/%u/pci",
+ xen_domid, xen_dmid);
+
+ dir = xs_directory(xs, XBT_NULL, path,&nb);
+ if (dir) {
+ for (i = 0; i< nb; i++) {
+ snprintf(path, sizeof (path),
"/local/domain/%u/image/dms/%u/pci/%s",
+ xen_domid, xen_dmid, dir[i]);
+ str = xs_read(xs, XBT_NULL, path,&len);
+ allowed_bdf = str_to_bdf(str);
+ free(str);
+ if (bdf == allowed_bdf)
+ {
+ rc = xc_hvm_register_pcidev(xen_xc, xen_domid, serverid, bdf);
+ break;
+ }
+ }
+ free(dir);
+ }
+
+ xs_close(xs);
+
+ return rc;
+}
+
void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
{
int i;