Annotation of qemu/hw/kvm/clock.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * QEMU KVM support, paravirtual clock device
        !             3:  *
        !             4:  * Copyright (C) 2011 Siemens AG
        !             5:  *
        !             6:  * Authors:
        !             7:  *  Jan Kiszka        <[email protected]>
        !             8:  *
        !             9:  * This work is licensed under the terms of the GNU GPL version 2.
        !            10:  * See the COPYING file in the top-level directory.
        !            11:  *
        !            12:  * Contributions after 2012-01-13 are licensed under the terms of the
        !            13:  * GNU GPL, version 2 or (at your option) any later version.
        !            14:  */
        !            15: 
        !            16: #include "qemu-common.h"
        !            17: #include "sysemu.h"
        !            18: #include "kvm.h"
        !            19: #include "hw/sysbus.h"
        !            20: #include "hw/kvm/clock.h"
        !            21: 
        !            22: #include <linux/kvm.h>
        !            23: #include <linux/kvm_para.h>
        !            24: 
        !            25: typedef struct KVMClockState {
        !            26:     SysBusDevice busdev;
        !            27:     uint64_t clock;
        !            28:     bool clock_valid;
        !            29: } KVMClockState;
        !            30: 
        !            31: static void kvmclock_pre_save(void *opaque)
        !            32: {
        !            33:     KVMClockState *s = opaque;
        !            34:     struct kvm_clock_data data;
        !            35:     int ret;
        !            36: 
        !            37:     if (s->clock_valid) {
        !            38:         return;
        !            39:     }
        !            40:     ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data);
        !            41:     if (ret < 0) {
        !            42:         fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
        !            43:         data.clock = 0;
        !            44:     }
        !            45:     s->clock = data.clock;
        !            46:     /*
        !            47:      * If the VM is stopped, declare the clock state valid to avoid re-reading
        !            48:      * it on next vmsave (which would return a different value). Will be reset
        !            49:      * when the VM is continued.
        !            50:      */
        !            51:     s->clock_valid = !runstate_is_running();
        !            52: }
        !            53: 
        !            54: static int kvmclock_post_load(void *opaque, int version_id)
        !            55: {
        !            56:     KVMClockState *s = opaque;
        !            57:     struct kvm_clock_data data;
        !            58: 
        !            59:     data.clock = s->clock;
        !            60:     data.flags = 0;
        !            61:     return kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data);
        !            62: }
        !            63: 
        !            64: static void kvmclock_vm_state_change(void *opaque, int running,
        !            65:                                      RunState state)
        !            66: {
        !            67:     KVMClockState *s = opaque;
        !            68:     CPUArchState *penv = first_cpu;
        !            69:     int cap_clock_ctrl = kvm_check_extension(kvm_state, KVM_CAP_KVMCLOCK_CTRL);
        !            70:     int ret;
        !            71: 
        !            72:     if (running) {
        !            73:         s->clock_valid = false;
        !            74: 
        !            75:         if (!cap_clock_ctrl) {
        !            76:             return;
        !            77:         }
        !            78:         for (penv = first_cpu; penv != NULL; penv = penv->next_cpu) {
        !            79:             ret = kvm_vcpu_ioctl(penv, KVM_KVMCLOCK_CTRL, 0);
        !            80:             if (ret) {
        !            81:                 if (ret != -EINVAL) {
        !            82:                     fprintf(stderr, "%s: %s\n", __func__, strerror(-ret));
        !            83:                 }
        !            84:                 return;
        !            85:             }
        !            86:         }
        !            87:     }
        !            88: }
        !            89: 
        !            90: static int kvmclock_init(SysBusDevice *dev)
        !            91: {
        !            92:     KVMClockState *s = FROM_SYSBUS(KVMClockState, dev);
        !            93: 
        !            94:     qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s);
        !            95:     return 0;
        !            96: }
        !            97: 
        !            98: static const VMStateDescription kvmclock_vmsd = {
        !            99:     .name = "kvmclock",
        !           100:     .version_id = 1,
        !           101:     .minimum_version_id = 1,
        !           102:     .minimum_version_id_old = 1,
        !           103:     .pre_save = kvmclock_pre_save,
        !           104:     .post_load = kvmclock_post_load,
        !           105:     .fields = (VMStateField[]) {
        !           106:         VMSTATE_UINT64(clock, KVMClockState),
        !           107:         VMSTATE_END_OF_LIST()
        !           108:     }
        !           109: };
        !           110: 
        !           111: static void kvmclock_class_init(ObjectClass *klass, void *data)
        !           112: {
        !           113:     DeviceClass *dc = DEVICE_CLASS(klass);
        !           114:     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
        !           115: 
        !           116:     k->init = kvmclock_init;
        !           117:     dc->no_user = 1;
        !           118:     dc->vmsd = &kvmclock_vmsd;
        !           119: }
        !           120: 
        !           121: static TypeInfo kvmclock_info = {
        !           122:     .name          = "kvmclock",
        !           123:     .parent        = TYPE_SYS_BUS_DEVICE,
        !           124:     .instance_size = sizeof(KVMClockState),
        !           125:     .class_init    = kvmclock_class_init,
        !           126: };
        !           127: 
        !           128: /* Note: Must be called after VCPU initialization. */
        !           129: void kvmclock_create(void)
        !           130: {
        !           131:     if (kvm_enabled() &&
        !           132:         first_cpu->cpuid_kvm_features & ((1ULL << KVM_FEATURE_CLOCKSOURCE) |
        !           133:                                          (1ULL << KVM_FEATURE_CLOCKSOURCE2))) {
        !           134:         sysbus_create_simple("kvmclock", -1, NULL);
        !           135:     }
        !           136: }
        !           137: 
        !           138: static void kvmclock_register_types(void)
        !           139: {
        !           140:     type_register_static(&kvmclock_info);
        !           141: }
        !           142: 
        !           143: type_init(kvmclock_register_types)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.