2 * s390 storage attributes device -- KVM object
4 * Copyright 2016 IBM Corp.
5 * Author(s): Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
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
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 #include "qapi/error.h"
22 Object
*kvm_s390_stattrib_create(void)
25 kvm_check_extension(kvm_state
, KVM_CAP_S390_CMMA_MIGRATION
)) {
26 return object_new(TYPE_KVM_S390_STATTRIB
);
31 static void kvm_s390_stattrib_instance_init(Object
*obj
)
33 KVMS390StAttribState
*sas
= KVM_S390_STATTRIB(obj
);
38 static int kvm_s390_stattrib_read_helper(S390StAttribState
*sa
,
44 KVMS390StAttribState
*sas
= KVM_S390_STATTRIB(sa
);
46 struct kvm_s390_cmma_log clog
= {
47 .values
= (uint64_t)values
,
48 .start_gfn
= *start_gfn
,
53 r
= kvm_vm_ioctl(kvm_state
, KVM_S390_GET_CMMA_BITS
, &clog
);
55 error_report("KVM_S390_GET_CMMA_BITS failed: %s", strerror(-r
));
59 *start_gfn
= clog
.start_gfn
;
60 sas
->still_dirty
= clog
.remaining
;
64 static int kvm_s390_stattrib_get_stattr(S390StAttribState
*sa
,
69 return kvm_s390_stattrib_read_helper(sa
, start_gfn
, count
, values
, 0);
72 static int kvm_s390_stattrib_peek_stattr(S390StAttribState
*sa
,
77 return kvm_s390_stattrib_read_helper(sa
, &start_gfn
, count
, values
,
81 static int kvm_s390_stattrib_set_stattr(S390StAttribState
*sa
,
86 KVMS390StAttribState
*sas
= KVM_S390_STATTRIB(sa
);
87 MachineState
*machine
= MACHINE(qdev_get_machine());
88 unsigned long max
= machine
->ram_size
/ TARGET_PAGE_SIZE
;
90 if (start_gfn
+ count
> max
) {
91 error_report("Out of memory bounds when setting storage attributes");
94 if (!sas
->incoming_buffer
) {
95 sas
->incoming_buffer
= g_malloc0(max
);
98 memcpy(sas
->incoming_buffer
+ start_gfn
, values
, count
);
103 static void kvm_s390_stattrib_synchronize(S390StAttribState
*sa
)
105 KVMS390StAttribState
*sas
= KVM_S390_STATTRIB(sa
);
106 MachineState
*machine
= MACHINE(qdev_get_machine());
107 unsigned long max
= machine
->ram_size
/ TARGET_PAGE_SIZE
;
108 /* We do not need to reach the maximum buffer size allowed */
109 unsigned long cx
, len
= KVM_S390_SKEYS_MAX
/ 2;
111 struct kvm_s390_cmma_log clog
= {
116 if (sas
->incoming_buffer
) {
117 for (cx
= 0; cx
+ len
<= max
; cx
+= len
) {
120 clog
.values
= (uint64_t)(sas
->incoming_buffer
+ cx
);
121 r
= kvm_vm_ioctl(kvm_state
, KVM_S390_SET_CMMA_BITS
, &clog
);
123 error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r
));
129 clog
.count
= max
- cx
;
130 clog
.values
= (uint64_t)(sas
->incoming_buffer
+ cx
);
131 r
= kvm_vm_ioctl(kvm_state
, KVM_S390_SET_CMMA_BITS
, &clog
);
133 error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r
));
136 g_free(sas
->incoming_buffer
);
137 sas
->incoming_buffer
= NULL
;
141 static int kvm_s390_stattrib_set_migrationmode(S390StAttribState
*sa
, bool val
,
144 struct kvm_device_attr attr
= {
145 .group
= KVM_S390_VM_MIGRATION
,
151 r
= kvm_vm_ioctl(kvm_state
, KVM_SET_DEVICE_ATTR
, &attr
);
153 error_setg_errno(errp
, -r
, "setting KVM_S390_VM_MIGRATION failed");
158 static long long kvm_s390_stattrib_get_dirtycount(S390StAttribState
*sa
)
160 KVMS390StAttribState
*sas
= KVM_S390_STATTRIB(sa
);
163 kvm_s390_stattrib_peek_stattr(sa
, 0, 1, val
);
164 return sas
->still_dirty
;
167 static int kvm_s390_stattrib_get_active(S390StAttribState
*sa
)
169 return kvm_s390_cmma_active() && sa
->migration_enabled
;
172 static void kvm_s390_stattrib_class_init(ObjectClass
*oc
, void *data
)
174 S390StAttribClass
*sac
= S390_STATTRIB_CLASS(oc
);
175 DeviceClass
*dc
= DEVICE_CLASS(oc
);
177 sac
->get_stattr
= kvm_s390_stattrib_get_stattr
;
178 sac
->peek_stattr
= kvm_s390_stattrib_peek_stattr
;
179 sac
->set_stattr
= kvm_s390_stattrib_set_stattr
;
180 sac
->set_migrationmode
= kvm_s390_stattrib_set_migrationmode
;
181 sac
->get_dirtycount
= kvm_s390_stattrib_get_dirtycount
;
182 sac
->synchronize
= kvm_s390_stattrib_synchronize
;
183 sac
->get_active
= kvm_s390_stattrib_get_active
;
185 /* Reason: Can only be instantiated one time (internally) */
186 dc
->user_creatable
= false;
189 static const TypeInfo kvm_s390_stattrib_info
= {
190 .name
= TYPE_KVM_S390_STATTRIB
,
191 .parent
= TYPE_S390_STATTRIB
,
192 .instance_init
= kvm_s390_stattrib_instance_init
,
193 .instance_size
= sizeof(KVMS390StAttribState
),
194 .class_init
= kvm_s390_stattrib_class_init
,
195 .class_size
= sizeof(S390StAttribClass
),
198 static void kvm_s390_stattrib_register_types(void)
200 type_register_static(&kvm_s390_stattrib_info
);
203 type_init(kvm_s390_stattrib_register_types
)