diff --git a/default-configs/pci.mak b/default-configs/pci.mak
index f250119..699a5a5 100644
--- a/default-configs/pci.mak
+++ b/default-configs/pci.mak
@@ -36,4 +36,5 @@ CONFIG_EDU=y
 CONFIG_VGA=y
 CONFIG_VGA_PCI=y
 CONFIG_IVSHMEM=$(CONFIG_POSIX)
+CONFIG_SLAVEPCIPASSTHRU=$(CONFIG_POSIX)
 CONFIG_ROCKER=y
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index d4765c2..e346a15 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -20,6 +20,7 @@ common-obj-$(CONFIG_PUV3) += puv3_pm.o
 common-obj-$(CONFIG_MACIO) += macio/
 
 obj-$(CONFIG_IVSHMEM) += ivshmem.o
+obj-$(CONFIG_SLAVEPCIPASSTHRU) += slavepci_passthru.o
 
 obj-$(CONFIG_REALVIEW) += arm_sysctl.o
 obj-$(CONFIG_NSERIES) += cbus.o
diff --git a/hw/misc/slavepci_passthru.c b/hw/misc/slavepci_passthru.c
new file mode 100644
index 0000000..ee709b7
--- /dev/null
+++ b/hw/misc/slavepci_passthru.c
@@ -0,0 +1,453 @@
+/*
+ * Host Device PCI-Card Slave Pass-Thru: based on ivshmem "qemu-device"
+ * 
+ *
+ * Author:
+ *      By Francesco Zuliani AT Neat S.r.l. <francesco.zuliani@neat.it>
+ *
+ * Based On: ivshmem.c
+ *          Original Author Cam Macdonell 
+ *
+ * This code is licensed under the GNU GPL v2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "hw/hw.h"
+#include "hw/i386/pc.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/msix.h"
+#include "sysemu/kvm.h"
+#include "migration/migration.h"
+#include "qemu/error-report.h"
+#include "qemu/event_notifier.h"
+#include "sysemu/char.h"
+
+#include <stdio.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#define PCI_VENDOR_ID_SLAVEPASSTHRU_DEFAULT PCI_VENDOR_ID_REDHAT_QUMRANET
+#define PCI_DEVICE_ID_SLAVEPASSTHRU_DEFAULT 0x2222
+
+#define STRINGIFY(a)  #a
+
+//#define DEBUG_SLAVEPASSTHRU
+#ifdef DEBUG_SLAVEPASSTHRU
+#define SLAVEPASSTHRU_DPRINTF(fmt, ...)        \
+    do {printf("SLAVEPASSTHRU: " fmt, ## __VA_ARGS__); } while (0)
+#else
+#define SLAVEPASSTHRU_DPRINTF(fmt, ...)
+#endif
+
+#define TYPE_SLAVEPASSTHRU "slavepassthru"
+#define SLAVEPASSTHRU(obj) \
+    OBJECT_CHECK(SlavepassthruState, (obj), TYPE_SLAVEPASSTHRU)
+
+typedef struct SlavepassthruState {
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
+  
+    /* We might need to register the BAR before we actually have the memory.
+     * So prepare a container MemoryRegion for the BAR immediately and
+     * add a subregion when we have the memory.
+     */
+    MemoryRegion bar1; /* Bar-region */
+    MemoryRegion bar2; /* Bar-region */
+    MemoryRegion bar3; /* Bar-region */
+    MemoryRegion bar4; /* Bar-region */
+    MemoryRegion bar5; /* Bar-region */
+    MemoryRegion bar6; /* Bar-region */
+
+    MemoryRegion slavepassthru1; /* Sub-region */
+    MemoryRegion slavepassthru2; /* Sub-region */
+    MemoryRegion slavepassthru3; /* Sub-region */
+    MemoryRegion slavepassthru4; /* Sub-region */
+    MemoryRegion slavepassthru5; /* Sub-region */
+    MemoryRegion slavepassthru6; /* Sub-region */
+
+    uint64_t slavepassthru_size1;
+    uint64_t slavepassthru_size2;
+    uint64_t slavepassthru_size3;
+    uint64_t slavepassthru_size4;
+    uint64_t slavepassthru_size5;
+    uint64_t slavepassthru_size6;
+
+    uint64_t slavepassthru_baseaddr1;
+    uint64_t slavepassthru_baseaddr2;
+    uint64_t slavepassthru_baseaddr3;
+    uint64_t slavepassthru_baseaddr4;
+    uint64_t slavepassthru_baseaddr5;
+    uint64_t slavepassthru_baseaddr6;
+
+    int mmap_fd1; /* mmap bar1 file descriptor */
+    int mmap_fd2; /* mmap bar2 file descriptor */
+    int mmap_fd3; /* mmap bar3 file descriptor */
+    int mmap_fd4; /* mmap bar4 file descriptor */
+    int mmap_fd5; /* mmap bar5 file descriptor */
+    int mmap_fd6; /* mmap bar6 file descriptor */
+
+    uint32_t slavepassthru_attr;
+
+    uint32_t slavepassthru_64bit;
+
+    char * sizearg1;
+    char * sizearg2;
+    char * sizearg3;
+    char * sizearg4;
+    char * sizearg5;
+    char * sizearg6;
+    char * baseaddrarg1;
+    char * baseaddrarg2;
+    char * baseaddrarg3;
+    char * baseaddrarg4;
+    char * baseaddrarg5;
+    char * baseaddrarg6;
+
+} SlavepassthruState;
+
+static inline bool is_power_of_two(uint64_t x) {
+    return (x & (x - 1)) == 0;
+}
+
+/* create the shared memory BAR when we are not using the server, so we can
+ * create the BAR and map the memory immediately */
+static void create_shared_memory_BAR(SlavepassthruState *s, int fd, int bar) {
+
+    void   *ptr=NULL;
+    void   *region=NULL ;
+    void   *subregion=NULL ;
+    off_t  baseaddr=NULL ;
+    size_t size=0 ;
+    char   name[255];
+    
+    if ( bar == 0 ) {
+      s->mmap_fd1 = fd;
+      region      = &s->bar1 ;
+      subregion   = &s->slavepassthru1 ;
+      baseaddr    = s->slavepassthru_baseaddr1;
+      size        = s->slavepassthru_size1 ;
+    } else if ( bar == 1 ) {
+      s->mmap_fd2 = fd;
+      region      = &s->bar2 ;
+      subregion   = &s->slavepassthru2 ;
+      baseaddr    = s->slavepassthru_baseaddr2;
+      size        = s->slavepassthru_size2 ;
+    } else if ( bar == 2 ) {
+      s->mmap_fd3 = fd;
+      region      = &s->bar3 ;
+      subregion   = &s->slavepassthru3 ;
+      baseaddr    = s->slavepassthru_baseaddr3;
+      size        = s->slavepassthru_size3 ;
+    } else if ( bar == 3 ) {
+      s->mmap_fd4 = fd;
+      region      = &s->bar4 ;
+      subregion   = &s->slavepassthru4 ;
+      baseaddr    = s->slavepassthru_baseaddr4;
+      size        = s->slavepassthru_size4 ;
+    } else if ( bar == 4 ) {
+      s->mmap_fd5 = fd;
+      region      = &s->bar5 ;
+      subregion   = &s->slavepassthru5 ;
+      baseaddr    = s->slavepassthru_baseaddr5;
+      size        = s->slavepassthru_size5 ;
+    } else if ( bar == 5 ) {
+      s->mmap_fd6 = fd;
+      region      = &s->bar6 ;
+      subregion   = &s->slavepassthru6 ;
+      baseaddr    = s->slavepassthru_baseaddr6;
+      size        = s->slavepassthru_size6 ;
+    } else {
+      printf("BAD BAR [0-5] CURR: %d\n", bar);
+      exit(1);
+    }
+
+    snprintf(name, 255, "slavepassthru.bar%d", bar);
+    
+    errno=0;
+    ptr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, baseaddr);
+
+    if (errno != 0 ) {
+      printf("DEBUG BAR %d %s\n", bar, name);
+      printf("DEBUG MMAP %p\n", ptr);
+      printf("DEBUG SIZE %ld\n", size);
+      printf("DEBUG ADDR %lx\n", baseaddr);
+      printf("DEBUG FD   %d\n", fd);
+      exit(1);
+    } else {
+      memory_region_init_ram_ptr( subregion, OBJECT(s), name, size, ptr);
+      memory_region_add_subregion( region, 0, subregion);
+      /* region for shared memory */
+      pci_register_bar(PCI_DEVICE(s), bar, s->slavepassthru_attr, region);
+    }
+}
+
+
+static void slavepassthru_reset(DeviceState *d)
+{
+    SlavepassthruState *s = SLAVEPASSTHRU(d);
+
+    slavepassthru_use_msix(s);
+}
+
+static uint64_t slavepassthru_get_size(char *src) {
+
+    uint64_t value;
+    char *ptr;
+
+    value = strtoull(src, &ptr, 10);
+
+    switch (*ptr) {
+        case 0:
+            break;
+        case 'K': case 'k':
+            value <<= 10;
+            break;
+        case 'M': case 'm':
+            value <<= 20;
+            break;
+        case 'G': case 'g':
+            value <<= 30;
+            break;
+        default:
+            error_report("invalid ram size: %s", src);
+            exit(1);
+    }
+
+    /* BARs must be a power of 2 */
+    if (!is_power_of_two(value)) {
+        error_report("grr size must be power of 2");
+	exit(1);
+    }
+
+    return value;
+}
+
+
+static uint64_t slavepassthru_get_hex(char * src)
+{
+
+    uint64_t value;
+    char *ptr;
+    
+    value = strtoull(src, &ptr, 16);
+
+    return value;
+}
+
+static uint64_t slavepassthru_get_baseaddr(char * src)
+{
+  return slavepassthru_get_hex(src);
+}
+
+static void slavepassthru_write_config(PCIDevice *pci_dev, uint32_t address,
+				 uint32_t val, int len)
+{
+    pci_default_write_config(pci_dev, address, val, len);
+}
+
+static int pci_slavepassthru_init(PCIDevice *dev)
+{
+    SlavepassthruState *s = SLAVEPASSTHRU(dev);
+    uint8_t *pci_conf;
+
+    if (s->sizearg1 == NULL ||
+	s->sizearg2 == NULL ||
+	s->sizearg3 == NULL ||
+	s->sizearg4 == NULL ||
+	s->sizearg5 == NULL ||
+	s->sizearg6 == NULL )
+      {
+        error_report("6 sizes mandatory");
+        exit(1);
+      }
+    else
+      {
+	s->slavepassthru_size1 = slavepassthru_get_size(s->sizearg1);
+	s->slavepassthru_size2 = slavepassthru_get_size(s->sizearg2);
+	s->slavepassthru_size3 = slavepassthru_get_size(s->sizearg3);
+	s->slavepassthru_size4 = slavepassthru_get_size(s->sizearg4);
+	s->slavepassthru_size5 = slavepassthru_get_size(s->sizearg5);
+	s->slavepassthru_size6 = slavepassthru_get_size(s->sizearg6);
+      }
+
+    if (s->baseaddrarg1 == NULL ||
+	s->baseaddrarg2 == NULL ||
+	s->baseaddrarg3 == NULL ||
+	s->baseaddrarg4 == NULL ||
+	s->baseaddrarg5 == NULL ||
+	s->baseaddrarg6 == NULL
+	)
+      {
+        error_report("6 baseaddr mandatory");
+        exit(1);
+      }
+    else
+      {
+	s->slavepassthru_baseaddr1 = slavepassthru_get_baseaddr(s->baseaddrarg1);
+	s->slavepassthru_baseaddr2 = slavepassthru_get_baseaddr(s->baseaddrarg2);
+	s->slavepassthru_baseaddr3 = slavepassthru_get_baseaddr(s->baseaddrarg3);
+	s->slavepassthru_baseaddr4 = slavepassthru_get_baseaddr(s->baseaddrarg4);
+	s->slavepassthru_baseaddr5 = slavepassthru_get_baseaddr(s->baseaddrarg5);
+	s->slavepassthru_baseaddr6 = slavepassthru_get_baseaddr(s->baseaddrarg6);
+      }
+
+    pci_conf = dev->config;
+    pci_conf[PCI_COMMAND] = PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+
+    pci_config_set_interrupt_pin(pci_conf, 1);
+
+    s->mmap_fd1 = 0;
+    s->mmap_fd2 = 0;
+    s->mmap_fd3 = 0;
+    s->mmap_fd4 = 0;
+    s->mmap_fd5 = 0;
+    s->mmap_fd6 = 0;
+
+    memory_region_init(&s->bar1, OBJECT(s), "slavepassthru-bar1-container", s->slavepassthru_size1);
+    memory_region_init(&s->bar2, OBJECT(s), "slavepassthru-bar2-container", s->slavepassthru_size2);
+    memory_region_init(&s->bar3, OBJECT(s), "slavepassthru-bar3-container", s->slavepassthru_size3);
+    memory_region_init(&s->bar4, OBJECT(s), "slavepassthru-bar4-container", s->slavepassthru_size4);
+    memory_region_init(&s->bar5, OBJECT(s), "slavepassthru-bar5-container", s->slavepassthru_size5);
+    memory_region_init(&s->bar6, OBJECT(s), "slavepassthru-bar6-container", s->slavepassthru_size6);
+
+
+    /* PCI Card usually not prefectch-able */
+    s->slavepassthru_attr = PCI_BASE_ADDRESS_SPACE_MEMORY ;
+
+    if (s->slavepassthru_64bit) {
+        s->slavepassthru_attr |= PCI_BASE_ADDRESS_MEM_TYPE_64;
+    }
+
+    {
+        /* just map the file immediately, we're not using a server */
+        int fd1=0;
+        int fd2=0;
+        int fd3=0;
+        int fd4=0;
+        int fd5=0;
+        int fd6=0;
+
+        /* try opening with O_EXCL and if it succeeds zero the memory
+         * by truncating to 0 */
+	if((fd1 = open("/dev/mem", O_RDWR)) < 0) {
+            error_report("could not open /dev/mem");
+            exit(1);
+        }
+
+	if((fd2 = open("/dev/mem", O_RDWR)) < 0) {
+            error_report("could not open /dev/mem");
+            exit(1);
+        }
+
+	if((fd3 = open("/dev/mem", O_RDWR)) < 0) {
+            error_report("could not open /dev/mem");
+            exit(1);
+        }
+
+	if((fd4 = open("/dev/mem", O_RDWR)) < 0) {
+            error_report("could not open /dev/mem");
+            exit(1);
+        }
+
+	if((fd5 = open("/dev/mem", O_RDWR)) < 0) {
+            error_report("could not open /dev/mem");
+            exit(1);
+        }
+
+	if((fd6 = open("/dev/mem", O_RDWR)) < 0) {
+            error_report("could not open /dev/mem");
+            exit(1);
+        }
+
+        create_shared_memory_BAR(s, fd1, 0);
+        create_shared_memory_BAR(s, fd2, 1);
+        create_shared_memory_BAR(s, fd3, 2);
+        create_shared_memory_BAR(s, fd4, 3);
+        create_shared_memory_BAR(s, fd5, 3);
+        create_shared_memory_BAR(s, fd6, 3);
+    }
+
+    dev->config_write = slavepassthru_write_config;
+
+    return 0;
+}
+
+static void pci_slavepassthru_uninit(PCIDevice *dev)
+{
+    SlavepassthruState *s = SLAVEPASSTHRU(dev);
+
+    memory_region_del_subregion(&s->bar1, &s->slavepassthru1);
+    memory_region_del_subregion(&s->bar2, &s->slavepassthru2);
+    memory_region_del_subregion(&s->bar3, &s->slavepassthru3);
+    memory_region_del_subregion(&s->bar4, &s->slavepassthru4);
+    memory_region_del_subregion(&s->bar5, &s->slavepassthru5);
+    memory_region_del_subregion(&s->bar6, &s->slavepassthru6);
+    close(s->mmap_fd1);
+    close(s->mmap_fd2);
+    close(s->mmap_fd3);
+    close(s->mmap_fd4);
+    close(s->mmap_fd5);
+    close(s->mmap_fd6);
+}
+
+static Property slavepassthru_properties[] = {
+    DEFINE_PROP_STRING("size1", SlavepassthruState, sizearg1),
+    DEFINE_PROP_STRING("baseaddr1", SlavepassthruState, baseaddrarg1),
+    DEFINE_PROP_STRING("size2", SlavepassthruState, sizearg2),
+    DEFINE_PROP_STRING("baseaddr2", SlavepassthruState, baseaddrarg2),
+    DEFINE_PROP_STRING("size3", SlavepassthruState, sizearg3),
+    DEFINE_PROP_STRING("baseaddr3", SlavepassthruState, baseaddrarg3),
+    DEFINE_PROP_STRING("size4", SlavepassthruState, sizearg4),
+    DEFINE_PROP_STRING("baseaddr4", SlavepassthruState, baseaddrarg4),
+    DEFINE_PROP_STRING("size5", SlavepassthruState, sizearg5),
+    DEFINE_PROP_STRING("baseaddr5", SlavepassthruState, baseaddrarg5),
+    DEFINE_PROP_STRING("size6", SlavepassthruState, sizearg6),
+    DEFINE_PROP_STRING("baseaddr6", SlavepassthruState, baseaddrarg6),
+
+    DEFINE_PROP_UINT32("use64", SlavepassthruState, slavepassthru_64bit, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void slavepassthru_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+    char *vid;
+    char *did;
+
+    vid=getenv("SLAVEPASSTHRU_VID");
+    did=getenv("SLAVEPASSTHRU_DID");
+
+    if (vid == NULL || did == NULL) {
+      printf("WARNING: Environment variable SLAVEPASSTHRU_VID e/o SLAVEPASSTHRU_DID are not assigned using DEFAULTS");
+      vid=strdup(STRINGIFY(PCI_VENDOR_ID_SLAVEPASSTHRU_DEFAULT));
+      did=strdup(STRINGIFY(PCI_DEVICE_ID_SLAVEPASSTHRU_DEFAULT));
+    }
+    
+    k->init = pci_slavepassthru_init;
+    k->exit = pci_slavepassthru_uninit;
+    k->vendor_id = slavepassthru_get_hex(vid);
+    k->device_id = slavepassthru_get_hex(did);
+    k->class_id = PCI_CLASS_MEMORY_RAM;
+    dc->reset = slavepassthru_reset;
+    dc->props = slavepassthru_properties;
+    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+}
+
+static const TypeInfo slavepassthru_info = {
+    .name          = TYPE_SLAVEPASSTHRU,
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(SlavepassthruState),
+    .class_init    = slavepassthru_class_init,
+};
+
+static void slavepassthru_register_types(void)
+{
+    type_register_static(&slavepassthru_info);
+}
+
+type_init(slavepassthru_register_types)
