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 <quintela@redhat.com> 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 <unistd.h> 43 #include <stdint.h> 44 #include <stdbool.h> 45 #include "slirp.h" 46 #include "stream.h" 47 48 #define stringify(s) tostring(s) 49 #define tostring(s) #s 50 51 typedef struct VMStateInfo VMStateInfo; 52 typedef struct VMStateDescription VMStateDescription; 53 typedef struct VMStateField VMStateField; 54 55 int slirp_vmstate_save_state(SlirpOStream *f, const VMStateDescription *vmsd, 56 void *opaque); 57 int slirp_vmstate_load_state(SlirpIStream *f, const VMStateDescription *vmsd, 58 void *opaque, int version_id); 59 60 /* VMStateInfo allows customized migration of objects that don't fit in 61 * any category in VMStateFlags. Additional information is always passed 62 * into get and put in terms of field and vmdesc parameters. However 63 * these two parameters should only be used in cases when customized 64 * handling is needed, such as QTAILQ. For primitive data types such as 65 * integer, field and vmdesc parameters should be ignored inside get/put. 66 */ 67 struct VMStateInfo { 68 const char *name; 69 int (*get)(SlirpIStream *f, void *pv, size_t size, 70 const VMStateField *field); 71 int (*put)(SlirpOStream *f, void *pv, size_t size, 72 const VMStateField *field); 73 }; 74 75 enum VMStateFlags { 76 /* Ignored */ 77 VMS_SINGLE = 0x001, 78 79 /* The struct member at opaque + VMStateField.offset is a pointer 80 * to the actual field (e.g. struct a { uint8_t *b; 81 * }). Dereference the pointer before using it as basis for 82 * further pointer arithmetic (see e.g. VMS_ARRAY). Does not 83 * affect the meaning of VMStateField.num_offset or 84 * VMStateField.size_offset; see VMS_VARRAY* and VMS_VBUFFER for 85 * those. */ 86 VMS_POINTER = 0x002, 87 88 /* The field is an array of fixed size. VMStateField.num contains 89 * the number of entries in the array. The size of each entry is 90 * given by VMStateField.size and / or opaque + 91 * VMStateField.size_offset; see VMS_VBUFFER and 92 * VMS_MULTIPLY. Each array entry will be processed individually 93 * (VMStateField.info.get()/put() if VMS_STRUCT is not set, 94 * recursion into VMStateField.vmsd if VMS_STRUCT is set). May not 95 * be combined with VMS_VARRAY*. */ 96 VMS_ARRAY = 0x004, 97 98 /* The field is itself a struct, containing one or more 99 * fields. Recurse into VMStateField.vmsd. Most useful in 100 * combination with VMS_ARRAY / VMS_VARRAY*, recursing into each 101 * array entry. */ 102 VMS_STRUCT = 0x008, 103 104 /* The field is an array of variable size. The int32_t at opaque + 105 * VMStateField.num_offset contains the number of entries in the 106 * array. See the VMS_ARRAY description regarding array handling 107 * in general. May not be combined with VMS_ARRAY or any other 108 * VMS_VARRAY*. */ 109 VMS_VARRAY_INT32 = 0x010, 110 111 /* Ignored */ 112 VMS_BUFFER = 0x020, 113 114 /* The field is a (fixed-size or variable-size) array of pointers 115 * (e.g. struct a { uint8_t *b[]; }). Dereference each array entry 116 * before using it. Note: Does not imply any one of VMS_ARRAY / 117 * VMS_VARRAY*; these need to be set explicitly. */ 118 VMS_ARRAY_OF_POINTER = 0x040, 119 120 /* The field is an array of variable size. The uint16_t at opaque 121 * + VMStateField.num_offset (subject to VMS_MULTIPLY_ELEMENTS) 122 * contains the number of entries in the array. See the VMS_ARRAY 123 * description regarding array handling in general. May not be 124 * combined with VMS_ARRAY or any other VMS_VARRAY*. */ 125 VMS_VARRAY_UINT16 = 0x080, 126 127 /* The size of the individual entries (a single array entry if 128 * VMS_ARRAY or any of VMS_VARRAY* are set, or the field itself if 129 * neither is set) is variable (i.e. not known at compile-time), 130 * but the same for all entries. Use the int32_t at opaque + 131 * VMStateField.size_offset (subject to VMS_MULTIPLY) to determine 132 * the size of each (and every) entry. */ 133 VMS_VBUFFER = 0x100, 134 135 /* Multiply the entry size given by the int32_t at opaque + 136 * VMStateField.size_offset (see VMS_VBUFFER description) with 137 * VMStateField.size to determine the number of bytes to be 138 * allocated. Only valid in combination with VMS_VBUFFER. */ 139 VMS_MULTIPLY = 0x200, 140 141 /* The field is an array of variable size. The uint8_t at opaque + 142 * VMStateField.num_offset (subject to VMS_MULTIPLY_ELEMENTS) 143 * contains the number of entries in the array. See the VMS_ARRAY 144 * description regarding array handling in general. May not be 145 * combined with VMS_ARRAY or any other VMS_VARRAY*. */ 146 VMS_VARRAY_UINT8 = 0x400, 147 148 /* The field is an array of variable size. The uint32_t at opaque 149 * + VMStateField.num_offset (subject to VMS_MULTIPLY_ELEMENTS) 150 * contains the number of entries in the array. See the VMS_ARRAY 151 * description regarding array handling in general. May not be 152 * combined with VMS_ARRAY or any other VMS_VARRAY*. */ 153 VMS_VARRAY_UINT32 = 0x800, 154 155 /* Fail loading the serialised VM state if this field is missing 156 * from the input. */ 157 VMS_MUST_EXIST = 0x1000, 158 159 /* When loading serialised VM state, allocate memory for the 160 * (entire) field. Only valid in combination with 161 * VMS_POINTER. Note: Not all combinations with other flags are 162 * currently supported, e.g. VMS_ALLOC|VMS_ARRAY_OF_POINTER won't 163 * cause the individual entries to be allocated. */ 164 VMS_ALLOC = 0x2000, 165 166 /* Multiply the number of entries given by the integer at opaque + 167 * VMStateField.num_offset (see VMS_VARRAY*) with VMStateField.num 168 * to determine the number of entries in the array. Only valid in 169 * combination with one of VMS_VARRAY*. */ 170 VMS_MULTIPLY_ELEMENTS = 0x4000, 171 172 /* A structure field that is like VMS_STRUCT, but uses 173 * VMStateField.struct_version_id to tell which version of the 174 * structure we are referencing to use. */ 175 VMS_VSTRUCT = 0x8000, 176 }; 177 178 struct VMStateField { 179 const char *name; 180 size_t offset; 181 size_t size; 182 size_t start; 183 int num; 184 size_t num_offset; 185 size_t size_offset; 186 const VMStateInfo *info; 187 enum VMStateFlags flags; 188 const VMStateDescription *vmsd; 189 int version_id; 190 int struct_version_id; 191 bool (*field_exists)(void *opaque, int version_id); 192 }; 193 194 struct VMStateDescription { 195 const char *name; 196 int version_id; 197 int (*pre_load)(void *opaque); 198 int (*post_load)(void *opaque, int version_id); 199 int (*pre_save)(void *opaque); 200 VMStateField *fields; 201 }; 202 203 204 extern const VMStateInfo slirp_vmstate_info_int16; 205 extern const VMStateInfo slirp_vmstate_info_int32; 206 extern const VMStateInfo slirp_vmstate_info_uint8; 207 extern const VMStateInfo slirp_vmstate_info_uint16; 208 extern const VMStateInfo slirp_vmstate_info_uint32; 209 210 /** Put this in the stream when migrating a null pointer.*/ 211 #define VMS_NULLPTR_MARKER (0x30U) /* '0' */ 212 extern const VMStateInfo slirp_vmstate_info_nullptr; 213 214 extern const VMStateInfo slirp_vmstate_info_buffer; 215 extern const VMStateInfo slirp_vmstate_info_tmp; 216 217 #define type_check_array(t1, t2, n) ((t1(*)[n])0 - (t2 *)0) 218 #define type_check_pointer(t1, t2) ((t1 **)0 - (t2 *)0) 219 #define typeof_field(type, field) typeof(((type *)0)->field) 220 #define type_check(t1, t2) ((t1 *)0 - (t2 *)0) 221 222 #define vmstate_offset_value(_state, _field, _type) \ 223 (offsetof(_state, _field) + type_check(_type, typeof_field(_state, _field))) 224 225 #define vmstate_offset_pointer(_state, _field, _type) \ 226 (offsetof(_state, _field) + \ 227 type_check_pointer(_type, typeof_field(_state, _field))) 228 229 #define vmstate_offset_array(_state, _field, _type, _num) \ 230 (offsetof(_state, _field) + \ 231 type_check_array(_type, typeof_field(_state, _field), _num)) 232 233 #define vmstate_offset_buffer(_state, _field) \ 234 vmstate_offset_array(_state, _field, uint8_t, \ 235 sizeof(typeof_field(_state, _field))) 236 237 /* In the macros below, if there is a _version, that means the macro's 238 * field will be processed only if the version being received is >= 239 * the _version specified. In general, if you add a new field, you 240 * would increment the structure's version and put that version 241 * number into the new field so it would only be processed with the 242 * new version. 243 * 244 * In particular, for VMSTATE_STRUCT() and friends the _version does 245 * *NOT* pick the version of the sub-structure. It works just as 246 * specified above. The version of the top-level structure received 247 * is passed down to all sub-structures. This means that the 248 * sub-structures must have version that are compatible with all the 249 * structures that use them. 250 * 251 * If you want to specify the version of the sub-structure, use 252 * VMSTATE_VSTRUCT(), which allows the specific sub-structure version 253 * to be directly specified. 254 */ 255 256 #define VMSTATE_SINGLE_TEST(_field, _state, _test, _version, _info, _type) \ 257 { \ 258 .name = (stringify(_field)), .version_id = (_version), \ 259 .field_exists = (_test), .size = sizeof(_type), .info = &(_info), \ 260 .flags = VMS_SINGLE, \ 261 .offset = vmstate_offset_value(_state, _field, _type), \ 262 } 263 264 #define VMSTATE_ARRAY(_field, _state, _num, _version, _info, _type) \ 265 { \ 266 .name = (stringify(_field)), .version_id = (_version), .num = (_num), \ 267 .info = &(_info), .size = sizeof(_type), .flags = VMS_ARRAY, \ 268 .offset = vmstate_offset_array(_state, _field, _type, _num), \ 269 } 270 271 #define VMSTATE_STRUCT_TEST(_field, _state, _test, _version, _vmsd, _type) \ 272 { \ 273 .name = (stringify(_field)), .version_id = (_version), \ 274 .field_exists = (_test), .vmsd = &(_vmsd), .size = sizeof(_type), \ 275 .flags = VMS_STRUCT, \ 276 .offset = vmstate_offset_value(_state, _field, _type), \ 277 } 278 279 #define VMSTATE_STRUCT_POINTER_V(_field, _state, _version, _vmsd, _type) \ 280 { \ 281 .name = (stringify(_field)), .version_id = (_version), \ 282 .vmsd = &(_vmsd), .size = sizeof(_type *), \ 283 .flags = VMS_STRUCT | VMS_POINTER, \ 284 .offset = vmstate_offset_pointer(_state, _field, _type), \ 285 } 286 287 #define VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, _test, _version, \ 288 _vmsd, _type) \ 289 { \ 290 .name = (stringify(_field)), .num = (_num), .field_exists = (_test), \ 291 .version_id = (_version), .vmsd = &(_vmsd), .size = sizeof(_type), \ 292 .flags = VMS_STRUCT | VMS_ARRAY, \ 293 .offset = vmstate_offset_array(_state, _field, _type, _num), \ 294 } 295 296 #define VMSTATE_STATIC_BUFFER(_field, _state, _version, _test, _start, _size) \ 297 { \ 298 .name = (stringify(_field)), .version_id = (_version), \ 299 .field_exists = (_test), .size = (_size - _start), \ 300 .info = &slirp_vmstate_info_buffer, .flags = VMS_BUFFER, \ 301 .offset = vmstate_offset_buffer(_state, _field) + _start, \ 302 } 303 304 #define VMSTATE_VBUFFER_UINT32(_field, _state, _version, _test, _field_size) \ 305 { \ 306 .name = (stringify(_field)), .version_id = (_version), \ 307 .field_exists = (_test), \ 308 .size_offset = vmstate_offset_value(_state, _field_size, uint32_t), \ 309 .info = &slirp_vmstate_info_buffer, \ 310 .flags = VMS_VBUFFER | VMS_POINTER, \ 311 .offset = offsetof(_state, _field), \ 312 } 313 314 #define QEMU_BUILD_BUG_ON_STRUCT(x) \ 315 struct { \ 316 int : (x) ? -1 : 1; \ 317 } 318 319 #define QEMU_BUILD_BUG_ON_ZERO(x) \ 320 (sizeof(QEMU_BUILD_BUG_ON_STRUCT(x)) - sizeof(QEMU_BUILD_BUG_ON_STRUCT(x))) 321 322 /* Allocate a temporary of type 'tmp_type', set tmp->parent to _state 323 * and execute the vmsd on the temporary. Note that we're working with 324 * the whole of _state here, not a field within it. 325 * We compile time check that: 326 * That _tmp_type contains a 'parent' member that's a pointer to the 327 * '_state' type 328 * That the pointer is right at the start of _tmp_type. 329 */ 330 #define VMSTATE_WITH_TMP(_state, _tmp_type, _vmsd) \ 331 { \ 332 .name = "tmp", \ 333 .size = sizeof(_tmp_type) + \ 334 QEMU_BUILD_BUG_ON_ZERO(offsetof(_tmp_type, parent) != 0) + \ 335 type_check_pointer(_state, typeof_field(_tmp_type, parent)), \ 336 .vmsd = &(_vmsd), .info = &slirp_vmstate_info_tmp, \ 337 } 338 339 #define VMSTATE_SINGLE(_field, _state, _version, _info, _type) \ 340 VMSTATE_SINGLE_TEST(_field, _state, NULL, _version, _info, _type) 341 342 #define VMSTATE_STRUCT(_field, _state, _version, _vmsd, _type) \ 343 VMSTATE_STRUCT_TEST(_field, _state, NULL, _version, _vmsd, _type) 344 345 #define VMSTATE_STRUCT_POINTER(_field, _state, _vmsd, _type) \ 346 VMSTATE_STRUCT_POINTER_V(_field, _state, 0, _vmsd, _type) 347 348 #define VMSTATE_STRUCT_ARRAY(_field, _state, _num, _version, _vmsd, _type) \ 349 VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, NULL, _version, _vmsd, \ 350 _type) 351 352 #define VMSTATE_INT16_V(_f, _s, _v) \ 353 VMSTATE_SINGLE(_f, _s, _v, slirp_vmstate_info_int16, int16_t) 354 #define VMSTATE_INT32_V(_f, _s, _v) \ 355 VMSTATE_SINGLE(_f, _s, _v, slirp_vmstate_info_int32, int32_t) 356 357 #define VMSTATE_UINT8_V(_f, _s, _v) \ 358 VMSTATE_SINGLE(_f, _s, _v, slirp_vmstate_info_uint8, uint8_t) 359 #define VMSTATE_UINT16_V(_f, _s, _v) \ 360 VMSTATE_SINGLE(_f, _s, _v, slirp_vmstate_info_uint16, uint16_t) 361 #define VMSTATE_UINT32_V(_f, _s, _v) \ 362 VMSTATE_SINGLE(_f, _s, _v, slirp_vmstate_info_uint32, uint32_t) 363 364 #define VMSTATE_INT16(_f, _s) VMSTATE_INT16_V(_f, _s, 0) 365 #define VMSTATE_INT32(_f, _s) VMSTATE_INT32_V(_f, _s, 0) 366 367 #define VMSTATE_UINT8(_f, _s) VMSTATE_UINT8_V(_f, _s, 0) 368 #define VMSTATE_UINT16(_f, _s) VMSTATE_UINT16_V(_f, _s, 0) 369 #define VMSTATE_UINT32(_f, _s) VMSTATE_UINT32_V(_f, _s, 0) 370 371 #define VMSTATE_UINT16_TEST(_f, _s, _t) \ 372 VMSTATE_SINGLE_TEST(_f, _s, _t, 0, slirp_vmstate_info_uint16, uint16_t) 373 374 #define VMSTATE_UINT32_TEST(_f, _s, _t) \ 375 VMSTATE_SINGLE_TEST(_f, _s, _t, 0, slirp_vmstate_info_uint32, uint32_t) 376 377 #define VMSTATE_INT16_ARRAY_V(_f, _s, _n, _v) \ 378 VMSTATE_ARRAY(_f, _s, _n, _v, slirp_vmstate_info_int16, int16_t) 379 380 #define VMSTATE_INT16_ARRAY(_f, _s, _n) VMSTATE_INT16_ARRAY_V(_f, _s, _n, 0) 381 382 #define VMSTATE_BUFFER_V(_f, _s, _v) \ 383 VMSTATE_STATIC_BUFFER(_f, _s, _v, NULL, 0, sizeof(typeof_field(_s, _f))) 384 385 #define VMSTATE_BUFFER(_f, _s) VMSTATE_BUFFER_V(_f, _s, 0) 386 387 #define VMSTATE_END_OF_LIST() \ 388 { \ 389 } 390 391 #endif 392