Path: blob/a-new-beginning/SharedDependencies/Sources/libslirp/include/vmstate.h
2 views
/* SPDX-License-Identifier: BSD-3-Clause */1/*2* QEMU migration/snapshot declarations3*4* Copyright (c) 2009-2011 Red Hat, Inc.5*6* Original author: Juan Quintela <[email protected]>7*8* Redistribution and use in source and binary forms, with or without9* modification, are permitted provided that the following conditions10* are met:11*12* 1. Redistributions of source code must retain the above13* copyright notice, this list of conditions and the following14* disclaimer.15*16* 2. Redistributions in binary form must reproduce the above17* copyright notice, this list of conditions and the following18* disclaimer in the documentation and/or other materials provided19* with the distribution.20*21* 3. Neither the name of the copyright holder nor the names of its22* contributors may be used to endorse or promote products derived23* from this software without specific prior written permission.24*25* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS26* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT27* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS28* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE29* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,30* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES31* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR32* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)33* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,34* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)35* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED36* OF THE POSSIBILITY OF SUCH DAMAGE.37*/38#ifndef VMSTATE_H_39#define VMSTATE_H_4041#include <stdint.h>42#include <stdbool.h>43#include "slirp.h"44#include "stream.h"4546#define stringify(s) tostring(s)47#define tostring(s) #s4849typedef struct VMStateInfo VMStateInfo;50typedef struct VMStateDescription VMStateDescription;51typedef struct VMStateField VMStateField;5253int slirp_vmstate_save_state(SlirpOStream *f, const VMStateDescription *vmsd,54void *opaque);55int slirp_vmstate_load_state(SlirpIStream *f, const VMStateDescription *vmsd,56void *opaque, int version_id);5758/* VMStateInfo allows customized migration of objects that don't fit in59* any category in VMStateFlags. Additional information is always passed60* into get and put in terms of field and vmdesc parameters. However61* these two parameters should only be used in cases when customized62* handling is needed, such as QTAILQ. For primitive data types such as63* integer, field and vmdesc parameters should be ignored inside get/put.64*/65struct VMStateInfo {66const char *name;67int (*get)(SlirpIStream *f, void *pv, size_t size,68const VMStateField *field);69int (*put)(SlirpOStream *f, void *pv, size_t size,70const VMStateField *field);71};7273enum VMStateFlags {74/* Ignored */75VMS_SINGLE = 0x001,7677/* The struct member at opaque + VMStateField.offset is a pointer78* to the actual field (e.g. struct a { uint8_t *b;79* }). Dereference the pointer before using it as basis for80* further pointer arithmetic (see e.g. VMS_ARRAY). Does not81* affect the meaning of VMStateField.num_offset or82* VMStateField.size_offset; see VMS_VARRAY* and VMS_VBUFFER for83* those. */84VMS_POINTER = 0x002,8586/* The field is an array of fixed size. VMStateField.num contains87* the number of entries in the array. The size of each entry is88* given by VMStateField.size and / or opaque +89* VMStateField.size_offset; see VMS_VBUFFER and90* VMS_MULTIPLY. Each array entry will be processed individually91* (VMStateField.info.get()/put() if VMS_STRUCT is not set,92* recursion into VMStateField.vmsd if VMS_STRUCT is set). May not93* be combined with VMS_VARRAY*. */94VMS_ARRAY = 0x004,9596/* The field is itself a struct, containing one or more97* fields. Recurse into VMStateField.vmsd. Most useful in98* combination with VMS_ARRAY / VMS_VARRAY*, recursing into each99* array entry. */100VMS_STRUCT = 0x008,101102/* The field is an array of variable size. The int32_t at opaque +103* VMStateField.num_offset contains the number of entries in the104* array. See the VMS_ARRAY description regarding array handling105* in general. May not be combined with VMS_ARRAY or any other106* VMS_VARRAY*. */107VMS_VARRAY_INT32 = 0x010,108109/* Ignored */110VMS_BUFFER = 0x020,111112/* The field is a (fixed-size or variable-size) array of pointers113* (e.g. struct a { uint8_t *b[]; }). Dereference each array entry114* before using it. Note: Does not imply any one of VMS_ARRAY /115* VMS_VARRAY*; these need to be set explicitly. */116VMS_ARRAY_OF_POINTER = 0x040,117118/* The field is an array of variable size. The uint16_t at opaque119* + VMStateField.num_offset (subject to VMS_MULTIPLY_ELEMENTS)120* contains the number of entries in the array. See the VMS_ARRAY121* description regarding array handling in general. May not be122* combined with VMS_ARRAY or any other VMS_VARRAY*. */123VMS_VARRAY_UINT16 = 0x080,124125/* The size of the individual entries (a single array entry if126* VMS_ARRAY or any of VMS_VARRAY* are set, or the field itself if127* neither is set) is variable (i.e. not known at compile-time),128* but the same for all entries. Use the int32_t at opaque +129* VMStateField.size_offset (subject to VMS_MULTIPLY) to determine130* the size of each (and every) entry. */131VMS_VBUFFER = 0x100,132133/* Multiply the entry size given by the int32_t at opaque +134* VMStateField.size_offset (see VMS_VBUFFER description) with135* VMStateField.size to determine the number of bytes to be136* allocated. Only valid in combination with VMS_VBUFFER. */137VMS_MULTIPLY = 0x200,138139/* The field is an array of variable size. The uint8_t at opaque +140* VMStateField.num_offset (subject to VMS_MULTIPLY_ELEMENTS)141* contains the number of entries in the array. See the VMS_ARRAY142* description regarding array handling in general. May not be143* combined with VMS_ARRAY or any other VMS_VARRAY*. */144VMS_VARRAY_UINT8 = 0x400,145146/* The field is an array of variable size. The uint32_t at opaque147* + VMStateField.num_offset (subject to VMS_MULTIPLY_ELEMENTS)148* contains the number of entries in the array. See the VMS_ARRAY149* description regarding array handling in general. May not be150* combined with VMS_ARRAY or any other VMS_VARRAY*. */151VMS_VARRAY_UINT32 = 0x800,152153/* Fail loading the serialised VM state if this field is missing154* from the input. */155VMS_MUST_EXIST = 0x1000,156157/* When loading serialised VM state, allocate memory for the158* (entire) field. Only valid in combination with159* VMS_POINTER. Note: Not all combinations with other flags are160* currently supported, e.g. VMS_ALLOC|VMS_ARRAY_OF_POINTER won't161* cause the individual entries to be allocated. */162VMS_ALLOC = 0x2000,163164/* Multiply the number of entries given by the integer at opaque +165* VMStateField.num_offset (see VMS_VARRAY*) with VMStateField.num166* to determine the number of entries in the array. Only valid in167* combination with one of VMS_VARRAY*. */168VMS_MULTIPLY_ELEMENTS = 0x4000,169170/* A structure field that is like VMS_STRUCT, but uses171* VMStateField.struct_version_id to tell which version of the172* structure we are referencing to use. */173VMS_VSTRUCT = 0x8000,174175/* Marker for end of list */176VMS_END = 0x10000177};178179struct VMStateField {180const char *name;181size_t offset;182size_t size;183size_t start;184int num;185size_t num_offset;186size_t size_offset;187const VMStateInfo *info;188enum VMStateFlags flags;189const VMStateDescription *vmsd;190int version_id;191int struct_version_id;192bool (*field_exists)(void *opaque, int version_id);193};194195struct VMStateDescription {196const char *name;197int version_id;198int (*pre_load)(void *opaque);199int (*post_load)(void *opaque, int version_id);200int (*pre_save)(void *opaque);201VMStateField *fields;202};203204205extern const VMStateInfo slirp_vmstate_info_int16;206extern const VMStateInfo slirp_vmstate_info_int32;207extern const VMStateInfo slirp_vmstate_info_uint8;208extern const VMStateInfo slirp_vmstate_info_uint16;209extern const VMStateInfo slirp_vmstate_info_uint32;210211/** Put this in the stream when migrating a null pointer.*/212#define VMS_NULLPTR_MARKER (0x30U) /* '0' */213extern const VMStateInfo slirp_vmstate_info_nullptr;214215extern const VMStateInfo slirp_vmstate_info_buffer;216extern const VMStateInfo slirp_vmstate_info_tmp;217218#ifdef __GNUC__219#define type_check_array(t1, t2, n) ((t1(*)[n])0 - (t2 *)0)220#define type_check_pointer(t1, t2) ((t1 **)0 - (t2 *)0)221#define typeof_field(type, field) typeof(((type *)0)->field)222#define type_check(t1, t2) ((t1 *)0 - (t2 *)0)223#else224#define type_check_array(t1, t2, n) 0225#define type_check_pointer(t1, t2) 0226#define typeof_field(type, field) (((type *)0)->field)227#define type_check(t1, t2) 0228#endif229230#define vmstate_offset_value(_state, _field, _type) \231(offsetof(_state, _field) + type_check(_type, typeof_field(_state, _field)))232233#define vmstate_offset_pointer(_state, _field, _type) \234(offsetof(_state, _field) + \235type_check_pointer(_type, typeof_field(_state, _field)))236237#define vmstate_offset_array(_state, _field, _type, _num) \238(offsetof(_state, _field) + \239type_check_array(_type, typeof_field(_state, _field), _num))240241#define vmstate_offset_buffer(_state, _field) \242vmstate_offset_array(_state, _field, uint8_t, \243sizeof(typeof_field(_state, _field)))244245/* In the macros below, if there is a _version, that means the macro's246* field will be processed only if the version being received is >=247* the _version specified. In general, if you add a new field, you248* would increment the structure's version and put that version249* number into the new field so it would only be processed with the250* new version.251*252* In particular, for VMSTATE_STRUCT() and friends the _version does253* *NOT* pick the version of the sub-structure. It works just as254* specified above. The version of the top-level structure received255* is passed down to all sub-structures. This means that the256* sub-structures must have version that are compatible with all the257* structures that use them.258*259* If you want to specify the version of the sub-structure, use260* VMSTATE_VSTRUCT(), which allows the specific sub-structure version261* to be directly specified.262*/263264#define VMSTATE_SINGLE_TEST(_field, _state, _test, _version, _info, _type) \265{ \266.name = (stringify(_field)), .version_id = (_version), \267.field_exists = (_test), .size = sizeof(_type), .info = &(_info), \268.flags = VMS_SINGLE, \269.offset = vmstate_offset_value(_state, _field, _type), \270}271272#define VMSTATE_ARRAY(_field, _state, _num, _version, _info, _type) \273{ \274.name = (stringify(_field)), .version_id = (_version), .num = (_num), \275.info = &(_info), .size = sizeof(_type), .flags = VMS_ARRAY, \276.offset = vmstate_offset_array(_state, _field, _type, _num), \277}278279#define VMSTATE_STRUCT_TEST(_field, _state, _test, _version, _vmsd, _type) \280{ \281.name = (stringify(_field)), .version_id = (_version), \282.field_exists = (_test), .vmsd = &(_vmsd), .size = sizeof(_type), \283.flags = VMS_STRUCT, \284.offset = vmstate_offset_value(_state, _field, _type), \285}286287#define VMSTATE_STRUCT_POINTER_V(_field, _state, _version, _vmsd, _type) \288{ \289.name = (stringify(_field)), .version_id = (_version), \290.vmsd = &(_vmsd), .size = sizeof(_type *), \291.flags = VMS_STRUCT | VMS_POINTER, \292.offset = vmstate_offset_pointer(_state, _field, _type), \293}294295#define VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, _test, _version, \296_vmsd, _type) \297{ \298.name = (stringify(_field)), .num = (_num), .field_exists = (_test), \299.version_id = (_version), .vmsd = &(_vmsd), .size = sizeof(_type), \300.flags = VMS_STRUCT | VMS_ARRAY, \301.offset = vmstate_offset_array(_state, _field, _type, _num), \302}303304#define VMSTATE_STATIC_BUFFER(_field, _state, _version, _test, _start, _size) \305{ \306.name = (stringify(_field)), .version_id = (_version), \307.field_exists = (_test), .size = (_size - _start), \308.info = &slirp_vmstate_info_buffer, .flags = VMS_BUFFER, \309.offset = vmstate_offset_buffer(_state, _field) + _start, \310}311312#define VMSTATE_VBUFFER_UINT32(_field, _state, _version, _test, _field_size) \313{ \314.name = (stringify(_field)), .version_id = (_version), \315.field_exists = (_test), \316.size_offset = vmstate_offset_value(_state, _field_size, uint32_t), \317.info = &slirp_vmstate_info_buffer, \318.flags = VMS_VBUFFER | VMS_POINTER, \319.offset = offsetof(_state, _field), \320}321322#define QEMU_BUILD_BUG_ON_STRUCT(x) \323struct { \324int : (x) ? -1 : 1; \325}326327#define QEMU_BUILD_BUG_ON_ZERO(x) \328(sizeof(QEMU_BUILD_BUG_ON_STRUCT(x)) - sizeof(QEMU_BUILD_BUG_ON_STRUCT(x)))329330/* Allocate a temporary of type 'tmp_type', set tmp->parent to _state331* and execute the vmsd on the temporary. Note that we're working with332* the whole of _state here, not a field within it.333* We compile time check that:334* That _tmp_type contains a 'parent' member that's a pointer to the335* '_state' type336* That the pointer is right at the start of _tmp_type.337*/338#define VMSTATE_WITH_TMP(_state, _tmp_type, _vmsd) \339{ \340.name = "tmp", \341.size = sizeof(_tmp_type) + \342QEMU_BUILD_BUG_ON_ZERO(offsetof(_tmp_type, parent) != 0) + \343type_check_pointer(_state, typeof_field(_tmp_type, parent)), \344.vmsd = &(_vmsd), .info = &slirp_vmstate_info_tmp, \345}346347#define VMSTATE_SINGLE(_field, _state, _version, _info, _type) \348VMSTATE_SINGLE_TEST(_field, _state, NULL, _version, _info, _type)349350#define VMSTATE_STRUCT(_field, _state, _version, _vmsd, _type) \351VMSTATE_STRUCT_TEST(_field, _state, NULL, _version, _vmsd, _type)352353#define VMSTATE_STRUCT_POINTER(_field, _state, _vmsd, _type) \354VMSTATE_STRUCT_POINTER_V(_field, _state, 0, _vmsd, _type)355356#define VMSTATE_STRUCT_ARRAY(_field, _state, _num, _version, _vmsd, _type) \357VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, NULL, _version, _vmsd, \358_type)359360#define VMSTATE_INT16_V(_f, _s, _v) \361VMSTATE_SINGLE(_f, _s, _v, slirp_vmstate_info_int16, int16_t)362#define VMSTATE_INT32_V(_f, _s, _v) \363VMSTATE_SINGLE(_f, _s, _v, slirp_vmstate_info_int32, int32_t)364365#define VMSTATE_UINT8_V(_f, _s, _v) \366VMSTATE_SINGLE(_f, _s, _v, slirp_vmstate_info_uint8, uint8_t)367#define VMSTATE_UINT16_V(_f, _s, _v) \368VMSTATE_SINGLE(_f, _s, _v, slirp_vmstate_info_uint16, uint16_t)369#define VMSTATE_UINT32_V(_f, _s, _v) \370VMSTATE_SINGLE(_f, _s, _v, slirp_vmstate_info_uint32, uint32_t)371372#define VMSTATE_INT16(_f, _s) VMSTATE_INT16_V(_f, _s, 0)373#define VMSTATE_INT32(_f, _s) VMSTATE_INT32_V(_f, _s, 0)374375#define VMSTATE_UINT8(_f, _s) VMSTATE_UINT8_V(_f, _s, 0)376#define VMSTATE_UINT16(_f, _s) VMSTATE_UINT16_V(_f, _s, 0)377#define VMSTATE_UINT32(_f, _s) VMSTATE_UINT32_V(_f, _s, 0)378379#define VMSTATE_UINT16_TEST(_f, _s, _t) \380VMSTATE_SINGLE_TEST(_f, _s, _t, 0, slirp_vmstate_info_uint16, uint16_t)381382#define VMSTATE_UINT32_TEST(_f, _s, _t) \383VMSTATE_SINGLE_TEST(_f, _s, _t, 0, slirp_vmstate_info_uint32, uint32_t)384385#define VMSTATE_INT16_ARRAY_V(_f, _s, _n, _v) \386VMSTATE_ARRAY(_f, _s, _n, _v, slirp_vmstate_info_int16, int16_t)387388#define VMSTATE_INT16_ARRAY(_f, _s, _n) VMSTATE_INT16_ARRAY_V(_f, _s, _n, 0)389390#define VMSTATE_BUFFER_V(_f, _s, _v) \391VMSTATE_STATIC_BUFFER(_f, _s, _v, NULL, 0, sizeof(typeof_field(_s, _f)))392393#define VMSTATE_BUFFER(_f, _s) VMSTATE_BUFFER_V(_f, _s, 0)394395#define VMSTATE_END_OF_LIST() \396{ \397.flags = VMS_END, \398}399400#endif /* VMSTATE_H_ */401402403