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"
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 /* 512KiB cover 2GB of guest memory */
24 #define CMMA_BLOCK_SIZE (512 * KiB)
26 #define STATTR_FLAG_EOS 0x01ULL
27 #define STATTR_FLAG_MORE 0x02ULL
28 #define STATTR_FLAG_ERROR 0x04ULL
29 #define STATTR_FLAG_DONE 0x08ULL
31 static S390StAttribState
*s390_get_stattrib_device(void)
33 S390StAttribState
*sas
;
35 sas
= S390_STATTRIB(object_resolve_path_type("", TYPE_S390_STATTRIB
, NULL
));
40 void s390_stattrib_init(void)
44 obj
= kvm_s390_stattrib_create();
46 obj
= object_new(TYPE_QEMU_S390_STATTRIB
);
49 object_property_add_child(qdev_get_machine(), TYPE_S390_STATTRIB
,
53 qdev_realize(DEVICE(obj
), NULL
, &error_fatal
);
56 /* Console commands: */
58 void hmp_migrationmode(Monitor
*mon
, const QDict
*qdict
)
60 S390StAttribState
*sas
= s390_get_stattrib_device();
61 S390StAttribClass
*sac
= S390_STATTRIB_GET_CLASS(sas
);
62 uint64_t what
= qdict_get_int(qdict
, "mode");
65 r
= sac
->set_migrationmode(sas
, what
);
67 monitor_printf(mon
, "Error: %s", strerror(-r
));
71 void hmp_info_cmma(Monitor
*mon
, const QDict
*qdict
)
73 S390StAttribState
*sas
= s390_get_stattrib_device();
74 S390StAttribClass
*sac
= S390_STATTRIB_GET_CLASS(sas
);
75 uint64_t addr
= qdict_get_int(qdict
, "addr");
76 uint64_t buflen
= qdict_get_try_int(qdict
, "count", 8);
80 vals
= g_try_malloc(buflen
);
82 monitor_printf(mon
, "Error: %s\n", strerror(errno
));
86 len
= sac
->peek_stattr(sas
, addr
/ TARGET_PAGE_SIZE
, buflen
, vals
);
88 monitor_printf(mon
, "Error: %s", strerror(-len
));
92 monitor_printf(mon
, " CMMA attributes, "
93 "pages %" PRIu64
"+%d (0x%" PRIx64
"):\n",
94 addr
/ TARGET_PAGE_SIZE
, len
, addr
& ~TARGET_PAGE_MASK
);
95 for (cx
= 0; cx
< len
; cx
++) {
97 monitor_printf(mon
, "%02x\n", vals
[cx
]);
99 monitor_printf(mon
, "%02x", vals
[cx
]);
102 monitor_printf(mon
, "\n");
108 /* Migration support: */
110 static int cmma_load(QEMUFile
*f
, void *opaque
, int version_id
)
112 S390StAttribState
*sas
= S390_STATTRIB(opaque
);
113 S390StAttribClass
*sac
= S390_STATTRIB_GET_CLASS(sas
);
114 uint64_t count
, cur_gfn
;
120 addr
= qemu_get_be64(f
);
121 flags
= addr
& ~TARGET_PAGE_MASK
;
122 addr
&= TARGET_PAGE_MASK
;
125 case STATTR_FLAG_MORE
: {
126 cur_gfn
= addr
/ TARGET_PAGE_SIZE
;
127 count
= qemu_get_be64(f
);
128 buf
= g_try_malloc(count
);
130 error_report("cmma_load could not allocate memory");
135 qemu_get_buffer(f
, buf
, count
);
136 ret
= sac
->set_stattr(sas
, cur_gfn
, count
, buf
);
138 error_report("Error %d while setting storage attributes", ret
);
143 case STATTR_FLAG_ERROR
: {
144 error_report("Storage attributes data is incomplete");
148 case STATTR_FLAG_DONE
:
149 /* This is after the last pre-copied value has been sent, nothing
150 * more will be sent after this. Pre-copy has finished, and we
151 * are done flushing all the remaining values. Now the target
152 * system is about to take over. We synchronize the buffer to
153 * apply the actual correct values where needed.
155 sac
->synchronize(sas
);
157 case STATTR_FLAG_EOS
:
161 error_report("Unexpected storage attribute flag data: %#x", flags
);
169 static int cmma_save_setup(QEMUFile
*f
, void *opaque
)
171 S390StAttribState
*sas
= S390_STATTRIB(opaque
);
172 S390StAttribClass
*sac
= S390_STATTRIB_GET_CLASS(sas
);
175 * Signal that we want to start a migration, thus needing PGSTE dirty
178 res
= sac
->set_migrationmode(sas
, 1);
182 qemu_put_be64(f
, STATTR_FLAG_EOS
);
186 static void cmma_save_pending(QEMUFile
*f
, void *opaque
, uint64_t max_size
,
187 uint64_t *res_precopy_only
,
188 uint64_t *res_compatible
,
189 uint64_t *res_postcopy_only
)
191 S390StAttribState
*sas
= S390_STATTRIB(opaque
);
192 S390StAttribClass
*sac
= S390_STATTRIB_GET_CLASS(sas
);
193 long long res
= sac
->get_dirtycount(sas
);
196 *res_precopy_only
+= res
;
200 static int cmma_save(QEMUFile
*f
, void *opaque
, int final
)
202 S390StAttribState
*sas
= S390_STATTRIB(opaque
);
203 S390StAttribClass
*sac
= S390_STATTRIB_GET_CLASS(sas
);
205 int r
, cx
, reallen
= 0, ret
= 0;
206 uint32_t buflen
= CMMA_BLOCK_SIZE
;
207 uint64_t start_gfn
= sas
->migration_cur_gfn
;
209 buf
= g_try_malloc(buflen
);
211 error_report("Could not allocate memory to save storage attributes");
215 while (final
? 1 : qemu_file_rate_limit(f
) == 0) {
216 reallen
= sac
->get_stattr(sas
, &start_gfn
, buflen
, buf
);
226 qemu_put_be64(f
, (start_gfn
<< TARGET_PAGE_BITS
) | STATTR_FLAG_MORE
);
227 qemu_put_be64(f
, reallen
);
228 for (cx
= 0; cx
< reallen
; cx
++) {
229 qemu_put_byte(f
, buf
[cx
]);
231 if (!sac
->get_dirtycount(sas
)) {
236 sas
->migration_cur_gfn
= start_gfn
+ reallen
;
239 qemu_put_be64(f
, STATTR_FLAG_DONE
);
241 qemu_put_be64(f
, STATTR_FLAG_EOS
);
243 r
= qemu_file_get_error(f
);
251 static int cmma_save_iterate(QEMUFile
*f
, void *opaque
)
253 return cmma_save(f
, opaque
, 0);
256 static int cmma_save_complete(QEMUFile
*f
, void *opaque
)
258 return cmma_save(f
, opaque
, 1);
261 static void cmma_save_cleanup(void *opaque
)
263 S390StAttribState
*sas
= S390_STATTRIB(opaque
);
264 S390StAttribClass
*sac
= S390_STATTRIB_GET_CLASS(sas
);
265 sac
->set_migrationmode(sas
, 0);
268 static bool cmma_active(void *opaque
)
270 S390StAttribState
*sas
= S390_STATTRIB(opaque
);
271 S390StAttribClass
*sac
= S390_STATTRIB_GET_CLASS(sas
);
272 return sac
->get_active(sas
);
277 static void qemu_s390_stattrib_instance_init(Object
*obj
)
281 static int qemu_s390_peek_stattr_stub(S390StAttribState
*sa
, uint64_t start_gfn
,
282 uint32_t count
, uint8_t *values
)
286 static void qemu_s390_synchronize_stub(S390StAttribState
*sa
)
289 static int qemu_s390_get_stattr_stub(S390StAttribState
*sa
, uint64_t *start_gfn
,
290 uint32_t count
, uint8_t *values
)
294 static long long qemu_s390_get_dirtycount_stub(S390StAttribState
*sa
)
298 static int qemu_s390_set_migrationmode_stub(S390StAttribState
*sa
, bool value
)
303 static int qemu_s390_get_active(S390StAttribState
*sa
)
305 return sa
->migration_enabled
;
308 static void qemu_s390_stattrib_class_init(ObjectClass
*oc
, void *data
)
310 S390StAttribClass
*sa_cl
= S390_STATTRIB_CLASS(oc
);
311 DeviceClass
*dc
= DEVICE_CLASS(oc
);
313 sa_cl
->synchronize
= qemu_s390_synchronize_stub
;
314 sa_cl
->get_stattr
= qemu_s390_get_stattr_stub
;
315 sa_cl
->set_stattr
= qemu_s390_peek_stattr_stub
;
316 sa_cl
->peek_stattr
= qemu_s390_peek_stattr_stub
;
317 sa_cl
->set_migrationmode
= qemu_s390_set_migrationmode_stub
;
318 sa_cl
->get_dirtycount
= qemu_s390_get_dirtycount_stub
;
319 sa_cl
->get_active
= qemu_s390_get_active
;
321 /* Reason: Can only be instantiated one time (internally) */
322 dc
->user_creatable
= false;
325 static const TypeInfo qemu_s390_stattrib_info
= {
326 .name
= TYPE_QEMU_S390_STATTRIB
,
327 .parent
= TYPE_S390_STATTRIB
,
328 .instance_init
= qemu_s390_stattrib_instance_init
,
329 .instance_size
= sizeof(QEMUS390StAttribState
),
330 .class_init
= qemu_s390_stattrib_class_init
,
331 .class_size
= sizeof(S390StAttribClass
),
334 /* Generic abstract object: */
336 static void s390_stattrib_realize(DeviceState
*dev
, Error
**errp
)
338 bool ambiguous
= false;
340 object_resolve_path_type("", TYPE_S390_STATTRIB
, &ambiguous
);
342 error_setg(errp
, "storage_attributes device already exists");
346 static void s390_stattrib_class_init(ObjectClass
*oc
, void *data
)
348 DeviceClass
*dc
= DEVICE_CLASS(oc
);
350 dc
->hotpluggable
= false;
351 set_bit(DEVICE_CATEGORY_MISC
, dc
->categories
);
352 dc
->realize
= s390_stattrib_realize
;
355 static inline bool s390_stattrib_get_migration_enabled(Object
*obj
,
358 S390StAttribState
*s
= S390_STATTRIB(obj
);
360 return s
->migration_enabled
;
363 static inline void s390_stattrib_set_migration_enabled(Object
*obj
, bool value
,
366 S390StAttribState
*s
= S390_STATTRIB(obj
);
368 s
->migration_enabled
= value
;
371 static SaveVMHandlers savevm_s390_stattrib_handlers
= {
372 .save_setup
= cmma_save_setup
,
373 .save_live_iterate
= cmma_save_iterate
,
374 .save_live_complete_precopy
= cmma_save_complete
,
375 .save_live_pending
= cmma_save_pending
,
376 .save_cleanup
= cmma_save_cleanup
,
377 .load_state
= cmma_load
,
378 .is_active
= cmma_active
,
381 static void s390_stattrib_instance_init(Object
*obj
)
383 S390StAttribState
*sas
= S390_STATTRIB(obj
);
385 register_savevm_live(TYPE_S390_STATTRIB
, 0, 0,
386 &savevm_s390_stattrib_handlers
, sas
);
388 object_property_add_bool(obj
, "migration-enabled",
389 s390_stattrib_get_migration_enabled
,
390 s390_stattrib_set_migration_enabled
);
391 object_property_set_bool(obj
, "migration-enabled", true, NULL
);
392 sas
->migration_cur_gfn
= 0;
395 static const TypeInfo s390_stattrib_info
= {
396 .name
= TYPE_S390_STATTRIB
,
397 .parent
= TYPE_DEVICE
,
398 .instance_init
= s390_stattrib_instance_init
,
399 .instance_size
= sizeof(S390StAttribState
),
400 .class_init
= s390_stattrib_class_init
,
401 .class_size
= sizeof(S390StAttribClass
),
405 static void s390_stattrib_register_types(void)
407 type_register_static(&s390_stattrib_info
);
408 type_register_static(&qemu_s390_stattrib_info
);
411 type_init(s390_stattrib_register_types
)