12
#include "qemu/osdep.h"
13
#include "qemu/units.h"
14
#include "migration/qemu-file.h"
15
#include "migration/register.h"
16
#include "hw/qdev-properties.h"
17
#include "hw/s390x/storage-attributes.h"
18
#include "qemu/error-report.h"
19
#include "exec/ram_addr.h"
20
#include "qapi/error.h"
21
#include "qapi/qmp/qdict.h"
25
#define CMMA_BLOCK_SIZE (512 * KiB)
27
#define STATTR_FLAG_EOS 0x01ULL
28
#define STATTR_FLAG_MORE 0x02ULL
29
#define STATTR_FLAG_ERROR 0x04ULL
30
#define STATTR_FLAG_DONE 0x08ULL
32
static S390StAttribState *s390_get_stattrib_device(void)
34
S390StAttribState *sas;
36
sas = S390_STATTRIB(object_resolve_path_type("", TYPE_S390_STATTRIB, NULL));
41
void s390_stattrib_init(void)
45
obj = kvm_s390_stattrib_create();
47
obj = object_new(TYPE_QEMU_S390_STATTRIB);
50
object_property_add_child(qdev_get_machine(), TYPE_S390_STATTRIB,
54
qdev_realize(DEVICE(obj), NULL, &error_fatal);
59
void hmp_migrationmode(Monitor *mon, const QDict *qdict)
61
S390StAttribState *sas = s390_get_stattrib_device();
62
S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas);
63
uint64_t what = qdict_get_int(qdict, "mode");
64
Error *local_err = NULL;
67
r = sac->set_migrationmode(sas, what, &local_err);
69
monitor_printf(mon, "Error: %s", error_get_pretty(local_err));
70
error_free(local_err);
74
void hmp_info_cmma(Monitor *mon, const QDict *qdict)
76
S390StAttribState *sas = s390_get_stattrib_device();
77
S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas);
78
uint64_t addr = qdict_get_int(qdict, "addr");
79
uint64_t buflen = qdict_get_try_int(qdict, "count", 8);
83
vals = g_try_malloc(buflen);
85
monitor_printf(mon, "Error: %s\n", strerror(errno));
89
len = sac->peek_stattr(sas, addr / TARGET_PAGE_SIZE, buflen, vals);
91
monitor_printf(mon, "Error: %s", strerror(-len));
95
monitor_printf(mon, " CMMA attributes, "
96
"pages %" PRIu64 "+%d (0x%" PRIx64 "):\n",
97
addr / TARGET_PAGE_SIZE, len, addr & ~TARGET_PAGE_MASK);
98
for (cx = 0; cx < len; cx++) {
100
monitor_printf(mon, "%02x\n", vals[cx]);
102
monitor_printf(mon, "%02x", vals[cx]);
105
monitor_printf(mon, "\n");
113
static int cmma_load(QEMUFile *f, void *opaque, int version_id)
115
S390StAttribState *sas = S390_STATTRIB(opaque);
116
S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas);
117
uint64_t count, cur_gfn;
123
addr = qemu_get_be64(f);
124
flags = addr & ~TARGET_PAGE_MASK;
125
addr &= TARGET_PAGE_MASK;
128
case STATTR_FLAG_MORE: {
129
cur_gfn = addr / TARGET_PAGE_SIZE;
130
count = qemu_get_be64(f);
131
buf = g_try_malloc(count);
133
error_report("cmma_load could not allocate memory");
138
qemu_get_buffer(f, buf, count);
139
ret = sac->set_stattr(sas, cur_gfn, count, buf);
141
error_report("Error %d while setting storage attributes", ret);
146
case STATTR_FLAG_ERROR: {
147
error_report("Storage attributes data is incomplete");
151
case STATTR_FLAG_DONE:
158
sac->synchronize(sas);
160
case STATTR_FLAG_EOS:
164
error_report("Unexpected storage attribute flag data: %#x", flags);
172
static int cmma_save_setup(QEMUFile *f, void *opaque, Error **errp)
174
S390StAttribState *sas = S390_STATTRIB(opaque);
175
S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas);
181
res = sac->set_migrationmode(sas, true, errp);
185
qemu_put_be64(f, STATTR_FLAG_EOS);
189
static void cmma_state_pending(void *opaque, uint64_t *must_precopy,
190
uint64_t *can_postcopy)
192
S390StAttribState *sas = S390_STATTRIB(opaque);
193
S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas);
194
long long res = sac->get_dirtycount(sas);
197
*must_precopy += res;
201
static int cmma_save(QEMUFile *f, void *opaque, int final)
203
S390StAttribState *sas = S390_STATTRIB(opaque);
204
S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas);
206
int r, cx, reallen = 0, ret = 0;
207
uint32_t buflen = CMMA_BLOCK_SIZE;
208
uint64_t start_gfn = sas->migration_cur_gfn;
210
buf = g_try_malloc(buflen);
212
error_report("Could not allocate memory to save storage attributes");
216
while (final ? 1 : migration_rate_exceeded(f) == 0) {
217
reallen = sac->get_stattr(sas, &start_gfn, buflen, buf);
227
qemu_put_be64(f, (start_gfn << TARGET_PAGE_BITS) | STATTR_FLAG_MORE);
228
qemu_put_be64(f, reallen);
229
for (cx = 0; cx < reallen; cx++) {
230
qemu_put_byte(f, buf[cx]);
232
if (!sac->get_dirtycount(sas)) {
237
sas->migration_cur_gfn = start_gfn + reallen;
240
qemu_put_be64(f, STATTR_FLAG_DONE);
242
qemu_put_be64(f, STATTR_FLAG_EOS);
244
r = qemu_file_get_error(f);
252
static int cmma_save_iterate(QEMUFile *f, void *opaque)
254
return cmma_save(f, opaque, 0);
257
static int cmma_save_complete(QEMUFile *f, void *opaque)
259
return cmma_save(f, opaque, 1);
262
static void cmma_save_cleanup(void *opaque)
264
S390StAttribState *sas = S390_STATTRIB(opaque);
265
S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas);
266
sac->set_migrationmode(sas, false, NULL);
269
static bool cmma_active(void *opaque)
271
S390StAttribState *sas = S390_STATTRIB(opaque);
272
S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas);
273
return sac->get_active(sas);
278
static void qemu_s390_stattrib_instance_init(Object *obj)
282
static int qemu_s390_peek_stattr_stub(S390StAttribState *sa, uint64_t start_gfn,
283
uint32_t count, uint8_t *values)
287
static void qemu_s390_synchronize_stub(S390StAttribState *sa)
290
static int qemu_s390_get_stattr_stub(S390StAttribState *sa, uint64_t *start_gfn,
291
uint32_t count, uint8_t *values)
295
static long long qemu_s390_get_dirtycount_stub(S390StAttribState *sa)
299
static int qemu_s390_set_migrationmode_stub(S390StAttribState *sa, bool value,
305
static int qemu_s390_get_active(S390StAttribState *sa)
307
return sa->migration_enabled;
310
static void qemu_s390_stattrib_class_init(ObjectClass *oc, void *data)
312
S390StAttribClass *sa_cl = S390_STATTRIB_CLASS(oc);
313
DeviceClass *dc = DEVICE_CLASS(oc);
315
sa_cl->synchronize = qemu_s390_synchronize_stub;
316
sa_cl->get_stattr = qemu_s390_get_stattr_stub;
317
sa_cl->set_stattr = qemu_s390_peek_stattr_stub;
318
sa_cl->peek_stattr = qemu_s390_peek_stattr_stub;
319
sa_cl->set_migrationmode = qemu_s390_set_migrationmode_stub;
320
sa_cl->get_dirtycount = qemu_s390_get_dirtycount_stub;
321
sa_cl->get_active = qemu_s390_get_active;
324
dc->user_creatable = false;
327
static const TypeInfo qemu_s390_stattrib_info = {
328
.name = TYPE_QEMU_S390_STATTRIB,
329
.parent = TYPE_S390_STATTRIB,
330
.instance_init = qemu_s390_stattrib_instance_init,
331
.instance_size = sizeof(QEMUS390StAttribState),
332
.class_init = qemu_s390_stattrib_class_init,
333
.class_size = sizeof(S390StAttribClass),
338
static SaveVMHandlers savevm_s390_stattrib_handlers = {
339
.save_setup = cmma_save_setup,
340
.save_live_iterate = cmma_save_iterate,
341
.save_live_complete_precopy = cmma_save_complete,
342
.state_pending_exact = cmma_state_pending,
343
.state_pending_estimate = cmma_state_pending,
344
.save_cleanup = cmma_save_cleanup,
345
.load_state = cmma_load,
346
.is_active = cmma_active,
349
static void s390_stattrib_realize(DeviceState *dev, Error **errp)
351
bool ambiguous = false;
353
object_resolve_path_type("", TYPE_S390_STATTRIB, &ambiguous);
355
error_setg(errp, "storage_attributes device already exists");
359
register_savevm_live(TYPE_S390_STATTRIB, 0, 0,
360
&savevm_s390_stattrib_handlers, dev);
363
static Property s390_stattrib_props[] = {
364
DEFINE_PROP_BOOL("migration-enabled", S390StAttribState, migration_enabled, true),
365
DEFINE_PROP_END_OF_LIST(),
368
static void s390_stattrib_class_init(ObjectClass *oc, void *data)
370
DeviceClass *dc = DEVICE_CLASS(oc);
372
dc->hotpluggable = false;
373
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
374
dc->realize = s390_stattrib_realize;
375
device_class_set_props(dc, s390_stattrib_props);
378
static void s390_stattrib_instance_init(Object *obj)
380
S390StAttribState *sas = S390_STATTRIB(obj);
382
sas->migration_cur_gfn = 0;
385
static const TypeInfo s390_stattrib_info = {
386
.name = TYPE_S390_STATTRIB,
387
.parent = TYPE_DEVICE,
388
.instance_init = s390_stattrib_instance_init,
389
.instance_size = sizeof(S390StAttribState),
390
.class_init = s390_stattrib_class_init,
391
.class_size = sizeof(S390StAttribClass),
395
static void s390_stattrib_register_types(void)
397
type_register_static(&s390_stattrib_info);
398
type_register_static(&qemu_s390_stattrib_info);
401
type_init(s390_stattrib_register_types)