Annotation of qemu/hw/kvm/clock.c, revision 1.1.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.