Patchwork [02/10] convert HPET as piix3 proper QOM child

login
register
mail settings
Submitter Wanpeng Li
Date Nov. 8, 2012, 5:36 a.m.
Message ID <1352352999-2561-3-git-send-email-liwanp@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/197773/
State New
Headers show

Comments

Wanpeng Li - Nov. 8, 2012, 5:36 a.m.
convert HPET as piix3 proper QOM child.

HPET creation for the PIIX3 is done by calling object_init() with
qdev_init() being called for each child device in the PIIX3 ::init
function.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Wanpeng Li <liwanp@linux.vnet.ibm.com>

---
 hw/hpet.c      |   35 -----------------------------------
 hw/hpet_emul.h |   40 ++++++++++++++++++++++++++++++++++++++++
 hw/pc.c        |   21 ---------------------
 hw/piix3.c     |   28 ++++++++++++++++++++++++++--
 hw/piix3.h     |    4 ++--
 5 files changed, 68 insertions(+), 60 deletions(-)

Patch

diff --git a/hw/hpet.c b/hw/hpet.c
index 50ac067..b128505 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -42,41 +42,6 @@ 
 
 #define HPET_MSI_SUPPORT        0
 
-struct HPETState;
-typedef struct HPETTimer {  /* timers */
-    uint8_t tn;             /*timer number*/
-    QEMUTimer *qemu_timer;
-    struct HPETState *state;
-    /* Memory-mapped, software visible timer registers */
-    uint64_t config;        /* configuration/cap */
-    uint64_t cmp;           /* comparator */
-    uint64_t fsb;           /* FSB route */
-    /* Hidden register state */
-    uint64_t period;        /* Last value written to comparator */
-    uint8_t wrap_flag;      /* timer pop will indicate wrap for one-shot 32-bit
-                             * mode. Next pop will be actual timer expiration.
-                             */
-} HPETTimer;
-
-typedef struct HPETState {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    uint64_t hpet_offset;
-    qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
-    uint32_t flags;
-    uint8_t rtc_irq_level;
-    qemu_irq pit_enabled;
-    uint8_t num_timers;
-    HPETTimer timer[HPET_MAX_TIMERS];
-
-    /* Memory-mapped, software visible registers */
-    uint64_t capability;        /* capabilities */
-    uint64_t config;            /* configuration */
-    uint64_t isr;               /* interrupt status reg */
-    uint64_t hpet_counter;      /* main counter */
-    uint8_t  hpet_id;           /* instance id */
-} HPETState;
-
 static uint32_t hpet_in_legacy_mode(HPETState *s)
 {
     return s->config & HPET_CFG_LEGACY;
diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
index 757f79f..46dee92 100644
--- a/hw/hpet_emul.h
+++ b/hw/hpet_emul.h
@@ -13,6 +13,8 @@ 
 #ifndef QEMU_HPET_EMUL_H
 #define QEMU_HPET_EMUL_H
 
+#include "sysbus.h"
+
 #define HPET_BASE               0xfed00000
 #define HPET_CLK_PERIOD         10000000ULL /* 10000000 femtoseconds == 10ns*/
 
@@ -71,4 +73,42 @@  struct hpet_fw_config
 } QEMU_PACKED;
 
 extern struct hpet_fw_config hpet_cfg;
+
+#define TYPE_HPET "hpet"
+
+struct HPETState;
+typedef struct HPETTimer {  /* timers */
+    uint8_t tn;             /*timer number*/
+    QEMUTimer *qemu_timer;
+    struct HPETState *state;
+    /* Memory-mapped, software visible timer registers */
+    uint64_t config;        /* configuration/cap */
+    uint64_t cmp;           /* comparator */
+    uint64_t fsb;           /* FSB route */
+    /* Hidden register state */
+    uint64_t period;        /* Last value written to comparator */
+    uint8_t wrap_flag;      /* timer pop will indicate wrap for one-shot 32-bit
+                             * mode. Next pop will be actual timer expiration.
+                             */
+} HPETTimer;
+
+typedef struct HPETState {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint64_t hpet_offset;
+    qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
+    uint32_t flags;
+    uint8_t rtc_irq_level;
+    qemu_irq pit_enabled;
+    uint8_t num_timers;
+    HPETTimer timer[HPET_MAX_TIMERS];
+
+    /* Memory-mapped, software visible registers */
+    uint64_t capability;        /* capabilities */
+    uint64_t config;            /* configuration */
+    uint64_t isr;               /* interrupt status reg */
+    uint64_t hpet_counter;      /* main counter */
+    uint8_t  hpet_id;           /* instance id */
+} HPETState;
+
 #endif
diff --git a/hw/pc.c b/hw/pc.c
index 7fed363..7105f4e 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -90,8 +90,6 @@  struct e820_table {
     struct e820_entry entry[E820_NR_ENTRIES];
 } QEMU_PACKED __attribute((__aligned__(4)));
 
-qemu_irq rtc_irq;
-
 static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
 static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
 static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
@@ -959,25 +957,6 @@  static void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
 
     register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
 
-    /*
-     * Check if an HPET shall be created.
-     *
-     * Without KVM_CAP_PIT_STATE2, we cannot switch off the in-kernel PIT
-     * when the HPET wants to take over. Thus we have to disable the latter.
-     */
-    if (!no_hpet && (!kvm_irqchip_in_kernel() || kvm_has_pit_state2())) {
-        hpet = sysbus_try_create_simple("hpet", HPET_BASE, NULL);
-
-        if (hpet) {
-            for (i = 0; i < GSI_NUM_PINS; i++) {
-                sysbus_connect_irq(sysbus_from_qdev(hpet), i, gsi[i]);
-            }
-            pit_isa_irq = -1;
-            pit_alt_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_PIT_INT);
-            rtc_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_RTC_INT);
-        }
-    }
-
     if (!xen_enabled()) {
         if (kvm_irqchip_in_kernel()) {
             pit = kvm_pit_init(isa_bus, 0x40);
diff --git a/hw/piix3.c b/hw/piix3.c
index a40c8cd..5fe41cd 100644
--- a/hw/piix3.c
+++ b/hw/piix3.c
@@ -193,6 +193,7 @@  static const VMStateDescription vmstate_piix3 = {
 static int piix3_realize(PCIDevice *dev)
 {
     PIIX3State *s = PIIX3(dev);
+    qemu_irq rtc_irq;
 
     /* Initialize ISA Bus */
     s->bus = isa_bus_new(DEVICE(dev), pci_address_space_io(dev));
@@ -202,13 +203,33 @@  static int piix3_realize(PCIDevice *dev)
     qdev_set_parent_bus(DEVICE(&s->rtc), BUS(s->bus));
     qdev_init_nofail(DEVICE(&s->rtc));
 
-    /* Setup the RTC IRQ */
+    /*
+     *Check if an HPET shall be created
+     *
+     * Without KVM_CAP_PIT_STATE2, we cannot switch off the in-kernel PIT
+     * when the HPET wants to take over, Thus we have to disable the latter.
+     */
     if (!no_hpet && (!kvm_irqchip_in_kernel() || kvm_has_pit_state2())) {
-        s->rtc.irq = rtc_irq;
+        int i;
+
+        /* We need to introduce a proper IRQ and Memory QOM infrastructure
+         * so that the HPET isn't a sysbus device */
+        qdev_set_parent_bus(DEVICE(&s->hpet), sysbus_get_default());
+        qdev_init_nofail(DEVICE(&s->hpet));
+
+        sysbus_mmio_map(SYS_BUS_DEVICE(&s->hpet), 0, HPET_BASE);
+        for (i = 0; i < GSI_NUM_PINS; i++) {
+            sysbus_connect_irq(SYS_BUS_DEVICE(&s->hpet), i, s->pic[i]);
+        }
+
+        rtc_irq = qdev_get_gpio_in(DEVICE(&s->hpet), HPET_LEGACY_RTC_INT);
     } else {
         isa_init_irq(ISA_DEVICE(&s->rtc), &rtc_irq, RTC_ISA_IRQ);
     }
 
+    /* Setup the RTC IRQ */
+    s->rtc.irq = rtc_irq;
+
     return 0;
 }
 
@@ -222,6 +243,9 @@  static void piix3_initfn(Object *obj)
     object_initialize(&s->rtc, TYPE_RTC);
     object_property_add_child(obj, "rtc", OBJECT(&s->rtc), NULL);
     qdev_prop_set_int32(DEVICE(&s->rtc), "base_year", 2000);
+
+    object_initialize(&s->hpet, TYPE_HPET);
+    object_property_add_child(obj, "hpet", OBJECT(&s->hpet), NULL);
 }
 
 static void piix3_class_init(ObjectClass *klass, void *data)
diff --git a/hw/piix3.h b/hw/piix3.h
index 23ee74a..ef22c03 100644
--- a/hw/piix3.h
+++ b/hw/piix3.h
@@ -31,6 +31,7 @@ 
 
 #include "pci.h"
 #include "mc146818rtc.h"
+#include "hpet_emul.h"
 
 #define PIIX_NUM_PIC_IRQS       16      /* i8259 * 2 */
 #define PIIX_NUM_PIRQS          4ULL    /* PIRQ[A-D] */
@@ -60,6 +61,7 @@  typedef struct PIIX3State {
     ISABus *bus;
 
     RTCState rtc;
+    HPETState hpet;
 
     qemu_irq *pic;
 
@@ -73,6 +75,4 @@  void piix3_set_irq_level(PIIX3State *piix3, int pirq, int level);
 
 void piix3_set_irq(void *opaque, int pirq, int level);
 
-extern qemu_irq rtc_irq;
-
 #endif