diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index a433902..e182282 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -358,44 +358,35 @@ static void create_pci_host(const VirtBoardInfo *vbi, qemu_irq *pic)
     PCIBus *pci_bus;
     DeviceState *dev;
     SysBusDevice *busdev;
-    uint32_t gic_phandle;
-    char *nodename;
-    int i;
+    PCIVPBState *ps;
+    int i, count = 0;
     hwaddr cfg_base = vbi->memmap[VIRT_PCI_CFG].base;
-    hwaddr cfg_size = vbi->memmap[VIRT_PCI_CFG].size;
     hwaddr io_base = vbi->memmap[VIRT_PCI_IO].base;
-    hwaddr io_size = vbi->memmap[VIRT_PCI_IO].size;
     hwaddr mem_base = vbi->memmap[VIRT_PCI_MEM].base;
-    hwaddr mem_size = vbi->memmap[VIRT_PCI_MEM].size;
-
-    nodename = g_strdup_printf("/pci@%" PRIx64, cfg_base);
-    qemu_fdt_add_subnode(vbi->fdt, nodename);
-    qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible",
-                            "pci-host-cam-generic");
-    qemu_fdt_setprop_string(vbi->fdt, nodename, "device_type", "pci");
-    qemu_fdt_setprop_cell(vbi->fdt, nodename, "#address-cells", 0x3);
-    qemu_fdt_setprop_cell(vbi->fdt, nodename, "#size-cells", 0x2);
-    qemu_fdt_setprop_cell(vbi->fdt, nodename, "#interrupt-cells", 0x1);
-
-    qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", 2, cfg_base,
-                                                           2, cfg_size);
-
-    qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "ranges",
-        1, 0x01000000, 2, 0x00000000, 2, io_base, 2, io_size,
-        1, 0x02000000, 2, 0x12000000, 2, mem_size, 2, mem_size);
-
-    gic_phandle = qemu_fdt_get_phandle(vbi->fdt, "/intc");
-    qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "interrupt-map-mask",
-        1, 0xf800, 1, 0x0, 1, 0x0, 1, 0x7);
-    qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "interrupt-map",
-        1, 0x0000, 2, 0x00000000, 1, 0x1, 1, gic_phandle, 1, 0, 1, 0x4, 1, 0x1,
-        1, 0x0800, 2, 0x00000000, 1, 0x1, 1, gic_phandle, 1, 0, 1, 0x5, 1, 0x1,
-        1, 0x1000, 2, 0x00000000, 1, 0x1, 1, gic_phandle, 1, 0, 1, 0x6, 1, 0x1,
-        1, 0x1800, 2, 0x00000000, 1, 0x1, 1, gic_phandle, 1, 0, 1, 0x7, 1, 0x1);
 
     dev = qdev_create(NULL, "generic_pci");
     busdev = SYS_BUS_DEVICE(dev);
+    ps = PCI_GEN(dev);
+
+    /* Set the mapping data in the device structure where:
+     * ptr[i] = base address
+     * ptr[i+1] = size
+     * i = 0 => config
+     * i = 2 => I/O
+     * i = 4 => memory
+     * These values are needed by the specific device code.
+     * */
+    hwaddr *ptr = g_malloc(6 * sizeof(hwaddr));
+    for (i = VIRT_PCI_CFG; i <= VIRT_PCI_MEM; i++) {
+        ptr[count++] = vbi->memmap[i].base;
+        ptr[count++] = vbi->memmap[i].size;
+    }
+    ps->dt_data.fdt = vbi->fdt;
+    ps->dt_data.irq_base = vbi->irqmap[VIRT_PCI_CFG];
+    ps->dt_data.addr_mapping = ptr;
+
     qdev_init_nofail(dev);
+
     sysbus_mmio_map(busdev, 0, cfg_base); /* PCI config */
     sysbus_mmio_map(busdev, 1, io_base);  /* PCI I/O */
     sysbus_mmio_map(busdev, 2, mem_base); /* PCI memory window */
@@ -407,8 +398,6 @@ static void create_pci_host(const VirtBoardInfo *vbi, qemu_irq *pic)
     pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
     pci_create_simple(pci_bus, -1, "pci-ohci");
     pci_create_simple(pci_bus, -1, "lsi53c895a");
-
-    g_free(nodename);
 }
 
 static void create_virtio_devices(const VirtBoardInfo *vbi, qemu_irq *pic)
@@ -454,6 +443,29 @@ static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size)
     return board->fdt;
 }
 
+static void machvirt_finalize_dt(MachineState *machine)
+{
+    BusState *bus;
+    BusChild *child;
+    VirtBoardInfo *vbi;
+    /* TODO store somewhere the CPU model used */
+    vbi = find_machine_info("cortex-a15");
+
+    /* If the device has been successfully created, create also its
+     * device node in the dt. */
+    bus = sysbus_get_default();
+    QTAILQ_FOREACH(child, &bus->children, sibling) {
+        DeviceState *dev = child->child;
+        if (!strcmp(object_get_typename(OBJECT(dev)), TYPE_GENERIC_PCI)) {
+            GenericPCIClass *gpci = GENERIC_PCI_GET_CLASS(OBJECT(dev));
+            /* create device tree node */
+            gpci->gen_dt_node(dev);
+        }
+    }
+
+    arm_load_kernel(ARM_CPU(first_cpu), &vbi->bootinfo);
+}
+
 static void machvirt_init(MachineState *machine)
 {
     MemoryRegion *sysmem = get_system_memory();
@@ -542,13 +554,13 @@ static void machvirt_init(MachineState *machine)
     vbi->bootinfo.board_id = -1;
     vbi->bootinfo.loader_start = vbi->memmap[VIRT_MEM].base;
     vbi->bootinfo.get_dtb = machvirt_dtb;
-    arm_load_kernel(ARM_CPU(first_cpu), &vbi->bootinfo);
 }
 
 static QEMUMachine machvirt_a15_machine = {
     .name = "virt",
     .desc = "ARM Virtual Machine",
     .init = machvirt_init,
+    .finalize_dt = machvirt_finalize_dt,
     .max_cpus = 4,
 };
 
diff --git a/hw/pci-host/generic-pci.c b/hw/pci-host/generic-pci.c
index 75aae45..2068079 100644
--- a/hw/pci-host/generic-pci.c
+++ b/hw/pci-host/generic-pci.c
@@ -14,6 +14,7 @@
 #include "hw/sysbus.h"
 #include "hw/pci-host/pci_generic.h"
 #include "exec/address-spaces.h"
+#include "sysemu/device_tree.h"
 
 static const VMStateDescription pci_generic_host_vmstate = {
     .name = "generic-host-pci",
@@ -130,6 +131,96 @@ static void pci_generic_host_class_init(ObjectClass *klass, void *data)
     dc->cannot_instantiate_with_device_add_yet = true;
 }
 
+struct dt_irq_mapping {
+        DeviceState *dev;
+        uint32_t gic_phandle;
+        int base_irq_num;
+        uint64_t *data;
+};
+
+#define IRQ_MAPPING_CELLS 14
+/* Generate the irq_mapping data and return the number of the device attached
+ * to the device bus.
+ * */
+static int generate_int_mapping(struct dt_irq_mapping *irq_map)
+{
+    BusState *inner_bus;
+    BusChild *inner;
+    int num_slots = 0;
+    uint64_t *data_ptr = irq_map->data;
+
+    QLIST_FOREACH(inner_bus, &irq_map->dev->child_bus, sibling) {
+        QTAILQ_FOREACH(inner, &inner_bus->children, sibling) {
+            DeviceState *dev = inner->child;
+            PCIDevice *pdev = PCI_DEVICE(dev);
+            int pci_slot = PCI_SLOT(pdev->devfn);
+
+            uint64_t buffer[IRQ_MAPPING_CELLS] =
+            {1, pci_slot << 11, 2, 0x00000000, 1, 0x1,
+             1, irq_map->gic_phandle, 1, 0, 1, irq_map->base_irq_num + pci_slot,
+             1, 0x1};
+
+            memcpy(data_ptr, buffer, IRQ_MAPPING_CELLS * sizeof(*buffer));
+            num_slots++;
+            data_ptr += IRQ_MAPPING_CELLS;
+        }
+    }
+
+    return num_slots;
+}
+
+static void generate_dt_node(DeviceState *dev)
+{
+    PCIVPBState *s = PCI_GEN(dev);
+    char *nodename;
+    uint32_t gic_phandle;
+    int num_dev;
+    hwaddr *map = s->dt_data.addr_mapping;
+    void *fdt = s->dt_data.fdt;
+
+    nodename = g_strdup_printf("/pci@%" PRIx64, map[0]);
+    qemu_fdt_add_subnode(fdt, nodename);
+    qemu_fdt_setprop_string(fdt, nodename, "compatible",
+                            "pci-host-cam-generic");
+    qemu_fdt_setprop_string(fdt, nodename, "device_type", "pci");
+    qemu_fdt_setprop_cell(fdt, nodename, "#address-cells", 0x3);
+    qemu_fdt_setprop_cell(fdt, nodename, "#size-cells", 0x2);
+    qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 0x1);
+
+    /* config space */
+    qemu_fdt_setprop_sized_cells(fdt, nodename, "reg", 2, map[0],
+                                                            2, map[1]);
+
+    qemu_fdt_setprop_sized_cells(fdt, nodename, "ranges",
+         1, 0x01000000, 2, 0x00000000, 2, map[2], 2, map[3],
+         1, 0x02000000, 2, 0x12000000, 2, map[4], 2, map[5]);
+
+    gic_phandle = qemu_fdt_get_phandle(fdt, "/intc");
+    qemu_fdt_setprop_sized_cells(fdt, nodename, "interrupt-map-mask",
+                                  1, 0xf800, 1, 0x0, 1, 0x0, 1, 0x7);
+
+    /* Generate the interrupt mapping according to the devices attached
+     * to the PCI bus of the device. */
+    uint64_t *int_mapping_data = g_malloc0(IRQ_MAPPING_CELLS * sizeof(uint64_t)
+                                                            * MAX_PCI_DEVICES);
+
+    struct dt_irq_mapping dt_map = {
+        .dev = dev,
+        .gic_phandle = gic_phandle,
+        .base_irq_num = s->dt_data.irq_base,
+        .data = int_mapping_data
+    };
+
+    num_dev = generate_int_mapping(&dt_map);
+    qemu_fdt_setprop_sized_cells_from_array(fdt, nodename, "interrupt-map",
+                        (num_dev * IRQ_MAPPING_CELLS)/2, int_mapping_data);
+
+    g_free(int_mapping_data);
+    g_free(nodename);
+    /* Once the dt node is created, this data is no longer necessary */
+    g_free(s->dt_data.addr_mapping);
+}
+
 static const TypeInfo pci_generic_host_info = {
     .name          = TYPE_GENERIC_PCI_HOST,
     .parent        = TYPE_PCI_DEVICE,
@@ -140,9 +231,11 @@ static const TypeInfo pci_generic_host_info = {
 static void pci_generic_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
+    GenericPCIClass *pc = GENERIC_PCI_CLASS(klass);
 
     dc->realize = pci_generic_host_realize;
     dc->vmsd = &pci_generic_host_vmstate;
+    pc->gen_dt_node = generate_dt_node;
 }
 
 static const TypeInfo pci_generic_info = {
@@ -151,6 +244,7 @@ static const TypeInfo pci_generic_info = {
     .instance_size = sizeof(PCIVPBState),
     .instance_init = pci_generic_host_init,
     .class_init    = pci_generic_class_init,
+    .class_size    = sizeof(GenericPCIClass),
 };
 
 static void generic_pci_host_register_types(void)
diff --git a/include/hw/pci-host/pci_generic.h b/include/hw/pci-host/pci_generic.h
index 2367d80..039549f 100644
--- a/include/hw/pci-host/pci_generic.h
+++ b/include/hw/pci-host/pci_generic.h
@@ -7,6 +7,12 @@
 
 #define MAX_PCI_DEVICES 10
 
+struct dt_data {
+    void *fdt;
+    int irq_base;
+    hwaddr *addr_mapping;
+};
+
 typedef struct {
     PCIHostState parent_obj;
 
@@ -22,8 +28,17 @@ typedef struct {
     MemoryRegion pci_mem_window;
     PCIBus pci_bus;
     PCIDevice pci_dev;
+    /* Device tree data set by the machine
+     */
+    struct dt_data dt_data;
 } PCIVPBState;
 
+typedef struct GenericPCIClass {
+    PCIDeviceClass parent_class;
+
+    void (*gen_dt_node)(DeviceState *dev);
+} GenericPCIClass;
+
 #define TYPE_GENERIC_PCI "generic_pci"
 #define PCI_GEN(obj) \
     OBJECT_CHECK(PCIVPBState, (obj), TYPE_GENERIC_PCI)
@@ -32,4 +47,9 @@ typedef struct {
 #define PCI_GEN_HOST(obj) \
     OBJECT_CHECK(PCIDevice, (obj), TYPE_GENERIC_PCIHOST)
 
+#define GENERIC_PCI_CLASS(klass) \
+     OBJECT_CLASS_CHECK(GenericPCIClass, (klass), TYPE_GENERIC_PCI)
+#define GENERIC_PCI_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(GenericPCIClass, (obj), TYPE_GENERIC_PCI)
+
 #endif
