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 "hw/boards.h"
15 #include "migration/qemu-file.h"
16 #include "migration/register.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"
23 #define CMMA_BLOCK_SIZE (1 << 10)
25 #define STATTR_FLAG_EOS 0x01ULL
26 #define STATTR_FLAG_MORE 0x02ULL
27 #define STATTR_FLAG_ERROR 0x04ULL
28 #define STATTR_FLAG_DONE 0x08ULL
30 static S390StAttribState
*s390_get_stattrib_device(void)
32 S390StAttribState
*sas
;
34 sas
= S390_STATTRIB(object_resolve_path_type("", TYPE_S390_STATTRIB
, NULL
));
39 void s390_stattrib_init(void)
43 obj
= kvm_s390_stattrib_create();
45 obj
= object_new(TYPE_QEMU_S390_STATTRIB
);
48 object_property_add_child(qdev_get_machine(), TYPE_S390_STATTRIB
,
52 qdev_init_nofail(DEVICE(obj
));
55 /* Console commands: */
57 void hmp_migrationmode(Monitor
*mon
, const QDict
*qdict
)
59 S390StAttribState
*sas
= s390_get_stattrib_device();
60 S390StAttribClass
*sac
= S390_STATTRIB_GET_CLASS(sas
);
61 uint64_t what
= qdict_get_int(qdict
, "mode");
64 r
= sac
->set_migrationmode(sas
, what
);
66 monitor_printf(mon
, "Error: %s", strerror(-r
));
70 void hmp_info_cmma(Monitor
*mon
, const QDict
*qdict
)
72 S390StAttribState
*sas
= s390_get_stattrib_device();
73 S390StAttribClass
*sac
= S390_STATTRIB_GET_CLASS(sas
);
74 uint64_t addr
= qdict_get_int(qdict
, "addr");
75 uint64_t buflen
= qdict_get_try_int(qdict
, "count", 8);
79 vals
= g_try_malloc(buflen
);
81 monitor_printf(mon
, "Error: %s\n", strerror(errno
));
85 len
= sac
->peek_stattr(sas
, addr
/ TARGET_PAGE_SIZE
, buflen
, vals
);
87 monitor_printf(mon
, "Error: %s", strerror(-len
));
91 monitor_printf(mon
, " CMMA attributes, "
92 "pages %" PRIu64
"+%d (0x%" PRIx64
"):\n",
93 addr
/ TARGET_PAGE_SIZE
, len
, addr
& ~TARGET_PAGE_MASK
);
94 for (cx
= 0; cx
< len
; cx
++) {
96 monitor_printf(mon
, "%02x\n", vals
[cx
]);
98 monitor_printf(mon
, "%02x", vals
[cx
]);
101 monitor_printf(mon
, "\n");
107 /* Migration support: */
109 static int cmma_load(QEMUFile
*f
, void *opaque
, int version_id
)
111 S390StAttribState
*sas
= S390_STATTRIB(opaque
);
112 S390StAttribClass
*sac
= S390_STATTRIB_GET_CLASS(sas
);
113 uint64_t count
, cur_gfn
;
119 addr
= qemu_get_be64(f
);
120 flags
= addr
& ~TARGET_PAGE_MASK
;
121 addr
&= TARGET_PAGE_MASK
;
124 case STATTR_FLAG_MORE
: {
125 cur_gfn
= addr
/ TARGET_PAGE_SIZE
;
126 count
= qemu_get_be64(f
);
127 buf
= g_try_malloc(count
);
129 error_report("cmma_load could not allocate memory");
134 qemu_get_buffer(f
, buf
, count
);
135 ret
= sac
->set_stattr(sas
, cur_gfn
, count
, buf
);
137 error_report("Error %d while setting storage attributes", ret
);
142 case STATTR_FLAG_ERROR
: {
143 error_report("Storage attributes data is incomplete");
147 case STATTR_FLAG_DONE
:
148 /* This is after the last pre-copied value has been sent, nothing
149 * more will be sent after this. Pre-copy has finished, and we
150 * are done flushing all the remaining values. Now the target
151 * system is about to take over. We synchronize the buffer to
152 * apply the actual correct values where needed.
154 sac
->synchronize(sas
);
156 case STATTR_FLAG_EOS
:
160 error_report("Unexpected storage attribute flag data: %#x", flags
);
168 static int cmma_save_setup(QEMUFile
*f
, void *opaque
)
170 S390StAttribState
*sas
= S390_STATTRIB(opaque
);
171 S390StAttribClass
*sac
= S390_STATTRIB_GET_CLASS(sas
);
174 * Signal that we want to start a migration, thus needing PGSTE dirty
177 res
= sac
->set_migrationmode(sas
, 1);
181 qemu_put_be64(f
, STATTR_FLAG_EOS
);
185 static void cmma_save_pending(QEMUFile
*f
, void *opaque
, uint64_t max_size
,
186 uint64_t *res_precopy_only
,
187 uint64_t *res_compatible
,
188 uint64_t *res_postcopy_only
)
190 S390StAttribState
*sas
= S390_STATTRIB(opaque
);
191 S390StAttribClass
*sac
= S390_STATTRIB_GET_CLASS(sas
);
192 long long res
= sac
->get_dirtycount(sas
);
195 *res_precopy_only
+= res
;
199 static int cmma_save(QEMUFile
*f
, void *opaque
, int final
)
201 S390StAttribState
*sas
= S390_STATTRIB(opaque
);
202 S390StAttribClass
*sac
= S390_STATTRIB_GET_CLASS(sas
);
204 int r
, cx
, reallen
= 0, ret
= 0;
205 uint32_t buflen
= 1 << 19; /* 512kB cover 2GB of guest memory */
206 uint64_t start_gfn
= sas
->migration_cur_gfn
;
208 buf
= g_try_malloc(buflen
);
210 error_report("Could not allocate memory to save storage attributes");
214 while (final
? 1 : qemu_file_rate_limit(f
) == 0) {
215 reallen
= sac
->get_stattr(sas
, &start_gfn
, buflen
, buf
);
225 qemu_put_be64(f
, (start_gfn
<< TARGET_PAGE_BITS
) | STATTR_FLAG_MORE
);
226 qemu_put_be64(f
, reallen
);
227 for (cx
= 0; cx
< reallen
; cx
++) {
228 qemu_put_byte(f
, buf
[cx
]);
230 if (!sac
->get_dirtycount(sas
)) {
235 sas
->migration_cur_gfn
= start_gfn
+ reallen
;
238 qemu_put_be64(f
, STATTR_FLAG_DONE
);
240 qemu_put_be64(f
, STATTR_FLAG_EOS
);
242 r
= qemu_file_get_error(f
);
250 static int cmma_save_iterate(QEMUFile
*f
, void *opaque
)
252 return cmma_save(f
, opaque
, 0);
255 static int cmma_save_complete(QEMUFile
*f
, void *opaque
)
257 return cmma_save(f
, opaque
, 1);
260 static void cmma_save_cleanup(void *opaque
)
262 S390StAttribState
*sas
= S390_STATTRIB(opaque
);
263 S390StAttribClass
*sac
= S390_STATTRIB_GET_CLASS(sas
);
264 sac
->set_migrationmode(sas
, 0);
267 static bool cmma_active(void *opaque
)
269 S390StAttribState
*sas
= S390_STATTRIB(opaque
);
270 S390StAttribClass
*sac
= S390_STATTRIB_GET_CLASS(sas
);
271 return sac
->get_active(sas
);
276 static void qemu_s390_stattrib_instance_init(Object
*obj
)
280 static int qemu_s390_peek_stattr_stub(S390StAttribState
*sa
, uint64_t start_gfn
,
281 uint32_t count
, uint8_t *values
)
285 static void qemu_s390_synchronize_stub(S390StAttribState
*sa
)
288 static int qemu_s390_get_stattr_stub(S390StAttribState
*sa
, uint64_t *start_gfn
,
289 uint32_t count
, uint8_t *values
)
293 static long long qemu_s390_get_dirtycount_stub(S390StAttribState
*sa
)
297 static int qemu_s390_set_migrationmode_stub(S390StAttribState
*sa
, bool value
)
302 static int qemu_s390_get_active(S390StAttribState
*sa
)
304 return sa
->migration_enabled
;
307 static void qemu_s390_stattrib_class_init(ObjectClass
*oc
, void *data
)
309 S390StAttribClass
*sa_cl
= S390_STATTRIB_CLASS(oc
);
310 DeviceClass
*dc
= DEVICE_CLASS(oc
);
312 sa_cl
->synchronize
= qemu_s390_synchronize_stub
;
313 sa_cl
->get_stattr
= qemu_s390_get_stattr_stub
;
314 sa_cl
->set_stattr
= qemu_s390_peek_stattr_stub
;
315 sa_cl
->peek_stattr
= qemu_s390_peek_stattr_stub
;
316 sa_cl
->set_migrationmode
= qemu_s390_set_migrationmode_stub
;
317 sa_cl
->get_dirtycount
= qemu_s390_get_dirtycount_stub
;
318 sa_cl
->get_active
= qemu_s390_get_active
;
320 /* Reason: Can only be instantiated one time (internally) */
321 dc
->user_creatable
= false;
324 static const TypeInfo qemu_s390_stattrib_info
= {
325 .name
= TYPE_QEMU_S390_STATTRIB
,
326 .parent
= TYPE_S390_STATTRIB
,
327 .instance_init
= qemu_s390_stattrib_instance_init
,
328 .instance_size
= sizeof(QEMUS390StAttribState
),
329 .class_init
= qemu_s390_stattrib_class_init
,
330 .class_size
= sizeof(S390StAttribClass
),
333 /* Generic abstract object: */
335 static void s390_stattrib_realize(DeviceState
*dev
, Error
**errp
)
337 bool ambiguous
= false;
339 object_resolve_path_type("", TYPE_S390_STATTRIB
, &ambiguous
);
341 error_setg(errp
, "storage_attributes device already exists");
345 static void s390_stattrib_class_init(ObjectClass
*oc
, void *data
)
347 DeviceClass
*dc
= DEVICE_CLASS(oc
);
349 dc
->hotpluggable
= false;
350 set_bit(DEVICE_CATEGORY_MISC
, dc
->categories
);
351 dc
->realize
= s390_stattrib_realize
;
354 static inline bool s390_stattrib_get_migration_enabled(Object
*obj
, Error
**e
)
356 S390StAttribState
*s
= S390_STATTRIB(obj
);
358 return s
->migration_enabled
;
361 static inline void s390_stattrib_set_migration_enabled(Object
*obj
, bool value
,
364 S390StAttribState
*s
= S390_STATTRIB(obj
);
366 s
->migration_enabled
= value
;
369 static SaveVMHandlers savevm_s390_stattrib_handlers
= {
370 .save_setup
= cmma_save_setup
,
371 .save_live_iterate
= cmma_save_iterate
,
372 .save_live_complete_precopy
= cmma_save_complete
,
373 .save_live_pending
= cmma_save_pending
,
374 .save_cleanup
= cmma_save_cleanup
,
375 .load_state
= cmma_load
,
376 .is_active
= cmma_active
,
379 static void s390_stattrib_instance_init(Object
*obj
)
381 S390StAttribState
*sas
= S390_STATTRIB(obj
);
383 register_savevm_live(NULL
, TYPE_S390_STATTRIB
, 0, 0,
384 &savevm_s390_stattrib_handlers
, sas
);
386 object_property_add_bool(obj
, "migration-enabled",
387 s390_stattrib_get_migration_enabled
,
388 s390_stattrib_set_migration_enabled
, NULL
);
389 object_property_set_bool(obj
, true, "migration-enabled", NULL
);
390 sas
->migration_cur_gfn
= 0;
393 static const TypeInfo s390_stattrib_info
= {
394 .name
= TYPE_S390_STATTRIB
,
395 .parent
= TYPE_DEVICE
,
396 .instance_init
= s390_stattrib_instance_init
,
397 .instance_size
= sizeof(S390StAttribState
),
398 .class_init
= s390_stattrib_class_init
,
399 .class_size
= sizeof(S390StAttribClass
),
403 static void s390_stattrib_register_types(void)
405 type_register_static(&s390_stattrib_info
);
406 type_register_static(&qemu_s390_stattrib_info
);
409 type_init(s390_stattrib_register_types
)