From de4e0840642f41b2a0feef8a97afc360c734bb2b Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 2 Jul 2008 13:54:20 +0100 Subject: stubdom: PCI passthrough support via PV-PCI Signed-off-by: Samuel Thibault --- stubdom/pciutils.patch | 299 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 stubdom/pciutils.patch (limited to 'stubdom/pciutils.patch') diff --git a/stubdom/pciutils.patch b/stubdom/pciutils.patch new file mode 100644 index 0000000000..189b7ff719 --- /dev/null +++ b/stubdom/pciutils.patch @@ -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 ++#ifdef PCI_OS_MINIOS ++#include ++#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 , 2008 ++ * ++ * Can be freely distributed and used under the terms of the GNU GPL. ++ */ ++ ++#include ++#include ++#include ++#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 -- cgit v1.2.3