@@ -1130,8 +1130,6 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
int i;
DriveInfo *fd[MAX_FD];
DeviceState *hpet = NULL;
- int pit_isa_irq = 0;
- qemu_irq pit_alt_irq = NULL;
qemu_irq rtc_irq = NULL;
qemu_irq *a20_line;
ISADevice *i8042, *port92, *vmmouse, *pit = NULL;
@@ -1145,24 +1143,6 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
memory_region_init_io(ioportF0_io, &ioportF0_io_ops, NULL, "ioportF0", 1);
memory_region_add_subregion(isa_bus->address_space_io, 0xf0, ioportF0_io);
- /*
- * 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(SYS_BUS_DEVICE(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);
- }
- }
*rtc_state = rtc_init(isa_bus, 2000, rtc_irq);
qemu_register_boot_set(pc_boot_set, *rtc_state);
@@ -1171,7 +1151,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
if (kvm_irqchip_in_kernel()) {
pit = kvm_pit_init(isa_bus, 0x40);
} else {
- pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq);
+ pit = pit_init(isa_bus, 0x40, 0, NULL);
}
if (hpet) {
/* connect PIT to output control line of the HPET */
@@ -135,12 +135,15 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
qdev_init_nofail(DEVICE(q35_host));
host_bus = q35_host->host.pci.bus;
/* create ISA bus */
- lpc = pci_create_simple_multifunction(host_bus, PCI_DEVFN(ICH9_LPC_DEV,
- ICH9_LPC_FUNC), true,
- TYPE_ICH9_LPC_DEVICE);
+ lpc = PCI_DEVICE(object_new(TYPE_ICH9_LPC_DEVICE));
ich9_lpc = ICH9_LPC_DEVICE(lpc);
ich9_lpc->pic = gsi;
+ qdev_prop_set_int32(DEVICE(ich9_lpc), "addr",
+ PCI_DEVFN(ICH9_LPC_DEV, ICH9_LPC_FUNC));
+ qdev_prop_set_bit(DEVICE(ich9_lpc), "multifunction", true);
+ qdev_set_parent_bus(DEVICE(ich9_lpc), BUS(host_bus));
ich9_lpc->ioapic = gsi_state->ioapic_irq;
+ qdev_init_nofail(DEVICE(ich9_lpc));
pci_bus_irqs(host_bus, ich9_lpc_set_irq, ich9_lpc_map_irq, ich9_lpc,
ICH9_LPC_NB_PIRQS);
pci_bus_set_route_irq_fn(host_bus, ich9_route_intx_pin_to_irq);
@@ -44,6 +44,7 @@
#include "hw/pci/pci_bus.h"
#include "exec/address-spaces.h"
#include "sysemu/sysemu.h"
+#include "hw/timer/hpet.h"
static int ich9_lpc_sci_irq(ICH9LPCState *lpc);
@@ -551,6 +552,21 @@ static int ich9_lpc_realize(PCIDevice *d)
ICH9_RST_CNT_IOPORT, &lpc->rst_cnt_mem,
1);
+ /* Realize HPET */
+ if (lpc->hpet) {
+ 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(lpc->hpet, sysbus_get_default());
+ qdev_init_nofail(lpc->hpet);
+
+ sysbus_mmio_map(SYS_BUS_DEVICE(lpc->hpet), 0, HPET_BASE);
+ for (i = 0; i < GSI_NUM_PINS; i++) {
+ sysbus_connect_irq(SYS_BUS_DEVICE(lpc->hpet), i, lpc->pic[i]);
+ }
+ }
+
return 0;
}
@@ -596,6 +612,18 @@ static const VMStateDescription vmstate_ich9_lpc = {
static void ich9_lpc_initfn(Object *obj)
{
+ ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
+
+ /*
+ * 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->hpet = DEVICE(object_new(TYPE_HPET));
+ object_property_add_child(obj, "hpet", OBJECT(s->hpet), NULL);
+ }
}
static void ich9_lpc_class_init(ObjectClass *klass, void *data)
@@ -32,6 +32,7 @@
#include "hw/xen/xen.h"
#include "hw/pci-host/pam.h"
#include "sysemu/sysemu.h"
+#include "hw/timer/hpet.h"
/*
* I440FX chipset data sheet.
@@ -70,6 +71,7 @@ typedef struct PIIX3State {
uint64_t pic_levels;
ISABus *bus;
+ DeviceState *hpet;
qemu_irq *pic;
@@ -580,6 +582,21 @@ static int piix3_realize(PCIDevice *dev)
s->bus = isa_bus_new(DEVICE(s), pci_address_space_io(dev));
+ /* Realize HPET */
+ if (s->hpet) {
+ 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(s->hpet, sysbus_get_default());
+ qdev_init_nofail(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]);
+ }
+ }
+
memory_region_init_io(&s->rcr_mem, &rcr_ops, s, "piix3-reset-control", 1);
memory_region_add_subregion_overlap(pci_address_space_io(dev), RCR_IOPORT,
&s->rcr_mem, 1);
@@ -589,6 +606,19 @@ static int piix3_realize(PCIDevice *dev)
static void piix3_initfn(Object *obj)
{
+ PIIX3State *s = PIIX3(obj);
+
+ /*
+ * 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->hpet = DEVICE(object_new(TYPE_HPET));
+ object_property_add_child(obj, "hpet", OBJECT(s->hpet), NULL);
+ }
+
}
static void piix3_class_init(ObjectClass *klass, void *data)
@@ -278,7 +278,7 @@ static const VMStateDescription vmstate_hpet_timer = {
};
static const VMStateDescription vmstate_hpet = {
- .name = "hpet",
+ .name = TYPE_HPET,
.version_id = 2,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
@@ -62,6 +62,8 @@ typedef struct ICH9LPCState {
MemoryRegion rbca_mem;
Notifier machine_ready;
+ DeviceState *hpet;
+
qemu_irq *pic;
qemu_irq *ioapic;
} ICH9LPCState;
@@ -71,4 +71,7 @@ struct hpet_fw_config
} QEMU_PACKED;
extern struct hpet_fw_config hpet_cfg;
+
+#define TYPE_HPET "hpet"
+
#endif
Signed-off-by: Hu Tao <hutao@cn.fujitsu.com> --- hw/i386/pc.c | 22 +--------------------- hw/i386/pc_q35.c | 9 ++++++--- hw/isa/lpc_ich9.c | 28 ++++++++++++++++++++++++++++ hw/pci-host/piix.c | 30 ++++++++++++++++++++++++++++++ hw/timer/hpet.c | 2 +- include/hw/i386/ich9.h | 2 ++ include/hw/timer/hpet.h | 3 +++ 7 files changed, 71 insertions(+), 25 deletions(-)