ia64/xen-unstable

changeset 17949:b3d827e63a09

stubdom: PCI passthrough support via PV-PCI

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jul 02 13:54:20 2008 +0100 (2008-07-02)
parents dea9d5769d56
children 3a40a6997cc0
files extras/mini-os/include/pcifront.h extras/mini-os/include/posix/sys/mman.h extras/mini-os/kernel.c extras/mini-os/pcifront.c stubdom/Makefile stubdom/libpci.config.h stubdom/libpci.config.mak stubdom/pciutils.patch tools/ioemu/Makefile.target tools/ioemu/hw/pass-through.c tools/ioemu/xenstore.c
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/extras/mini-os/include/pcifront.h	Wed Jul 02 13:54:20 2008 +0100
     1.3 @@ -0,0 +1,15 @@
     1.4 +#include <types.h>
     1.5 +#include <xen/io/pciif.h>
     1.6 +struct pcifront_dev;
     1.7 +struct pcifront_dev *init_pcifront(char *nodename);
     1.8 +void pcifront_scan(struct pcifront_dev *dev, void (*fun)(unsigned int domain, unsigned int bus, unsigned slot, unsigned int fun));
     1.9 +void pcifront_op(struct pcifront_dev *dev, struct xen_pci_op *op);
    1.10 +void shutdown_pcifront(struct pcifront_dev *dev);
    1.11 +int pcifront_conf_read(struct pcifront_dev *dev,
    1.12 +                       unsigned int dom,
    1.13 +                       unsigned int bus, unsigned int slot, unsigned long fun,
    1.14 +                       unsigned int off, unsigned int size, unsigned int *val);
    1.15 +int pcifront_conf_write(struct pcifront_dev *dev,
    1.16 +                        unsigned int dom,
    1.17 +                        unsigned int bus, unsigned int slot, unsigned long fun,
    1.18 +                        unsigned int off, unsigned int size, unsigned int val);
     2.1 --- a/extras/mini-os/include/posix/sys/mman.h	Wed Jul 02 13:37:16 2008 +0100
     2.2 +++ b/extras/mini-os/include/posix/sys/mman.h	Wed Jul 02 13:54:20 2008 +0100
     2.3 @@ -9,6 +9,9 @@
     2.4  #define MAP_PRIVATE	0x02
     2.5  #define MAP_ANON	0x20
     2.6  
     2.7 +/* Pages are always resident anyway */
     2.8 +#define MAP_LOCKED	0x0
     2.9 +
    2.10  #define MAP_FAILED	((void*)0)
    2.11  
    2.12  void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
     3.1 --- a/extras/mini-os/kernel.c	Wed Jul 02 13:37:16 2008 +0100
     3.2 +++ b/extras/mini-os/kernel.c	Wed Jul 02 13:54:20 2008 +0100
     3.3 @@ -40,6 +40,7 @@
     3.4  #include <netfront.h>
     3.5  #include <blkfront.h>
     3.6  #include <fbfront.h>
     3.7 +#include <pcifront.h>
     3.8  #include <fs.h>
     3.9  #include <xmalloc.h>
    3.10  #include <fcntl.h>
    3.11 @@ -431,6 +432,27 @@ static void kbdfront_thread(void *p)
    3.12      }
    3.13  }
    3.14  
    3.15 +static struct pcifront_dev *pci_dev;
    3.16 +
    3.17 +static void pcifront_thread(void *p)
    3.18 +{
    3.19 +    void print(unsigned int domain, unsigned int bus, unsigned int slot, unsigned int fun)
    3.20 +    {
    3.21 +        unsigned int vendor, device, rev, class;
    3.22 +
    3.23 +        pcifront_conf_read(pci_dev, domain, bus, slot, fun, 0x00, 2, &vendor);
    3.24 +        pcifront_conf_read(pci_dev, domain, bus, slot, fun, 0x02, 2, &device);
    3.25 +        pcifront_conf_read(pci_dev, domain, bus, slot, fun, 0x08, 1, &rev);
    3.26 +        pcifront_conf_read(pci_dev, domain, bus, slot, fun, 0x0a, 2, &class);
    3.27 +
    3.28 +        printk("%04x:%02x:%02x.%02x %04x: %04x:%04x (rev %02x)\n", domain, bus, slot, fun, class, vendor, device, rev);
    3.29 +    }
    3.30 +
    3.31 +    pci_dev = init_pcifront(NULL);
    3.32 +    printk("PCI devices:\n");
    3.33 +    pcifront_scan(pci_dev, print);
    3.34 +}
    3.35 +
    3.36  static void fs_thread(void *p)
    3.37  {
    3.38      init_fs_frontend();
    3.39 @@ -446,6 +468,7 @@ static void fs_thread(void *p)
    3.40      create_thread("blkfront", blkfront_thread, si);
    3.41      create_thread("fbfront", fbfront_thread, si);
    3.42      create_thread("kbdfront", kbdfront_thread, si);
    3.43 +    create_thread("pcifront", pcifront_thread, si);
    3.44      create_thread("fs-frontend", fs_thread, si);
    3.45      return 0;
    3.46  }
    3.47 @@ -524,6 +547,9 @@ void stop_kernel(void)
    3.48      if (kbd_dev)
    3.49          shutdown_kbdfront(kbd_dev);
    3.50  
    3.51 +    if (pci_dev)
    3.52 +        shutdown_pcifront(pci_dev);
    3.53 +
    3.54      /* TODO: fs import */
    3.55  
    3.56      local_irq_disable();
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/extras/mini-os/pcifront.c	Wed Jul 02 13:54:20 2008 +0100
     4.3 @@ -0,0 +1,278 @@
     4.4 +/* Minimal PCI driver for Mini-OS. 
     4.5 + * Copyright (c) 2007-2008 Samuel Thibault.
     4.6 + * Based on blkfront.c.
     4.7 + */
     4.8 +
     4.9 +#include <os.h>
    4.10 +#include <xenbus.h>
    4.11 +#include <events.h>
    4.12 +#include <errno.h>
    4.13 +#include <gnttab.h>
    4.14 +#include <xmalloc.h>
    4.15 +#include <wait.h>
    4.16 +#include <pcifront.h>
    4.17 +
    4.18 +#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
    4.19 +
    4.20 +DECLARE_WAIT_QUEUE_HEAD(pcifront_queue);
    4.21 +
    4.22 +struct pcifront_dev {
    4.23 +    domid_t dom;
    4.24 +
    4.25 +    struct xen_pci_sharedinfo *info;
    4.26 +    grant_ref_t info_ref;
    4.27 +    evtchn_port_t evtchn;
    4.28 +
    4.29 +    char *nodename;
    4.30 +    char *backend;
    4.31 +
    4.32 +    xenbus_event_queue events;
    4.33 +};
    4.34 +
    4.35 +void pcifront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
    4.36 +{
    4.37 +    wake_up(&pcifront_queue);
    4.38 +}
    4.39 +
    4.40 +static void free_pcifront(struct pcifront_dev *dev)
    4.41 +{
    4.42 +    mask_evtchn(dev->evtchn);
    4.43 +
    4.44 +    free(dev->backend);
    4.45 +
    4.46 +    gnttab_end_access(dev->info_ref);
    4.47 +    free_page(dev->info);
    4.48 +
    4.49 +    unbind_evtchn(dev->evtchn);
    4.50 +
    4.51 +    free(dev->nodename);
    4.52 +    free(dev);
    4.53 +}
    4.54 +
    4.55 +struct pcifront_dev *init_pcifront(char *nodename)
    4.56 +{
    4.57 +    xenbus_transaction_t xbt;
    4.58 +    char* err;
    4.59 +    char* message=NULL;
    4.60 +    int retry=0;
    4.61 +    char* msg;
    4.62 +
    4.63 +    struct pcifront_dev *dev;
    4.64 +
    4.65 +    if (!nodename)
    4.66 +        nodename = "device/pci/0";
    4.67 +
    4.68 +    char path[strlen(nodename) + 1 + 10 + 1];
    4.69 +
    4.70 +    printk("******************* PCIFRONT for %s **********\n\n\n", nodename);
    4.71 +
    4.72 +    dev = malloc(sizeof(*dev));
    4.73 +    memset(dev, 0, sizeof(*dev));
    4.74 +    dev->nodename = strdup(nodename);
    4.75 +
    4.76 +    snprintf(path, sizeof(path), "%s/backend-id", nodename);
    4.77 +    dev->dom = xenbus_read_integer(path); 
    4.78 +    evtchn_alloc_unbound(dev->dom, pcifront_handler, dev, &dev->evtchn);
    4.79 +
    4.80 +    dev->info = (struct xen_pci_sharedinfo*) alloc_page();
    4.81 +    memset(dev->info,0,PAGE_SIZE);
    4.82 +
    4.83 +    dev->info_ref = gnttab_grant_access(dev->dom,virt_to_mfn(dev->info),0);
    4.84 +
    4.85 +    dev->events = NULL;
    4.86 +
    4.87 +again:
    4.88 +    err = xenbus_transaction_start(&xbt);
    4.89 +    if (err) {
    4.90 +        printk("starting transaction\n");
    4.91 +    }
    4.92 +
    4.93 +    err = xenbus_printf(xbt, nodename, "pci-op-ref","%u",
    4.94 +                dev->info_ref);
    4.95 +    if (err) {
    4.96 +        message = "writing pci-op-ref";
    4.97 +        goto abort_transaction;
    4.98 +    }
    4.99 +    err = xenbus_printf(xbt, nodename,
   4.100 +                "event-channel", "%u", dev->evtchn);
   4.101 +    if (err) {
   4.102 +        message = "writing event-channel";
   4.103 +        goto abort_transaction;
   4.104 +    }
   4.105 +    err = xenbus_printf(xbt, nodename,
   4.106 +                "magic", XEN_PCI_MAGIC);
   4.107 +    if (err) {
   4.108 +        message = "writing magic";
   4.109 +        goto abort_transaction;
   4.110 +    }
   4.111 +
   4.112 +    err = xenbus_printf(xbt, nodename, "state", "%u",
   4.113 +            3); /* initialised */
   4.114 +
   4.115 +
   4.116 +    err = xenbus_transaction_end(xbt, 0, &retry);
   4.117 +    if (retry) {
   4.118 +            goto again;
   4.119 +        printk("completing transaction\n");
   4.120 +    }
   4.121 +
   4.122 +    goto done;
   4.123 +
   4.124 +abort_transaction:
   4.125 +    xenbus_transaction_end(xbt, 1, &retry);
   4.126 +    goto error;
   4.127 +
   4.128 +done:
   4.129 +
   4.130 +    snprintf(path, sizeof(path), "%s/backend", nodename);
   4.131 +    msg = xenbus_read(XBT_NIL, path, &dev->backend);
   4.132 +    if (msg) {
   4.133 +        printk("Error %s when reading the backend path %s\n", msg, path);
   4.134 +        goto error;
   4.135 +    }
   4.136 +
   4.137 +    printk("backend at %s\n", dev->backend);
   4.138 +
   4.139 +    {
   4.140 +        char path[strlen(dev->backend) + 1 + 5 + 1];
   4.141 +        snprintf(path, sizeof(path), "%s/state", dev->backend);
   4.142 +
   4.143 +        xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
   4.144 +
   4.145 +        xenbus_wait_for_value(path, "4", &dev->events);
   4.146 +
   4.147 +        xenbus_printf(xbt, nodename, "state", "%u", 4); /* connected */
   4.148 +    }
   4.149 +    unmask_evtchn(dev->evtchn);
   4.150 +
   4.151 +    printk("**************************\n");
   4.152 +
   4.153 +    return dev;
   4.154 +
   4.155 +error:
   4.156 +    free_pcifront(dev);
   4.157 +    return NULL;
   4.158 +}
   4.159 +
   4.160 +void pcifront_scan(struct pcifront_dev *dev, void (*func)(unsigned int domain, unsigned int bus, unsigned slot, unsigned int fun))
   4.161 +{
   4.162 +    char path[strlen(dev->backend) + 1 + 5 + 10 + 1];
   4.163 +    int i, n;
   4.164 +    char *s, *msg;
   4.165 +    unsigned int domain, bus, slot, fun;
   4.166 +
   4.167 +    snprintf(path, sizeof(path), "%s/num_devs", dev->backend);
   4.168 +    n = xenbus_read_integer(path);
   4.169 +
   4.170 +    for (i = 0; i < n; i++) {
   4.171 +        snprintf(path, sizeof(path), "%s/vdev-%d", dev->backend, i);
   4.172 +        msg = xenbus_read(XBT_NIL, path, &s);
   4.173 +        if (msg) {
   4.174 +            printk("Error %s when reading the PCI root name at %s\n", path);
   4.175 +            continue;
   4.176 +        }
   4.177 +
   4.178 +        if (sscanf(s, "%x:%x:%x.%x", &domain, &bus, &slot, &fun) != 4) {
   4.179 +            printk("\"%s\" does not look like a PCI device address\n", s);
   4.180 +            free(s);
   4.181 +            continue;
   4.182 +        }
   4.183 +        free(s);
   4.184 +
   4.185 +        func(domain, bus, slot, fun);
   4.186 +    }
   4.187 +}
   4.188 +
   4.189 +void shutdown_pcifront(struct pcifront_dev *dev)
   4.190 +{
   4.191 +    char* err;
   4.192 +    char *nodename = dev->nodename;
   4.193 +
   4.194 +    char path[strlen(dev->backend) + 1 + 5 + 1];
   4.195 +
   4.196 +    printk("close pci: backend at %s\n",dev->backend);
   4.197 +
   4.198 +    snprintf(path, sizeof(path), "%s/state", dev->backend);
   4.199 +    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
   4.200 +    xenbus_wait_for_value(path, "5", &dev->events);
   4.201 +
   4.202 +    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
   4.203 +    xenbus_wait_for_value(path, "6", &dev->events);
   4.204 +
   4.205 +    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
   4.206 +    xenbus_wait_for_value(path, "2", &dev->events);
   4.207 +
   4.208 +    xenbus_unwatch_path(XBT_NIL, path);
   4.209 +
   4.210 +    snprintf(path, sizeof(path), "%s/info-ref", nodename);
   4.211 +    xenbus_rm(XBT_NIL, path);
   4.212 +    snprintf(path, sizeof(path), "%s/event-channel", nodename);
   4.213 +    xenbus_rm(XBT_NIL, path);
   4.214 +
   4.215 +    free_pcifront(dev);
   4.216 +}
   4.217 +
   4.218 +
   4.219 +void pcifront_op(struct pcifront_dev *dev, struct xen_pci_op *op)
   4.220 +{
   4.221 +    dev->info->op = *op;
   4.222 +    /* Make sure info is written before the flag */
   4.223 +    wmb();
   4.224 +    set_bit(_XEN_PCIF_active, &dev->info->flags);
   4.225 +    notify_remote_via_evtchn(dev->evtchn);
   4.226 +
   4.227 +    wait_event(pcifront_queue, !test_bit(_XEN_PCIF_active, &dev->info->flags));
   4.228 +
   4.229 +    /* Make sure flag is read before info */
   4.230 +    rmb();
   4.231 +    *op = dev->info->op;
   4.232 +}
   4.233 +
   4.234 +int pcifront_conf_read(struct pcifront_dev *dev,
   4.235 +                       unsigned int dom,
   4.236 +                       unsigned int bus, unsigned int slot, unsigned long fun,
   4.237 +                       unsigned int off, unsigned int size, unsigned int *val)
   4.238 +{
   4.239 +    struct xen_pci_op op;
   4.240 +
   4.241 +    memset(&op, 0, sizeof(op));
   4.242 +
   4.243 +    op.cmd = XEN_PCI_OP_conf_read;
   4.244 +    op.domain = dom;
   4.245 +    op.bus = bus;
   4.246 +    op.devfn = PCI_DEVFN(slot, fun);
   4.247 +    op.offset = off;
   4.248 +    op.size = size;
   4.249 +
   4.250 +    pcifront_op(dev, &op);
   4.251 +
   4.252 +    if (op.err)
   4.253 +        return op.err;
   4.254 +
   4.255 +    *val = op.value;
   4.256 +
   4.257 +    return 0;
   4.258 +}
   4.259 +
   4.260 +int pcifront_conf_write(struct pcifront_dev *dev,
   4.261 +                        unsigned int dom,
   4.262 +                        unsigned int bus, unsigned int slot, unsigned long fun,
   4.263 +                        unsigned int off, unsigned int size, unsigned int val)
   4.264 +{
   4.265 +    struct xen_pci_op op;
   4.266 +
   4.267 +    memset(&op, 0, sizeof(op));
   4.268 +
   4.269 +    op.cmd = XEN_PCI_OP_conf_write;
   4.270 +    op.domain = dom;
   4.271 +    op.bus = bus;
   4.272 +    op.devfn = PCI_DEVFN(slot, fun);
   4.273 +    op.offset = off;
   4.274 +    op.size = size;
   4.275 +
   4.276 +    op.value = val;
   4.277 +
   4.278 +    pcifront_op(dev, &op);
   4.279 +
   4.280 +    return op.err;
   4.281 +}
     5.1 --- a/stubdom/Makefile	Wed Jul 02 13:37:16 2008 +0100
     5.2 +++ b/stubdom/Makefile	Wed Jul 02 13:54:20 2008 +0100
     5.3 @@ -131,16 +131,20 @@ cross-zlib: $(ZLIB_STAMPFILE)
     5.4  pciutils-$(LIBPCI_VERSION).tar.bz2:
     5.5  	$(WGET) http://www.kernel.org/pub/software/utils/pciutils/pciutils-$(LIBPCI_VERSION).tar.bz2
     5.6  
     5.7 +pciutils-$(LIBPCI_VERSION): pciutils-$(LIBPCI_VERSION).tar.bz2
     5.8 +	tar xjf $<
     5.9 +	patch -d $@ -p1 < pciutils.patch
    5.10 +	touch $@
    5.11 +
    5.12  LIBPCI_STAMPFILE=$(CROSS_ROOT)/$(GNU_TARGET_ARCH)-xen-elf/lib/libpci.a
    5.13  .PHONY: cross-libpci
    5.14  cross-libpci: $(LIBPCI_STAMPFILE)
    5.15 -$(LIBPCI_STAMPFILE): pciutils-$(LIBPCI_VERSION).tar.bz2 $(NEWLIB_STAMPFILE) $(ZLIB_STAMPFILE)
    5.16 -	tar xjf $<
    5.17 +$(LIBPCI_STAMPFILE): pciutils-$(LIBPCI_VERSION) $(NEWLIB_STAMPFILE) $(ZLIB_STAMPFILE)
    5.18  	( cd pciutils-$(LIBPCI_VERSION) && \
    5.19  	  cp ../libpci.config.h lib/config.h && \
    5.20  	  echo '#define PCILIB_VERSION "$(LIBPCI_VERSION)"' >> lib/config.h && \
    5.21  	  cp ../libpci.config.mak lib/config.mk && \
    5.22 -	  $(MAKE) CC="$(GNU_TARGET_ARCH)-xen-elf-gcc $(TARGET_CFLAGS)" lib/libpci.a && \
    5.23 +	  $(MAKE) CC="$(GNU_TARGET_ARCH)-xen-elf-gcc $(TARGET_CFLAGS) -I$(realpath $(MINI_OS)/include)" lib/libpci.a && \
    5.24  	  $(INSTALL_DATA) lib/libpci.a $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/lib/ && \
    5.25  	  $(INSTALL_DIR) $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/include/pci && \
    5.26  	  $(INSTALL_DATA) lib/{config,header,pci,types}.h $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/include/pci/ \
     6.1 --- a/stubdom/libpci.config.h	Wed Jul 02 13:37:16 2008 +0100
     6.2 +++ b/stubdom/libpci.config.h	Wed Jul 02 13:54:20 2008 +0100
     6.3 @@ -1,4 +1,4 @@
     6.4 -#define PCI_OS_STUBDOM
     6.5 +#define PCI_OS_MINIOS
     6.6  #define PCI_HAVE_STDINT_H
     6.7  #define PCI_PATH_IDS_DIR "."
     6.8  #define PCI_COMPRESSED_IDS
     7.1 --- a/stubdom/libpci.config.mak	Wed Jul 02 13:37:16 2008 +0100
     7.2 +++ b/stubdom/libpci.config.mak	Wed Jul 02 13:54:20 2008 +0100
     7.3 @@ -1,2 +1,7 @@
     7.4  LIBZ=-lz
     7.5  LDLIBS+=$(LIBZ)
     7.6 +PCI_OS_MINIOS=1
     7.7 +PCI_HAVE_STDINT_H=1
     7.8 +PCI_PATH_IDS_DIR=.
     7.9 +PCI_COMPRESSED_IDS=1
    7.10 +PCI_IDS=pci.ids.gz
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/stubdom/pciutils.patch	Wed Jul 02 13:54:20 2008 +0100
     8.3 @@ -0,0 +1,299 @@
     8.4 +diff -urN pciutils-2.2.9.orig/lib/access.c pciutils-2.2.9/lib/access.c
     8.5 +--- pciutils-2.2.9.orig/lib/access.c	2007-02-06 11:59:43.000000000 +0000
     8.6 ++++ pciutils-2.2.9/lib/access.c	2008-06-30 19:07:09.713187000 +0100
     8.7 +@@ -57,6 +57,11 @@
     8.8 + #else
     8.9 +   NULL,
    8.10 + #endif
    8.11 ++#ifdef PCI_OS_MINIOS
    8.12 ++  &pm_minios,
    8.13 ++#else
    8.14 ++  NULL,
    8.15 ++#endif
    8.16 + };
    8.17 + 
    8.18 + struct pci_access *
    8.19 +--- pciutils-2.2.9.orig/lib/pci.h	2006-09-09 13:46:06.000000000 +0100
    8.20 ++++ pciutils-2.2.9/lib/pci.h	2008-06-30 18:56:15.350111000 +0100
    8.21 +@@ -33,6 +33,7 @@
    8.22 +   PCI_ACCESS_NBSD_LIBPCI,		/* NetBSD libpci */
    8.23 +   PCI_ACCESS_OBSD_DEVICE,		/* OpenBSD /dev/pci */
    8.24 +   PCI_ACCESS_DUMP,			/* Dump file (params: filename) */
    8.25 ++  PCI_ACCESS_MINIOS,			/* MiniOS */
    8.26 +   PCI_ACCESS_MAX
    8.27 + };
    8.28 + 
    8.29 +@@ -63,6 +64,7 @@
    8.30 +   int fd_rw;				/* proc: fd opened read-write */
    8.31 +   struct pci_dev *cached_dev;		/* proc: device the fd is for */
    8.32 +   int fd_pos;				/* proc: current position */
    8.33 ++  void *minios;
    8.34 + };
    8.35 + 
    8.36 + /* Initialize PCI access */
    8.37 +--- pciutils-2.2.9.orig/lib/internal.h	2006-09-09 11:52:47.000000000 +0100
    8.38 ++++ pciutils-2.2.9/lib/internal.h	2008-07-01 10:46:24.968202000 +0100
    8.39 +@@ -37,4 +37,4 @@
    8.40 + 
    8.41 + extern struct pci_methods pm_intel_conf1, pm_intel_conf2, pm_linux_proc,
    8.42 + 	pm_fbsd_device, pm_aix_device, pm_nbsd_libpci, pm_obsd_device,
    8.43 +-	pm_dump, pm_linux_sysfs;
    8.44 ++	pm_dump, pm_linux_sysfs, pm_minios;
    8.45 +--- pciutils-2.2.9.orig/lib/Makefile	2007-10-19 13:41:34.000000000 +0100
    8.46 ++++ pciutils-2.2.9/lib/Makefile	2008-07-01 12:13:14.400525000 +0100
    8.47 +@@ -46,6 +46,12 @@
    8.48 + PCILIB=libpciutils.a
    8.49 + endif
    8.50 + 
    8.51 ++ifdef PCI_OS_MINIOS
    8.52 ++XEN_ROOT=../../..
    8.53 ++include $(XEN_ROOT)/Config.mk
    8.54 ++OBJS += minios.o
    8.55 ++endif
    8.56 ++
    8.57 + all: $(PCILIB) $(PCILIBPC)
    8.58 + 
    8.59 + $(PCILIB): $(OBJS)
    8.60 +--- pciutils-2.2.9.orig/lib/types.h	2007-09-03 09:44:15.000000000 +0100
    8.61 ++++ pciutils-2.2.9/lib/types.h	2008-07-01 12:17:08.396156000 +0100
    8.62 +@@ -17,9 +17,13 @@
    8.63 + typedef DWORD u32;
    8.64 + #elif defined(PCI_HAVE_STDINT_H)
    8.65 + #include <stdint.h>
    8.66 ++#ifdef PCI_OS_MINIOS
    8.67 ++#include <types.h>
    8.68 ++#else
    8.69 + typedef uint8_t u8;
    8.70 + typedef uint16_t u16;
    8.71 + typedef uint32_t u32;
    8.72 ++#endif
    8.73 + #else
    8.74 + typedef u_int8_t u8;
    8.75 + typedef u_int16_t u16;
    8.76 +--- pciutils-2.2.9.orig/lib/minios.c	1970-01-01 01:00:00.000000000 +0100
    8.77 ++++ pciutils-2.2.9/lib/minios.c	2008-07-01 12:31:40.554260000 +0100
    8.78 +@@ -0,0 +1,113 @@
    8.79 ++/*
    8.80 ++ *	The PCI Library -- MiniOS PCI frontend access
    8.81 ++ *
    8.82 ++ *	Samuel Thibault <samuel.thibault@eu.citrix.com>, 2008
    8.83 ++ *
    8.84 ++ *	Can be freely distributed and used under the terms of the GNU GPL.
    8.85 ++ */
    8.86 ++
    8.87 ++#include <os.h>
    8.88 ++#include <pcifront.h>
    8.89 ++#include <xenbus.h>
    8.90 ++#include "internal.h"
    8.91 ++
    8.92 ++static int
    8.93 ++minios_detect(struct pci_access *a)
    8.94 ++{
    8.95 ++  return 1;
    8.96 ++}
    8.97 ++
    8.98 ++static void
    8.99 ++minios_init(struct pci_access *a)
   8.100 ++{
   8.101 ++  a->minios = init_pcifront(NULL);
   8.102 ++  if (!a->minios)
   8.103 ++    a->warning("minios_init open failed");
   8.104 ++}
   8.105 ++
   8.106 ++static void
   8.107 ++minios_cleanup(struct pci_access *a)
   8.108 ++{
   8.109 ++  if (a->minios)
   8.110 ++    shutdown_pcifront(a->minios);
   8.111 ++}
   8.112 ++
   8.113 ++static void
   8.114 ++minios_scan(struct pci_access *a)
   8.115 ++{
   8.116 ++  if (!a->minios)
   8.117 ++    return;
   8.118 ++
   8.119 ++  void func(unsigned int domain, unsigned int bus, unsigned int slot, unsigned int fun)
   8.120 ++  {
   8.121 ++    struct pci_dev *d = pci_alloc_dev(a);
   8.122 ++
   8.123 ++    d->domain = domain;
   8.124 ++    d->bus = bus;
   8.125 ++    d->dev = slot;
   8.126 ++    d->func = fun;
   8.127 ++
   8.128 ++    pci_link_dev(a, d);
   8.129 ++  }
   8.130 ++
   8.131 ++  pcifront_scan(a->minios, func);
   8.132 ++}
   8.133 ++
   8.134 ++static int
   8.135 ++minios_read(struct pci_dev *d, int pos, byte *buf, int len)
   8.136 ++{
   8.137 ++  unsigned int val;
   8.138 ++  switch (len) {
   8.139 ++    case 1:
   8.140 ++      if (pcifront_conf_read(d->access->minios, d->domain, d->bus, d->dev, d->func, pos, len, &val))
   8.141 ++        return 0;
   8.142 ++      * buf = val;
   8.143 ++      return 1;
   8.144 ++    case 2:
   8.145 ++      if (pcifront_conf_read(d->access->minios, d->domain, d->bus, d->dev, d->func, pos, len, &val))
   8.146 ++        return 0;
   8.147 ++      *(u16 *) buf = cpu_to_le16((u16) val);
   8.148 ++      return 1;
   8.149 ++    case 4:
   8.150 ++      if (pcifront_conf_read(d->access->minios, d->domain, d->bus, d->dev, d->func, pos, len, &val))
   8.151 ++        return 0;
   8.152 ++      *(u32 *) buf = cpu_to_le32((u32) val);
   8.153 ++      return 1;
   8.154 ++    default:
   8.155 ++      return pci_generic_block_read(d, pos, buf, len);
   8.156 ++  }
   8.157 ++}
   8.158 ++
   8.159 ++static int
   8.160 ++minios_write(struct pci_dev *d, int pos, byte *buf, int len)
   8.161 ++{
   8.162 ++  unsigned int val;
   8.163 ++  switch (len) {
   8.164 ++    case 1:
   8.165 ++      val = * buf;
   8.166 ++      break;
   8.167 ++    case 2:
   8.168 ++      val = le16_to_cpu(*(u16 *) buf);
   8.169 ++      break;
   8.170 ++    case 4:
   8.171 ++      val = le32_to_cpu(*(u32 *) buf);
   8.172 ++      break;
   8.173 ++    default:
   8.174 ++      return pci_generic_block_write(d, pos, buf, len);
   8.175 ++  }
   8.176 ++  return !pcifront_conf_write(d->access->minios, d->domain, d->bus, d->dev, d->func, pos, len, val);
   8.177 ++}
   8.178 ++
   8.179 ++struct pci_methods pm_minios = {
   8.180 ++  "MiniOS-device",
   8.181 ++  NULL,                                 /* config */
   8.182 ++  minios_detect,
   8.183 ++  minios_init,
   8.184 ++  minios_cleanup,
   8.185 ++  minios_scan,
   8.186 ++  pci_generic_fill_info,
   8.187 ++  minios_read,
   8.188 ++  minios_write,
   8.189 ++  NULL,                                 /* dev_init */
   8.190 ++  NULL                                  /* dev_cleanup */
   8.191 ++};
   8.192 +--- pciutils-2.2.9/lib/generic.c	2007-02-06 12:00:05.000000000 +0000
   8.193 ++++ pciutils-2.2.9-mine/lib/generic.c	2008-07-01 19:13:52.289949000 +0100
   8.194 +@@ -74,6 +74,19 @@
   8.195 +   pci_generic_scan_bus(a, busmap, 0);
   8.196 + }
   8.197 + 
   8.198 ++static u32 pci_size(u32 base, u32 maxbase, u32 mask)
   8.199 ++{
   8.200 ++  u32 size = mask & maxbase;
   8.201 ++  if (!size)
   8.202 ++    return 0;
   8.203 ++  size = (size & ~(size-1)) - 1;
   8.204 ++
   8.205 ++  if (base == maxbase && ((base | size) & mask) != mask)
   8.206 ++    return 0;
   8.207 ++
   8.208 ++  return size + 1;
   8.209 ++}
   8.210 ++
   8.211 + int
   8.212 + pci_generic_fill_info(struct pci_dev *d, int flags)
   8.213 + {
   8.214 +@@ -114,23 +127,61 @@
   8.215 + 	      if (!x || x == (u32) ~0)
   8.216 + 		continue;
   8.217 + 	      if ((x & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
   8.218 +-		d->base_addr[i] = x;
   8.219 +-	      else
   8.220 ++                {
   8.221 ++                  d->base_addr[i] = x & PCI_BASE_ADDRESS_IO_MASK;
   8.222 ++                  if (flags & PCI_FILL_SIZES)
   8.223 ++                    {
   8.224 ++                      u32 size;
   8.225 ++                      pci_write_long(d, PCI_BASE_ADDRESS_0 + i*4, ~0);
   8.226 ++                      d->size[i] = pci_size(x, pci_read_long(d, PCI_BASE_ADDRESS_0 + i*4), PCI_BASE_ADDRESS_IO_MASK);
   8.227 ++                      pci_write_long(d, PCI_BASE_ADDRESS_0 + i*4, x);
   8.228 ++                    }
   8.229 ++                }
   8.230 ++              else
   8.231 + 		{
   8.232 + 		  if ((x & PCI_BASE_ADDRESS_MEM_TYPE_MASK) != PCI_BASE_ADDRESS_MEM_TYPE_64)
   8.233 +-		    d->base_addr[i] = x;
   8.234 ++                    {
   8.235 ++                      d->base_addr[i] = x & PCI_BASE_ADDRESS_MEM_MASK;
   8.236 ++                      if (flags & PCI_FILL_SIZES)
   8.237 ++                        {
   8.238 ++                          u32 size;
   8.239 ++                          pci_write_long(d, PCI_BASE_ADDRESS_0 + i*4, ~0);
   8.240 ++                          d->size[i] = pci_read_long(d, PCI_BASE_ADDRESS_0 + i*4);
   8.241 ++                          d->size[i] = pci_size(x, pci_read_long(d, PCI_BASE_ADDRESS_0 + i*4), PCI_BASE_ADDRESS_MEM_MASK);
   8.242 ++                          pci_write_long(d, PCI_BASE_ADDRESS_0 + i*4, x);
   8.243 ++                        }
   8.244 ++                    }
   8.245 + 		  else if (i >= cnt-1)
   8.246 + 		    a->warning("%04x:%02x:%02x.%d: Invalid 64-bit address seen for BAR %d.", d->domain, d->bus, d->dev, d->func, i);
   8.247 + 		  else
   8.248 + 		    {
   8.249 + 		      u32 y = pci_read_long(d, PCI_BASE_ADDRESS_0 + (++i)*4);
   8.250 + #ifdef PCI_HAVE_64BIT_ADDRESS
   8.251 +-		      d->base_addr[i-1] = x | (((pciaddr_t) y) << 32);
   8.252 ++		      d->base_addr[i-1] = (x | (((pciaddr_t) y) << 32)) & PCI_BASE_ADDRESS_MEM_MASK;
   8.253 ++                      if (flags & PCI_FILL_SIZES)
   8.254 ++                        {
   8.255 ++                          u32 size;
   8.256 ++                          pci_write_long(d, PCI_BASE_ADDRESS_0 + (i-1)*4, ~0);
   8.257 ++                          pci_write_long(d, PCI_BASE_ADDRESS_0 + i*4, ~0);
   8.258 ++                          d->size[i-1] = pci_size(y, pci_read_long(d, PCI_BASE_ADDRESS_0 + (i-1)*4) | 
   8.259 ++                                         pci_read_long(d, PCI_BASE_ADDRESS_0 + i*4), 0xffffffff );
   8.260 ++                          pci_write_long(d, PCI_BASE_ADDRESS_0 + (i-1)*4, x);
   8.261 ++                          pci_write_long(d, PCI_BASE_ADDRESS_0 + i*4, y);
   8.262 ++                        }
   8.263 + #else
   8.264 + 		      if (y)
   8.265 + 			a->warning("%04x:%02x:%02x.%d 64-bit device address ignored.", d->domain, d->bus, d->dev, d->func);
   8.266 + 		      else
   8.267 +-			d->base_addr[i-1] = x;
   8.268 ++                        {
   8.269 ++                          d->base_addr[i-1] = x & PCI_BASE_ADDRESS_MEM_MASK;
   8.270 ++                          if (flags & PCI_FILL_SIZES)
   8.271 ++                            {
   8.272 ++                              u32 size;
   8.273 ++                              pci_write_long(d, PCI_BASE_ADDRESS_0 + (i-1)*4, ~0);
   8.274 ++                              d->size[i-1] = pci_size(x, pci_read_long(d, PCI_BASE_ADDRESS_0 + (i-1)*4), PCI_BASE_ADDRESS_MEM_MASK);
   8.275 ++                              pci_write_long(d, PCI_BASE_ADDRESS_0 + (i-1)*4, x);
   8.276 ++                            }
   8.277 ++                        }
   8.278 + #endif
   8.279 + 		    }
   8.280 + 		}
   8.281 +@@ -154,10 +205,19 @@
   8.282 + 	{
   8.283 + 	  u32 u = pci_read_long(d, reg);
   8.284 + 	  if (u != 0xffffffff)
   8.285 +-	    d->rom_base_addr = u;
   8.286 ++            {
   8.287 ++              d->rom_base_addr = u;
   8.288 ++              if (flags & PCI_FILL_SIZES)
   8.289 ++                {
   8.290 ++                  u32 size;
   8.291 ++                  pci_write_long(d, reg, ~0);
   8.292 ++                  d->rom_size = pci_read_long(d, reg);
   8.293 ++                  pci_write_long(d, reg, u);
   8.294 ++                }
   8.295 ++            }
   8.296 + 	}
   8.297 +     }
   8.298 +-  return flags & ~PCI_FILL_SIZES;
   8.299 ++  return flags;
   8.300 + }
   8.301 + 
   8.302 + static int
     9.1 --- a/tools/ioemu/Makefile.target	Wed Jul 02 13:37:16 2008 +0100
     9.2 +++ b/tools/ioemu/Makefile.target	Wed Jul 02 13:54:20 2008 +0100
     9.3 @@ -358,7 +358,7 @@ VL_OBJS+=tap-win32.o
     9.4  endif
     9.5  
     9.6  ifdef CONFIG_STUBDOM
     9.7 -#CONFIG_PASSTHROUGH=1
     9.8 +CONFIG_PASSTHROUGH=1
     9.9  else
    9.10    ifeq (,$(wildcard /usr/include/pci))
    9.11  $(warning *** pciutils-devl package not found - missing /usr/include/pci)
    10.1 --- a/tools/ioemu/hw/pass-through.c	Wed Jul 02 13:37:16 2008 +0100
    10.2 +++ b/tools/ioemu/hw/pass-through.c	Wed Jul 02 13:54:20 2008 +0100
    10.3 @@ -515,6 +515,7 @@ struct pt_dev * register_real_device(PCI
    10.4          PT_LOG("Error: couldn't locate device in libpci structures\n");
    10.5          return NULL;
    10.6      }
    10.7 +    pci_fill_info(pci_dev, PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES);
    10.8  
    10.9      if ( e_devfn == PT_VIRT_DEVFN_AUTO ) {
   10.10          /*indicate a static assignment(not hotplug), so find a free PCI hot plug slot */
    11.1 --- a/tools/ioemu/xenstore.c	Wed Jul 02 13:37:16 2008 +0100
    11.2 +++ b/tools/ioemu/xenstore.c	Wed Jul 02 13:54:20 2008 +0100
    11.3 @@ -320,7 +320,7 @@ void xenstore_parse_domain_config(int hv
    11.4  
    11.5      /* get the pci pass-through parameter */
    11.6      if (pasprintf(&buf, "/local/domain/0/backend/pci/%u/%u/num_devs",
    11.7 -                  domid, pci_devid) == -1)
    11.8 +                  hvm_domid, pci_devid) == -1)
    11.9          goto out;
   11.10  
   11.11      free(params);
   11.12 @@ -331,7 +331,7 @@ void xenstore_parse_domain_config(int hv
   11.13  
   11.14      for ( i = 0; i < num; i++ ) {
   11.15          if (pasprintf(&buf, "/local/domain/0/backend/pci/%u/%u/dev-%d",
   11.16 -                    domid, pci_devid, i) != -1) {
   11.17 +                    hvm_domid, pci_devid, i) != -1) {
   11.18              free(dev);
   11.19              dev = xs_read(xsh, XBT_NULL, buf, &len);
   11.20