All of lore.kernel.org
 help / color / mirror / Atom feed
From: Samuel Thibault <samuel.thibault@eu.citrix.com>
To: xen-devel@lists.xensource.com
Subject: [PATCH] stubdom: PCI passthrough support via PV-PCI
Date: Wed, 2 Jul 2008 13:50:55 +0100	[thread overview]
Message-ID: <20080702125055.GF4714@implementation.uk.xensource.com> (raw)

stubdom: PCI passthrough support via PV-PCI

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>

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@eu.citrix.com>, 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);

             reply	other threads:[~2008-07-02 12:50 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-07-02 12:50 Samuel Thibault [this message]
2008-07-02 12:58 ` PCI passthrough support via PV-PCI Samuel Thibault
2008-07-02 12:59   ` Keir Fraser
2008-07-02 13:29     ` Samuel Thibault
2008-07-02 14:18       ` Espen Skoglund
2008-07-02 14:28         ` Samuel Thibault
2008-07-02 16:01           ` Keir Fraser

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080702125055.GF4714@implementation.uk.xensource.com \
    --to=samuel.thibault@eu.citrix.com \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.