[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |