X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/5b8e6b4cc279e4434ddda94a6b2848834883ec9c..4f67d30b5e74e060b8dbe10528829b47345cd6e8:/hw/timer/hpet.c diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c index 78140e6092..8dbcbdca16 100644 --- a/hw/timer/hpet.c +++ b/hw/timer/hpet.c @@ -25,15 +25,17 @@ */ #include "qemu/osdep.h" -#include "hw/hw.h" #include "hw/i386/pc.h" +#include "hw/irq.h" #include "ui/console.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/timer.h" #include "hw/timer/hpet.h" #include "hw/sysbus.h" -#include "hw/timer/mc146818rtc.h" +#include "hw/rtc/mc146818rtc.h" +#include "hw/rtc/mc146818rtc_regs.h" +#include "migration/vmstate.h" #include "hw/timer/i8254.h" //#define HPET_DEBUG @@ -70,6 +72,7 @@ typedef struct HPETState { MemoryRegion iomem; uint64_t hpet_offset; + bool hpet_offset_saved; qemu_irq irqs[HPET_NUM_IRQ_ROUTES]; uint32_t flags; uint8_t rtc_irq_level; @@ -201,12 +204,7 @@ static void update_irq(struct HPETTimer *timer, int set) if (!set || !timer_enabled(timer) || !hpet_enabled(timer->state)) { s->isr &= ~mask; if (!timer_fsb_route(timer)) { - /* fold the ICH PIRQ# pin's internal inversion logic into hpet */ - if (route >= ISA_NUM_IRQS) { - qemu_irq_raise(s->irqs[route]); - } else { - qemu_irq_lower(s->irqs[route]); - } + qemu_irq_lower(s->irqs[route]); } } else if (timer_fsb_route(timer)) { address_space_stl_le(&address_space_memory, timer->fsb >> 32, @@ -214,24 +212,23 @@ static void update_irq(struct HPETTimer *timer, int set) NULL); } else if (timer->config & HPET_TN_TYPE_LEVEL) { s->isr |= mask; - /* fold the ICH PIRQ# pin's internal inversion logic into hpet */ - if (route >= ISA_NUM_IRQS) { - qemu_irq_lower(s->irqs[route]); - } else { - qemu_irq_raise(s->irqs[route]); - } + qemu_irq_raise(s->irqs[route]); } else { s->isr &= ~mask; qemu_irq_pulse(s->irqs[route]); } } -static void hpet_pre_save(void *opaque) +static int hpet_pre_save(void *opaque) { HPETState *s = opaque; /* save current counter value */ - s->hpet_counter = hpet_get_ticks(s); + if (hpet_enabled(s)) { + s->hpet_counter = hpet_get_ticks(s); + } + + return 0; } static int hpet_pre_load(void *opaque) @@ -260,7 +257,10 @@ static int hpet_post_load(void *opaque, int version_id) HPETState *s = opaque; /* Recalculate the offset between the main counter and guest time */ - s->hpet_offset = ticks_to_ns(s->hpet_counter) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + if (!s->hpet_offset_saved) { + s->hpet_offset = ticks_to_ns(s->hpet_counter) + - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + } /* Push number of timers into capability returned via HPET_ID */ s->capability &= ~HPET_ID_NUM_TIM_MASK; @@ -275,6 +275,13 @@ static int hpet_post_load(void *opaque, int version_id) return 0; } +static bool hpet_offset_needed(void *opaque) +{ + HPETState *s = opaque; + + return hpet_enabled(s) && s->hpet_offset_saved; +} + static bool hpet_rtc_irq_level_needed(void *opaque) { HPETState *s = opaque; @@ -293,6 +300,17 @@ static const VMStateDescription vmstate_hpet_rtc_irq_level = { } }; +static const VMStateDescription vmstate_hpet_offset = { + .name = "hpet/offset", + .version_id = 1, + .minimum_version_id = 1, + .needed = hpet_offset_needed, + .fields = (VMStateField[]) { + VMSTATE_UINT64(hpet_offset, HPETState), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_hpet_timer = { .name = "hpet_timer", .version_id = 1, @@ -328,6 +346,7 @@ static const VMStateDescription vmstate_hpet = { }, .subsections = (const VMStateDescription*[]) { &vmstate_hpet_rtc_irq_level, + &vmstate_hpet_offset, NULL } }; @@ -727,7 +746,7 @@ static void hpet_realize(DeviceState *dev, Error **errp) HPETTimer *timer; if (!s->intcap) { - error_printf("Hpet's intcap not initialized.\n"); + warn_report("Hpet's intcap not initialized"); } if (hpet_cfg.count == UINT8_MAX) { /* first instance */ @@ -770,6 +789,7 @@ static Property hpet_device_properties[] = { DEFINE_PROP_UINT8("timers", HPETState, num_timers, HPET_MIN_TIMERS), DEFINE_PROP_BIT("msi", HPETState, flags, HPET_MSI_SUPPORT, false), DEFINE_PROP_UINT32(HPET_INTCAP, HPETState, intcap, 0), + DEFINE_PROP_BOOL("hpet-offset-saved", HPETState, hpet_offset_saved, true), DEFINE_PROP_END_OF_LIST(), }; @@ -780,7 +800,7 @@ static void hpet_device_class_init(ObjectClass *klass, void *data) dc->realize = hpet_realize; dc->reset = hpet_reset; dc->vmsd = &vmstate_hpet; - dc->props = hpet_device_properties; + device_class_set_props(dc, hpet_device_properties); } static const TypeInfo hpet_device_info = {