2 * s390 storage attributes device
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 "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"
24 /* 512KiB cover 2GB of guest memory */
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
);
57 /* Console commands: */
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");
111 /* Migration support: */
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
:
152 /* This is after the last pre-copied value has been sent, nothing
153 * more will be sent after this. Pre-copy has finished, and we
154 * are done flushing all the remaining values. Now the target
155 * system is about to take over. We synchronize the buffer to
156 * apply the actual correct values where needed.
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
);
178 * Signal that we want to start a migration, thus needing PGSTE dirty
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
;
323 /* Reason: Can only be instantiated one time (internally) */
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
),
336 /* Generic abstract object: */
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
)