31
32
typedef struct VMStateInfo VMStateInfo;
33
typedef struct VMStateField VMStateField;
34
+typedef struct VMStateStructMember VMStateStructMember;
35
36
/*
37
* VMStateInfo allows customized migration of objects that don't fit in
68
* to the actual field (e.g. struct a { uint8_t *b;
69
* }). Dereference the pointer before using it as basis for
70
* further pointer arithmetic (see e.g. VMS_ARRAY). Does not
70
- * affect the meaning of VMStateField.num_offset or
71
- * VMStateField.size_offset; see VMS_VARRAY* and VMS_VBUFFER for
71
+ * affect the meaning of VMStateField.num_indirect or
72
+ * VMStateField.size_indirect; see VMS_VARRAY* and VMS_VBUFFER for
73
* those. */
74
VMS_POINTER = 0x002,
75
76
/* The field is an array of fixed size. VMStateField.num contains
77
* the number of entries in the array. The size of each entry is
78
* given by VMStateField.size and / or opaque +
78
- * VMStateField.size_offset; see VMS_VBUFFER and
79
+ * VMStateField.size_indirect; see VMS_VBUFFER and
80
* VMS_MULTIPLY. Each array entry will be processed individually
81
* (VMStateField.info.get()/put() if VMS_STRUCT is not set,
82
* recursion into VMStateField.vmsd if VMS_STRUCT is set). May not
89
* array entry. */
90
VMS_STRUCT = 0x008,
91
91
- /* The field is an array of variable size. The int32_t at opaque +
92
- * VMStateField.num_offset contains the number of entries in the
92
+ /*
93
+ * The field is an array of variable size. The integer at opaque +
94
+ * VMStateField.num_indirect contains the number of entries in the
95
* array. See the VMS_ARRAY description regarding array handling
96
* in general. May not be combined with VMS_ARRAY or any other
97
* VMS_VARRAY*. */
107
VMS_ARRAY_OF_POINTER = 0x040,
108
109
/* The field is an array of variable size. The uint16_t at opaque
108
- * + VMStateField.num_offset
110
+ * + VMStateField.num_indirect
111
* contains the number of entries in the array. See the VMS_ARRAY
112
* description regarding array handling in general. May not be
113
* combined with VMS_ARRAY or any other VMS_VARRAY*. */
116
/* The size of the individual entries (a single array entry if
117
* VMS_ARRAY or any of VMS_VARRAY* are set, or the field itself if
118
* neither is set) is variable (i.e. not known at compile-time),
117
- * but the same for all entries. Use the int32_t at opaque +
118
- * VMStateField.size_offset (subject to VMS_MULTIPLY) to determine
119
+ * but the same for all entries. Use the integer at opaque +
120
+ * VMStateField.size_indirect (subject to VMS_MULTIPLY) to determine
121
* the size of each (and every) entry. */
122
VMS_VBUFFER = 0x100,
123
122
- /* Multiply the entry size given by the int32_t at opaque +
123
- * VMStateField.size_offset (see VMS_VBUFFER description) with
124
+ /*
125
+ * Multiply the entry size given by the integer at opaque +
126
+ * VMStateField.size_indirect (see VMS_VBUFFER description) with
127
* VMStateField.size to determine the number of bytes to be
128
* allocated. Only valid in combination with VMS_VBUFFER. */
129
VMS_MULTIPLY = 0x200,
130
131
/* The field is an array of variable size. The uint8_t at opaque +
129
- * VMStateField.num_offset
132
+ * VMStateField.num_indirect
133
* contains the number of entries in the array. See the VMS_ARRAY
134
* description regarding array handling in general. May not be
135
* combined with VMS_ARRAY or any other VMS_VARRAY*. */
136
VMS_VARRAY_UINT8 = 0x400,
137
138
/* The field is an array of variable size. The uint32_t at opaque
136
- * + VMStateField.num_offset
139
+ * + VMStateField.num_indirect
140
* contains the number of entries in the array. See the VMS_ARRAY
141
* description regarding array handling in general. May not be
142
* combined with VMS_ARRAY or any other VMS_VARRAY*. */
190
MIG_PRI_MAX,
191
} MigrationPriority;
192
193
+
194
+/*
195
+ * VMStateStructMember: Metadata about a single member of the struct
196
+ * being migrated by the vmstate. This is kept separate from
197
+ * VMStateField because a single VMStateField can reference other
198
+ * members of the struct aside from the main struct member that's
199
+ * being migrated.
200
+ *
201
+ * One situation where extra fields are referenced is the common case
202
+ * of a struct containing an array or buffer, the size of which is
203
+ * stored in another member of the same struct.
204
+ *
205
+ * Example 1:
206
+ * struct IDEState {
207
+ * ...
208
+ * uint8_t *io_buffer;
209
+ * int32_t io_buffer_total_len;
210
+ * ...
211
+ * }
212
+ * VMSTATE_VARRAY_INT32(io_buffer, IDEState, io_buffer_total_len, 1,
213
+ * vmstate_info_uint8, uint8_t)
214
+ *
215
+ * In the above, io_buffer is the main field being migrated by the
216
+ * VMSTATE_VARRAY while io_buffer_total_len is the meta field that
217
+ * provides the size of the io_buffer. In this particular case,
218
+ * io_buffer_total_len is never migrated.
219
+ *
220
+ * Example 2:
221
+ * struct SpaprMachineState {
222
+ * ...
223
+ * uint32_t fdt_size;
224
+ * void *fdt_blob;
225
+ * ...
226
+ * }
227
+ * VMSTATE_UINT32(fdt_size, SpaprMachineState),
228
+ * VMSTATE_VBUFFER_ALLOC_UINT32(fdt_blob, SpaprMachineState, 0, NULL, fdt_size),
229
+ *
230
+ * Here, fdt_blob is the field being migrated by VMSTATE_VBUFFER_ALLOC
231
+ * and fdt_size is the meta field providing the size. In this case,
232
+ * the extra field is also independently migrated by the
233
+ * VMSTATE_UINT32 above.
234
+ */
235
+struct VMStateStructMember {
236
+ /* offsetof the field inside the migrated struct */
237
+ uint32_t offset;
238
+ /* size of field itself */
239
+ uint8_t size;
240
+};
241
+
242
struct VMStateField {
243
const char *name;
244
size_t offset;
245
246
/*
195
- * @size or @size_offset specifies the size of the element embeded in
196
- * the field. Only one of them should be present never both. When
197
- * @size_offset is used together with VMS_VBUFFER, it means the size is
198
- * dynamic calculated instead of a constant.
247
+ * @size directly specifies the size of the element being
248
+ * migrated.
249
+ *
250
+ * @size_indirect specifies the offset inside a struct where the
251
+ * size of the element is stored.
252
+ *
253
+ * Only one of the above should be present (except for
254
+ * VMSTATE_MULTIPLY which uses .size as a multiplier). When
255
+ * @size_indirect is used together with VMS_VBUFFER, it means
256
+ * the size is dynamic calculated instead of a constant.
257
+ *
258
+ * When the field is an array of any type, these refer to the size
259
+ * of one element of the array.
260
*
200
- * When the field is an array of any type, this stores the size of one
201
- * element of the array.
261
+ * NOTE: even if VMS_POINTER or VMS_ARRAY_OF_POINTER may be
262
+ * specified, these parameters always reflect the real size of the
263
+ * objects that a pointer point to.
264
*
203
- * NOTE: even if VMS_POINTER or VMS_ARRAY_OF_POINTER may be specified,
204
- * this parameter always reflects the real size of the objects that a
205
- * pointer point to.
265
+ * @num_indirect specifies the offset inside a struct where the
266
+ * number of elements of an array is stored.
267
*/
268
size_t size;
208
- size_t size_offset;
269
+ VMStateStructMember size_indirect;
270
+ VMStateStructMember num_indirect;
271
272
size_t start;
273
int num;
212
- size_t num_offset;
274
+
275
const VMStateInfo *info;
276
enum VMStateFlags flags;
277
const VMStateDescription *vmsd;
390
(type_check(t1, typeof_elt_of_field(t2, f)) \
391
+ QEMU_BUILD_BUG_ON_ZERO(!QEMU_IS_ARRAY(((t2 *)0)->f)))
392
393
+#define type_check_int64(t) \
394
+ (~((t)0) * sizeof(struct { \
395
+ QEMU_BUILD_BUG_ON(sizeof(t) > sizeof(uint64_t)); \
396
+ }))
397
+
398
+#define vmstate_field_offset(_state, _field) { \
399
+ .offset = (offsetof(_state, _field) + \
400
+ type_check_int64(typeof_field(_state, _field))), \
401
+ .size = sizeof(typeof_field(_state, _field)), \
402
+}
403
+
404
#define vmstate_offset_value(_state, _field, _type) \
405
(offsetof(_state, _field) + \
406
type_check(_type, typeof_field(_state, _field)))
527
#define VMSTATE_VARRAY_INT32(_field, _state, _field_num, _version, _info, _type) {\
528
.name = (stringify(_field)), \
529
.version_id = (_version), \
457
- .num_offset = vmstate_offset_value(_state, _field_num, int32_t), \
530
+ .num_indirect = vmstate_field_offset(_state, _field_num), \
531
.info = &(_info), \
532
.size = sizeof(_type), \
533
.flags = VMS_VARRAY_INT32|VMS_POINTER, \
537
#define VMSTATE_VARRAY_UINT32(_field, _state, _field_num, _version, _info, _type) {\
538
.name = (stringify(_field)), \
539
.version_id = (_version), \
467
- .num_offset = vmstate_offset_value(_state, _field_num, uint32_t),\
540
+ .num_indirect = vmstate_field_offset(_state, _field_num), \
541
.info = &(_info), \
542
.size = sizeof(_type), \
543
.flags = VMS_VARRAY_UINT32|VMS_POINTER, \
547
#define VMSTATE_VARRAY_INT32_ALLOC(_field, _state, _field_num, _version, _info, _type) {\
548
.name = (stringify(_field)), \
549
.version_id = (_version), \
477
- .num_offset = vmstate_offset_value(_state, _field_num, int32_t), \
550
+ .num_indirect = vmstate_field_offset(_state, _field_num), \
551
.info = &(_info), \
552
.size = sizeof(_type), \
553
.flags = VMS_VARRAY_INT32 | VMS_POINTER | VMS_ALLOC, \
557
#define VMSTATE_VARRAY_UINT32_ALLOC(_field, _state, _field_num, _version, _info, _type) {\
558
.name = (stringify(_field)), \
559
.version_id = (_version), \
487
- .num_offset = vmstate_offset_value(_state, _field_num, uint32_t),\
560
+ .num_indirect = vmstate_field_offset(_state, _field_num), \
561
.info = &(_info), \
562
.size = sizeof(_type), \
563
.flags = VMS_VARRAY_UINT32|VMS_POINTER|VMS_ALLOC, \
567
#define VMSTATE_VARRAY_UINT16_ALLOC(_field, _state, _field_num, _version, _info, _type) {\
568
.name = (stringify(_field)), \
569
.version_id = (_version), \
497
- .num_offset = vmstate_offset_value(_state, _field_num, uint16_t),\
570
+ .num_indirect = vmstate_field_offset(_state, _field_num), \
571
.info = &(_info), \
572
.size = sizeof(_type), \
573
.flags = VMS_VARRAY_UINT16 | VMS_POINTER | VMS_ALLOC, \
577
#define VMSTATE_VARRAY_UINT16_UNSAFE(_field, _state, _field_num, _version, _info, _type) {\
578
.name = (stringify(_field)), \
579
.version_id = (_version), \
507
- .num_offset = vmstate_offset_value(_state, _field_num, uint16_t),\
580
+ .num_indirect = vmstate_field_offset(_state, _field_num), \
581
.info = &(_info), \
582
.size = sizeof(_type), \
583
.flags = VMS_VARRAY_UINT16, \
656
_field, _state, _field_num, _version, _vmsd, _type) { \
657
.name = (stringify(_field)), \
658
.version_id = (_version), \
586
- .num_offset = vmstate_offset_value(_state, _field_num, uint8_t), \
659
+ .num_indirect = vmstate_field_offset(_state, _field_num), \
660
.vmsd = &(_vmsd), \
661
.size = sizeof(_type), \
662
.flags = VMS_POINTER | VMS_VARRAY_UINT8 | \
669
_field, _state, _field_num, _version, _vmsd, _type) { \
670
.name = (stringify(_field)), \
671
.version_id = (_version), \
599
- .num_offset = vmstate_offset_value(_state, _field_num, uint32_t), \
672
+ .num_indirect = vmstate_field_offset(_state, _field_num), \
673
.vmsd = &(_vmsd), \
674
.size = sizeof(_type), \
675
.flags = VMS_POINTER | VMS_VARRAY_UINT32 | \
681
#define VMSTATE_VARRAY_OF_POINTER_UINT32(_field, _state, _field_num, _version, _info, _type) { \
682
.name = (stringify(_field)), \
683
.version_id = (_version), \
611
- .num_offset = vmstate_offset_value(_state, _field_num, uint32_t), \
684
+ .num_indirect = vmstate_field_offset(_state, _field_num), \
685
.info = &(_info), \
686
.flags = VMS_VARRAY_UINT32 | VMS_ARRAY_OF_POINTER | VMS_POINTER, \
687
.offset = vmstate_offset_pointer(_state, _field, _type *), \
723
724
#define VMSTATE_STRUCT_VARRAY_UINT8(_field, _state, _field_num, _version, _vmsd, _type) { \
725
.name = (stringify(_field)), \
653
- .num_offset = vmstate_offset_value(_state, _field_num, uint8_t), \
726
+ .num_indirect = vmstate_field_offset(_state, _field_num), \
727
.version_id = (_version), \
728
.vmsd = &(_vmsd), \
729
.size = sizeof(_type), \
747
#define VMSTATE_STRUCT_VARRAY_POINTER_INT32(_field, _state, _field_num, _vmsd, _type) { \
748
.name = (stringify(_field)), \
749
.version_id = 0, \
677
- .num_offset = vmstate_offset_value(_state, _field_num, int32_t), \
750
+ .num_indirect = vmstate_field_offset(_state, _field_num), \
751
.size = sizeof(_type), \
752
.vmsd = &(_vmsd), \
753
.flags = VMS_POINTER | VMS_VARRAY_INT32 | VMS_STRUCT, \
757
#define VMSTATE_STRUCT_VARRAY_POINTER_UINT32(_field, _state, _field_num, _vmsd, _type) { \
758
.name = (stringify(_field)), \
759
.version_id = 0, \
687
- .num_offset = vmstate_offset_value(_state, _field_num, uint32_t),\
760
+ .num_indirect = vmstate_field_offset(_state, _field_num), \
761
.size = sizeof(_type), \
762
.vmsd = &(_vmsd), \
763
.flags = VMS_POINTER | VMS_VARRAY_INT32 | VMS_STRUCT, \
767
#define VMSTATE_STRUCT_VARRAY_POINTER_UINT16(_field, _state, _field_num, _vmsd, _type) { \
768
.name = (stringify(_field)), \
769
.version_id = 0, \
697
- .num_offset = vmstate_offset_value(_state, _field_num, uint16_t),\
770
+ .num_indirect = vmstate_field_offset(_state, _field_num), \
771
.size = sizeof(_type), \
772
.vmsd = &(_vmsd), \
773
.flags = VMS_POINTER | VMS_VARRAY_UINT16 | VMS_STRUCT, \
776
777
#define VMSTATE_STRUCT_VARRAY_UINT32(_field, _state, _field_num, _version, _vmsd, _type) { \
778
.name = (stringify(_field)), \
706
- .num_offset = vmstate_offset_value(_state, _field_num, uint32_t), \
779
+ .num_indirect = vmstate_field_offset(_state, _field_num), \
780
.version_id = (_version), \
781
.vmsd = &(_vmsd), \
782
.size = sizeof(_type), \
788
.name = (stringify(_field)), \
789
.version_id = (_version), \
790
.vmsd = &(_vmsd), \
718
- .num_offset = vmstate_offset_value(_state, _field_num, int32_t), \
791
+ .num_indirect = vmstate_field_offset(_state, _field_num), \
792
.size = sizeof(_type), \
793
.flags = VMS_STRUCT|VMS_VARRAY_INT32|VMS_ALLOC|VMS_POINTER, \
794
.offset = vmstate_offset_pointer(_state, _field, _type), \
809
.name = (stringify(_field)), \
810
.version_id = (_version), \
811
.field_exists = (_test), \
739
- .size_offset = vmstate_offset_value(_state, _field_size, uint32_t),\
812
+ .size_indirect = vmstate_field_offset(_state, _field_size), \
813
.size = (_multiply), \
814
.info = &vmstate_info_buffer, \
815
.flags = VMS_VBUFFER|VMS_POINTER|VMS_MULTIPLY, \
820
.name = (stringify(_field)), \
821
.version_id = (_version), \
822
.field_exists = (_test), \
750
- .size_offset = vmstate_offset_value(_state, _field_size, int32_t),\
823
+ .size_indirect = vmstate_field_offset(_state, _field_size), \
824
.info = &vmstate_info_buffer, \
825
.flags = VMS_VBUFFER|VMS_POINTER, \
826
.offset = offsetof(_state, _field), \
830
.name = (stringify(_field)), \
831
.version_id = (_version), \
832
.field_exists = (_test), \
760
- .size_offset = vmstate_offset_value(_state, _field_size, uint32_t),\
833
+ .size_indirect = vmstate_field_offset(_state, _field_size), \
834
.info = &vmstate_info_buffer, \
835
.flags = VMS_VBUFFER|VMS_POINTER, \
836
.offset = offsetof(_state, _field), \
840
.name = (stringify(_field)), \
841
.version_id = (_version), \
842
.field_exists = (_test), \
770
- .size_offset = vmstate_offset_value(_state, _field_size, uint64_t),\
843
+ .size_indirect = vmstate_field_offset(_state, _field_size), \
844
.info = &vmstate_info_buffer, \
845
.flags = VMS_VBUFFER | VMS_POINTER, \
846
.offset = offsetof(_state, _field), \
851
.name = (stringify(_field)), \
852
.version_id = (_version), \
853
.field_exists = (_test), \
781
- .size_offset = vmstate_offset_value(_state, _field_size, uint32_t),\
854
+ .size_indirect = vmstate_field_offset(_state, _field_size), \
855
.info = &vmstate_info_buffer, \
856
.flags = VMS_VBUFFER|VMS_POINTER|VMS_ALLOC, \
857
.offset = offsetof(_state, _field), \
911
#define VMSTATE_UNUSED_VARRAY_UINT32(_state, _test, _version, _field_num, _size) {\
912
.name = "unused", \
913
.field_exists = (_test), \
841
- .num_offset = vmstate_offset_value(_state, _field_num, uint32_t),\
914
+ .num_indirect = vmstate_field_offset(_state, _field_num), \
915
.version_id = (_version), \
916
.size = (_size), \
917
.info = &vmstate_info_unused_buffer, \
925
.name = (stringify(_field)), \
926
.field_exists = (_test), \
927
.version_id = (_version), \
855
- .size_offset = vmstate_offset_value(_state, _field_size, int32_t),\
928
+ .size_indirect = vmstate_field_offset(_state, _field_size), \
929
.info = &vmstate_info_bitmap, \
930
.flags = VMS_VBUFFER|VMS_POINTER, \
931
.offset = offsetof(_state, _field), \