[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] stubdom: PCI passthrough support via PV-PCI



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1215003260 -3600
# Node ID b3d827e63a09d8d54b5bea688c2bb5d953d1464f
# Parent  dea9d5769d5619823834eec68672c5f2a67b149d
stubdom: PCI passthrough support via PV-PCI

Signed-off-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>
---
 extras/mini-os/include/pcifront.h       |   15 +
 extras/mini-os/include/posix/sys/mman.h |    3 
 extras/mini-os/kernel.c                 |   26 ++
 extras/mini-os/pcifront.c               |  278 ++++++++++++++++++++++++++++++++
 stubdom/Makefile                        |   10 -
 stubdom/libpci.config.h                 |    2 
 stubdom/libpci.config.mak               |    5 
 stubdom/pciutils.patch                  |   94 ++++++++++
 tools/ioemu/Makefile.target             |    2 
 tools/ioemu/hw/pass-through.c           |    1 
 tools/ioemu/xenstore.c                  |    4 
 11 files changed, 433 insertions(+), 7 deletions(-)

diff -r dea9d5769d56 -r b3d827e63a09 extras/mini-os/include/pcifront.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/pcifront.h Wed Jul 02 13:54:20 2008 +0100
@@ -0,0 +1,15 @@
+#include <types.h>
+#include <xen/io/pciif.h>
+struct pcifront_dev;
+struct pcifront_dev *init_pcifront(char *nodename);
+void pcifront_scan(struct pcifront_dev *dev, void (*fun)(unsigned int domain, 
unsigned int bus, unsigned slot, unsigned int fun));
+void pcifront_op(struct pcifront_dev *dev, struct xen_pci_op *op);
+void shutdown_pcifront(struct pcifront_dev *dev);
+int pcifront_conf_read(struct pcifront_dev *dev,
+                       unsigned int dom,
+                       unsigned int bus, unsigned int slot, unsigned long fun,
+                       unsigned int off, unsigned int size, unsigned int *val);
+int pcifront_conf_write(struct pcifront_dev *dev,
+                        unsigned int dom,
+                        unsigned int bus, unsigned int slot, unsigned long fun,
+                        unsigned int off, unsigned int size, unsigned int val);
diff -r dea9d5769d56 -r b3d827e63a09 extras/mini-os/include/posix/sys/mman.h
--- a/extras/mini-os/include/posix/sys/mman.h   Wed Jul 02 13:37:16 2008 +0100
+++ b/extras/mini-os/include/posix/sys/mman.h   Wed Jul 02 13:54:20 2008 +0100
@@ -9,6 +9,9 @@
 #define MAP_PRIVATE    0x02
 #define MAP_ANON       0x20
 
+/* Pages are always resident anyway */
+#define MAP_LOCKED     0x0
+
 #define MAP_FAILED     ((void*)0)
 
 void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t 
offset);
diff -r dea9d5769d56 -r b3d827e63a09 extras/mini-os/kernel.c
--- a/extras/mini-os/kernel.c   Wed Jul 02 13:37:16 2008 +0100
+++ b/extras/mini-os/kernel.c   Wed Jul 02 13:54:20 2008 +0100
@@ -40,6 +40,7 @@
 #include <netfront.h>
 #include <blkfront.h>
 #include <fbfront.h>
+#include <pcifront.h>
 #include <fs.h>
 #include <xmalloc.h>
 #include <fcntl.h>
@@ -431,6 +432,27 @@ static void kbdfront_thread(void *p)
     }
 }
 
+static struct pcifront_dev *pci_dev;
+
+static void pcifront_thread(void *p)
+{
+    void print(unsigned int domain, unsigned int bus, unsigned int slot, 
unsigned int fun)
+    {
+        unsigned int vendor, device, rev, class;
+
+        pcifront_conf_read(pci_dev, domain, bus, slot, fun, 0x00, 2, &vendor);
+        pcifront_conf_read(pci_dev, domain, bus, slot, fun, 0x02, 2, &device);
+        pcifront_conf_read(pci_dev, domain, bus, slot, fun, 0x08, 1, &rev);
+        pcifront_conf_read(pci_dev, domain, bus, slot, fun, 0x0a, 2, &class);
+
+        printk("%04x:%02x:%02x.%02x %04x: %04x:%04x (rev %02x)\n", domain, 
bus, slot, fun, class, vendor, device, rev);
+    }
+
+    pci_dev = init_pcifront(NULL);
+    printk("PCI devices:\n");
+    pcifront_scan(pci_dev, print);
+}
+
 static void fs_thread(void *p)
 {
     init_fs_frontend();
@@ -446,6 +468,7 @@ __attribute__((weak)) int app_main(start
     create_thread("blkfront", blkfront_thread, si);
     create_thread("fbfront", fbfront_thread, si);
     create_thread("kbdfront", kbdfront_thread, si);
+    create_thread("pcifront", pcifront_thread, si);
     create_thread("fs-frontend", fs_thread, si);
     return 0;
 }
@@ -524,6 +547,9 @@ void stop_kernel(void)
     if (kbd_dev)
         shutdown_kbdfront(kbd_dev);
 
+    if (pci_dev)
+        shutdown_pcifront(pci_dev);
+
     /* TODO: fs import */
 
     local_irq_disable();
diff -r dea9d5769d56 -r b3d827e63a09 extras/mini-os/pcifront.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/pcifront.c Wed Jul 02 13:54:20 2008 +0100
@@ -0,0 +1,278 @@
+/* Minimal PCI driver for Mini-OS. 
+ * Copyright (c) 2007-2008 Samuel Thibault.
+ * Based on blkfront.c.
+ */
+
+#include <os.h>
+#include <xenbus.h>
+#include <events.h>
+#include <errno.h>
+#include <gnttab.h>
+#include <xmalloc.h>
+#include <wait.h>
+#include <pcifront.h>
+
+#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
+
+DECLARE_WAIT_QUEUE_HEAD(pcifront_queue);
+
+struct pcifront_dev {
+    domid_t dom;
+
+    struct xen_pci_sharedinfo *info;
+    grant_ref_t info_ref;
+    evtchn_port_t evtchn;
+
+    char *nodename;
+    char *backend;
+
+    xenbus_event_queue events;
+};
+
+void pcifront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
+{
+    wake_up(&pcifront_queue);
+}
+
+static void free_pcifront(struct pcifront_dev *dev)
+{
+    mask_evtchn(dev->evtchn);
+
+    free(dev->backend);
+
+    gnttab_end_access(dev->info_ref);
+    free_page(dev->info);
+
+    unbind_evtchn(dev->evtchn);
+
+    free(dev->nodename);
+    free(dev);
+}
+
+struct pcifront_dev *init_pcifront(char *nodename)
+{
+    xenbus_transaction_t xbt;
+    char* err;
+    char* message=NULL;
+    int retry=0;
+    char* msg;
+
+    struct pcifront_dev *dev;
+
+    if (!nodename)
+        nodename = "device/pci/0";
+
+    char path[strlen(nodename) + 1 + 10 + 1];
+
+    printk("******************* PCIFRONT for %s **********\n\n\n", nodename);
+
+    dev = malloc(sizeof(*dev));
+    memset(dev, 0, sizeof(*dev));
+    dev->nodename = strdup(nodename);
+
+    snprintf(path, sizeof(path), "%s/backend-id", nodename);
+    dev->dom = xenbus_read_integer(path); 
+    evtchn_alloc_unbound(dev->dom, pcifront_handler, dev, &dev->evtchn);
+
+    dev->info = (struct xen_pci_sharedinfo*) alloc_page();
+    memset(dev->info,0,PAGE_SIZE);
+
+    dev->info_ref = gnttab_grant_access(dev->dom,virt_to_mfn(dev->info),0);
+
+    dev->events = NULL;
+
+again:
+    err = xenbus_transaction_start(&xbt);
+    if (err) {
+        printk("starting transaction\n");
+    }
+
+    err = xenbus_printf(xbt, nodename, "pci-op-ref","%u",
+                dev->info_ref);
+    if (err) {
+        message = "writing pci-op-ref";
+        goto abort_transaction;
+    }
+    err = xenbus_printf(xbt, nodename,
+                "event-channel", "%u", dev->evtchn);
+    if (err) {
+        message = "writing event-channel";
+        goto abort_transaction;
+    }
+    err = xenbus_printf(xbt, nodename,
+                "magic", XEN_PCI_MAGIC);
+    if (err) {
+        message = "writing magic";
+        goto abort_transaction;
+    }
+
+    err = xenbus_printf(xbt, nodename, "state", "%u",
+            3); /* initialised */
+
+
+    err = xenbus_transaction_end(xbt, 0, &retry);
+    if (retry) {
+            goto again;
+        printk("completing transaction\n");
+    }
+
+    goto done;
+
+abort_transaction:
+    xenbus_transaction_end(xbt, 1, &retry);
+    goto error;
+
+done:
+
+    snprintf(path, sizeof(path), "%s/backend", nodename);
+    msg = xenbus_read(XBT_NIL, path, &dev->backend);
+    if (msg) {
+        printk("Error %s when reading the backend path %s\n", msg, path);
+        goto error;
+    }
+
+    printk("backend at %s\n", dev->backend);
+
+    {
+        char path[strlen(dev->backend) + 1 + 5 + 1];
+        snprintf(path, sizeof(path), "%s/state", dev->backend);
+
+        xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
+
+        xenbus_wait_for_value(path, "4", &dev->events);
+
+        xenbus_printf(xbt, nodename, "state", "%u", 4); /* connected */
+    }
+    unmask_evtchn(dev->evtchn);
+
+    printk("**************************\n");
+
+    return dev;
+
+error:
+    free_pcifront(dev);
+    return NULL;
+}
+
+void pcifront_scan(struct pcifront_dev *dev, void (*func)(unsigned int domain, 
unsigned int bus, unsigned slot, unsigned int fun))
+{
+    char path[strlen(dev->backend) + 1 + 5 + 10 + 1];
+    int i, n;
+    char *s, *msg;
+    unsigned int domain, bus, slot, fun;
+
+    snprintf(path, sizeof(path), "%s/num_devs", dev->backend);
+    n = xenbus_read_integer(path);
+
+    for (i = 0; i < n; i++) {
+        snprintf(path, sizeof(path), "%s/vdev-%d", dev->backend, i);
+        msg = xenbus_read(XBT_NIL, path, &s);
+        if (msg) {
+            printk("Error %s when reading the PCI root name at %s\n", path);
+            continue;
+        }
+
+        if (sscanf(s, "%x:%x:%x.%x", &domain, &bus, &slot, &fun) != 4) {
+            printk("\"%s\" does not look like a PCI device address\n", s);
+            free(s);
+            continue;
+        }
+        free(s);
+
+        func(domain, bus, slot, fun);
+    }
+}
+
+void shutdown_pcifront(struct pcifront_dev *dev)
+{
+    char* err;
+    char *nodename = dev->nodename;
+
+    char path[strlen(dev->backend) + 1 + 5 + 1];
+
+    printk("close pci: backend at %s\n",dev->backend);
+
+    snprintf(path, sizeof(path), "%s/state", dev->backend);
+    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
+    xenbus_wait_for_value(path, "5", &dev->events);
+
+    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
+    xenbus_wait_for_value(path, "6", &dev->events);
+
+    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
+    xenbus_wait_for_value(path, "2", &dev->events);
+
+    xenbus_unwatch_path(XBT_NIL, path);
+
+    snprintf(path, sizeof(path), "%s/info-ref", nodename);
+    xenbus_rm(XBT_NIL, path);
+    snprintf(path, sizeof(path), "%s/event-channel", nodename);
+    xenbus_rm(XBT_NIL, path);
+
+    free_pcifront(dev);
+}
+
+
+void pcifront_op(struct pcifront_dev *dev, struct xen_pci_op *op)
+{
+    dev->info->op = *op;
+    /* Make sure info is written before the flag */
+    wmb();
+    set_bit(_XEN_PCIF_active, &dev->info->flags);
+    notify_remote_via_evtchn(dev->evtchn);
+
+    wait_event(pcifront_queue, !test_bit(_XEN_PCIF_active, &dev->info->flags));
+
+    /* Make sure flag is read before info */
+    rmb();
+    *op = dev->info->op;
+}
+
+int pcifront_conf_read(struct pcifront_dev *dev,
+                       unsigned int dom,
+                       unsigned int bus, unsigned int slot, unsigned long fun,
+                       unsigned int off, unsigned int size, unsigned int *val)
+{
+    struct xen_pci_op op;
+
+    memset(&op, 0, sizeof(op));
+
+    op.cmd = XEN_PCI_OP_conf_read;
+    op.domain = dom;
+    op.bus = bus;
+    op.devfn = PCI_DEVFN(slot, fun);
+    op.offset = off;
+    op.size = size;
+
+    pcifront_op(dev, &op);
+
+    if (op.err)
+        return op.err;
+
+    *val = op.value;
+
+    return 0;
+}
+
+int pcifront_conf_write(struct pcifront_dev *dev,
+                        unsigned int dom,
+                        unsigned int bus, unsigned int slot, unsigned long fun,
+                        unsigned int off, unsigned int size, unsigned int val)
+{
+    struct xen_pci_op op;
+
+    memset(&op, 0, sizeof(op));
+
+    op.cmd = XEN_PCI_OP_conf_write;
+    op.domain = dom;
+    op.bus = bus;
+    op.devfn = PCI_DEVFN(slot, fun);
+    op.offset = off;
+    op.size = size;
+
+    op.value = val;
+
+    pcifront_op(dev, &op);
+
+    return op.err;
+}
diff -r dea9d5769d56 -r b3d827e63a09 stubdom/Makefile
--- a/stubdom/Makefile  Wed Jul 02 13:37:16 2008 +0100
+++ b/stubdom/Makefile  Wed Jul 02 13:54:20 2008 +0100
@@ -131,16 +131,20 @@ pciutils-$(LIBPCI_VERSION).tar.bz2:
 pciutils-$(LIBPCI_VERSION).tar.bz2:
        $(WGET) 
http://www.kernel.org/pub/software/utils/pciutils/pciutils-$(LIBPCI_VERSION).tar.bz2
 
+pciutils-$(LIBPCI_VERSION): pciutils-$(LIBPCI_VERSION).tar.bz2
+       tar xjf $<
+       patch -d $@ -p1 < pciutils.patch
+       touch $@
+
 LIBPCI_STAMPFILE=$(CROSS_ROOT)/$(GNU_TARGET_ARCH)-xen-elf/lib/libpci.a
 .PHONY: cross-libpci
 cross-libpci: $(LIBPCI_STAMPFILE)
-$(LIBPCI_STAMPFILE): pciutils-$(LIBPCI_VERSION).tar.bz2 $(NEWLIB_STAMPFILE) 
$(ZLIB_STAMPFILE)
-       tar xjf $<
+$(LIBPCI_STAMPFILE): pciutils-$(LIBPCI_VERSION) $(NEWLIB_STAMPFILE) 
$(ZLIB_STAMPFILE)
        ( cd pciutils-$(LIBPCI_VERSION) && \
          cp ../libpci.config.h lib/config.h && \
          echo '#define PCILIB_VERSION "$(LIBPCI_VERSION)"' >> lib/config.h && \
          cp ../libpci.config.mak lib/config.mk && \
-         $(MAKE) CC="$(GNU_TARGET_ARCH)-xen-elf-gcc $(TARGET_CFLAGS)" 
lib/libpci.a && \
+         $(MAKE) CC="$(GNU_TARGET_ARCH)-xen-elf-gcc $(TARGET_CFLAGS) 
-I$(realpath $(MINI_OS)/include)" lib/libpci.a && \
          $(INSTALL_DATA) lib/libpci.a 
$(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/lib/ && \
          $(INSTALL_DIR) $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/include/pci 
&& \
          $(INSTALL_DATA) lib/{config,header,pci,types}.h 
$(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/include/pci/ \
diff -r dea9d5769d56 -r b3d827e63a09 stubdom/libpci.config.h
--- a/stubdom/libpci.config.h   Wed Jul 02 13:37:16 2008 +0100
+++ b/stubdom/libpci.config.h   Wed Jul 02 13:54:20 2008 +0100
@@ -1,4 +1,4 @@
-#define PCI_OS_STUBDOM
+#define PCI_OS_MINIOS
 #define PCI_HAVE_STDINT_H
 #define PCI_PATH_IDS_DIR "."
 #define PCI_COMPRESSED_IDS
diff -r dea9d5769d56 -r b3d827e63a09 stubdom/libpci.config.mak
--- a/stubdom/libpci.config.mak Wed Jul 02 13:37:16 2008 +0100
+++ b/stubdom/libpci.config.mak Wed Jul 02 13:54:20 2008 +0100
@@ -1,2 +1,7 @@ LIBZ=-lz
 LIBZ=-lz
 LDLIBS+=$(LIBZ)
+PCI_OS_MINIOS=1
+PCI_HAVE_STDINT_H=1
+PCI_PATH_IDS_DIR=.
+PCI_COMPRESSED_IDS=1
+PCI_IDS=pci.ids.gz
diff -r dea9d5769d56 -r b3d827e63a09 stubdom/pciutils.patch
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/pciutils.patch    Wed Jul 02 13:54:20 2008 +0100
@@ -0,0 +1,299 @@
+diff -urN pciutils-2.2.9.orig/lib/access.c pciutils-2.2.9/lib/access.c
+--- pciutils-2.2.9.orig/lib/access.c   2007-02-06 11:59:43.000000000 +0000
++++ pciutils-2.2.9/lib/access.c        2008-06-30 19:07:09.713187000 +0100
+@@ -57,6 +57,11 @@
+ #else
+   NULL,
+ #endif
++#ifdef PCI_OS_MINIOS
++  &pm_minios,
++#else
++  NULL,
++#endif
+ };
+ 
+ struct pci_access *
+--- pciutils-2.2.9.orig/lib/pci.h      2006-09-09 13:46:06.000000000 +0100
++++ pciutils-2.2.9/lib/pci.h   2008-06-30 18:56:15.350111000 +0100
+@@ -33,6 +33,7 @@
+   PCI_ACCESS_NBSD_LIBPCI,             /* NetBSD libpci */
+   PCI_ACCESS_OBSD_DEVICE,             /* OpenBSD /dev/pci */
+   PCI_ACCESS_DUMP,                    /* Dump file (params: filename) */
++  PCI_ACCESS_MINIOS,                  /* MiniOS */
+   PCI_ACCESS_MAX
+ };
+ 
+@@ -63,6 +64,7 @@
+   int fd_rw;                          /* proc: fd opened read-write */
+   struct pci_dev *cached_dev;         /* proc: device the fd is for */
+   int fd_pos;                         /* proc: current position */
++  void *minios;
+ };
+ 
+ /* Initialize PCI access */
+--- pciutils-2.2.9.orig/lib/internal.h 2006-09-09 11:52:47.000000000 +0100
++++ pciutils-2.2.9/lib/internal.h      2008-07-01 10:46:24.968202000 +0100
+@@ -37,4 +37,4 @@
+ 
+ extern struct pci_methods pm_intel_conf1, pm_intel_conf2, pm_linux_proc,
+       pm_fbsd_device, pm_aix_device, pm_nbsd_libpci, pm_obsd_device,
+-      pm_dump, pm_linux_sysfs;
++      pm_dump, pm_linux_sysfs, pm_minios;
+--- pciutils-2.2.9.orig/lib/Makefile   2007-10-19 13:41:34.000000000 +0100
++++ pciutils-2.2.9/lib/Makefile        2008-07-01 12:13:14.400525000 +0100
+@@ -46,6 +46,12 @@
+ PCILIB=libpciutils.a
+ endif
+ 
++ifdef PCI_OS_MINIOS
++XEN_ROOT=../../..
++include $(XEN_ROOT)/Config.mk
++OBJS += minios.o
++endif
++
+ all: $(PCILIB) $(PCILIBPC)
+ 
+ $(PCILIB): $(OBJS)
+--- pciutils-2.2.9.orig/lib/types.h    2007-09-03 09:44:15.000000000 +0100
++++ pciutils-2.2.9/lib/types.h 2008-07-01 12:17:08.396156000 +0100
+@@ -17,9 +17,13 @@
+ typedef DWORD u32;
+ #elif defined(PCI_HAVE_STDINT_H)
+ #include <stdint.h>
++#ifdef PCI_OS_MINIOS
++#include <types.h>
++#else
+ typedef uint8_t u8;
+ typedef uint16_t u16;
+ typedef uint32_t u32;
++#endif
+ #else
+ typedef u_int8_t u8;
+ typedef u_int16_t u16;
+--- pciutils-2.2.9.orig/lib/minios.c   1970-01-01 01:00:00.000000000 +0100
++++ pciutils-2.2.9/lib/minios.c        2008-07-01 12:31:40.554260000 +0100
+@@ -0,0 +1,113 @@
++/*
++ *    The PCI Library -- MiniOS PCI frontend access
++ *
++ *    Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>, 2008
++ *
++ *    Can be freely distributed and used under the terms of the GNU GPL.
++ */
++
++#include <os.h>
++#include <pcifront.h>
++#include <xenbus.h>
++#include "internal.h"
++
++static int
++minios_detect(struct pci_access *a)
++{
++  return 1;
++}
++
++static void
++minios_init(struct pci_access *a)
++{
++  a->minios = init_pcifront(NULL);
++  if (!a->minios)
++    a->warning("minios_init open failed");
++}
++
++static void
++minios_cleanup(struct pci_access *a)
++{
++  if (a->minios)
++    shutdown_pcifront(a->minios);
++}
++
++static void
++minios_scan(struct pci_access *a)
++{
++  if (!a->minios)
++    return;
++
++  void func(unsigned int domain, unsigned int bus, unsigned int slot, 
unsigned int fun)
++  {
++    struct pci_dev *d = pci_alloc_dev(a);
++
++    d->domain = domain;
++    d->bus = bus;
++    d->dev = slot;
++    d->func = fun;
++
++    pci_link_dev(a, d);
++  }
++
++  pcifront_scan(a->minios, func);
++}
++
++static int
++minios_read(struct pci_dev *d, int pos, byte *buf, int len)
++{
++  unsigned int val;
++  switch (len) {
++    case 1:
++      if (pcifront_conf_read(d->access->minios, d->domain, d->bus, d->dev, 
d->func, pos, len, &val))
++        return 0;
++      * buf = val;
++      return 1;
++    case 2:
++      if (pcifront_conf_read(d->access->minios, d->domain, d->bus, d->dev, 
d->func, pos, len, &val))
++        return 0;
++      *(u16 *) buf = cpu_to_le16((u16) val);
++      return 1;
++    case 4:
++      if (pcifront_conf_read(d->access->minios, d->domain, d->bus, d->dev, 
d->func, pos, len, &val))
++        return 0;
++      *(u32 *) buf = cpu_to_le32((u32) val);
++      return 1;
++    default:
++      return pci_generic_block_read(d, pos, buf, len);
++  }
++}
++
++static int
++minios_write(struct pci_dev *d, int pos, byte *buf, int len)
++{
++  unsigned int val;
++  switch (len) {
++    case 1:
++      val = * buf;
++      break;
++    case 2:
++      val = le16_to_cpu(*(u16 *) buf);
++      break;
++    case 4:
++      val = le32_to_cpu(*(u32 *) buf);
++      break;
++    default:
++      return pci_generic_block_write(d, pos, buf, len);
++  }
++  return !pcifront_conf_write(d->access->minios, d->domain, d->bus, d->dev, 
d->func, pos, len, val);
++}
++
++struct pci_methods pm_minios = {
++  "MiniOS-device",
++  NULL,                                 /* config */
++  minios_detect,
++  minios_init,
++  minios_cleanup,
++  minios_scan,
++  pci_generic_fill_info,
++  minios_read,
++  minios_write,
++  NULL,                                 /* dev_init */
++  NULL                                  /* dev_cleanup */
++};
+--- pciutils-2.2.9/lib/generic.c       2007-02-06 12:00:05.000000000 +0000
++++ pciutils-2.2.9-mine/lib/generic.c  2008-07-01 19:13:52.289949000 +0100
+@@ -74,6 +74,19 @@
+   pci_generic_scan_bus(a, busmap, 0);
+ }
+ 
++static u32 pci_size(u32 base, u32 maxbase, u32 mask)
++{
++  u32 size = mask & maxbase;
++  if (!size)
++    return 0;
++  size = (size & ~(size-1)) - 1;
++
++  if (base == maxbase && ((base | size) & mask) != mask)
++    return 0;
++
++  return size + 1;
++}
++
+ int
+ pci_generic_fill_info(struct pci_dev *d, int flags)
+ {
+@@ -114,23 +127,61 @@
+             if (!x || x == (u32) ~0)
+               continue;
+             if ((x & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
+-              d->base_addr[i] = x;
+-            else
++                {
++                  d->base_addr[i] = x & PCI_BASE_ADDRESS_IO_MASK;
++                  if (flags & PCI_FILL_SIZES)
++                    {
++                      u32 size;
++                      pci_write_long(d, PCI_BASE_ADDRESS_0 + i*4, ~0);
++                      d->size[i] = pci_size(x, pci_read_long(d, 
PCI_BASE_ADDRESS_0 + i*4), PCI_BASE_ADDRESS_IO_MASK);
++                      pci_write_long(d, PCI_BASE_ADDRESS_0 + i*4, x);
++                    }
++                }
++              else
+               {
+                 if ((x & PCI_BASE_ADDRESS_MEM_TYPE_MASK) != 
PCI_BASE_ADDRESS_MEM_TYPE_64)
+-                  d->base_addr[i] = x;
++                    {
++                      d->base_addr[i] = x & PCI_BASE_ADDRESS_MEM_MASK;
++                      if (flags & PCI_FILL_SIZES)
++                        {
++                          u32 size;
++                          pci_write_long(d, PCI_BASE_ADDRESS_0 + i*4, ~0);
++                          d->size[i] = pci_read_long(d, PCI_BASE_ADDRESS_0 + 
i*4);
++                          d->size[i] = pci_size(x, pci_read_long(d, 
PCI_BASE_ADDRESS_0 + i*4), PCI_BASE_ADDRESS_MEM_MASK);
++                          pci_write_long(d, PCI_BASE_ADDRESS_0 + i*4, x);
++                        }
++                    }
+                 else if (i >= cnt-1)
+                   a->warning("%04x:%02x:%02x.%d: Invalid 64-bit address seen 
for BAR %d.", d->domain, d->bus, d->dev, d->func, i);
+                 else
+                   {
+                     u32 y = pci_read_long(d, PCI_BASE_ADDRESS_0 + (++i)*4);
+ #ifdef PCI_HAVE_64BIT_ADDRESS
+-                    d->base_addr[i-1] = x | (((pciaddr_t) y) << 32);
++                    d->base_addr[i-1] = (x | (((pciaddr_t) y) << 32)) & 
PCI_BASE_ADDRESS_MEM_MASK;
++                      if (flags & PCI_FILL_SIZES)
++                        {
++                          u32 size;
++                          pci_write_long(d, PCI_BASE_ADDRESS_0 + (i-1)*4, ~0);
++                          pci_write_long(d, PCI_BASE_ADDRESS_0 + i*4, ~0);
++                          d->size[i-1] = pci_size(y, pci_read_long(d, 
PCI_BASE_ADDRESS_0 + (i-1)*4) | 
++                                         pci_read_long(d, PCI_BASE_ADDRESS_0 
+ i*4), 0xffffffff );
++                          pci_write_long(d, PCI_BASE_ADDRESS_0 + (i-1)*4, x);
++                          pci_write_long(d, PCI_BASE_ADDRESS_0 + i*4, y);
++                        }
+ #else
+                     if (y)
+                       a->warning("%04x:%02x:%02x.%d 64-bit device address 
ignored.", d->domain, d->bus, d->dev, d->func);
+                     else
+-                      d->base_addr[i-1] = x;
++                        {
++                          d->base_addr[i-1] = x & PCI_BASE_ADDRESS_MEM_MASK;
++                          if (flags & PCI_FILL_SIZES)
++                            {
++                              u32 size;
++                              pci_write_long(d, PCI_BASE_ADDRESS_0 + (i-1)*4, 
~0);
++                              d->size[i-1] = pci_size(x, pci_read_long(d, 
PCI_BASE_ADDRESS_0 + (i-1)*4), PCI_BASE_ADDRESS_MEM_MASK);
++                              pci_write_long(d, PCI_BASE_ADDRESS_0 + (i-1)*4, 
x);
++                            }
++                        }
+ #endif
+                   }
+               }
+@@ -154,10 +205,19 @@
+       {
+         u32 u = pci_read_long(d, reg);
+         if (u != 0xffffffff)
+-          d->rom_base_addr = u;
++            {
++              d->rom_base_addr = u;
++              if (flags & PCI_FILL_SIZES)
++                {
++                  u32 size;
++                  pci_write_long(d, reg, ~0);
++                  d->rom_size = pci_read_long(d, reg);
++                  pci_write_long(d, reg, u);
++                }
++            }
+       }
+     }
+-  return flags & ~PCI_FILL_SIZES;
++  return flags;
+ }
+ 
+ static int
diff -r dea9d5769d56 -r b3d827e63a09 tools/ioemu/Makefile.target
--- a/tools/ioemu/Makefile.target       Wed Jul 02 13:37:16 2008 +0100
+++ b/tools/ioemu/Makefile.target       Wed Jul 02 13:54:20 2008 +0100
@@ -358,7 +358,7 @@ endif
 endif
 
 ifdef CONFIG_STUBDOM
-#CONFIG_PASSTHROUGH=1
+CONFIG_PASSTHROUGH=1
 else
   ifeq (,$(wildcard /usr/include/pci))
 $(warning *** pciutils-devl package not found - missing /usr/include/pci)
diff -r dea9d5769d56 -r b3d827e63a09 tools/ioemu/hw/pass-through.c
--- a/tools/ioemu/hw/pass-through.c     Wed Jul 02 13:37:16 2008 +0100
+++ b/tools/ioemu/hw/pass-through.c     Wed Jul 02 13:54:20 2008 +0100
@@ -515,6 +515,7 @@ struct pt_dev * register_real_device(PCI
         PT_LOG("Error: couldn't locate device in libpci structures\n");
         return NULL;
     }
+    pci_fill_info(pci_dev, PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | 
PCI_FILL_SIZES);
 
     if ( e_devfn == PT_VIRT_DEVFN_AUTO ) {
         /*indicate a static assignment(not hotplug), so find a free PCI hot 
plug slot */
diff -r dea9d5769d56 -r b3d827e63a09 tools/ioemu/xenstore.c
--- a/tools/ioemu/xenstore.c    Wed Jul 02 13:37:16 2008 +0100
+++ b/tools/ioemu/xenstore.c    Wed Jul 02 13:54:20 2008 +0100
@@ -320,7 +320,7 @@ void xenstore_parse_domain_config(int hv
 
     /* get the pci pass-through parameter */
     if (pasprintf(&buf, "/local/domain/0/backend/pci/%u/%u/num_devs",
-                  domid, pci_devid) == -1)
+                  hvm_domid, pci_devid) == -1)
         goto out;
 
     free(params);
@@ -331,7 +331,7 @@ void xenstore_parse_domain_config(int hv
 
     for ( i = 0; i < num; i++ ) {
         if (pasprintf(&buf, "/local/domain/0/backend/pci/%u/%u/dev-%d",
-                    domid, pci_devid, i) != -1) {
+                    hvm_domid, pci_devid, i) != -1) {
             free(dev);
             dev = xs_read(xsh, XBT_NULL, buf, &len);
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.