diff --git a/hw/ioapic.c b/hw/ioapic.c
index 7273095..927a099 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -245,7 +245,7 @@ static void ioapic_class_init(ObjectClass *klass, void *data)
 }
 
 static TypeInfo ioapic_info = {
-    .name          = "ioapic",
+    .name          = TYPE_IOAPIC,
     .parent        = TYPE_IOAPIC_COMMON,
     .instance_size = sizeof(IOAPICCommonState),
     .class_init    = ioapic_class_init,
diff --git a/hw/ioapic.h b/hw/ioapic.h
index 86e63da..649dd0c 100644
--- a/hw/ioapic.h
+++ b/hw/ioapic.h
@@ -20,8 +20,6 @@
 #ifndef HW_IOAPIC_H
 #define HW_IOAPIC_H
 
-#define IOAPIC_NUM_PINS 24
-
 void ioapic_eoi_broadcast(int vector);
 
 #endif /* !HW_IOAPIC_H */
diff --git a/hw/ioapic_internal.h b/hw/ioapic_internal.h
index e04c9f3..d3cb4c9 100644
--- a/hw/ioapic_internal.h
+++ b/hw/ioapic_internal.h
@@ -88,6 +88,8 @@ typedef struct IOAPICCommonClass {
     void (*post_load)(IOAPICCommonState *s);
 } IOAPICCommonClass;
 
+#define IOAPIC_NUM_PINS 24
+
 struct IOAPICCommonState {
     SysBusDevice busdev;
     MemoryRegion io_memory;
diff --git a/hw/kvm/ioapic.c b/hw/kvm/ioapic.c
index 6c3b8fe..e88843e 100644
--- a/hw/kvm/ioapic.c
+++ b/hw/kvm/ioapic.c
@@ -15,13 +15,6 @@
 #include "hw/apic_internal.h"
 #include "kvm.h"
 
-typedef struct KVMIOAPICState KVMIOAPICState;
-
-struct KVMIOAPICState {
-    IOAPICCommonState ioapic;
-    uint32_t kvm_gsi_base;
-};
-
 static void kvm_ioapic_get(IOAPICCommonState *s)
 {
     struct kvm_irqchip chip;
@@ -111,7 +104,7 @@ static void kvm_ioapic_class_init(ObjectClass *klass, void *data)
 }
 
 static TypeInfo kvm_ioapic_info = {
-    .name  = "kvm-ioapic",
+    .name  = TYPE_KVM_IOAPIC,
     .parent = TYPE_IOAPIC_COMMON,
     .instance_size = sizeof(KVMIOAPICState),
     .class_init = kvm_ioapic_class_init,
diff --git a/hw/pc.c b/hw/pc.c
index 74cec55..31031fa 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -79,6 +79,8 @@
 
 BusState *idebus[MAX_IDE_BUS];
 
+GSIState *gsi_state;
+
 struct e820_entry {
     uint64_t address;
     uint64_t length;
@@ -1011,30 +1013,6 @@ static void kvm_piix3_gsi_handler(void *opaque, int n, int level)
     }
 }
 
-static void ioapic_init(GSIState *gsi_state)
-{
-    DeviceState *dev;
-    SysBusDevice *d;
-    unsigned int i;
-
-    if (kvm_irqchip_in_kernel()) {
-        dev = qdev_create(NULL, "kvm-ioapic");
-    } else {
-        dev = qdev_create(NULL, "ioapic");
-    }
-
-    /* FIXME: this should be under the piix3.  */
-    object_property_add_child(object_resolve_path("i440fx", NULL),
-                              "ioapic", OBJECT(dev), NULL);
-    qdev_init_nofail(dev);
-    d = sysbus_from_qdev(dev);
-    sysbus_mmio_map(d, 0, 0xfec00000);
-
-    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
-        gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i);
-    }
-}
-
 static PCIBus *i440fx_init(I440FXPMCState **pi440fx_state, int *piix3_devfn,
                            ISABus **isa_bus, qemu_irq *pic,
                            MemoryRegion *address_space_mem,
@@ -1091,7 +1069,6 @@ static void pc_init1(MemoryRegion *system_memory,
     qemu_irq *gsi;
     qemu_irq *i8259;
     qemu_irq *smi_irq;
-    GSIState *gsi_state;
     ISADevice *rtc_state;
     ISADevice *floppy;
 
@@ -1153,9 +1130,6 @@ static void pc_init1(MemoryRegion *system_memory,
     for (i = 0; i < ISA_NUM_IRQS; i++) {
         gsi_state->i8259_irq[i] = i8259[i];
     }
-    if (pci_enabled) {
-        ioapic_init(gsi_state);
-    }
 
     pc_register_ferr_irq(gsi[13]);
 
diff --git a/hw/pc.h b/hw/pc.h
index 620349f..7f6ff93 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -54,6 +54,8 @@ typedef struct GSIState {
     qemu_irq ioapic_irq[IOAPIC_NUM_PINS];
 } GSIState;
 
+extern GSIState *gsi_state;
+
 void vmport_register(unsigned char command, IOPortReadFunc *func, void *opaque);
 void vmmouse_get_data(uint32_t *data);
 void vmmouse_set_data(const uint32_t *data);
diff --git a/hw/piix3.c b/hw/piix3.c
index 7ca0f83..99b1ecc 100644
--- a/hw/piix3.c
+++ b/hw/piix3.c
@@ -203,6 +203,7 @@ static int piix3_realize(PCIDevice *dev)
     qemu_irq *a20_line;
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     int i;
+    SysBusDevice *d;
 
     /* Initialize ISA Bus */
     s->bus = isa_bus_new(DEVICE(dev), pci_address_space_io(dev));
@@ -313,6 +314,31 @@ static int piix3_realize(PCIDevice *dev)
         }
     }
 
+    /* Realize the IOAPIC */
+    if (pci_is_enabled) {
+        if (kvm_irqchip_in_kernel()) {
+            qdev_set_parent_bus(DEVICE(&s->ioapic.kvm_ioapic),
+                                                   sysbus_get_default());
+            qdev_init_nofail(DEVICE(&s->ioapic.kvm_ioapic));
+            d = sysbus_from_qdev(DEVICE(&s->ioapic.kvm_ioapic));
+            sysbus_mmio_map(d, 0, 0xfec00000);
+            for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+                gsi_state->ioapic_irq[i] = qdev_get_gpio_in(
+                                       DEVICE(&s->ioapic.kvm_ioapic), i);
+            }
+        } else {
+            qdev_set_parent_bus(DEVICE(&s->ioapic.ioapic),
+                                                    sysbus_get_default());
+            qdev_init_nofail(DEVICE(&s->ioapic.ioapic));
+            d = sysbus_from_qdev(DEVICE(&s->ioapic.ioapic));
+            sysbus_mmio_map(d, 0, 0xfec00000);
+            for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+                gsi_state->ioapic_irq[i] = qdev_get_gpio_in(
+                                             DEVICE(&s->ioapic.ioapic), i);
+            }
+        }
+    }
+
     return 0;
 }
 
@@ -375,6 +401,18 @@ static void piix3_initfn(Object *obj)
         object_property_add_child(obj, "isa-ide",
                                           OBJECT(&s->ide.isa), NULL);
     }
+
+    if (pci_is_enabled) {
+        if (kvm_irqchip_in_kernel()) {
+            object_initialize(&s->ioapic.kvm_ioapic, TYPE_KVM_IOAPIC);
+            object_property_add_child(obj, "kvm-ioapic",
+                                        OBJECT(&s->ioapic.kvm_ioapic), NULL);
+        } else {
+            object_initialize(&s->ioapic.ioapic, TYPE_IOAPIC);
+            object_property_add_child(obj,
+                                   "ioapic", OBJECT(&s->ioapic.ioapic), NULL);
+        }
+    }
 }
 
 static void piix3_class_init(ObjectClass *klass, void *data)
diff --git a/hw/piix3.h b/hw/piix3.h
index 8916e4a..c6be9e6 100644
--- a/hw/piix3.h
+++ b/hw/piix3.h
@@ -38,6 +38,7 @@
 #include "ps2.h"
 #include "console.h"
 #include "ide/pci.h"
+#include "ioapic_internal.h"
 
 #define PIIX_NUM_PIC_IRQS       16      /* i8259 * 2 */
 #define PIIX_NUM_PIRQS          4ULL    /* PIRQ[A-D] */
@@ -64,6 +65,9 @@ typedef struct KVMPITState {
 
 #define MAX_IDE_BUS 2
 
+#define TYPE_IOAPIC "ioapic"
+#define TYPE_KVM_IOAPIC "kvm-ioapic"
+
 typedef struct _VMMouseState {
     ISADevice dev;
     uint32_t queue[VMMOUSE_QUEUE_SIZE];
@@ -112,6 +116,11 @@ typedef struct ISAKBDState {
     MemoryRegion io[2];
 } ISAKBDState;
 
+typedef struct KVMIOAPICState {
+    IOAPICCommonState ioapic;
+    uint32_t kvm_gsi_base;
+} KVMIOAPICState;
+
 typedef struct PIIX3State {
     PCIDevice dev;
 
@@ -148,6 +157,10 @@ typedef struct PIIX3State {
         ISAIDEState isa;
         PCIIDEState pci;
     } ide;
+    union {
+        IOAPICCommonState ioapic;
+        KVMIOAPICState kvm_ioapic;
+    } ioapic;
 
     qemu_irq *pic;
 
