static void kvm_pit_vm_state_change(void *opaque, int running, RunState state) { KVMPITState *s = opaque; if (running) { kvm_pit_update_clock_offset(s); kvm_pit_put(PIT_COMMON(s)); s->vm_stopped = false; } else { kvm_pit_update_clock_offset(s); kvm_pit_get(PIT_COMMON(s)); s->vm_stopped = true; } }
static void kvm_pit_reset(DeviceState *dev) { PITCommonState *s = PIT_COMMON(dev); pit_reset_common(s); kvm_pit_put(s); }
static void kvm_pit_realizefn(DeviceState *dev, Error **errp) { PITCommonState *pit = PIT_COMMON(dev); KVMPITClass *kpc = KVM_PIT_GET_CLASS(dev); KVMPITState *s = KVM_PIT(pit); struct kvm_pit_config config = { .flags = 0, }; int ret; if (kvm_check_extension(kvm_state, KVM_CAP_PIT2)) { ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_PIT2, &config); } else { ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_PIT); } if (ret < 0) { error_setg(errp, "Create kernel PIC irqchip failed: %s", strerror(ret)); return; } switch (s->lost_tick_policy) { case LOST_TICK_DELAY: break; /* enabled by default */ case LOST_TICK_DISCARD: if (kvm_check_extension(kvm_state, KVM_CAP_REINJECT_CONTROL)) { struct kvm_reinject_control control = { .pit_reinject = 0 }; ret = kvm_vm_ioctl(kvm_state, KVM_REINJECT_CONTROL, &control); if (ret < 0) { error_setg(errp, "Can't disable in-kernel PIT reinjection: %s", strerror(ret)); return; } } break; default: error_setg(errp, "Lost tick policy not supported."); return; } memory_region_init_reservation(&pit->ioports, NULL, "kvm-pit", 4); qdev_init_gpio_in(dev, kvm_pit_irq_control, 1); qemu_add_vm_change_state_handler(kvm_pit_vm_state_change, s); kpc->parent_realize(dev, errp); } static Property kvm_pit_properties[] = { DEFINE_PROP_HEX32("iobase", PITCommonState, iobase, -1), DEFINE_PROP_LOSTTICKPOLICY("lost_tick_policy", KVMPITState, lost_tick_policy, LOST_TICK_DELAY), DEFINE_PROP_END_OF_LIST(), }; static void kvm_pit_class_init(ObjectClass *klass, void *data) { KVMPITClass *kpc = KVM_PIT_CLASS(klass); PITCommonClass *k = PIT_COMMON_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); kpc->parent_realize = dc->realize; dc->realize = kvm_pit_realizefn; k->set_channel_gate = kvm_pit_set_gate; k->get_channel_info = kvm_pit_get_channel_info; k->pre_save = kvm_pit_get; k->post_load = kvm_pit_put; dc->reset = kvm_pit_reset; dc->props = kvm_pit_properties; } static const TypeInfo kvm_pit_info = { .name = TYPE_KVM_I8254, .parent = TYPE_PIT_COMMON, .instance_size = sizeof(KVMPITState), .class_init = kvm_pit_class_init, .class_size = sizeof(KVMPITClass), }; static void kvm_pit_register(void) { type_register_static(&kvm_pit_info); } type_init(kvm_pit_register)