Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/SharedDependencies/Sources/libslirp/include/vmstate.h
2 views
1
/* SPDX-License-Identifier: BSD-3-Clause */
2
/*
3
* QEMU migration/snapshot declarations
4
*
5
* Copyright (c) 2009-2011 Red Hat, Inc.
6
*
7
* Original author: Juan Quintela <[email protected]>
8
*
9
* Redistribution and use in source and binary forms, with or without
10
* modification, are permitted provided that the following conditions
11
* are met:
12
*
13
* 1. Redistributions of source code must retain the above
14
* copyright notice, this list of conditions and the following
15
* disclaimer.
16
*
17
* 2. Redistributions in binary form must reproduce the above
18
* copyright notice, this list of conditions and the following
19
* disclaimer in the documentation and/or other materials provided
20
* with the distribution.
21
*
22
* 3. Neither the name of the copyright holder nor the names of its
23
* contributors may be used to endorse or promote products derived
24
* from this software without specific prior written permission.
25
*
26
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
31
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
37
* OF THE POSSIBILITY OF SUCH DAMAGE.
38
*/
39
#ifndef VMSTATE_H_
40
#define VMSTATE_H_
41
42
#include <stdint.h>
43
#include <stdbool.h>
44
#include "slirp.h"
45
#include "stream.h"
46
47
#define stringify(s) tostring(s)
48
#define tostring(s) #s
49
50
typedef struct VMStateInfo VMStateInfo;
51
typedef struct VMStateDescription VMStateDescription;
52
typedef struct VMStateField VMStateField;
53
54
int slirp_vmstate_save_state(SlirpOStream *f, const VMStateDescription *vmsd,
55
void *opaque);
56
int slirp_vmstate_load_state(SlirpIStream *f, const VMStateDescription *vmsd,
57
void *opaque, int version_id);
58
59
/* VMStateInfo allows customized migration of objects that don't fit in
60
* any category in VMStateFlags. Additional information is always passed
61
* into get and put in terms of field and vmdesc parameters. However
62
* these two parameters should only be used in cases when customized
63
* handling is needed, such as QTAILQ. For primitive data types such as
64
* integer, field and vmdesc parameters should be ignored inside get/put.
65
*/
66
struct VMStateInfo {
67
const char *name;
68
int (*get)(SlirpIStream *f, void *pv, size_t size,
69
const VMStateField *field);
70
int (*put)(SlirpOStream *f, void *pv, size_t size,
71
const VMStateField *field);
72
};
73
74
enum VMStateFlags {
75
/* Ignored */
76
VMS_SINGLE = 0x001,
77
78
/* The struct member at opaque + VMStateField.offset is a pointer
79
* to the actual field (e.g. struct a { uint8_t *b;
80
* }). Dereference the pointer before using it as basis for
81
* further pointer arithmetic (see e.g. VMS_ARRAY). Does not
82
* affect the meaning of VMStateField.num_offset or
83
* VMStateField.size_offset; see VMS_VARRAY* and VMS_VBUFFER for
84
* those. */
85
VMS_POINTER = 0x002,
86
87
/* The field is an array of fixed size. VMStateField.num contains
88
* the number of entries in the array. The size of each entry is
89
* given by VMStateField.size and / or opaque +
90
* VMStateField.size_offset; see VMS_VBUFFER and
91
* VMS_MULTIPLY. Each array entry will be processed individually
92
* (VMStateField.info.get()/put() if VMS_STRUCT is not set,
93
* recursion into VMStateField.vmsd if VMS_STRUCT is set). May not
94
* be combined with VMS_VARRAY*. */
95
VMS_ARRAY = 0x004,
96
97
/* The field is itself a struct, containing one or more
98
* fields. Recurse into VMStateField.vmsd. Most useful in
99
* combination with VMS_ARRAY / VMS_VARRAY*, recursing into each
100
* array entry. */
101
VMS_STRUCT = 0x008,
102
103
/* The field is an array of variable size. The int32_t at opaque +
104
* VMStateField.num_offset contains the number of entries in the
105
* array. See the VMS_ARRAY description regarding array handling
106
* in general. May not be combined with VMS_ARRAY or any other
107
* VMS_VARRAY*. */
108
VMS_VARRAY_INT32 = 0x010,
109
110
/* Ignored */
111
VMS_BUFFER = 0x020,
112
113
/* The field is a (fixed-size or variable-size) array of pointers
114
* (e.g. struct a { uint8_t *b[]; }). Dereference each array entry
115
* before using it. Note: Does not imply any one of VMS_ARRAY /
116
* VMS_VARRAY*; these need to be set explicitly. */
117
VMS_ARRAY_OF_POINTER = 0x040,
118
119
/* The field is an array of variable size. The uint16_t at opaque
120
* + VMStateField.num_offset (subject to VMS_MULTIPLY_ELEMENTS)
121
* contains the number of entries in the array. See the VMS_ARRAY
122
* description regarding array handling in general. May not be
123
* combined with VMS_ARRAY or any other VMS_VARRAY*. */
124
VMS_VARRAY_UINT16 = 0x080,
125
126
/* The size of the individual entries (a single array entry if
127
* VMS_ARRAY or any of VMS_VARRAY* are set, or the field itself if
128
* neither is set) is variable (i.e. not known at compile-time),
129
* but the same for all entries. Use the int32_t at opaque +
130
* VMStateField.size_offset (subject to VMS_MULTIPLY) to determine
131
* the size of each (and every) entry. */
132
VMS_VBUFFER = 0x100,
133
134
/* Multiply the entry size given by the int32_t at opaque +
135
* VMStateField.size_offset (see VMS_VBUFFER description) with
136
* VMStateField.size to determine the number of bytes to be
137
* allocated. Only valid in combination with VMS_VBUFFER. */
138
VMS_MULTIPLY = 0x200,
139
140
/* The field is an array of variable size. The uint8_t at opaque +
141
* VMStateField.num_offset (subject to VMS_MULTIPLY_ELEMENTS)
142
* contains the number of entries in the array. See the VMS_ARRAY
143
* description regarding array handling in general. May not be
144
* combined with VMS_ARRAY or any other VMS_VARRAY*. */
145
VMS_VARRAY_UINT8 = 0x400,
146
147
/* The field is an array of variable size. The uint32_t at opaque
148
* + VMStateField.num_offset (subject to VMS_MULTIPLY_ELEMENTS)
149
* contains the number of entries in the array. See the VMS_ARRAY
150
* description regarding array handling in general. May not be
151
* combined with VMS_ARRAY or any other VMS_VARRAY*. */
152
VMS_VARRAY_UINT32 = 0x800,
153
154
/* Fail loading the serialised VM state if this field is missing
155
* from the input. */
156
VMS_MUST_EXIST = 0x1000,
157
158
/* When loading serialised VM state, allocate memory for the
159
* (entire) field. Only valid in combination with
160
* VMS_POINTER. Note: Not all combinations with other flags are
161
* currently supported, e.g. VMS_ALLOC|VMS_ARRAY_OF_POINTER won't
162
* cause the individual entries to be allocated. */
163
VMS_ALLOC = 0x2000,
164
165
/* Multiply the number of entries given by the integer at opaque +
166
* VMStateField.num_offset (see VMS_VARRAY*) with VMStateField.num
167
* to determine the number of entries in the array. Only valid in
168
* combination with one of VMS_VARRAY*. */
169
VMS_MULTIPLY_ELEMENTS = 0x4000,
170
171
/* A structure field that is like VMS_STRUCT, but uses
172
* VMStateField.struct_version_id to tell which version of the
173
* structure we are referencing to use. */
174
VMS_VSTRUCT = 0x8000,
175
176
/* Marker for end of list */
177
VMS_END = 0x10000
178
};
179
180
struct VMStateField {
181
const char *name;
182
size_t offset;
183
size_t size;
184
size_t start;
185
int num;
186
size_t num_offset;
187
size_t size_offset;
188
const VMStateInfo *info;
189
enum VMStateFlags flags;
190
const VMStateDescription *vmsd;
191
int version_id;
192
int struct_version_id;
193
bool (*field_exists)(void *opaque, int version_id);
194
};
195
196
struct VMStateDescription {
197
const char *name;
198
int version_id;
199
int (*pre_load)(void *opaque);
200
int (*post_load)(void *opaque, int version_id);
201
int (*pre_save)(void *opaque);
202
VMStateField *fields;
203
};
204
205
206
extern const VMStateInfo slirp_vmstate_info_int16;
207
extern const VMStateInfo slirp_vmstate_info_int32;
208
extern const VMStateInfo slirp_vmstate_info_uint8;
209
extern const VMStateInfo slirp_vmstate_info_uint16;
210
extern const VMStateInfo slirp_vmstate_info_uint32;
211
212
/** Put this in the stream when migrating a null pointer.*/
213
#define VMS_NULLPTR_MARKER (0x30U) /* '0' */
214
extern const VMStateInfo slirp_vmstate_info_nullptr;
215
216
extern const VMStateInfo slirp_vmstate_info_buffer;
217
extern const VMStateInfo slirp_vmstate_info_tmp;
218
219
#ifdef __GNUC__
220
#define type_check_array(t1, t2, n) ((t1(*)[n])0 - (t2 *)0)
221
#define type_check_pointer(t1, t2) ((t1 **)0 - (t2 *)0)
222
#define typeof_field(type, field) typeof(((type *)0)->field)
223
#define type_check(t1, t2) ((t1 *)0 - (t2 *)0)
224
#else
225
#define type_check_array(t1, t2, n) 0
226
#define type_check_pointer(t1, t2) 0
227
#define typeof_field(type, field) (((type *)0)->field)
228
#define type_check(t1, t2) 0
229
#endif
230
231
#define vmstate_offset_value(_state, _field, _type) \
232
(offsetof(_state, _field) + type_check(_type, typeof_field(_state, _field)))
233
234
#define vmstate_offset_pointer(_state, _field, _type) \
235
(offsetof(_state, _field) + \
236
type_check_pointer(_type, typeof_field(_state, _field)))
237
238
#define vmstate_offset_array(_state, _field, _type, _num) \
239
(offsetof(_state, _field) + \
240
type_check_array(_type, typeof_field(_state, _field), _num))
241
242
#define vmstate_offset_buffer(_state, _field) \
243
vmstate_offset_array(_state, _field, uint8_t, \
244
sizeof(typeof_field(_state, _field)))
245
246
/* In the macros below, if there is a _version, that means the macro's
247
* field will be processed only if the version being received is >=
248
* the _version specified. In general, if you add a new field, you
249
* would increment the structure's version and put that version
250
* number into the new field so it would only be processed with the
251
* new version.
252
*
253
* In particular, for VMSTATE_STRUCT() and friends the _version does
254
* *NOT* pick the version of the sub-structure. It works just as
255
* specified above. The version of the top-level structure received
256
* is passed down to all sub-structures. This means that the
257
* sub-structures must have version that are compatible with all the
258
* structures that use them.
259
*
260
* If you want to specify the version of the sub-structure, use
261
* VMSTATE_VSTRUCT(), which allows the specific sub-structure version
262
* to be directly specified.
263
*/
264
265
#define VMSTATE_SINGLE_TEST(_field, _state, _test, _version, _info, _type) \
266
{ \
267
.name = (stringify(_field)), .version_id = (_version), \
268
.field_exists = (_test), .size = sizeof(_type), .info = &(_info), \
269
.flags = VMS_SINGLE, \
270
.offset = vmstate_offset_value(_state, _field, _type), \
271
}
272
273
#define VMSTATE_ARRAY(_field, _state, _num, _version, _info, _type) \
274
{ \
275
.name = (stringify(_field)), .version_id = (_version), .num = (_num), \
276
.info = &(_info), .size = sizeof(_type), .flags = VMS_ARRAY, \
277
.offset = vmstate_offset_array(_state, _field, _type, _num), \
278
}
279
280
#define VMSTATE_STRUCT_TEST(_field, _state, _test, _version, _vmsd, _type) \
281
{ \
282
.name = (stringify(_field)), .version_id = (_version), \
283
.field_exists = (_test), .vmsd = &(_vmsd), .size = sizeof(_type), \
284
.flags = VMS_STRUCT, \
285
.offset = vmstate_offset_value(_state, _field, _type), \
286
}
287
288
#define VMSTATE_STRUCT_POINTER_V(_field, _state, _version, _vmsd, _type) \
289
{ \
290
.name = (stringify(_field)), .version_id = (_version), \
291
.vmsd = &(_vmsd), .size = sizeof(_type *), \
292
.flags = VMS_STRUCT | VMS_POINTER, \
293
.offset = vmstate_offset_pointer(_state, _field, _type), \
294
}
295
296
#define VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, _test, _version, \
297
_vmsd, _type) \
298
{ \
299
.name = (stringify(_field)), .num = (_num), .field_exists = (_test), \
300
.version_id = (_version), .vmsd = &(_vmsd), .size = sizeof(_type), \
301
.flags = VMS_STRUCT | VMS_ARRAY, \
302
.offset = vmstate_offset_array(_state, _field, _type, _num), \
303
}
304
305
#define VMSTATE_STATIC_BUFFER(_field, _state, _version, _test, _start, _size) \
306
{ \
307
.name = (stringify(_field)), .version_id = (_version), \
308
.field_exists = (_test), .size = (_size - _start), \
309
.info = &slirp_vmstate_info_buffer, .flags = VMS_BUFFER, \
310
.offset = vmstate_offset_buffer(_state, _field) + _start, \
311
}
312
313
#define VMSTATE_VBUFFER_UINT32(_field, _state, _version, _test, _field_size) \
314
{ \
315
.name = (stringify(_field)), .version_id = (_version), \
316
.field_exists = (_test), \
317
.size_offset = vmstate_offset_value(_state, _field_size, uint32_t), \
318
.info = &slirp_vmstate_info_buffer, \
319
.flags = VMS_VBUFFER | VMS_POINTER, \
320
.offset = offsetof(_state, _field), \
321
}
322
323
#define QEMU_BUILD_BUG_ON_STRUCT(x) \
324
struct { \
325
int : (x) ? -1 : 1; \
326
}
327
328
#define QEMU_BUILD_BUG_ON_ZERO(x) \
329
(sizeof(QEMU_BUILD_BUG_ON_STRUCT(x)) - sizeof(QEMU_BUILD_BUG_ON_STRUCT(x)))
330
331
/* Allocate a temporary of type 'tmp_type', set tmp->parent to _state
332
* and execute the vmsd on the temporary. Note that we're working with
333
* the whole of _state here, not a field within it.
334
* We compile time check that:
335
* That _tmp_type contains a 'parent' member that's a pointer to the
336
* '_state' type
337
* That the pointer is right at the start of _tmp_type.
338
*/
339
#define VMSTATE_WITH_TMP(_state, _tmp_type, _vmsd) \
340
{ \
341
.name = "tmp", \
342
.size = sizeof(_tmp_type) + \
343
QEMU_BUILD_BUG_ON_ZERO(offsetof(_tmp_type, parent) != 0) + \
344
type_check_pointer(_state, typeof_field(_tmp_type, parent)), \
345
.vmsd = &(_vmsd), .info = &slirp_vmstate_info_tmp, \
346
}
347
348
#define VMSTATE_SINGLE(_field, _state, _version, _info, _type) \
349
VMSTATE_SINGLE_TEST(_field, _state, NULL, _version, _info, _type)
350
351
#define VMSTATE_STRUCT(_field, _state, _version, _vmsd, _type) \
352
VMSTATE_STRUCT_TEST(_field, _state, NULL, _version, _vmsd, _type)
353
354
#define VMSTATE_STRUCT_POINTER(_field, _state, _vmsd, _type) \
355
VMSTATE_STRUCT_POINTER_V(_field, _state, 0, _vmsd, _type)
356
357
#define VMSTATE_STRUCT_ARRAY(_field, _state, _num, _version, _vmsd, _type) \
358
VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, NULL, _version, _vmsd, \
359
_type)
360
361
#define VMSTATE_INT16_V(_f, _s, _v) \
362
VMSTATE_SINGLE(_f, _s, _v, slirp_vmstate_info_int16, int16_t)
363
#define VMSTATE_INT32_V(_f, _s, _v) \
364
VMSTATE_SINGLE(_f, _s, _v, slirp_vmstate_info_int32, int32_t)
365
366
#define VMSTATE_UINT8_V(_f, _s, _v) \
367
VMSTATE_SINGLE(_f, _s, _v, slirp_vmstate_info_uint8, uint8_t)
368
#define VMSTATE_UINT16_V(_f, _s, _v) \
369
VMSTATE_SINGLE(_f, _s, _v, slirp_vmstate_info_uint16, uint16_t)
370
#define VMSTATE_UINT32_V(_f, _s, _v) \
371
VMSTATE_SINGLE(_f, _s, _v, slirp_vmstate_info_uint32, uint32_t)
372
373
#define VMSTATE_INT16(_f, _s) VMSTATE_INT16_V(_f, _s, 0)
374
#define VMSTATE_INT32(_f, _s) VMSTATE_INT32_V(_f, _s, 0)
375
376
#define VMSTATE_UINT8(_f, _s) VMSTATE_UINT8_V(_f, _s, 0)
377
#define VMSTATE_UINT16(_f, _s) VMSTATE_UINT16_V(_f, _s, 0)
378
#define VMSTATE_UINT32(_f, _s) VMSTATE_UINT32_V(_f, _s, 0)
379
380
#define VMSTATE_UINT16_TEST(_f, _s, _t) \
381
VMSTATE_SINGLE_TEST(_f, _s, _t, 0, slirp_vmstate_info_uint16, uint16_t)
382
383
#define VMSTATE_UINT32_TEST(_f, _s, _t) \
384
VMSTATE_SINGLE_TEST(_f, _s, _t, 0, slirp_vmstate_info_uint32, uint32_t)
385
386
#define VMSTATE_INT16_ARRAY_V(_f, _s, _n, _v) \
387
VMSTATE_ARRAY(_f, _s, _n, _v, slirp_vmstate_info_int16, int16_t)
388
389
#define VMSTATE_INT16_ARRAY(_f, _s, _n) VMSTATE_INT16_ARRAY_V(_f, _s, _n, 0)
390
391
#define VMSTATE_BUFFER_V(_f, _s, _v) \
392
VMSTATE_STATIC_BUFFER(_f, _s, _v, NULL, 0, sizeof(typeof_field(_s, _f)))
393
394
#define VMSTATE_BUFFER(_f, _s) VMSTATE_BUFFER_V(_f, _s, 0)
395
396
#define VMSTATE_END_OF_LIST() \
397
{ \
398
.flags = VMS_END, \
399
}
400
401
#endif /* VMSTATE_H_ */
402
403