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 <aligu...@us.ibm.com> Signed-off-by: Wanpeng Li <liw...@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(-) 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 -- 1.7.7.6