Statistics
| Branch: | Revision:

root / vmstate.c @ feature-archipelago

History | View | Annotate | Download (15.5 kB)

1 b6fcfa59 Eduardo Habkost
#include "qemu-common.h"
2 b6fcfa59 Eduardo Habkost
#include "migration/migration.h"
3 b6fcfa59 Eduardo Habkost
#include "migration/qemu-file.h"
4 b6fcfa59 Eduardo Habkost
#include "migration/vmstate.h"
5 b6fcfa59 Eduardo Habkost
#include "qemu/bitops.h"
6 b6fcfa59 Eduardo Habkost
7 b6fcfa59 Eduardo Habkost
static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
8 b6fcfa59 Eduardo Habkost
                                    void *opaque);
9 b6fcfa59 Eduardo Habkost
static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
10 b6fcfa59 Eduardo Habkost
                                   void *opaque);
11 b6fcfa59 Eduardo Habkost
12 b6fcfa59 Eduardo Habkost
int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
13 b6fcfa59 Eduardo Habkost
                       void *opaque, int version_id)
14 b6fcfa59 Eduardo Habkost
{
15 b6fcfa59 Eduardo Habkost
    VMStateField *field = vmsd->fields;
16 b6fcfa59 Eduardo Habkost
    int ret;
17 b6fcfa59 Eduardo Habkost
18 b6fcfa59 Eduardo Habkost
    if (version_id > vmsd->version_id) {
19 b6fcfa59 Eduardo Habkost
        return -EINVAL;
20 b6fcfa59 Eduardo Habkost
    }
21 b6fcfa59 Eduardo Habkost
    if (version_id < vmsd->minimum_version_id_old) {
22 b6fcfa59 Eduardo Habkost
        return -EINVAL;
23 b6fcfa59 Eduardo Habkost
    }
24 b6fcfa59 Eduardo Habkost
    if  (version_id < vmsd->minimum_version_id) {
25 b6fcfa59 Eduardo Habkost
        return vmsd->load_state_old(f, opaque, version_id);
26 b6fcfa59 Eduardo Habkost
    }
27 b6fcfa59 Eduardo Habkost
    if (vmsd->pre_load) {
28 b6fcfa59 Eduardo Habkost
        int ret = vmsd->pre_load(opaque);
29 b6fcfa59 Eduardo Habkost
        if (ret) {
30 b6fcfa59 Eduardo Habkost
            return ret;
31 b6fcfa59 Eduardo Habkost
        }
32 b6fcfa59 Eduardo Habkost
    }
33 b6fcfa59 Eduardo Habkost
    while (field->name) {
34 b6fcfa59 Eduardo Habkost
        if ((field->field_exists &&
35 b6fcfa59 Eduardo Habkost
             field->field_exists(opaque, version_id)) ||
36 b6fcfa59 Eduardo Habkost
            (!field->field_exists &&
37 b6fcfa59 Eduardo Habkost
             field->version_id <= version_id)) {
38 b6fcfa59 Eduardo Habkost
            void *base_addr = opaque + field->offset;
39 b6fcfa59 Eduardo Habkost
            int i, n_elems = 1;
40 b6fcfa59 Eduardo Habkost
            int size = field->size;
41 b6fcfa59 Eduardo Habkost
42 b6fcfa59 Eduardo Habkost
            if (field->flags & VMS_VBUFFER) {
43 b6fcfa59 Eduardo Habkost
                size = *(int32_t *)(opaque+field->size_offset);
44 b6fcfa59 Eduardo Habkost
                if (field->flags & VMS_MULTIPLY) {
45 b6fcfa59 Eduardo Habkost
                    size *= field->size;
46 b6fcfa59 Eduardo Habkost
                }
47 b6fcfa59 Eduardo Habkost
            }
48 b6fcfa59 Eduardo Habkost
            if (field->flags & VMS_ARRAY) {
49 b6fcfa59 Eduardo Habkost
                n_elems = field->num;
50 b6fcfa59 Eduardo Habkost
            } else if (field->flags & VMS_VARRAY_INT32) {
51 b6fcfa59 Eduardo Habkost
                n_elems = *(int32_t *)(opaque+field->num_offset);
52 b6fcfa59 Eduardo Habkost
            } else if (field->flags & VMS_VARRAY_UINT32) {
53 b6fcfa59 Eduardo Habkost
                n_elems = *(uint32_t *)(opaque+field->num_offset);
54 b6fcfa59 Eduardo Habkost
            } else if (field->flags & VMS_VARRAY_UINT16) {
55 b6fcfa59 Eduardo Habkost
                n_elems = *(uint16_t *)(opaque+field->num_offset);
56 b6fcfa59 Eduardo Habkost
            } else if (field->flags & VMS_VARRAY_UINT8) {
57 b6fcfa59 Eduardo Habkost
                n_elems = *(uint8_t *)(opaque+field->num_offset);
58 b6fcfa59 Eduardo Habkost
            }
59 b6fcfa59 Eduardo Habkost
            if (field->flags & VMS_POINTER) {
60 b6fcfa59 Eduardo Habkost
                base_addr = *(void **)base_addr + field->start;
61 b6fcfa59 Eduardo Habkost
            }
62 b6fcfa59 Eduardo Habkost
            for (i = 0; i < n_elems; i++) {
63 b6fcfa59 Eduardo Habkost
                void *addr = base_addr + size * i;
64 b6fcfa59 Eduardo Habkost
65 b6fcfa59 Eduardo Habkost
                if (field->flags & VMS_ARRAY_OF_POINTER) {
66 b6fcfa59 Eduardo Habkost
                    addr = *(void **)addr;
67 b6fcfa59 Eduardo Habkost
                }
68 b6fcfa59 Eduardo Habkost
                if (field->flags & VMS_STRUCT) {
69 b6fcfa59 Eduardo Habkost
                    ret = vmstate_load_state(f, field->vmsd, addr,
70 b6fcfa59 Eduardo Habkost
                                             field->vmsd->version_id);
71 b6fcfa59 Eduardo Habkost
                } else {
72 b6fcfa59 Eduardo Habkost
                    ret = field->info->get(f, addr, size);
73 b6fcfa59 Eduardo Habkost
74 b6fcfa59 Eduardo Habkost
                }
75 b6fcfa59 Eduardo Habkost
                if (ret < 0) {
76 b6fcfa59 Eduardo Habkost
                    return ret;
77 b6fcfa59 Eduardo Habkost
                }
78 b6fcfa59 Eduardo Habkost
            }
79 b6fcfa59 Eduardo Habkost
        }
80 b6fcfa59 Eduardo Habkost
        field++;
81 b6fcfa59 Eduardo Habkost
    }
82 b6fcfa59 Eduardo Habkost
    ret = vmstate_subsection_load(f, vmsd, opaque);
83 b6fcfa59 Eduardo Habkost
    if (ret != 0) {
84 b6fcfa59 Eduardo Habkost
        return ret;
85 b6fcfa59 Eduardo Habkost
    }
86 b6fcfa59 Eduardo Habkost
    if (vmsd->post_load) {
87 b6fcfa59 Eduardo Habkost
        return vmsd->post_load(opaque, version_id);
88 b6fcfa59 Eduardo Habkost
    }
89 b6fcfa59 Eduardo Habkost
    return 0;
90 b6fcfa59 Eduardo Habkost
}
91 b6fcfa59 Eduardo Habkost
92 b6fcfa59 Eduardo Habkost
void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
93 b6fcfa59 Eduardo Habkost
                        void *opaque)
94 b6fcfa59 Eduardo Habkost
{
95 b6fcfa59 Eduardo Habkost
    VMStateField *field = vmsd->fields;
96 b6fcfa59 Eduardo Habkost
97 b6fcfa59 Eduardo Habkost
    if (vmsd->pre_save) {
98 b6fcfa59 Eduardo Habkost
        vmsd->pre_save(opaque);
99 b6fcfa59 Eduardo Habkost
    }
100 b6fcfa59 Eduardo Habkost
    while (field->name) {
101 b6fcfa59 Eduardo Habkost
        if (!field->field_exists ||
102 b6fcfa59 Eduardo Habkost
            field->field_exists(opaque, vmsd->version_id)) {
103 b6fcfa59 Eduardo Habkost
            void *base_addr = opaque + field->offset;
104 b6fcfa59 Eduardo Habkost
            int i, n_elems = 1;
105 b6fcfa59 Eduardo Habkost
            int size = field->size;
106 b6fcfa59 Eduardo Habkost
107 b6fcfa59 Eduardo Habkost
            if (field->flags & VMS_VBUFFER) {
108 b6fcfa59 Eduardo Habkost
                size = *(int32_t *)(opaque+field->size_offset);
109 b6fcfa59 Eduardo Habkost
                if (field->flags & VMS_MULTIPLY) {
110 b6fcfa59 Eduardo Habkost
                    size *= field->size;
111 b6fcfa59 Eduardo Habkost
                }
112 b6fcfa59 Eduardo Habkost
            }
113 b6fcfa59 Eduardo Habkost
            if (field->flags & VMS_ARRAY) {
114 b6fcfa59 Eduardo Habkost
                n_elems = field->num;
115 b6fcfa59 Eduardo Habkost
            } else if (field->flags & VMS_VARRAY_INT32) {
116 b6fcfa59 Eduardo Habkost
                n_elems = *(int32_t *)(opaque+field->num_offset);
117 b6fcfa59 Eduardo Habkost
            } else if (field->flags & VMS_VARRAY_UINT32) {
118 b6fcfa59 Eduardo Habkost
                n_elems = *(uint32_t *)(opaque+field->num_offset);
119 b6fcfa59 Eduardo Habkost
            } else if (field->flags & VMS_VARRAY_UINT16) {
120 b6fcfa59 Eduardo Habkost
                n_elems = *(uint16_t *)(opaque+field->num_offset);
121 b6fcfa59 Eduardo Habkost
            } else if (field->flags & VMS_VARRAY_UINT8) {
122 b6fcfa59 Eduardo Habkost
                n_elems = *(uint8_t *)(opaque+field->num_offset);
123 b6fcfa59 Eduardo Habkost
            }
124 b6fcfa59 Eduardo Habkost
            if (field->flags & VMS_POINTER) {
125 b6fcfa59 Eduardo Habkost
                base_addr = *(void **)base_addr + field->start;
126 b6fcfa59 Eduardo Habkost
            }
127 b6fcfa59 Eduardo Habkost
            for (i = 0; i < n_elems; i++) {
128 b6fcfa59 Eduardo Habkost
                void *addr = base_addr + size * i;
129 b6fcfa59 Eduardo Habkost
130 b6fcfa59 Eduardo Habkost
                if (field->flags & VMS_ARRAY_OF_POINTER) {
131 b6fcfa59 Eduardo Habkost
                    addr = *(void **)addr;
132 b6fcfa59 Eduardo Habkost
                }
133 b6fcfa59 Eduardo Habkost
                if (field->flags & VMS_STRUCT) {
134 b6fcfa59 Eduardo Habkost
                    vmstate_save_state(f, field->vmsd, addr);
135 b6fcfa59 Eduardo Habkost
                } else {
136 b6fcfa59 Eduardo Habkost
                    field->info->put(f, addr, size);
137 b6fcfa59 Eduardo Habkost
                }
138 b6fcfa59 Eduardo Habkost
            }
139 b6fcfa59 Eduardo Habkost
        }
140 b6fcfa59 Eduardo Habkost
        field++;
141 b6fcfa59 Eduardo Habkost
    }
142 b6fcfa59 Eduardo Habkost
    vmstate_subsection_save(f, vmsd, opaque);
143 b6fcfa59 Eduardo Habkost
}
144 b6fcfa59 Eduardo Habkost
145 b6fcfa59 Eduardo Habkost
static const VMStateDescription *
146 b6fcfa59 Eduardo Habkost
    vmstate_get_subsection(const VMStateSubsection *sub, char *idstr)
147 b6fcfa59 Eduardo Habkost
{
148 b6fcfa59 Eduardo Habkost
    while (sub && sub->needed) {
149 b6fcfa59 Eduardo Habkost
        if (strcmp(idstr, sub->vmsd->name) == 0) {
150 b6fcfa59 Eduardo Habkost
            return sub->vmsd;
151 b6fcfa59 Eduardo Habkost
        }
152 b6fcfa59 Eduardo Habkost
        sub++;
153 b6fcfa59 Eduardo Habkost
    }
154 b6fcfa59 Eduardo Habkost
    return NULL;
155 b6fcfa59 Eduardo Habkost
}
156 b6fcfa59 Eduardo Habkost
157 b6fcfa59 Eduardo Habkost
static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
158 b6fcfa59 Eduardo Habkost
                                   void *opaque)
159 b6fcfa59 Eduardo Habkost
{
160 b6fcfa59 Eduardo Habkost
    while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) {
161 b6fcfa59 Eduardo Habkost
        char idstr[256];
162 b6fcfa59 Eduardo Habkost
        int ret;
163 b6fcfa59 Eduardo Habkost
        uint8_t version_id, len, size;
164 b6fcfa59 Eduardo Habkost
        const VMStateDescription *sub_vmsd;
165 b6fcfa59 Eduardo Habkost
166 b6fcfa59 Eduardo Habkost
        len = qemu_peek_byte(f, 1);
167 b6fcfa59 Eduardo Habkost
        if (len < strlen(vmsd->name) + 1) {
168 b6fcfa59 Eduardo Habkost
            /* subsection name has be be "section_name/a" */
169 b6fcfa59 Eduardo Habkost
            return 0;
170 b6fcfa59 Eduardo Habkost
        }
171 b6fcfa59 Eduardo Habkost
        size = qemu_peek_buffer(f, (uint8_t *)idstr, len, 2);
172 b6fcfa59 Eduardo Habkost
        if (size != len) {
173 b6fcfa59 Eduardo Habkost
            return 0;
174 b6fcfa59 Eduardo Habkost
        }
175 b6fcfa59 Eduardo Habkost
        idstr[size] = 0;
176 b6fcfa59 Eduardo Habkost
177 b6fcfa59 Eduardo Habkost
        if (strncmp(vmsd->name, idstr, strlen(vmsd->name)) != 0) {
178 b6fcfa59 Eduardo Habkost
            /* it don't have a valid subsection name */
179 b6fcfa59 Eduardo Habkost
            return 0;
180 b6fcfa59 Eduardo Habkost
        }
181 b6fcfa59 Eduardo Habkost
        sub_vmsd = vmstate_get_subsection(vmsd->subsections, idstr);
182 b6fcfa59 Eduardo Habkost
        if (sub_vmsd == NULL) {
183 b6fcfa59 Eduardo Habkost
            return -ENOENT;
184 b6fcfa59 Eduardo Habkost
        }
185 b6fcfa59 Eduardo Habkost
        qemu_file_skip(f, 1); /* subsection */
186 b6fcfa59 Eduardo Habkost
        qemu_file_skip(f, 1); /* len */
187 b6fcfa59 Eduardo Habkost
        qemu_file_skip(f, len); /* idstr */
188 b6fcfa59 Eduardo Habkost
        version_id = qemu_get_be32(f);
189 b6fcfa59 Eduardo Habkost
190 b6fcfa59 Eduardo Habkost
        ret = vmstate_load_state(f, sub_vmsd, opaque, version_id);
191 b6fcfa59 Eduardo Habkost
        if (ret) {
192 b6fcfa59 Eduardo Habkost
            return ret;
193 b6fcfa59 Eduardo Habkost
        }
194 b6fcfa59 Eduardo Habkost
    }
195 b6fcfa59 Eduardo Habkost
    return 0;
196 b6fcfa59 Eduardo Habkost
}
197 b6fcfa59 Eduardo Habkost
198 b6fcfa59 Eduardo Habkost
static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
199 b6fcfa59 Eduardo Habkost
                                    void *opaque)
200 b6fcfa59 Eduardo Habkost
{
201 b6fcfa59 Eduardo Habkost
    const VMStateSubsection *sub = vmsd->subsections;
202 b6fcfa59 Eduardo Habkost
203 b6fcfa59 Eduardo Habkost
    while (sub && sub->needed) {
204 b6fcfa59 Eduardo Habkost
        if (sub->needed(opaque)) {
205 b6fcfa59 Eduardo Habkost
            const VMStateDescription *vmsd = sub->vmsd;
206 b6fcfa59 Eduardo Habkost
            uint8_t len;
207 b6fcfa59 Eduardo Habkost
208 b6fcfa59 Eduardo Habkost
            qemu_put_byte(f, QEMU_VM_SUBSECTION);
209 b6fcfa59 Eduardo Habkost
            len = strlen(vmsd->name);
210 b6fcfa59 Eduardo Habkost
            qemu_put_byte(f, len);
211 b6fcfa59 Eduardo Habkost
            qemu_put_buffer(f, (uint8_t *)vmsd->name, len);
212 b6fcfa59 Eduardo Habkost
            qemu_put_be32(f, vmsd->version_id);
213 b6fcfa59 Eduardo Habkost
            vmstate_save_state(f, vmsd, opaque);
214 b6fcfa59 Eduardo Habkost
        }
215 b6fcfa59 Eduardo Habkost
        sub++;
216 b6fcfa59 Eduardo Habkost
    }
217 b6fcfa59 Eduardo Habkost
}
218 b6fcfa59 Eduardo Habkost
219 b6fcfa59 Eduardo Habkost
/* bool */
220 b6fcfa59 Eduardo Habkost
221 b6fcfa59 Eduardo Habkost
static int get_bool(QEMUFile *f, void *pv, size_t size)
222 b6fcfa59 Eduardo Habkost
{
223 b6fcfa59 Eduardo Habkost
    bool *v = pv;
224 b6fcfa59 Eduardo Habkost
    *v = qemu_get_byte(f);
225 b6fcfa59 Eduardo Habkost
    return 0;
226 b6fcfa59 Eduardo Habkost
}
227 b6fcfa59 Eduardo Habkost
228 b6fcfa59 Eduardo Habkost
static void put_bool(QEMUFile *f, void *pv, size_t size)
229 b6fcfa59 Eduardo Habkost
{
230 b6fcfa59 Eduardo Habkost
    bool *v = pv;
231 b6fcfa59 Eduardo Habkost
    qemu_put_byte(f, *v);
232 b6fcfa59 Eduardo Habkost
}
233 b6fcfa59 Eduardo Habkost
234 b6fcfa59 Eduardo Habkost
const VMStateInfo vmstate_info_bool = {
235 b6fcfa59 Eduardo Habkost
    .name = "bool",
236 b6fcfa59 Eduardo Habkost
    .get  = get_bool,
237 b6fcfa59 Eduardo Habkost
    .put  = put_bool,
238 b6fcfa59 Eduardo Habkost
};
239 b6fcfa59 Eduardo Habkost
240 b6fcfa59 Eduardo Habkost
/* 8 bit int */
241 b6fcfa59 Eduardo Habkost
242 b6fcfa59 Eduardo Habkost
static int get_int8(QEMUFile *f, void *pv, size_t size)
243 b6fcfa59 Eduardo Habkost
{
244 b6fcfa59 Eduardo Habkost
    int8_t *v = pv;
245 b6fcfa59 Eduardo Habkost
    qemu_get_s8s(f, v);
246 b6fcfa59 Eduardo Habkost
    return 0;
247 b6fcfa59 Eduardo Habkost
}
248 b6fcfa59 Eduardo Habkost
249 b6fcfa59 Eduardo Habkost
static void put_int8(QEMUFile *f, void *pv, size_t size)
250 b6fcfa59 Eduardo Habkost
{
251 b6fcfa59 Eduardo Habkost
    int8_t *v = pv;
252 b6fcfa59 Eduardo Habkost
    qemu_put_s8s(f, v);
253 b6fcfa59 Eduardo Habkost
}
254 b6fcfa59 Eduardo Habkost
255 b6fcfa59 Eduardo Habkost
const VMStateInfo vmstate_info_int8 = {
256 b6fcfa59 Eduardo Habkost
    .name = "int8",
257 b6fcfa59 Eduardo Habkost
    .get  = get_int8,
258 b6fcfa59 Eduardo Habkost
    .put  = put_int8,
259 b6fcfa59 Eduardo Habkost
};
260 b6fcfa59 Eduardo Habkost
261 b6fcfa59 Eduardo Habkost
/* 16 bit int */
262 b6fcfa59 Eduardo Habkost
263 b6fcfa59 Eduardo Habkost
static int get_int16(QEMUFile *f, void *pv, size_t size)
264 b6fcfa59 Eduardo Habkost
{
265 b6fcfa59 Eduardo Habkost
    int16_t *v = pv;
266 b6fcfa59 Eduardo Habkost
    qemu_get_sbe16s(f, v);
267 b6fcfa59 Eduardo Habkost
    return 0;
268 b6fcfa59 Eduardo Habkost
}
269 b6fcfa59 Eduardo Habkost
270 b6fcfa59 Eduardo Habkost
static void put_int16(QEMUFile *f, void *pv, size_t size)
271 b6fcfa59 Eduardo Habkost
{
272 b6fcfa59 Eduardo Habkost
    int16_t *v = pv;
273 b6fcfa59 Eduardo Habkost
    qemu_put_sbe16s(f, v);
274 b6fcfa59 Eduardo Habkost
}
275 b6fcfa59 Eduardo Habkost
276 b6fcfa59 Eduardo Habkost
const VMStateInfo vmstate_info_int16 = {
277 b6fcfa59 Eduardo Habkost
    .name = "int16",
278 b6fcfa59 Eduardo Habkost
    .get  = get_int16,
279 b6fcfa59 Eduardo Habkost
    .put  = put_int16,
280 b6fcfa59 Eduardo Habkost
};
281 b6fcfa59 Eduardo Habkost
282 b6fcfa59 Eduardo Habkost
/* 32 bit int */
283 b6fcfa59 Eduardo Habkost
284 b6fcfa59 Eduardo Habkost
static int get_int32(QEMUFile *f, void *pv, size_t size)
285 b6fcfa59 Eduardo Habkost
{
286 b6fcfa59 Eduardo Habkost
    int32_t *v = pv;
287 b6fcfa59 Eduardo Habkost
    qemu_get_sbe32s(f, v);
288 b6fcfa59 Eduardo Habkost
    return 0;
289 b6fcfa59 Eduardo Habkost
}
290 b6fcfa59 Eduardo Habkost
291 b6fcfa59 Eduardo Habkost
static void put_int32(QEMUFile *f, void *pv, size_t size)
292 b6fcfa59 Eduardo Habkost
{
293 b6fcfa59 Eduardo Habkost
    int32_t *v = pv;
294 b6fcfa59 Eduardo Habkost
    qemu_put_sbe32s(f, v);
295 b6fcfa59 Eduardo Habkost
}
296 b6fcfa59 Eduardo Habkost
297 b6fcfa59 Eduardo Habkost
const VMStateInfo vmstate_info_int32 = {
298 b6fcfa59 Eduardo Habkost
    .name = "int32",
299 b6fcfa59 Eduardo Habkost
    .get  = get_int32,
300 b6fcfa59 Eduardo Habkost
    .put  = put_int32,
301 b6fcfa59 Eduardo Habkost
};
302 b6fcfa59 Eduardo Habkost
303 b6fcfa59 Eduardo Habkost
/* 32 bit int. See that the received value is the same than the one
304 b6fcfa59 Eduardo Habkost
   in the field */
305 b6fcfa59 Eduardo Habkost
306 b6fcfa59 Eduardo Habkost
static int get_int32_equal(QEMUFile *f, void *pv, size_t size)
307 b6fcfa59 Eduardo Habkost
{
308 b6fcfa59 Eduardo Habkost
    int32_t *v = pv;
309 b6fcfa59 Eduardo Habkost
    int32_t v2;
310 b6fcfa59 Eduardo Habkost
    qemu_get_sbe32s(f, &v2);
311 b6fcfa59 Eduardo Habkost
312 b6fcfa59 Eduardo Habkost
    if (*v == v2) {
313 b6fcfa59 Eduardo Habkost
        return 0;
314 b6fcfa59 Eduardo Habkost
    }
315 b6fcfa59 Eduardo Habkost
    return -EINVAL;
316 b6fcfa59 Eduardo Habkost
}
317 b6fcfa59 Eduardo Habkost
318 b6fcfa59 Eduardo Habkost
const VMStateInfo vmstate_info_int32_equal = {
319 b6fcfa59 Eduardo Habkost
    .name = "int32 equal",
320 b6fcfa59 Eduardo Habkost
    .get  = get_int32_equal,
321 b6fcfa59 Eduardo Habkost
    .put  = put_int32,
322 b6fcfa59 Eduardo Habkost
};
323 b6fcfa59 Eduardo Habkost
324 24a370ef Dr. David Alan Gilbert
/* 32 bit int. Check that the received value is less than or equal to
325 24a370ef Dr. David Alan Gilbert
   the one in the field */
326 b6fcfa59 Eduardo Habkost
327 b6fcfa59 Eduardo Habkost
static int get_int32_le(QEMUFile *f, void *pv, size_t size)
328 b6fcfa59 Eduardo Habkost
{
329 24a370ef Dr. David Alan Gilbert
    int32_t *cur = pv;
330 24a370ef Dr. David Alan Gilbert
    int32_t loaded;
331 24a370ef Dr. David Alan Gilbert
    qemu_get_sbe32s(f, &loaded);
332 b6fcfa59 Eduardo Habkost
333 24a370ef Dr. David Alan Gilbert
    if (loaded <= *cur) {
334 24a370ef Dr. David Alan Gilbert
        *cur = loaded;
335 b6fcfa59 Eduardo Habkost
        return 0;
336 b6fcfa59 Eduardo Habkost
    }
337 b6fcfa59 Eduardo Habkost
    return -EINVAL;
338 b6fcfa59 Eduardo Habkost
}
339 b6fcfa59 Eduardo Habkost
340 b6fcfa59 Eduardo Habkost
const VMStateInfo vmstate_info_int32_le = {
341 24a370ef Dr. David Alan Gilbert
    .name = "int32 le",
342 b6fcfa59 Eduardo Habkost
    .get  = get_int32_le,
343 b6fcfa59 Eduardo Habkost
    .put  = put_int32,
344 b6fcfa59 Eduardo Habkost
};
345 b6fcfa59 Eduardo Habkost
346 b6fcfa59 Eduardo Habkost
/* 64 bit int */
347 b6fcfa59 Eduardo Habkost
348 b6fcfa59 Eduardo Habkost
static int get_int64(QEMUFile *f, void *pv, size_t size)
349 b6fcfa59 Eduardo Habkost
{
350 b6fcfa59 Eduardo Habkost
    int64_t *v = pv;
351 b6fcfa59 Eduardo Habkost
    qemu_get_sbe64s(f, v);
352 b6fcfa59 Eduardo Habkost
    return 0;
353 b6fcfa59 Eduardo Habkost
}
354 b6fcfa59 Eduardo Habkost
355 b6fcfa59 Eduardo Habkost
static void put_int64(QEMUFile *f, void *pv, size_t size)
356 b6fcfa59 Eduardo Habkost
{
357 b6fcfa59 Eduardo Habkost
    int64_t *v = pv;
358 b6fcfa59 Eduardo Habkost
    qemu_put_sbe64s(f, v);
359 b6fcfa59 Eduardo Habkost
}
360 b6fcfa59 Eduardo Habkost
361 b6fcfa59 Eduardo Habkost
const VMStateInfo vmstate_info_int64 = {
362 b6fcfa59 Eduardo Habkost
    .name = "int64",
363 b6fcfa59 Eduardo Habkost
    .get  = get_int64,
364 b6fcfa59 Eduardo Habkost
    .put  = put_int64,
365 b6fcfa59 Eduardo Habkost
};
366 b6fcfa59 Eduardo Habkost
367 b6fcfa59 Eduardo Habkost
/* 8 bit unsigned int */
368 b6fcfa59 Eduardo Habkost
369 b6fcfa59 Eduardo Habkost
static int get_uint8(QEMUFile *f, void *pv, size_t size)
370 b6fcfa59 Eduardo Habkost
{
371 b6fcfa59 Eduardo Habkost
    uint8_t *v = pv;
372 b6fcfa59 Eduardo Habkost
    qemu_get_8s(f, v);
373 b6fcfa59 Eduardo Habkost
    return 0;
374 b6fcfa59 Eduardo Habkost
}
375 b6fcfa59 Eduardo Habkost
376 b6fcfa59 Eduardo Habkost
static void put_uint8(QEMUFile *f, void *pv, size_t size)
377 b6fcfa59 Eduardo Habkost
{
378 b6fcfa59 Eduardo Habkost
    uint8_t *v = pv;
379 b6fcfa59 Eduardo Habkost
    qemu_put_8s(f, v);
380 b6fcfa59 Eduardo Habkost
}
381 b6fcfa59 Eduardo Habkost
382 b6fcfa59 Eduardo Habkost
const VMStateInfo vmstate_info_uint8 = {
383 b6fcfa59 Eduardo Habkost
    .name = "uint8",
384 b6fcfa59 Eduardo Habkost
    .get  = get_uint8,
385 b6fcfa59 Eduardo Habkost
    .put  = put_uint8,
386 b6fcfa59 Eduardo Habkost
};
387 b6fcfa59 Eduardo Habkost
388 b6fcfa59 Eduardo Habkost
/* 16 bit unsigned int */
389 b6fcfa59 Eduardo Habkost
390 b6fcfa59 Eduardo Habkost
static int get_uint16(QEMUFile *f, void *pv, size_t size)
391 b6fcfa59 Eduardo Habkost
{
392 b6fcfa59 Eduardo Habkost
    uint16_t *v = pv;
393 b6fcfa59 Eduardo Habkost
    qemu_get_be16s(f, v);
394 b6fcfa59 Eduardo Habkost
    return 0;
395 b6fcfa59 Eduardo Habkost
}
396 b6fcfa59 Eduardo Habkost
397 b6fcfa59 Eduardo Habkost
static void put_uint16(QEMUFile *f, void *pv, size_t size)
398 b6fcfa59 Eduardo Habkost
{
399 b6fcfa59 Eduardo Habkost
    uint16_t *v = pv;
400 b6fcfa59 Eduardo Habkost
    qemu_put_be16s(f, v);
401 b6fcfa59 Eduardo Habkost
}
402 b6fcfa59 Eduardo Habkost
403 b6fcfa59 Eduardo Habkost
const VMStateInfo vmstate_info_uint16 = {
404 b6fcfa59 Eduardo Habkost
    .name = "uint16",
405 b6fcfa59 Eduardo Habkost
    .get  = get_uint16,
406 b6fcfa59 Eduardo Habkost
    .put  = put_uint16,
407 b6fcfa59 Eduardo Habkost
};
408 b6fcfa59 Eduardo Habkost
409 b6fcfa59 Eduardo Habkost
/* 32 bit unsigned int */
410 b6fcfa59 Eduardo Habkost
411 b6fcfa59 Eduardo Habkost
static int get_uint32(QEMUFile *f, void *pv, size_t size)
412 b6fcfa59 Eduardo Habkost
{
413 b6fcfa59 Eduardo Habkost
    uint32_t *v = pv;
414 b6fcfa59 Eduardo Habkost
    qemu_get_be32s(f, v);
415 b6fcfa59 Eduardo Habkost
    return 0;
416 b6fcfa59 Eduardo Habkost
}
417 b6fcfa59 Eduardo Habkost
418 b6fcfa59 Eduardo Habkost
static void put_uint32(QEMUFile *f, void *pv, size_t size)
419 b6fcfa59 Eduardo Habkost
{
420 b6fcfa59 Eduardo Habkost
    uint32_t *v = pv;
421 b6fcfa59 Eduardo Habkost
    qemu_put_be32s(f, v);
422 b6fcfa59 Eduardo Habkost
}
423 b6fcfa59 Eduardo Habkost
424 b6fcfa59 Eduardo Habkost
const VMStateInfo vmstate_info_uint32 = {
425 b6fcfa59 Eduardo Habkost
    .name = "uint32",
426 b6fcfa59 Eduardo Habkost
    .get  = get_uint32,
427 b6fcfa59 Eduardo Habkost
    .put  = put_uint32,
428 b6fcfa59 Eduardo Habkost
};
429 b6fcfa59 Eduardo Habkost
430 b6fcfa59 Eduardo Habkost
/* 32 bit uint. See that the received value is the same than the one
431 b6fcfa59 Eduardo Habkost
   in the field */
432 b6fcfa59 Eduardo Habkost
433 b6fcfa59 Eduardo Habkost
static int get_uint32_equal(QEMUFile *f, void *pv, size_t size)
434 b6fcfa59 Eduardo Habkost
{
435 b6fcfa59 Eduardo Habkost
    uint32_t *v = pv;
436 b6fcfa59 Eduardo Habkost
    uint32_t v2;
437 b6fcfa59 Eduardo Habkost
    qemu_get_be32s(f, &v2);
438 b6fcfa59 Eduardo Habkost
439 b6fcfa59 Eduardo Habkost
    if (*v == v2) {
440 b6fcfa59 Eduardo Habkost
        return 0;
441 b6fcfa59 Eduardo Habkost
    }
442 b6fcfa59 Eduardo Habkost
    return -EINVAL;
443 b6fcfa59 Eduardo Habkost
}
444 b6fcfa59 Eduardo Habkost
445 b6fcfa59 Eduardo Habkost
const VMStateInfo vmstate_info_uint32_equal = {
446 b6fcfa59 Eduardo Habkost
    .name = "uint32 equal",
447 b6fcfa59 Eduardo Habkost
    .get  = get_uint32_equal,
448 b6fcfa59 Eduardo Habkost
    .put  = put_uint32,
449 b6fcfa59 Eduardo Habkost
};
450 b6fcfa59 Eduardo Habkost
451 b6fcfa59 Eduardo Habkost
/* 64 bit unsigned int */
452 b6fcfa59 Eduardo Habkost
453 b6fcfa59 Eduardo Habkost
static int get_uint64(QEMUFile *f, void *pv, size_t size)
454 b6fcfa59 Eduardo Habkost
{
455 b6fcfa59 Eduardo Habkost
    uint64_t *v = pv;
456 b6fcfa59 Eduardo Habkost
    qemu_get_be64s(f, v);
457 b6fcfa59 Eduardo Habkost
    return 0;
458 b6fcfa59 Eduardo Habkost
}
459 b6fcfa59 Eduardo Habkost
460 b6fcfa59 Eduardo Habkost
static void put_uint64(QEMUFile *f, void *pv, size_t size)
461 b6fcfa59 Eduardo Habkost
{
462 b6fcfa59 Eduardo Habkost
    uint64_t *v = pv;
463 b6fcfa59 Eduardo Habkost
    qemu_put_be64s(f, v);
464 b6fcfa59 Eduardo Habkost
}
465 b6fcfa59 Eduardo Habkost
466 b6fcfa59 Eduardo Habkost
const VMStateInfo vmstate_info_uint64 = {
467 b6fcfa59 Eduardo Habkost
    .name = "uint64",
468 b6fcfa59 Eduardo Habkost
    .get  = get_uint64,
469 b6fcfa59 Eduardo Habkost
    .put  = put_uint64,
470 b6fcfa59 Eduardo Habkost
};
471 b6fcfa59 Eduardo Habkost
472 b6fcfa59 Eduardo Habkost
/* 64 bit unsigned int. See that the received value is the same than the one
473 b6fcfa59 Eduardo Habkost
   in the field */
474 b6fcfa59 Eduardo Habkost
475 b6fcfa59 Eduardo Habkost
static int get_uint64_equal(QEMUFile *f, void *pv, size_t size)
476 b6fcfa59 Eduardo Habkost
{
477 b6fcfa59 Eduardo Habkost
    uint64_t *v = pv;
478 b6fcfa59 Eduardo Habkost
    uint64_t v2;
479 b6fcfa59 Eduardo Habkost
    qemu_get_be64s(f, &v2);
480 b6fcfa59 Eduardo Habkost
481 b6fcfa59 Eduardo Habkost
    if (*v == v2) {
482 b6fcfa59 Eduardo Habkost
        return 0;
483 b6fcfa59 Eduardo Habkost
    }
484 b6fcfa59 Eduardo Habkost
    return -EINVAL;
485 b6fcfa59 Eduardo Habkost
}
486 b6fcfa59 Eduardo Habkost
487 b6fcfa59 Eduardo Habkost
const VMStateInfo vmstate_info_uint64_equal = {
488 b6fcfa59 Eduardo Habkost
    .name = "int64 equal",
489 b6fcfa59 Eduardo Habkost
    .get  = get_uint64_equal,
490 b6fcfa59 Eduardo Habkost
    .put  = put_uint64,
491 b6fcfa59 Eduardo Habkost
};
492 b6fcfa59 Eduardo Habkost
493 b6fcfa59 Eduardo Habkost
/* 8 bit int. See that the received value is the same than the one
494 b6fcfa59 Eduardo Habkost
   in the field */
495 b6fcfa59 Eduardo Habkost
496 b6fcfa59 Eduardo Habkost
static int get_uint8_equal(QEMUFile *f, void *pv, size_t size)
497 b6fcfa59 Eduardo Habkost
{
498 b6fcfa59 Eduardo Habkost
    uint8_t *v = pv;
499 b6fcfa59 Eduardo Habkost
    uint8_t v2;
500 b6fcfa59 Eduardo Habkost
    qemu_get_8s(f, &v2);
501 b6fcfa59 Eduardo Habkost
502 b6fcfa59 Eduardo Habkost
    if (*v == v2) {
503 b6fcfa59 Eduardo Habkost
        return 0;
504 b6fcfa59 Eduardo Habkost
    }
505 b6fcfa59 Eduardo Habkost
    return -EINVAL;
506 b6fcfa59 Eduardo Habkost
}
507 b6fcfa59 Eduardo Habkost
508 b6fcfa59 Eduardo Habkost
const VMStateInfo vmstate_info_uint8_equal = {
509 b6fcfa59 Eduardo Habkost
    .name = "uint8 equal",
510 b6fcfa59 Eduardo Habkost
    .get  = get_uint8_equal,
511 b6fcfa59 Eduardo Habkost
    .put  = put_uint8,
512 b6fcfa59 Eduardo Habkost
};
513 b6fcfa59 Eduardo Habkost
514 b6fcfa59 Eduardo Habkost
/* 16 bit unsigned int int. See that the received value is the same than the one
515 b6fcfa59 Eduardo Habkost
   in the field */
516 b6fcfa59 Eduardo Habkost
517 b6fcfa59 Eduardo Habkost
static int get_uint16_equal(QEMUFile *f, void *pv, size_t size)
518 b6fcfa59 Eduardo Habkost
{
519 b6fcfa59 Eduardo Habkost
    uint16_t *v = pv;
520 b6fcfa59 Eduardo Habkost
    uint16_t v2;
521 b6fcfa59 Eduardo Habkost
    qemu_get_be16s(f, &v2);
522 b6fcfa59 Eduardo Habkost
523 b6fcfa59 Eduardo Habkost
    if (*v == v2) {
524 b6fcfa59 Eduardo Habkost
        return 0;
525 b6fcfa59 Eduardo Habkost
    }
526 b6fcfa59 Eduardo Habkost
    return -EINVAL;
527 b6fcfa59 Eduardo Habkost
}
528 b6fcfa59 Eduardo Habkost
529 b6fcfa59 Eduardo Habkost
const VMStateInfo vmstate_info_uint16_equal = {
530 b6fcfa59 Eduardo Habkost
    .name = "uint16 equal",
531 b6fcfa59 Eduardo Habkost
    .get  = get_uint16_equal,
532 b6fcfa59 Eduardo Habkost
    .put  = put_uint16,
533 b6fcfa59 Eduardo Habkost
};
534 b6fcfa59 Eduardo Habkost
535 b6fcfa59 Eduardo Habkost
/* floating point */
536 b6fcfa59 Eduardo Habkost
537 b6fcfa59 Eduardo Habkost
static int get_float64(QEMUFile *f, void *pv, size_t size)
538 b6fcfa59 Eduardo Habkost
{
539 b6fcfa59 Eduardo Habkost
    float64 *v = pv;
540 b6fcfa59 Eduardo Habkost
541 b6fcfa59 Eduardo Habkost
    *v = make_float64(qemu_get_be64(f));
542 b6fcfa59 Eduardo Habkost
    return 0;
543 b6fcfa59 Eduardo Habkost
}
544 b6fcfa59 Eduardo Habkost
545 b6fcfa59 Eduardo Habkost
static void put_float64(QEMUFile *f, void *pv, size_t size)
546 b6fcfa59 Eduardo Habkost
{
547 b6fcfa59 Eduardo Habkost
    uint64_t *v = pv;
548 b6fcfa59 Eduardo Habkost
549 b6fcfa59 Eduardo Habkost
    qemu_put_be64(f, float64_val(*v));
550 b6fcfa59 Eduardo Habkost
}
551 b6fcfa59 Eduardo Habkost
552 b6fcfa59 Eduardo Habkost
const VMStateInfo vmstate_info_float64 = {
553 b6fcfa59 Eduardo Habkost
    .name = "float64",
554 b6fcfa59 Eduardo Habkost
    .get  = get_float64,
555 b6fcfa59 Eduardo Habkost
    .put  = put_float64,
556 b6fcfa59 Eduardo Habkost
};
557 b6fcfa59 Eduardo Habkost
558 b6fcfa59 Eduardo Habkost
/* uint8_t buffers */
559 b6fcfa59 Eduardo Habkost
560 b6fcfa59 Eduardo Habkost
static int get_buffer(QEMUFile *f, void *pv, size_t size)
561 b6fcfa59 Eduardo Habkost
{
562 b6fcfa59 Eduardo Habkost
    uint8_t *v = pv;
563 b6fcfa59 Eduardo Habkost
    qemu_get_buffer(f, v, size);
564 b6fcfa59 Eduardo Habkost
    return 0;
565 b6fcfa59 Eduardo Habkost
}
566 b6fcfa59 Eduardo Habkost
567 b6fcfa59 Eduardo Habkost
static void put_buffer(QEMUFile *f, void *pv, size_t size)
568 b6fcfa59 Eduardo Habkost
{
569 b6fcfa59 Eduardo Habkost
    uint8_t *v = pv;
570 b6fcfa59 Eduardo Habkost
    qemu_put_buffer(f, v, size);
571 b6fcfa59 Eduardo Habkost
}
572 b6fcfa59 Eduardo Habkost
573 b6fcfa59 Eduardo Habkost
const VMStateInfo vmstate_info_buffer = {
574 b6fcfa59 Eduardo Habkost
    .name = "buffer",
575 b6fcfa59 Eduardo Habkost
    .get  = get_buffer,
576 b6fcfa59 Eduardo Habkost
    .put  = put_buffer,
577 b6fcfa59 Eduardo Habkost
};
578 b6fcfa59 Eduardo Habkost
579 b6fcfa59 Eduardo Habkost
/* unused buffers: space that was used for some fields that are
580 b6fcfa59 Eduardo Habkost
   not useful anymore */
581 b6fcfa59 Eduardo Habkost
582 b6fcfa59 Eduardo Habkost
static int get_unused_buffer(QEMUFile *f, void *pv, size_t size)
583 b6fcfa59 Eduardo Habkost
{
584 b6fcfa59 Eduardo Habkost
    uint8_t buf[1024];
585 b6fcfa59 Eduardo Habkost
    int block_len;
586 b6fcfa59 Eduardo Habkost
587 b6fcfa59 Eduardo Habkost
    while (size > 0) {
588 b6fcfa59 Eduardo Habkost
        block_len = MIN(sizeof(buf), size);
589 b6fcfa59 Eduardo Habkost
        size -= block_len;
590 b6fcfa59 Eduardo Habkost
        qemu_get_buffer(f, buf, block_len);
591 b6fcfa59 Eduardo Habkost
    }
592 b6fcfa59 Eduardo Habkost
   return 0;
593 b6fcfa59 Eduardo Habkost
}
594 b6fcfa59 Eduardo Habkost
595 b6fcfa59 Eduardo Habkost
static void put_unused_buffer(QEMUFile *f, void *pv, size_t size)
596 b6fcfa59 Eduardo Habkost
{
597 b6fcfa59 Eduardo Habkost
    static const uint8_t buf[1024];
598 b6fcfa59 Eduardo Habkost
    int block_len;
599 b6fcfa59 Eduardo Habkost
600 b6fcfa59 Eduardo Habkost
    while (size > 0) {
601 b6fcfa59 Eduardo Habkost
        block_len = MIN(sizeof(buf), size);
602 b6fcfa59 Eduardo Habkost
        size -= block_len;
603 b6fcfa59 Eduardo Habkost
        qemu_put_buffer(f, buf, block_len);
604 b6fcfa59 Eduardo Habkost
    }
605 b6fcfa59 Eduardo Habkost
}
606 b6fcfa59 Eduardo Habkost
607 b6fcfa59 Eduardo Habkost
const VMStateInfo vmstate_info_unused_buffer = {
608 b6fcfa59 Eduardo Habkost
    .name = "unused_buffer",
609 b6fcfa59 Eduardo Habkost
    .get  = get_unused_buffer,
610 b6fcfa59 Eduardo Habkost
    .put  = put_unused_buffer,
611 b6fcfa59 Eduardo Habkost
};
612 b6fcfa59 Eduardo Habkost
613 b6fcfa59 Eduardo Habkost
/* bitmaps (as defined by bitmap.h). Note that size here is the size
614 b6fcfa59 Eduardo Habkost
 * of the bitmap in bits. The on-the-wire format of a bitmap is 64
615 b6fcfa59 Eduardo Habkost
 * bit words with the bits in big endian order. The in-memory format
616 b6fcfa59 Eduardo Habkost
 * is an array of 'unsigned long', which may be either 32 or 64 bits.
617 b6fcfa59 Eduardo Habkost
 */
618 b6fcfa59 Eduardo Habkost
/* This is the number of 64 bit words sent over the wire */
619 b6fcfa59 Eduardo Habkost
#define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64)
620 b6fcfa59 Eduardo Habkost
static int get_bitmap(QEMUFile *f, void *pv, size_t size)
621 b6fcfa59 Eduardo Habkost
{
622 b6fcfa59 Eduardo Habkost
    unsigned long *bmp = pv;
623 b6fcfa59 Eduardo Habkost
    int i, idx = 0;
624 b6fcfa59 Eduardo Habkost
    for (i = 0; i < BITS_TO_U64S(size); i++) {
625 b6fcfa59 Eduardo Habkost
        uint64_t w = qemu_get_be64(f);
626 b6fcfa59 Eduardo Habkost
        bmp[idx++] = w;
627 b6fcfa59 Eduardo Habkost
        if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) {
628 b6fcfa59 Eduardo Habkost
            bmp[idx++] = w >> 32;
629 b6fcfa59 Eduardo Habkost
        }
630 b6fcfa59 Eduardo Habkost
    }
631 b6fcfa59 Eduardo Habkost
    return 0;
632 b6fcfa59 Eduardo Habkost
}
633 b6fcfa59 Eduardo Habkost
634 b6fcfa59 Eduardo Habkost
static void put_bitmap(QEMUFile *f, void *pv, size_t size)
635 b6fcfa59 Eduardo Habkost
{
636 b6fcfa59 Eduardo Habkost
    unsigned long *bmp = pv;
637 b6fcfa59 Eduardo Habkost
    int i, idx = 0;
638 b6fcfa59 Eduardo Habkost
    for (i = 0; i < BITS_TO_U64S(size); i++) {
639 b6fcfa59 Eduardo Habkost
        uint64_t w = bmp[idx++];
640 b6fcfa59 Eduardo Habkost
        if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) {
641 b6fcfa59 Eduardo Habkost
            w |= ((uint64_t)bmp[idx++]) << 32;
642 b6fcfa59 Eduardo Habkost
        }
643 b6fcfa59 Eduardo Habkost
        qemu_put_be64(f, w);
644 b6fcfa59 Eduardo Habkost
    }
645 b6fcfa59 Eduardo Habkost
}
646 b6fcfa59 Eduardo Habkost
647 b6fcfa59 Eduardo Habkost
const VMStateInfo vmstate_info_bitmap = {
648 b6fcfa59 Eduardo Habkost
    .name = "bitmap",
649 b6fcfa59 Eduardo Habkost
    .get = get_bitmap,
650 b6fcfa59 Eduardo Habkost
    .put = put_bitmap,
651 b6fcfa59 Eduardo Habkost
};