qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

s390-stattrib-kvm.c (6245B)


      1 /*
      2  * s390 storage attributes device -- KVM object
      3  *
      4  * Copyright 2016 IBM Corp.
      5  * Author(s): Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
      6  *
      7  * This work is licensed under the terms of the GNU GPL, version 2 or (at
      8  * your option) any later version. See the COPYING file in the top-level
      9  * directory.
     10  */
     11 
     12 #include "qemu/osdep.h"
     13 #include "hw/boards.h"
     14 #include "migration/qemu-file.h"
     15 #include "hw/s390x/storage-attributes.h"
     16 #include "qemu/error-report.h"
     17 #include "sysemu/kvm.h"
     18 #include "exec/ram_addr.h"
     19 #include "kvm/kvm_s390x.h"
     20 
     21 Object *kvm_s390_stattrib_create(void)
     22 {
     23     if (kvm_enabled() &&
     24                 kvm_check_extension(kvm_state, KVM_CAP_S390_CMMA_MIGRATION)) {
     25         return object_new(TYPE_KVM_S390_STATTRIB);
     26     }
     27     return NULL;
     28 }
     29 
     30 static void kvm_s390_stattrib_instance_init(Object *obj)
     31 {
     32     KVMS390StAttribState *sas = KVM_S390_STATTRIB(obj);
     33 
     34     sas->still_dirty = 0;
     35 }
     36 
     37 static int kvm_s390_stattrib_read_helper(S390StAttribState *sa,
     38                                          uint64_t *start_gfn,
     39                                          uint32_t count,
     40                                          uint8_t *values,
     41                                          uint32_t flags)
     42 {
     43     KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa);
     44     int r;
     45     struct kvm_s390_cmma_log clog = {
     46         .values = (uint64_t)values,
     47         .start_gfn = *start_gfn,
     48         .count = count,
     49         .flags = flags,
     50     };
     51 
     52     r = kvm_vm_ioctl(kvm_state, KVM_S390_GET_CMMA_BITS, &clog);
     53     if (r < 0) {
     54         error_report("KVM_S390_GET_CMMA_BITS failed: %s", strerror(-r));
     55         return r;
     56     }
     57 
     58     *start_gfn = clog.start_gfn;
     59     sas->still_dirty = clog.remaining;
     60     return clog.count;
     61 }
     62 
     63 static int kvm_s390_stattrib_get_stattr(S390StAttribState *sa,
     64                                         uint64_t *start_gfn,
     65                                         uint32_t count,
     66                                         uint8_t *values)
     67 {
     68     return kvm_s390_stattrib_read_helper(sa, start_gfn, count, values, 0);
     69 }
     70 
     71 static int kvm_s390_stattrib_peek_stattr(S390StAttribState *sa,
     72                                          uint64_t start_gfn,
     73                                          uint32_t count,
     74                                          uint8_t *values)
     75 {
     76     return kvm_s390_stattrib_read_helper(sa, &start_gfn, count, values,
     77                                          KVM_S390_CMMA_PEEK);
     78 }
     79 
     80 static int kvm_s390_stattrib_set_stattr(S390StAttribState *sa,
     81                                         uint64_t start_gfn,
     82                                         uint32_t count,
     83                                         uint8_t *values)
     84 {
     85     KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa);
     86     MachineState *machine = MACHINE(qdev_get_machine());
     87     unsigned long max = machine->ram_size / TARGET_PAGE_SIZE;
     88 
     89     if (start_gfn + count > max) {
     90         error_report("Out of memory bounds when setting storage attributes");
     91         return -1;
     92     }
     93     if (!sas->incoming_buffer) {
     94         sas->incoming_buffer = g_malloc0(max);
     95     }
     96 
     97     memcpy(sas->incoming_buffer + start_gfn, values, count);
     98 
     99     return 0;
    100 }
    101 
    102 static void kvm_s390_stattrib_synchronize(S390StAttribState *sa)
    103 {
    104     KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa);
    105     MachineState *machine = MACHINE(qdev_get_machine());
    106     unsigned long max = machine->ram_size / TARGET_PAGE_SIZE;
    107     /* We do not need to reach the maximum buffer size allowed */
    108     unsigned long cx, len = KVM_S390_SKEYS_MAX / 2;
    109     int r;
    110     struct kvm_s390_cmma_log clog = {
    111         .flags = 0,
    112         .mask = ~0ULL,
    113     };
    114 
    115     if (sas->incoming_buffer) {
    116         for (cx = 0; cx + len <= max; cx += len) {
    117             clog.start_gfn = cx;
    118             clog.count = len;
    119             clog.values = (uint64_t)(sas->incoming_buffer + cx);
    120             r = kvm_vm_ioctl(kvm_state, KVM_S390_SET_CMMA_BITS, &clog);
    121             if (r) {
    122                 error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r));
    123                 return;
    124             }
    125         }
    126         if (cx < max) {
    127             clog.start_gfn = cx;
    128             clog.count = max - cx;
    129             clog.values = (uint64_t)(sas->incoming_buffer + cx);
    130             r = kvm_vm_ioctl(kvm_state, KVM_S390_SET_CMMA_BITS, &clog);
    131             if (r) {
    132                 error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r));
    133             }
    134         }
    135         g_free(sas->incoming_buffer);
    136         sas->incoming_buffer = NULL;
    137     }
    138 }
    139 
    140 static int kvm_s390_stattrib_set_migrationmode(S390StAttribState *sa, bool val)
    141 {
    142     struct kvm_device_attr attr = {
    143         .group = KVM_S390_VM_MIGRATION,
    144         .attr = val,
    145         .addr = 0,
    146     };
    147     return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr);
    148 }
    149 
    150 static long long kvm_s390_stattrib_get_dirtycount(S390StAttribState *sa)
    151 {
    152     KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa);
    153     uint8_t val[8];
    154 
    155     kvm_s390_stattrib_peek_stattr(sa, 0, 1, val);
    156     return sas->still_dirty;
    157 }
    158 
    159 static int kvm_s390_stattrib_get_active(S390StAttribState *sa)
    160 {
    161     return kvm_s390_cmma_active() && sa->migration_enabled;
    162 }
    163 
    164 static void kvm_s390_stattrib_class_init(ObjectClass *oc, void *data)
    165 {
    166     S390StAttribClass *sac = S390_STATTRIB_CLASS(oc);
    167     DeviceClass *dc = DEVICE_CLASS(oc);
    168 
    169     sac->get_stattr = kvm_s390_stattrib_get_stattr;
    170     sac->peek_stattr = kvm_s390_stattrib_peek_stattr;
    171     sac->set_stattr = kvm_s390_stattrib_set_stattr;
    172     sac->set_migrationmode = kvm_s390_stattrib_set_migrationmode;
    173     sac->get_dirtycount = kvm_s390_stattrib_get_dirtycount;
    174     sac->synchronize = kvm_s390_stattrib_synchronize;
    175     sac->get_active = kvm_s390_stattrib_get_active;
    176 
    177     /* Reason: Can only be instantiated one time (internally) */
    178     dc->user_creatable = false;
    179 }
    180 
    181 static const TypeInfo kvm_s390_stattrib_info = {
    182     .name          = TYPE_KVM_S390_STATTRIB,
    183     .parent        = TYPE_S390_STATTRIB,
    184     .instance_init = kvm_s390_stattrib_instance_init,
    185     .instance_size = sizeof(KVMS390StAttribState),
    186     .class_init    = kvm_s390_stattrib_class_init,
    187     .class_size    = sizeof(S390StAttribClass),
    188 };
    189 
    190 static void kvm_s390_stattrib_register_types(void)
    191 {
    192     type_register_static(&kvm_s390_stattrib_info);
    193 }
    194 
    195 type_init(kvm_s390_stattrib_register_types)