WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] stubdom: PCI passthrough support via PV-PCI

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] stubdom: PCI passthrough support via PV-PCI
From: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>
Date: Wed, 2 Jul 2008 13:50:55 +0100
Delivery-date: Wed, 02 Jul 2008 05:51:36 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Mail-followup-to: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mutt/1.5.12-2006-07-14
stubdom: PCI passthrough support via PV-PCI

Signed-off-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>

diff -r 0361bcf5d310 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:43:01 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 0361bcf5d310 extras/mini-os/include/posix/sys/mman.h
--- a/extras/mini-os/include/posix/sys/mman.h   Tue Jul 01 14:48:29 2008 +0100
+++ b/extras/mini-os/include/posix/sys/mman.h   Wed Jul 02 13:43:01 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 0361bcf5d310 extras/mini-os/kernel.c
--- a/extras/mini-os/kernel.c   Tue Jul 01 14:48:29 2008 +0100
+++ b/extras/mini-os/kernel.c   Wed Jul 02 13:43:01 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 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 @@
     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 @@
     if (kbd_dev)
         shutdown_kbdfront(kbd_dev);
 
+    if (pci_dev)
+        shutdown_pcifront(pci_dev);
+
     /* TODO: fs import */
 
     local_irq_disable();
diff -r 0361bcf5d310 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:43:01 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 0361bcf5d310 stubdom/Makefile
--- a/stubdom/Makefile  Tue Jul 01 14:48:29 2008 +0100
+++ b/stubdom/Makefile  Wed Jul 02 13:43:01 2008 +0100
@@ -132,16 +132,20 @@
 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 0361bcf5d310 stubdom/libpci.config.h
--- a/stubdom/libpci.config.h   Tue Jul 01 14:48:29 2008 +0100
+++ b/stubdom/libpci.config.h   Wed Jul 02 13:43:01 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 0361bcf5d310 stubdom/libpci.config.mak
--- a/stubdom/libpci.config.mak Tue Jul 01 14:48:29 2008 +0100
+++ b/stubdom/libpci.config.mak Wed Jul 02 13:43:01 2008 +0100
@@ -1,2 +1,7 @@
 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 0361bcf5d310 stubdom/pciutils.patch
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/stubdom/pciutils.patch    Wed Jul 02 13:43:01 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 0361bcf5d310 tools/ioemu/Makefile.target
--- a/tools/ioemu/Makefile.target       Tue Jul 01 14:48:29 2008 +0100
+++ b/tools/ioemu/Makefile.target       Wed Jul 02 13:43:01 2008 +0100
@@ -358,7 +358,7 @@
 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 0361bcf5d310 tools/ioemu/hw/pass-through.c
--- a/tools/ioemu/hw/pass-through.c     Tue Jul 01 14:48:29 2008 +0100
+++ b/tools/ioemu/hw/pass-through.c     Wed Jul 02 13:43:01 2008 +0100
@@ -515,6 +515,7 @@
         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 0361bcf5d310 tools/ioemu/xenstore.c
--- a/tools/ioemu/xenstore.c    Tue Jul 01 14:48:29 2008 +0100
+++ b/tools/ioemu/xenstore.c    Wed Jul 02 13:43:01 2008 +0100
@@ -322,7 +322,7 @@
 
     /* 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);
@@ -333,7 +333,7 @@
 
     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-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel