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 "hw/boards.h"
16 #include "migration/qemu-file.h"
17 #include "migration/register.h"
18 #include "hw/s390x/storage-attributes.h"
19 #include "qemu/error-report.h"
20 #include "exec/ram_addr.h"
21 #include "qapi/error.h"
22 #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_init_nofail(DEVICE(obj
));
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");
66 r
= sac
->set_migrationmode(sas
, what
);
68 monitor_printf(mon
, "Error: %s", strerror(-r
));
72 void hmp_info_cmma(Monitor
*mon
, const QDict
*qdict
)
74 S390StAttribState
*sas
= s390_get_stattrib_device();
75 S390StAttribClass
*sac
= S390_STATTRIB_GET_CLASS(sas
);
76 uint64_t addr
= qdict_get_int(qdict
, "addr");
77 uint64_t buflen
= qdict_get_try_int(qdict
, "count", 8);
81 vals
= g_try_malloc(buflen
);
83 monitor_printf(mon
, "Error: %s\n", strerror(errno
));
87 len
= sac
->peek_stattr(sas
, addr
/ TARGET_PAGE_SIZE
, buflen
, vals
);
89 monitor_printf(mon
, "Error: %s", strerror(-len
));
93 monitor_printf(mon
, " CMMA attributes, "
94 "pages %" PRIu64
"+%d (0x%" PRIx64
"):\n",
95 addr
/ TARGET_PAGE_SIZE
, len
, addr
& ~TARGET_PAGE_MASK
);
96 for (cx
= 0; cx
< len
; cx
++) {
98 monitor_printf(mon
, "%02x\n", vals
[cx
]);
100 monitor_printf(mon
, "%02x", vals
[cx
]);
103 monitor_printf(mon
, "\n");
109 /* Migration support: */
111 static int cmma_load(QEMUFile
*f
, void *opaque
, int version_id
)
113 S390StAttribState
*sas
= S390_STATTRIB(opaque
);
114 S390StAttribClass
*sac
= S390_STATTRIB_GET_CLASS(sas
);
115 uint64_t count
, cur_gfn
;
121 addr
= qemu_get_be64(f
);
122 flags
= addr
& ~TARGET_PAGE_MASK
;
123 addr
&= TARGET_PAGE_MASK
;
126 case STATTR_FLAG_MORE
: {
127 cur_gfn
= addr
/ TARGET_PAGE_SIZE
;
128 count
= qemu_get_be64(f
);
129 buf
= g_try_malloc(count
);
131 error_report("cmma_load could not allocate memory");
136 qemu_get_buffer(f
, buf
, count
);
137 ret
= sac
->set_stattr(sas
, cur_gfn
, count
, buf
);
139 error_report("Error %d while setting storage attributes", ret
);
144 case STATTR_FLAG_ERROR
: {
145 error_report("Storage attributes data is incomplete");
149 case STATTR_FLAG_DONE
:
150 /* This is after the last pre-copied value has been sent, nothing
151 * more will be sent after this. Pre-copy has finished, and we
152 * are done flushing all the remaining values. Now the target
153 * system is about to take over. We synchronize the buffer to
154 * apply the actual correct values where needed.
156 sac
->synchronize(sas
);
158 case STATTR_FLAG_EOS
:
162 error_report("Unexpected storage attribute flag data: %#x", flags
);
170 static int cmma_save_setup(QEMUFile
*f
, void *opaque
)
172 S390StAttribState
*sas
= S390_STATTRIB(opaque
);
173 S390StAttribClass
*sac
= S390_STATTRIB_GET_CLASS(sas
);
176 * Signal that we want to start a migration, thus needing PGSTE dirty
179 res
= sac
->set_migrationmode(sas
, 1);
183 qemu_put_be64(f
, STATTR_FLAG_EOS
);
187 static void cmma_save_pending(QEMUFile
*f
, void *opaque
, uint64_t max_size
,
188 uint64_t *res_precopy_only
,
189 uint64_t *res_compatible
,
190 uint64_t *res_postcopy_only
)
192 S390StAttribState
*sas
= S390_STATTRIB(opaque
);
193 S390StAttribClass
*sac
= S390_STATTRIB_GET_CLASS(sas
);
194 long long res
= sac
->get_dirtycount(sas
);
197 *res_precopy_only
+= 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 : qemu_file_rate_limit(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
, 0);
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
)
304 static int qemu_s390_get_active(S390StAttribState
*sa
)
306 return sa
->migration_enabled
;
309 static void qemu_s390_stattrib_class_init(ObjectClass
*oc
, void *data
)
311 S390StAttribClass
*sa_cl
= S390_STATTRIB_CLASS(oc
);
312 DeviceClass
*dc
= DEVICE_CLASS(oc
);
314 sa_cl
->synchronize
= qemu_s390_synchronize_stub
;
315 sa_cl
->get_stattr
= qemu_s390_get_stattr_stub
;
316 sa_cl
->set_stattr
= qemu_s390_peek_stattr_stub
;
317 sa_cl
->peek_stattr
= qemu_s390_peek_stattr_stub
;
318 sa_cl
->set_migrationmode
= qemu_s390_set_migrationmode_stub
;
319 sa_cl
->get_dirtycount
= qemu_s390_get_dirtycount_stub
;
320 sa_cl
->get_active
= qemu_s390_get_active
;
322 /* Reason: Can only be instantiated one time (internally) */
323 dc
->user_creatable
= false;
326 static const TypeInfo qemu_s390_stattrib_info
= {
327 .name
= TYPE_QEMU_S390_STATTRIB
,
328 .parent
= TYPE_S390_STATTRIB
,
329 .instance_init
= qemu_s390_stattrib_instance_init
,
330 .instance_size
= sizeof(QEMUS390StAttribState
),
331 .class_init
= qemu_s390_stattrib_class_init
,
332 .class_size
= sizeof(S390StAttribClass
),
335 /* Generic abstract object: */
337 static void s390_stattrib_realize(DeviceState
*dev
, Error
**errp
)
339 bool ambiguous
= false;
341 object_resolve_path_type("", TYPE_S390_STATTRIB
, &ambiguous
);
343 error_setg(errp
, "storage_attributes device already exists");
347 static void s390_stattrib_class_init(ObjectClass
*oc
, void *data
)
349 DeviceClass
*dc
= DEVICE_CLASS(oc
);
351 dc
->hotpluggable
= false;
352 set_bit(DEVICE_CATEGORY_MISC
, dc
->categories
);
353 dc
->realize
= s390_stattrib_realize
;
356 static inline bool s390_stattrib_get_migration_enabled(Object
*obj
, Error
**e
)
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(NULL
, 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
, NULL
);
391 object_property_set_bool(obj
, true, "migration-enabled", 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
)