Statistics
| Branch: | Revision:

root / savevm.c @ ee77dfb2

History | View | Annotate | Download (57.2 kB)

1 a672b469 aliguori
/*
2 a672b469 aliguori
 * QEMU System Emulator
3 a672b469 aliguori
 *
4 a672b469 aliguori
 * Copyright (c) 2003-2008 Fabrice Bellard
5 a672b469 aliguori
 *
6 a672b469 aliguori
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 a672b469 aliguori
 * of this software and associated documentation files (the "Software"), to deal
8 a672b469 aliguori
 * in the Software without restriction, including without limitation the rights
9 a672b469 aliguori
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 a672b469 aliguori
 * copies of the Software, and to permit persons to whom the Software is
11 a672b469 aliguori
 * furnished to do so, subject to the following conditions:
12 a672b469 aliguori
 *
13 a672b469 aliguori
 * The above copyright notice and this permission notice shall be included in
14 a672b469 aliguori
 * all copies or substantial portions of the Software.
15 a672b469 aliguori
 *
16 a672b469 aliguori
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 a672b469 aliguori
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 a672b469 aliguori
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 a672b469 aliguori
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 a672b469 aliguori
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 a672b469 aliguori
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 a672b469 aliguori
 * THE SOFTWARE.
23 a672b469 aliguori
 */
24 a672b469 aliguori
#include <unistd.h>
25 a672b469 aliguori
#include <fcntl.h>
26 a672b469 aliguori
#include <time.h>
27 a672b469 aliguori
#include <errno.h>
28 a672b469 aliguori
#include <sys/time.h>
29 a672b469 aliguori
#include <zlib.h>
30 a672b469 aliguori
31 71e72a19 Juan Quintela
/* Needed early for CONFIG_BSD etc. */
32 d40cdb10 blueswir1
#include "config-host.h"
33 d40cdb10 blueswir1
34 a672b469 aliguori
#ifndef _WIN32
35 a672b469 aliguori
#include <sys/times.h>
36 a672b469 aliguori
#include <sys/wait.h>
37 a672b469 aliguori
#include <termios.h>
38 a672b469 aliguori
#include <sys/mman.h>
39 a672b469 aliguori
#include <sys/ioctl.h>
40 a672b469 aliguori
#include <sys/resource.h>
41 a672b469 aliguori
#include <sys/socket.h>
42 a672b469 aliguori
#include <netinet/in.h>
43 a672b469 aliguori
#include <net/if.h>
44 a672b469 aliguori
#include <arpa/inet.h>
45 a672b469 aliguori
#include <dirent.h>
46 a672b469 aliguori
#include <netdb.h>
47 a672b469 aliguori
#include <sys/select.h>
48 71e72a19 Juan Quintela
#ifdef CONFIG_BSD
49 a672b469 aliguori
#include <sys/stat.h>
50 a167ba50 Aurelien Jarno
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
51 a672b469 aliguori
#include <libutil.h>
52 a672b469 aliguori
#else
53 a672b469 aliguori
#include <util.h>
54 a672b469 aliguori
#endif
55 a672b469 aliguori
#ifdef __linux__
56 a672b469 aliguori
#include <pty.h>
57 a672b469 aliguori
#include <malloc.h>
58 a672b469 aliguori
#include <linux/rtc.h>
59 a672b469 aliguori
#endif
60 a672b469 aliguori
#endif
61 a672b469 aliguori
#endif
62 a672b469 aliguori
63 a672b469 aliguori
#ifdef _WIN32
64 49dc768d aliguori
#include <windows.h>
65 a672b469 aliguori
#include <malloc.h>
66 a672b469 aliguori
#include <sys/timeb.h>
67 a672b469 aliguori
#include <mmsystem.h>
68 a672b469 aliguori
#define getopt_long_only getopt_long
69 a672b469 aliguori
#define memalign(align, size) malloc(size)
70 a672b469 aliguori
#endif
71 a672b469 aliguori
72 511d2b14 blueswir1
#include "qemu-common.h"
73 511d2b14 blueswir1
#include "hw/hw.h"
74 7685ee6a Alex Williamson
#include "hw/qdev.h"
75 511d2b14 blueswir1
#include "net.h"
76 511d2b14 blueswir1
#include "monitor.h"
77 511d2b14 blueswir1
#include "sysemu.h"
78 511d2b14 blueswir1
#include "qemu-timer.h"
79 511d2b14 blueswir1
#include "qemu-char.h"
80 511d2b14 blueswir1
#include "audio/audio.h"
81 511d2b14 blueswir1
#include "migration.h"
82 511d2b14 blueswir1
#include "qemu_socket.h"
83 72cf2d4f Blue Swirl
#include "qemu-queue.h"
84 2ff68d07 Paolo Bonzini
#include "qemu-timer.h"
85 17a4663e Blue Swirl
#include "cpus.h"
86 c5705a77 Avi Kivity
#include "memory.h"
87 511d2b14 blueswir1
88 a672b469 aliguori
#define SELF_ANNOUNCE_ROUNDS 5
89 a672b469 aliguori
90 18995b98 Nolan
#ifndef ETH_P_RARP
91 f8778a77 Stefan Berger
#define ETH_P_RARP 0x8035
92 18995b98 Nolan
#endif
93 18995b98 Nolan
#define ARP_HTYPE_ETH 0x0001
94 18995b98 Nolan
#define ARP_PTYPE_IP 0x0800
95 18995b98 Nolan
#define ARP_OP_REQUEST_REV 0x3
96 18995b98 Nolan
97 18995b98 Nolan
static int announce_self_create(uint8_t *buf,
98 a672b469 aliguori
                                uint8_t *mac_addr)
99 a672b469 aliguori
{
100 18995b98 Nolan
    /* Ethernet header. */
101 18995b98 Nolan
    memset(buf, 0xff, 6);         /* destination MAC addr */
102 18995b98 Nolan
    memcpy(buf + 6, mac_addr, 6); /* source MAC addr */
103 18995b98 Nolan
    *(uint16_t *)(buf + 12) = htons(ETH_P_RARP); /* ethertype */
104 18995b98 Nolan
105 18995b98 Nolan
    /* RARP header. */
106 18995b98 Nolan
    *(uint16_t *)(buf + 14) = htons(ARP_HTYPE_ETH); /* hardware addr space */
107 18995b98 Nolan
    *(uint16_t *)(buf + 16) = htons(ARP_PTYPE_IP); /* protocol addr space */
108 18995b98 Nolan
    *(buf + 18) = 6; /* hardware addr length (ethernet) */
109 18995b98 Nolan
    *(buf + 19) = 4; /* protocol addr length (IPv4) */
110 18995b98 Nolan
    *(uint16_t *)(buf + 20) = htons(ARP_OP_REQUEST_REV); /* opcode */
111 18995b98 Nolan
    memcpy(buf + 22, mac_addr, 6); /* source hw addr */
112 18995b98 Nolan
    memset(buf + 28, 0x00, 4);     /* source protocol addr */
113 18995b98 Nolan
    memcpy(buf + 32, mac_addr, 6); /* target hw addr */
114 18995b98 Nolan
    memset(buf + 38, 0x00, 4);     /* target protocol addr */
115 18995b98 Nolan
116 18995b98 Nolan
    /* Padding to get up to 60 bytes (ethernet min packet size, minus FCS). */
117 18995b98 Nolan
    memset(buf + 42, 0x00, 18);
118 18995b98 Nolan
119 18995b98 Nolan
    return 60; /* len (FCS will be added by hardware) */
120 a672b469 aliguori
}
121 a672b469 aliguori
122 f401ca22 Mark McLoughlin
static void qemu_announce_self_iter(NICState *nic, void *opaque)
123 a672b469 aliguori
{
124 18995b98 Nolan
    uint8_t buf[60];
125 f401ca22 Mark McLoughlin
    int len;
126 f401ca22 Mark McLoughlin
127 f401ca22 Mark McLoughlin
    len = announce_self_create(buf, nic->conf->macaddr.a);
128 f401ca22 Mark McLoughlin
129 f401ca22 Mark McLoughlin
    qemu_send_packet_raw(&nic->nc, buf, len);
130 f401ca22 Mark McLoughlin
}
131 f401ca22 Mark McLoughlin
132 f401ca22 Mark McLoughlin
133 f401ca22 Mark McLoughlin
static void qemu_announce_self_once(void *opaque)
134 f401ca22 Mark McLoughlin
{
135 ed8b330b Gleb Natapov
    static int count = SELF_ANNOUNCE_ROUNDS;
136 ed8b330b Gleb Natapov
    QEMUTimer *timer = *(QEMUTimer **)opaque;
137 a672b469 aliguori
138 f401ca22 Mark McLoughlin
    qemu_foreach_nic(qemu_announce_self_iter, NULL);
139 f401ca22 Mark McLoughlin
140 18995b98 Nolan
    if (--count) {
141 18995b98 Nolan
        /* delay 50ms, 150ms, 250ms, ... */
142 7bd427d8 Paolo Bonzini
        qemu_mod_timer(timer, qemu_get_clock_ms(rt_clock) +
143 18995b98 Nolan
                       50 + (SELF_ANNOUNCE_ROUNDS - count - 1) * 100);
144 ed8b330b Gleb Natapov
    } else {
145 ed8b330b Gleb Natapov
            qemu_del_timer(timer);
146 ed8b330b Gleb Natapov
            qemu_free_timer(timer);
147 ed8b330b Gleb Natapov
    }
148 ed8b330b Gleb Natapov
}
149 ed8b330b Gleb Natapov
150 ed8b330b Gleb Natapov
void qemu_announce_self(void)
151 ed8b330b Gleb Natapov
{
152 ed8b330b Gleb Natapov
        static QEMUTimer *timer;
153 7bd427d8 Paolo Bonzini
        timer = qemu_new_timer_ms(rt_clock, qemu_announce_self_once, &timer);
154 ed8b330b Gleb Natapov
        qemu_announce_self_once(&timer);
155 a672b469 aliguori
}
156 a672b469 aliguori
157 a672b469 aliguori
/***********************************************************/
158 a672b469 aliguori
/* savevm/loadvm support */
159 a672b469 aliguori
160 a672b469 aliguori
#define IO_BUF_SIZE 32768
161 a672b469 aliguori
162 a672b469 aliguori
struct QEMUFile {
163 a672b469 aliguori
    QEMUFilePutBufferFunc *put_buffer;
164 a672b469 aliguori
    QEMUFileGetBufferFunc *get_buffer;
165 a672b469 aliguori
    QEMUFileCloseFunc *close;
166 a672b469 aliguori
    QEMUFileRateLimit *rate_limit;
167 19629537 Glauber Costa
    QEMUFileSetRateLimit *set_rate_limit;
168 c163b5ca lirans@il.ibm.com
    QEMUFileGetRateLimit *get_rate_limit;
169 a672b469 aliguori
    void *opaque;
170 a672b469 aliguori
    int is_write;
171 a672b469 aliguori
172 a672b469 aliguori
    int64_t buf_offset; /* start of buffer when writing, end of buffer
173 a672b469 aliguori
                           when reading */
174 a672b469 aliguori
    int buf_index;
175 a672b469 aliguori
    int buf_size; /* 0 when writing */
176 a672b469 aliguori
    uint8_t buf[IO_BUF_SIZE];
177 a672b469 aliguori
178 3961b4dd Juan Quintela
    int last_error;
179 a672b469 aliguori
};
180 a672b469 aliguori
181 7f79dd28 Paolo Bonzini
typedef struct QEMUFileStdio
182 a672b469 aliguori
{
183 7f79dd28 Paolo Bonzini
    FILE *stdio_file;
184 a672b469 aliguori
    QEMUFile *file;
185 7f79dd28 Paolo Bonzini
} QEMUFileStdio;
186 a672b469 aliguori
187 a672b469 aliguori
typedef struct QEMUFileSocket
188 a672b469 aliguori
{
189 a672b469 aliguori
    int fd;
190 a672b469 aliguori
    QEMUFile *file;
191 a672b469 aliguori
} QEMUFileSocket;
192 a672b469 aliguori
193 a672b469 aliguori
static int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
194 a672b469 aliguori
{
195 a672b469 aliguori
    QEMUFileSocket *s = opaque;
196 a672b469 aliguori
    ssize_t len;
197 a672b469 aliguori
198 a672b469 aliguori
    do {
199 00aa0040 Blue Swirl
        len = qemu_recv(s->fd, buf, size, 0);
200 a672b469 aliguori
    } while (len == -1 && socket_error() == EINTR);
201 a672b469 aliguori
202 a672b469 aliguori
    if (len == -1)
203 a672b469 aliguori
        len = -socket_error();
204 a672b469 aliguori
205 a672b469 aliguori
    return len;
206 a672b469 aliguori
}
207 a672b469 aliguori
208 a672b469 aliguori
static int socket_close(void *opaque)
209 a672b469 aliguori
{
210 a672b469 aliguori
    QEMUFileSocket *s = opaque;
211 7267c094 Anthony Liguori
    g_free(s);
212 a672b469 aliguori
    return 0;
213 a672b469 aliguori
}
214 a672b469 aliguori
215 7f79dd28 Paolo Bonzini
static int stdio_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size)
216 a672b469 aliguori
{
217 7f79dd28 Paolo Bonzini
    QEMUFileStdio *s = opaque;
218 7f79dd28 Paolo Bonzini
    return fwrite(buf, 1, size, s->stdio_file);
219 a672b469 aliguori
}
220 a672b469 aliguori
221 7f79dd28 Paolo Bonzini
static int stdio_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
222 a672b469 aliguori
{
223 7f79dd28 Paolo Bonzini
    QEMUFileStdio *s = opaque;
224 7f79dd28 Paolo Bonzini
    FILE *fp = s->stdio_file;
225 8a67ec4d Uri Lublin
    int bytes;
226 8a67ec4d Uri Lublin
227 8a67ec4d Uri Lublin
    do {
228 8a67ec4d Uri Lublin
        clearerr(fp);
229 8a67ec4d Uri Lublin
        bytes = fread(buf, 1, size, fp);
230 8a67ec4d Uri Lublin
    } while ((bytes == 0) && ferror(fp) && (errno == EINTR));
231 8a67ec4d Uri Lublin
    return bytes;
232 a672b469 aliguori
}
233 a672b469 aliguori
234 7f79dd28 Paolo Bonzini
static int stdio_pclose(void *opaque)
235 7f79dd28 Paolo Bonzini
{
236 7f79dd28 Paolo Bonzini
    QEMUFileStdio *s = opaque;
237 41ef56e6 Anthony Liguori
    int ret;
238 41ef56e6 Anthony Liguori
    ret = pclose(s->stdio_file);
239 26f1af0a Eduardo Habkost
    if (ret == -1) {
240 26f1af0a Eduardo Habkost
        ret = -errno;
241 26f1af0a Eduardo Habkost
    }
242 7267c094 Anthony Liguori
    g_free(s);
243 41ef56e6 Anthony Liguori
    return ret;
244 7f79dd28 Paolo Bonzini
}
245 7f79dd28 Paolo Bonzini
246 7f79dd28 Paolo Bonzini
static int stdio_fclose(void *opaque)
247 a672b469 aliguori
{
248 7f79dd28 Paolo Bonzini
    QEMUFileStdio *s = opaque;
249 0e286705 Eduardo Habkost
    int ret = 0;
250 0e286705 Eduardo Habkost
    if (fclose(s->stdio_file) == EOF) {
251 0e286705 Eduardo Habkost
        ret = -errno;
252 0e286705 Eduardo Habkost
    }
253 7267c094 Anthony Liguori
    g_free(s);
254 0e286705 Eduardo Habkost
    return ret;
255 a672b469 aliguori
}
256 a672b469 aliguori
257 7f79dd28 Paolo Bonzini
QEMUFile *qemu_popen(FILE *stdio_file, const char *mode)
258 a672b469 aliguori
{
259 7f79dd28 Paolo Bonzini
    QEMUFileStdio *s;
260 a672b469 aliguori
261 7f79dd28 Paolo Bonzini
    if (stdio_file == NULL || mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) {
262 a672b469 aliguori
        fprintf(stderr, "qemu_popen: Argument validity check failed\n");
263 a672b469 aliguori
        return NULL;
264 a672b469 aliguori
    }
265 a672b469 aliguori
266 7267c094 Anthony Liguori
    s = g_malloc0(sizeof(QEMUFileStdio));
267 a672b469 aliguori
268 7f79dd28 Paolo Bonzini
    s->stdio_file = stdio_file;
269 a672b469 aliguori
270 a672b469 aliguori
    if(mode[0] == 'r') {
271 c163b5ca lirans@il.ibm.com
        s->file = qemu_fopen_ops(s, NULL, stdio_get_buffer, stdio_pclose, 
272 c163b5ca lirans@il.ibm.com
                                 NULL, NULL, NULL);
273 a672b469 aliguori
    } else {
274 c163b5ca lirans@il.ibm.com
        s->file = qemu_fopen_ops(s, stdio_put_buffer, NULL, stdio_pclose, 
275 c163b5ca lirans@il.ibm.com
                                 NULL, NULL, NULL);
276 a672b469 aliguori
    }
277 a672b469 aliguori
    return s->file;
278 a672b469 aliguori
}
279 a672b469 aliguori
280 a672b469 aliguori
QEMUFile *qemu_popen_cmd(const char *command, const char *mode)
281 a672b469 aliguori
{
282 a672b469 aliguori
    FILE *popen_file;
283 a672b469 aliguori
284 a672b469 aliguori
    popen_file = popen(command, mode);
285 a672b469 aliguori
    if(popen_file == NULL) {
286 a672b469 aliguori
        return NULL;
287 a672b469 aliguori
    }
288 a672b469 aliguori
289 a672b469 aliguori
    return qemu_popen(popen_file, mode);
290 a672b469 aliguori
}
291 a672b469 aliguori
292 7f79dd28 Paolo Bonzini
int qemu_stdio_fd(QEMUFile *f)
293 8a43b1ea Chris Lalancette
{
294 7f79dd28 Paolo Bonzini
    QEMUFileStdio *p;
295 8a43b1ea Chris Lalancette
    int fd;
296 8a43b1ea Chris Lalancette
297 7f79dd28 Paolo Bonzini
    p = (QEMUFileStdio *)f->opaque;
298 7f79dd28 Paolo Bonzini
    fd = fileno(p->stdio_file);
299 8a43b1ea Chris Lalancette
300 8a43b1ea Chris Lalancette
    return fd;
301 8a43b1ea Chris Lalancette
}
302 8a43b1ea Chris Lalancette
303 5ac1fad3 Paolo Bonzini
QEMUFile *qemu_fdopen(int fd, const char *mode)
304 5ac1fad3 Paolo Bonzini
{
305 5ac1fad3 Paolo Bonzini
    QEMUFileStdio *s;
306 5ac1fad3 Paolo Bonzini
307 5ac1fad3 Paolo Bonzini
    if (mode == NULL ||
308 5ac1fad3 Paolo Bonzini
        (mode[0] != 'r' && mode[0] != 'w') ||
309 5ac1fad3 Paolo Bonzini
        mode[1] != 'b' || mode[2] != 0) {
310 5ac1fad3 Paolo Bonzini
        fprintf(stderr, "qemu_fdopen: Argument validity check failed\n");
311 5ac1fad3 Paolo Bonzini
        return NULL;
312 5ac1fad3 Paolo Bonzini
    }
313 5ac1fad3 Paolo Bonzini
314 7267c094 Anthony Liguori
    s = g_malloc0(sizeof(QEMUFileStdio));
315 5ac1fad3 Paolo Bonzini
    s->stdio_file = fdopen(fd, mode);
316 5ac1fad3 Paolo Bonzini
    if (!s->stdio_file)
317 5ac1fad3 Paolo Bonzini
        goto fail;
318 5ac1fad3 Paolo Bonzini
319 5ac1fad3 Paolo Bonzini
    if(mode[0] == 'r') {
320 c163b5ca lirans@il.ibm.com
        s->file = qemu_fopen_ops(s, NULL, stdio_get_buffer, stdio_fclose, 
321 c163b5ca lirans@il.ibm.com
                                 NULL, NULL, NULL);
322 5ac1fad3 Paolo Bonzini
    } else {
323 c163b5ca lirans@il.ibm.com
        s->file = qemu_fopen_ops(s, stdio_put_buffer, NULL, stdio_fclose, 
324 c163b5ca lirans@il.ibm.com
                                 NULL, NULL, NULL);
325 5ac1fad3 Paolo Bonzini
    }
326 5ac1fad3 Paolo Bonzini
    return s->file;
327 5ac1fad3 Paolo Bonzini
328 5ac1fad3 Paolo Bonzini
fail:
329 7267c094 Anthony Liguori
    g_free(s);
330 5ac1fad3 Paolo Bonzini
    return NULL;
331 5ac1fad3 Paolo Bonzini
}
332 5ac1fad3 Paolo Bonzini
333 a672b469 aliguori
QEMUFile *qemu_fopen_socket(int fd)
334 a672b469 aliguori
{
335 7267c094 Anthony Liguori
    QEMUFileSocket *s = g_malloc0(sizeof(QEMUFileSocket));
336 a672b469 aliguori
337 a672b469 aliguori
    s->fd = fd;
338 c163b5ca lirans@il.ibm.com
    s->file = qemu_fopen_ops(s, NULL, socket_get_buffer, socket_close, 
339 c163b5ca lirans@il.ibm.com
                             NULL, NULL, NULL);
340 a672b469 aliguori
    return s->file;
341 a672b469 aliguori
}
342 a672b469 aliguori
343 a672b469 aliguori
static int file_put_buffer(void *opaque, const uint8_t *buf,
344 a672b469 aliguori
                            int64_t pos, int size)
345 a672b469 aliguori
{
346 a672b469 aliguori
    QEMUFileStdio *s = opaque;
347 7f79dd28 Paolo Bonzini
    fseek(s->stdio_file, pos, SEEK_SET);
348 5fdb3aa1 Kirill A. Shutemov
    return fwrite(buf, 1, size, s->stdio_file);
349 a672b469 aliguori
}
350 a672b469 aliguori
351 a672b469 aliguori
static int file_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
352 a672b469 aliguori
{
353 a672b469 aliguori
    QEMUFileStdio *s = opaque;
354 7f79dd28 Paolo Bonzini
    fseek(s->stdio_file, pos, SEEK_SET);
355 7f79dd28 Paolo Bonzini
    return fread(buf, 1, size, s->stdio_file);
356 a672b469 aliguori
}
357 a672b469 aliguori
358 a672b469 aliguori
QEMUFile *qemu_fopen(const char *filename, const char *mode)
359 a672b469 aliguori
{
360 a672b469 aliguori
    QEMUFileStdio *s;
361 a672b469 aliguori
362 7f79dd28 Paolo Bonzini
    if (mode == NULL ||
363 7f79dd28 Paolo Bonzini
        (mode[0] != 'r' && mode[0] != 'w') ||
364 7f79dd28 Paolo Bonzini
        mode[1] != 'b' || mode[2] != 0) {
365 090414a3 Blue Swirl
        fprintf(stderr, "qemu_fopen: Argument validity check failed\n");
366 7f79dd28 Paolo Bonzini
        return NULL;
367 7f79dd28 Paolo Bonzini
    }
368 7f79dd28 Paolo Bonzini
369 7267c094 Anthony Liguori
    s = g_malloc0(sizeof(QEMUFileStdio));
370 a672b469 aliguori
371 7f79dd28 Paolo Bonzini
    s->stdio_file = fopen(filename, mode);
372 7f79dd28 Paolo Bonzini
    if (!s->stdio_file)
373 a672b469 aliguori
        goto fail;
374 c163b5ca lirans@il.ibm.com
    
375 7f79dd28 Paolo Bonzini
    if(mode[0] == 'w') {
376 c163b5ca lirans@il.ibm.com
        s->file = qemu_fopen_ops(s, file_put_buffer, NULL, stdio_fclose, 
377 c163b5ca lirans@il.ibm.com
                                 NULL, NULL, NULL);
378 7f79dd28 Paolo Bonzini
    } else {
379 c163b5ca lirans@il.ibm.com
        s->file = qemu_fopen_ops(s, NULL, file_get_buffer, stdio_fclose, 
380 c163b5ca lirans@il.ibm.com
                               NULL, NULL, NULL);
381 7f79dd28 Paolo Bonzini
    }
382 7f79dd28 Paolo Bonzini
    return s->file;
383 a672b469 aliguori
fail:
384 7267c094 Anthony Liguori
    g_free(s);
385 a672b469 aliguori
    return NULL;
386 a672b469 aliguori
}
387 a672b469 aliguori
388 178e08a5 aliguori
static int block_put_buffer(void *opaque, const uint8_t *buf,
389 a672b469 aliguori
                           int64_t pos, int size)
390 a672b469 aliguori
{
391 45566e9c Christoph Hellwig
    bdrv_save_vmstate(opaque, buf, pos, size);
392 a672b469 aliguori
    return size;
393 a672b469 aliguori
}
394 a672b469 aliguori
395 178e08a5 aliguori
static int block_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
396 a672b469 aliguori
{
397 45566e9c Christoph Hellwig
    return bdrv_load_vmstate(opaque, buf, pos, size);
398 a672b469 aliguori
}
399 a672b469 aliguori
400 a672b469 aliguori
static int bdrv_fclose(void *opaque)
401 a672b469 aliguori
{
402 a672b469 aliguori
    return 0;
403 a672b469 aliguori
}
404 a672b469 aliguori
405 45566e9c Christoph Hellwig
static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable)
406 a672b469 aliguori
{
407 a672b469 aliguori
    if (is_writable)
408 c163b5ca lirans@il.ibm.com
        return qemu_fopen_ops(bs, block_put_buffer, NULL, bdrv_fclose, 
409 c163b5ca lirans@il.ibm.com
                              NULL, NULL, NULL);
410 c163b5ca lirans@il.ibm.com
    return qemu_fopen_ops(bs, NULL, block_get_buffer, bdrv_fclose, NULL, NULL, NULL);
411 a672b469 aliguori
}
412 a672b469 aliguori
413 a672b469 aliguori
QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer,
414 a672b469 aliguori
                         QEMUFileGetBufferFunc *get_buffer,
415 a672b469 aliguori
                         QEMUFileCloseFunc *close,
416 19629537 Glauber Costa
                         QEMUFileRateLimit *rate_limit,
417 c163b5ca lirans@il.ibm.com
                         QEMUFileSetRateLimit *set_rate_limit,
418 c163b5ca lirans@il.ibm.com
                         QEMUFileGetRateLimit *get_rate_limit)
419 a672b469 aliguori
{
420 a672b469 aliguori
    QEMUFile *f;
421 a672b469 aliguori
422 7267c094 Anthony Liguori
    f = g_malloc0(sizeof(QEMUFile));
423 a672b469 aliguori
424 a672b469 aliguori
    f->opaque = opaque;
425 a672b469 aliguori
    f->put_buffer = put_buffer;
426 a672b469 aliguori
    f->get_buffer = get_buffer;
427 a672b469 aliguori
    f->close = close;
428 a672b469 aliguori
    f->rate_limit = rate_limit;
429 19629537 Glauber Costa
    f->set_rate_limit = set_rate_limit;
430 c163b5ca lirans@il.ibm.com
    f->get_rate_limit = get_rate_limit;
431 a672b469 aliguori
    f->is_write = 0;
432 a672b469 aliguori
433 a672b469 aliguori
    return f;
434 a672b469 aliguori
}
435 a672b469 aliguori
436 624b9cc2 Juan Quintela
int qemu_file_get_error(QEMUFile *f)
437 a672b469 aliguori
{
438 3961b4dd Juan Quintela
    return f->last_error;
439 a672b469 aliguori
}
440 a672b469 aliguori
441 dcd1d224 Juan Quintela
void qemu_file_set_error(QEMUFile *f, int ret)
442 4dabe248 aliguori
{
443 3961b4dd Juan Quintela
    f->last_error = ret;
444 4dabe248 aliguori
}
445 4dabe248 aliguori
446 d82ca915 Eduardo Habkost
/** Sets last_error conditionally
447 d82ca915 Eduardo Habkost
 *
448 d82ca915 Eduardo Habkost
 * Sets last_error only if ret is negative _and_ no error
449 d82ca915 Eduardo Habkost
 * was set before.
450 d82ca915 Eduardo Habkost
 */
451 d82ca915 Eduardo Habkost
static void qemu_file_set_if_error(QEMUFile *f, int ret)
452 d82ca915 Eduardo Habkost
{
453 d82ca915 Eduardo Habkost
    if (ret < 0 && !f->last_error) {
454 d82ca915 Eduardo Habkost
        qemu_file_set_error(f, ret);
455 d82ca915 Eduardo Habkost
    }
456 d82ca915 Eduardo Habkost
}
457 d82ca915 Eduardo Habkost
458 d82ca915 Eduardo Habkost
/** Flushes QEMUFile buffer
459 d82ca915 Eduardo Habkost
 *
460 d82ca915 Eduardo Habkost
 * In case of error, last_error is set.
461 d82ca915 Eduardo Habkost
 */
462 a672b469 aliguori
void qemu_fflush(QEMUFile *f)
463 a672b469 aliguori
{
464 a672b469 aliguori
    if (!f->put_buffer)
465 a672b469 aliguori
        return;
466 a672b469 aliguori
467 a672b469 aliguori
    if (f->is_write && f->buf_index > 0) {
468 a672b469 aliguori
        int len;
469 a672b469 aliguori
470 a672b469 aliguori
        len = f->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index);
471 a672b469 aliguori
        if (len > 0)
472 a672b469 aliguori
            f->buf_offset += f->buf_index;
473 a672b469 aliguori
        else
474 c29110d5 Eduardo Habkost
            qemu_file_set_error(f, -EINVAL);
475 a672b469 aliguori
        f->buf_index = 0;
476 a672b469 aliguori
    }
477 a672b469 aliguori
}
478 a672b469 aliguori
479 a672b469 aliguori
static void qemu_fill_buffer(QEMUFile *f)
480 a672b469 aliguori
{
481 a672b469 aliguori
    int len;
482 0046c45b Juan Quintela
    int pending;
483 a672b469 aliguori
484 a672b469 aliguori
    if (!f->get_buffer)
485 a672b469 aliguori
        return;
486 a672b469 aliguori
487 a672b469 aliguori
    if (f->is_write)
488 a672b469 aliguori
        abort();
489 a672b469 aliguori
490 0046c45b Juan Quintela
    pending = f->buf_size - f->buf_index;
491 0046c45b Juan Quintela
    if (pending > 0) {
492 0046c45b Juan Quintela
        memmove(f->buf, f->buf + f->buf_index, pending);
493 0046c45b Juan Quintela
    }
494 0046c45b Juan Quintela
    f->buf_index = 0;
495 0046c45b Juan Quintela
    f->buf_size = pending;
496 0046c45b Juan Quintela
497 0046c45b Juan Quintela
    len = f->get_buffer(f->opaque, f->buf + pending, f->buf_offset,
498 0046c45b Juan Quintela
                        IO_BUF_SIZE - pending);
499 a672b469 aliguori
    if (len > 0) {
500 0046c45b Juan Quintela
        f->buf_size += len;
501 a672b469 aliguori
        f->buf_offset += len;
502 fa39a30f Juan Quintela
    } else if (len == 0) {
503 fa39a30f Juan Quintela
        f->last_error = -EIO;
504 a672b469 aliguori
    } else if (len != -EAGAIN)
505 c29110d5 Eduardo Habkost
        qemu_file_set_error(f, len);
506 a672b469 aliguori
}
507 a672b469 aliguori
508 d82ca915 Eduardo Habkost
/** Calls close function and set last_error if needed
509 d82ca915 Eduardo Habkost
 *
510 d82ca915 Eduardo Habkost
 * Internal function. qemu_fflush() must be called before this.
511 d82ca915 Eduardo Habkost
 *
512 d82ca915 Eduardo Habkost
 * Returns f->close() return value, or 0 if close function is not set.
513 d82ca915 Eduardo Habkost
 */
514 d82ca915 Eduardo Habkost
static int qemu_close(QEMUFile *f)
515 a672b469 aliguori
{
516 a672b469 aliguori
    int ret = 0;
517 d82ca915 Eduardo Habkost
    if (f->close) {
518 a672b469 aliguori
        ret = f->close(f->opaque);
519 d82ca915 Eduardo Habkost
        qemu_file_set_if_error(f, ret);
520 d82ca915 Eduardo Habkost
    }
521 d82ca915 Eduardo Habkost
    return ret;
522 d82ca915 Eduardo Habkost
}
523 d82ca915 Eduardo Habkost
524 d82ca915 Eduardo Habkost
/** Closes the file
525 d82ca915 Eduardo Habkost
 *
526 d82ca915 Eduardo Habkost
 * Returns negative error value if any error happened on previous operations or
527 d82ca915 Eduardo Habkost
 * while closing the file. Returns 0 or positive number on success.
528 d82ca915 Eduardo Habkost
 *
529 d82ca915 Eduardo Habkost
 * The meaning of return value on success depends on the specific backend
530 d82ca915 Eduardo Habkost
 * being used.
531 d82ca915 Eduardo Habkost
 */
532 d82ca915 Eduardo Habkost
int qemu_fclose(QEMUFile *f)
533 d82ca915 Eduardo Habkost
{
534 d82ca915 Eduardo Habkost
    int ret;
535 d82ca915 Eduardo Habkost
    qemu_fflush(f);
536 d82ca915 Eduardo Habkost
    ret = qemu_close(f);
537 d82ca915 Eduardo Habkost
    /* If any error was spotted before closing, we should report it
538 d82ca915 Eduardo Habkost
     * instead of the close() return value.
539 d82ca915 Eduardo Habkost
     */
540 d82ca915 Eduardo Habkost
    if (f->last_error) {
541 d82ca915 Eduardo Habkost
        ret = f->last_error;
542 d82ca915 Eduardo Habkost
    }
543 7267c094 Anthony Liguori
    g_free(f);
544 a672b469 aliguori
    return ret;
545 a672b469 aliguori
}
546 a672b469 aliguori
547 a672b469 aliguori
void qemu_file_put_notify(QEMUFile *f)
548 a672b469 aliguori
{
549 a672b469 aliguori
    f->put_buffer(f->opaque, NULL, 0, 0);
550 a672b469 aliguori
}
551 a672b469 aliguori
552 a672b469 aliguori
void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
553 a672b469 aliguori
{
554 a672b469 aliguori
    int l;
555 a672b469 aliguori
556 3961b4dd Juan Quintela
    if (!f->last_error && f->is_write == 0 && f->buf_index > 0) {
557 a672b469 aliguori
        fprintf(stderr,
558 a672b469 aliguori
                "Attempted to write to buffer while read buffer is not empty\n");
559 a672b469 aliguori
        abort();
560 a672b469 aliguori
    }
561 a672b469 aliguori
562 3961b4dd Juan Quintela
    while (!f->last_error && size > 0) {
563 a672b469 aliguori
        l = IO_BUF_SIZE - f->buf_index;
564 a672b469 aliguori
        if (l > size)
565 a672b469 aliguori
            l = size;
566 a672b469 aliguori
        memcpy(f->buf + f->buf_index, buf, l);
567 a672b469 aliguori
        f->is_write = 1;
568 a672b469 aliguori
        f->buf_index += l;
569 a672b469 aliguori
        buf += l;
570 a672b469 aliguori
        size -= l;
571 a672b469 aliguori
        if (f->buf_index >= IO_BUF_SIZE)
572 a672b469 aliguori
            qemu_fflush(f);
573 a672b469 aliguori
    }
574 a672b469 aliguori
}
575 a672b469 aliguori
576 a672b469 aliguori
void qemu_put_byte(QEMUFile *f, int v)
577 a672b469 aliguori
{
578 3961b4dd Juan Quintela
    if (!f->last_error && f->is_write == 0 && f->buf_index > 0) {
579 a672b469 aliguori
        fprintf(stderr,
580 a672b469 aliguori
                "Attempted to write to buffer while read buffer is not empty\n");
581 a672b469 aliguori
        abort();
582 a672b469 aliguori
    }
583 a672b469 aliguori
584 a672b469 aliguori
    f->buf[f->buf_index++] = v;
585 a672b469 aliguori
    f->is_write = 1;
586 a672b469 aliguori
    if (f->buf_index >= IO_BUF_SIZE)
587 a672b469 aliguori
        qemu_fflush(f);
588 a672b469 aliguori
}
589 a672b469 aliguori
590 c6380724 Juan Quintela
static void qemu_file_skip(QEMUFile *f, int size)
591 a672b469 aliguori
{
592 c6380724 Juan Quintela
    if (f->buf_index + size <= f->buf_size) {
593 c6380724 Juan Quintela
        f->buf_index += size;
594 c6380724 Juan Quintela
    }
595 c6380724 Juan Quintela
}
596 c6380724 Juan Quintela
597 c6380724 Juan Quintela
static int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset)
598 a672b469 aliguori
{
599 c6380724 Juan Quintela
    int pending;
600 c6380724 Juan Quintela
    int index;
601 a672b469 aliguori
602 b9ce1454 Juan Quintela
    if (f->is_write) {
603 a672b469 aliguori
        abort();
604 b9ce1454 Juan Quintela
    }
605 a672b469 aliguori
606 c6380724 Juan Quintela
    index = f->buf_index + offset;
607 c6380724 Juan Quintela
    pending = f->buf_size - index;
608 c6380724 Juan Quintela
    if (pending < size) {
609 c6380724 Juan Quintela
        qemu_fill_buffer(f);
610 c6380724 Juan Quintela
        index = f->buf_index + offset;
611 c6380724 Juan Quintela
        pending = f->buf_size - index;
612 c6380724 Juan Quintela
    }
613 c6380724 Juan Quintela
614 c6380724 Juan Quintela
    if (pending <= 0) {
615 c6380724 Juan Quintela
        return 0;
616 c6380724 Juan Quintela
    }
617 c6380724 Juan Quintela
    if (size > pending) {
618 c6380724 Juan Quintela
        size = pending;
619 c6380724 Juan Quintela
    }
620 c6380724 Juan Quintela
621 c6380724 Juan Quintela
    memcpy(buf, f->buf + index, size);
622 c6380724 Juan Quintela
    return size;
623 c6380724 Juan Quintela
}
624 c6380724 Juan Quintela
625 c6380724 Juan Quintela
int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
626 c6380724 Juan Quintela
{
627 c6380724 Juan Quintela
    int pending = size;
628 c6380724 Juan Quintela
    int done = 0;
629 c6380724 Juan Quintela
630 c6380724 Juan Quintela
    while (pending > 0) {
631 c6380724 Juan Quintela
        int res;
632 c6380724 Juan Quintela
633 c6380724 Juan Quintela
        res = qemu_peek_buffer(f, buf, pending, 0);
634 c6380724 Juan Quintela
        if (res == 0) {
635 c6380724 Juan Quintela
            return done;
636 a672b469 aliguori
        }
637 c6380724 Juan Quintela
        qemu_file_skip(f, res);
638 c6380724 Juan Quintela
        buf += res;
639 c6380724 Juan Quintela
        pending -= res;
640 c6380724 Juan Quintela
        done += res;
641 a672b469 aliguori
    }
642 c6380724 Juan Quintela
    return done;
643 a672b469 aliguori
}
644 a672b469 aliguori
645 c6380724 Juan Quintela
static int qemu_peek_byte(QEMUFile *f, int offset)
646 811814bd Juan Quintela
{
647 c6380724 Juan Quintela
    int index = f->buf_index + offset;
648 c6380724 Juan Quintela
649 b9ce1454 Juan Quintela
    if (f->is_write) {
650 811814bd Juan Quintela
        abort();
651 b9ce1454 Juan Quintela
    }
652 811814bd Juan Quintela
653 c6380724 Juan Quintela
    if (index >= f->buf_size) {
654 811814bd Juan Quintela
        qemu_fill_buffer(f);
655 c6380724 Juan Quintela
        index = f->buf_index + offset;
656 c6380724 Juan Quintela
        if (index >= f->buf_size) {
657 811814bd Juan Quintela
            return 0;
658 b9ce1454 Juan Quintela
        }
659 811814bd Juan Quintela
    }
660 c6380724 Juan Quintela
    return f->buf[index];
661 811814bd Juan Quintela
}
662 811814bd Juan Quintela
663 a672b469 aliguori
int qemu_get_byte(QEMUFile *f)
664 a672b469 aliguori
{
665 65f3bb3d Juan Quintela
    int result;
666 a672b469 aliguori
667 c6380724 Juan Quintela
    result = qemu_peek_byte(f, 0);
668 c6380724 Juan Quintela
    qemu_file_skip(f, 1);
669 65f3bb3d Juan Quintela
    return result;
670 a672b469 aliguori
}
671 a672b469 aliguori
672 a672b469 aliguori
int64_t qemu_ftell(QEMUFile *f)
673 a672b469 aliguori
{
674 a672b469 aliguori
    return f->buf_offset - f->buf_size + f->buf_index;
675 a672b469 aliguori
}
676 a672b469 aliguori
677 a672b469 aliguori
int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence)
678 a672b469 aliguori
{
679 a672b469 aliguori
    if (whence == SEEK_SET) {
680 a672b469 aliguori
        /* nothing to do */
681 a672b469 aliguori
    } else if (whence == SEEK_CUR) {
682 a672b469 aliguori
        pos += qemu_ftell(f);
683 a672b469 aliguori
    } else {
684 a672b469 aliguori
        /* SEEK_END not supported */
685 a672b469 aliguori
        return -1;
686 a672b469 aliguori
    }
687 a672b469 aliguori
    if (f->put_buffer) {
688 a672b469 aliguori
        qemu_fflush(f);
689 a672b469 aliguori
        f->buf_offset = pos;
690 a672b469 aliguori
    } else {
691 a672b469 aliguori
        f->buf_offset = pos;
692 a672b469 aliguori
        f->buf_index = 0;
693 a672b469 aliguori
        f->buf_size = 0;
694 a672b469 aliguori
    }
695 a672b469 aliguori
    return pos;
696 a672b469 aliguori
}
697 a672b469 aliguori
698 a672b469 aliguori
int qemu_file_rate_limit(QEMUFile *f)
699 a672b469 aliguori
{
700 a672b469 aliguori
    if (f->rate_limit)
701 a672b469 aliguori
        return f->rate_limit(f->opaque);
702 a672b469 aliguori
703 a672b469 aliguori
    return 0;
704 a672b469 aliguori
}
705 a672b469 aliguori
706 3d002df3 Michael S. Tsirkin
int64_t qemu_file_get_rate_limit(QEMUFile *f)
707 c163b5ca lirans@il.ibm.com
{
708 c163b5ca lirans@il.ibm.com
    if (f->get_rate_limit)
709 c163b5ca lirans@il.ibm.com
        return f->get_rate_limit(f->opaque);
710 c163b5ca lirans@il.ibm.com
711 c163b5ca lirans@il.ibm.com
    return 0;
712 c163b5ca lirans@il.ibm.com
}
713 c163b5ca lirans@il.ibm.com
714 3d002df3 Michael S. Tsirkin
int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate)
715 19629537 Glauber Costa
{
716 0bb05eaf Glauber Costa
    /* any failed or completed migration keeps its state to allow probing of
717 0bb05eaf Glauber Costa
     * migration data, but has no associated file anymore */
718 0bb05eaf Glauber Costa
    if (f && f->set_rate_limit)
719 19629537 Glauber Costa
        return f->set_rate_limit(f->opaque, new_rate);
720 19629537 Glauber Costa
721 19629537 Glauber Costa
    return 0;
722 19629537 Glauber Costa
}
723 19629537 Glauber Costa
724 a672b469 aliguori
void qemu_put_be16(QEMUFile *f, unsigned int v)
725 a672b469 aliguori
{
726 a672b469 aliguori
    qemu_put_byte(f, v >> 8);
727 a672b469 aliguori
    qemu_put_byte(f, v);
728 a672b469 aliguori
}
729 a672b469 aliguori
730 a672b469 aliguori
void qemu_put_be32(QEMUFile *f, unsigned int v)
731 a672b469 aliguori
{
732 a672b469 aliguori
    qemu_put_byte(f, v >> 24);
733 a672b469 aliguori
    qemu_put_byte(f, v >> 16);
734 a672b469 aliguori
    qemu_put_byte(f, v >> 8);
735 a672b469 aliguori
    qemu_put_byte(f, v);
736 a672b469 aliguori
}
737 a672b469 aliguori
738 a672b469 aliguori
void qemu_put_be64(QEMUFile *f, uint64_t v)
739 a672b469 aliguori
{
740 a672b469 aliguori
    qemu_put_be32(f, v >> 32);
741 a672b469 aliguori
    qemu_put_be32(f, v);
742 a672b469 aliguori
}
743 a672b469 aliguori
744 a672b469 aliguori
unsigned int qemu_get_be16(QEMUFile *f)
745 a672b469 aliguori
{
746 a672b469 aliguori
    unsigned int v;
747 a672b469 aliguori
    v = qemu_get_byte(f) << 8;
748 a672b469 aliguori
    v |= qemu_get_byte(f);
749 a672b469 aliguori
    return v;
750 a672b469 aliguori
}
751 a672b469 aliguori
752 a672b469 aliguori
unsigned int qemu_get_be32(QEMUFile *f)
753 a672b469 aliguori
{
754 a672b469 aliguori
    unsigned int v;
755 a672b469 aliguori
    v = qemu_get_byte(f) << 24;
756 a672b469 aliguori
    v |= qemu_get_byte(f) << 16;
757 a672b469 aliguori
    v |= qemu_get_byte(f) << 8;
758 a672b469 aliguori
    v |= qemu_get_byte(f);
759 a672b469 aliguori
    return v;
760 a672b469 aliguori
}
761 a672b469 aliguori
762 a672b469 aliguori
uint64_t qemu_get_be64(QEMUFile *f)
763 a672b469 aliguori
{
764 a672b469 aliguori
    uint64_t v;
765 a672b469 aliguori
    v = (uint64_t)qemu_get_be32(f) << 32;
766 a672b469 aliguori
    v |= qemu_get_be32(f);
767 a672b469 aliguori
    return v;
768 a672b469 aliguori
}
769 a672b469 aliguori
770 2ff68d07 Paolo Bonzini
771 2ff68d07 Paolo Bonzini
/* timer */
772 2ff68d07 Paolo Bonzini
773 2ff68d07 Paolo Bonzini
void qemu_put_timer(QEMUFile *f, QEMUTimer *ts)
774 2ff68d07 Paolo Bonzini
{
775 2ff68d07 Paolo Bonzini
    uint64_t expire_time;
776 2ff68d07 Paolo Bonzini
777 2ff68d07 Paolo Bonzini
    expire_time = qemu_timer_expire_time_ns(ts);
778 2ff68d07 Paolo Bonzini
    qemu_put_be64(f, expire_time);
779 2ff68d07 Paolo Bonzini
}
780 2ff68d07 Paolo Bonzini
781 2ff68d07 Paolo Bonzini
void qemu_get_timer(QEMUFile *f, QEMUTimer *ts)
782 2ff68d07 Paolo Bonzini
{
783 2ff68d07 Paolo Bonzini
    uint64_t expire_time;
784 2ff68d07 Paolo Bonzini
785 2ff68d07 Paolo Bonzini
    expire_time = qemu_get_be64(f);
786 2ff68d07 Paolo Bonzini
    if (expire_time != -1) {
787 2ff68d07 Paolo Bonzini
        qemu_mod_timer_ns(ts, expire_time);
788 2ff68d07 Paolo Bonzini
    } else {
789 2ff68d07 Paolo Bonzini
        qemu_del_timer(ts);
790 2ff68d07 Paolo Bonzini
    }
791 2ff68d07 Paolo Bonzini
}
792 2ff68d07 Paolo Bonzini
793 2ff68d07 Paolo Bonzini
794 cdae5cfb Gerd Hoffmann
/* bool */
795 cdae5cfb Gerd Hoffmann
796 cdae5cfb Gerd Hoffmann
static int get_bool(QEMUFile *f, void *pv, size_t size)
797 cdae5cfb Gerd Hoffmann
{
798 cdae5cfb Gerd Hoffmann
    bool *v = pv;
799 cdae5cfb Gerd Hoffmann
    *v = qemu_get_byte(f);
800 cdae5cfb Gerd Hoffmann
    return 0;
801 cdae5cfb Gerd Hoffmann
}
802 cdae5cfb Gerd Hoffmann
803 cdae5cfb Gerd Hoffmann
static void put_bool(QEMUFile *f, void *pv, size_t size)
804 cdae5cfb Gerd Hoffmann
{
805 cdae5cfb Gerd Hoffmann
    bool *v = pv;
806 cdae5cfb Gerd Hoffmann
    qemu_put_byte(f, *v);
807 cdae5cfb Gerd Hoffmann
}
808 cdae5cfb Gerd Hoffmann
809 cdae5cfb Gerd Hoffmann
const VMStateInfo vmstate_info_bool = {
810 cdae5cfb Gerd Hoffmann
    .name = "bool",
811 cdae5cfb Gerd Hoffmann
    .get  = get_bool,
812 cdae5cfb Gerd Hoffmann
    .put  = put_bool,
813 cdae5cfb Gerd Hoffmann
};
814 cdae5cfb Gerd Hoffmann
815 9ed7d6ae Juan Quintela
/* 8 bit int */
816 9ed7d6ae Juan Quintela
817 9ed7d6ae Juan Quintela
static int get_int8(QEMUFile *f, void *pv, size_t size)
818 9ed7d6ae Juan Quintela
{
819 9ed7d6ae Juan Quintela
    int8_t *v = pv;
820 9ed7d6ae Juan Quintela
    qemu_get_s8s(f, v);
821 9ed7d6ae Juan Quintela
    return 0;
822 9ed7d6ae Juan Quintela
}
823 9ed7d6ae Juan Quintela
824 84e2e3eb Juan Quintela
static void put_int8(QEMUFile *f, void *pv, size_t size)
825 9ed7d6ae Juan Quintela
{
826 84e2e3eb Juan Quintela
    int8_t *v = pv;
827 9ed7d6ae Juan Quintela
    qemu_put_s8s(f, v);
828 9ed7d6ae Juan Quintela
}
829 9ed7d6ae Juan Quintela
830 9ed7d6ae Juan Quintela
const VMStateInfo vmstate_info_int8 = {
831 9ed7d6ae Juan Quintela
    .name = "int8",
832 9ed7d6ae Juan Quintela
    .get  = get_int8,
833 9ed7d6ae Juan Quintela
    .put  = put_int8,
834 9ed7d6ae Juan Quintela
};
835 9ed7d6ae Juan Quintela
836 9ed7d6ae Juan Quintela
/* 16 bit int */
837 9ed7d6ae Juan Quintela
838 9ed7d6ae Juan Quintela
static int get_int16(QEMUFile *f, void *pv, size_t size)
839 9ed7d6ae Juan Quintela
{
840 9ed7d6ae Juan Quintela
    int16_t *v = pv;
841 9ed7d6ae Juan Quintela
    qemu_get_sbe16s(f, v);
842 9ed7d6ae Juan Quintela
    return 0;
843 9ed7d6ae Juan Quintela
}
844 9ed7d6ae Juan Quintela
845 84e2e3eb Juan Quintela
static void put_int16(QEMUFile *f, void *pv, size_t size)
846 9ed7d6ae Juan Quintela
{
847 84e2e3eb Juan Quintela
    int16_t *v = pv;
848 9ed7d6ae Juan Quintela
    qemu_put_sbe16s(f, v);
849 9ed7d6ae Juan Quintela
}
850 9ed7d6ae Juan Quintela
851 9ed7d6ae Juan Quintela
const VMStateInfo vmstate_info_int16 = {
852 9ed7d6ae Juan Quintela
    .name = "int16",
853 9ed7d6ae Juan Quintela
    .get  = get_int16,
854 9ed7d6ae Juan Quintela
    .put  = put_int16,
855 9ed7d6ae Juan Quintela
};
856 9ed7d6ae Juan Quintela
857 9ed7d6ae Juan Quintela
/* 32 bit int */
858 9ed7d6ae Juan Quintela
859 9ed7d6ae Juan Quintela
static int get_int32(QEMUFile *f, void *pv, size_t size)
860 9ed7d6ae Juan Quintela
{
861 9ed7d6ae Juan Quintela
    int32_t *v = pv;
862 9ed7d6ae Juan Quintela
    qemu_get_sbe32s(f, v);
863 9ed7d6ae Juan Quintela
    return 0;
864 9ed7d6ae Juan Quintela
}
865 9ed7d6ae Juan Quintela
866 84e2e3eb Juan Quintela
static void put_int32(QEMUFile *f, void *pv, size_t size)
867 9ed7d6ae Juan Quintela
{
868 84e2e3eb Juan Quintela
    int32_t *v = pv;
869 9ed7d6ae Juan Quintela
    qemu_put_sbe32s(f, v);
870 9ed7d6ae Juan Quintela
}
871 9ed7d6ae Juan Quintela
872 9ed7d6ae Juan Quintela
const VMStateInfo vmstate_info_int32 = {
873 9ed7d6ae Juan Quintela
    .name = "int32",
874 9ed7d6ae Juan Quintela
    .get  = get_int32,
875 9ed7d6ae Juan Quintela
    .put  = put_int32,
876 9ed7d6ae Juan Quintela
};
877 9ed7d6ae Juan Quintela
878 82501660 Juan Quintela
/* 32 bit int. See that the received value is the same than the one
879 82501660 Juan Quintela
   in the field */
880 82501660 Juan Quintela
881 82501660 Juan Quintela
static int get_int32_equal(QEMUFile *f, void *pv, size_t size)
882 82501660 Juan Quintela
{
883 82501660 Juan Quintela
    int32_t *v = pv;
884 82501660 Juan Quintela
    int32_t v2;
885 82501660 Juan Quintela
    qemu_get_sbe32s(f, &v2);
886 82501660 Juan Quintela
887 82501660 Juan Quintela
    if (*v == v2)
888 82501660 Juan Quintela
        return 0;
889 82501660 Juan Quintela
    return -EINVAL;
890 82501660 Juan Quintela
}
891 82501660 Juan Quintela
892 82501660 Juan Quintela
const VMStateInfo vmstate_info_int32_equal = {
893 82501660 Juan Quintela
    .name = "int32 equal",
894 82501660 Juan Quintela
    .get  = get_int32_equal,
895 82501660 Juan Quintela
    .put  = put_int32,
896 82501660 Juan Quintela
};
897 82501660 Juan Quintela
898 0a031e0a Juan Quintela
/* 32 bit int. See that the received value is the less or the same
899 0a031e0a Juan Quintela
   than the one in the field */
900 0a031e0a Juan Quintela
901 0a031e0a Juan Quintela
static int get_int32_le(QEMUFile *f, void *pv, size_t size)
902 0a031e0a Juan Quintela
{
903 0a031e0a Juan Quintela
    int32_t *old = pv;
904 0a031e0a Juan Quintela
    int32_t new;
905 0a031e0a Juan Quintela
    qemu_get_sbe32s(f, &new);
906 0a031e0a Juan Quintela
907 0a031e0a Juan Quintela
    if (*old <= new)
908 0a031e0a Juan Quintela
        return 0;
909 0a031e0a Juan Quintela
    return -EINVAL;
910 0a031e0a Juan Quintela
}
911 0a031e0a Juan Quintela
912 0a031e0a Juan Quintela
const VMStateInfo vmstate_info_int32_le = {
913 0a031e0a Juan Quintela
    .name = "int32 equal",
914 0a031e0a Juan Quintela
    .get  = get_int32_le,
915 0a031e0a Juan Quintela
    .put  = put_int32,
916 0a031e0a Juan Quintela
};
917 0a031e0a Juan Quintela
918 9ed7d6ae Juan Quintela
/* 64 bit int */
919 9ed7d6ae Juan Quintela
920 9ed7d6ae Juan Quintela
static int get_int64(QEMUFile *f, void *pv, size_t size)
921 9ed7d6ae Juan Quintela
{
922 9ed7d6ae Juan Quintela
    int64_t *v = pv;
923 9ed7d6ae Juan Quintela
    qemu_get_sbe64s(f, v);
924 9ed7d6ae Juan Quintela
    return 0;
925 9ed7d6ae Juan Quintela
}
926 9ed7d6ae Juan Quintela
927 84e2e3eb Juan Quintela
static void put_int64(QEMUFile *f, void *pv, size_t size)
928 9ed7d6ae Juan Quintela
{
929 84e2e3eb Juan Quintela
    int64_t *v = pv;
930 9ed7d6ae Juan Quintela
    qemu_put_sbe64s(f, v);
931 9ed7d6ae Juan Quintela
}
932 9ed7d6ae Juan Quintela
933 9ed7d6ae Juan Quintela
const VMStateInfo vmstate_info_int64 = {
934 9ed7d6ae Juan Quintela
    .name = "int64",
935 9ed7d6ae Juan Quintela
    .get  = get_int64,
936 9ed7d6ae Juan Quintela
    .put  = put_int64,
937 9ed7d6ae Juan Quintela
};
938 9ed7d6ae Juan Quintela
939 9ed7d6ae Juan Quintela
/* 8 bit unsigned int */
940 9ed7d6ae Juan Quintela
941 9ed7d6ae Juan Quintela
static int get_uint8(QEMUFile *f, void *pv, size_t size)
942 9ed7d6ae Juan Quintela
{
943 9ed7d6ae Juan Quintela
    uint8_t *v = pv;
944 9ed7d6ae Juan Quintela
    qemu_get_8s(f, v);
945 9ed7d6ae Juan Quintela
    return 0;
946 9ed7d6ae Juan Quintela
}
947 9ed7d6ae Juan Quintela
948 84e2e3eb Juan Quintela
static void put_uint8(QEMUFile *f, void *pv, size_t size)
949 9ed7d6ae Juan Quintela
{
950 84e2e3eb Juan Quintela
    uint8_t *v = pv;
951 9ed7d6ae Juan Quintela
    qemu_put_8s(f, v);
952 9ed7d6ae Juan Quintela
}
953 9ed7d6ae Juan Quintela
954 9ed7d6ae Juan Quintela
const VMStateInfo vmstate_info_uint8 = {
955 9ed7d6ae Juan Quintela
    .name = "uint8",
956 9ed7d6ae Juan Quintela
    .get  = get_uint8,
957 9ed7d6ae Juan Quintela
    .put  = put_uint8,
958 9ed7d6ae Juan Quintela
};
959 9ed7d6ae Juan Quintela
960 9ed7d6ae Juan Quintela
/* 16 bit unsigned int */
961 9ed7d6ae Juan Quintela
962 9ed7d6ae Juan Quintela
static int get_uint16(QEMUFile *f, void *pv, size_t size)
963 9ed7d6ae Juan Quintela
{
964 9ed7d6ae Juan Quintela
    uint16_t *v = pv;
965 9ed7d6ae Juan Quintela
    qemu_get_be16s(f, v);
966 9ed7d6ae Juan Quintela
    return 0;
967 9ed7d6ae Juan Quintela
}
968 9ed7d6ae Juan Quintela
969 84e2e3eb Juan Quintela
static void put_uint16(QEMUFile *f, void *pv, size_t size)
970 9ed7d6ae Juan Quintela
{
971 84e2e3eb Juan Quintela
    uint16_t *v = pv;
972 9ed7d6ae Juan Quintela
    qemu_put_be16s(f, v);
973 9ed7d6ae Juan Quintela
}
974 9ed7d6ae Juan Quintela
975 9ed7d6ae Juan Quintela
const VMStateInfo vmstate_info_uint16 = {
976 9ed7d6ae Juan Quintela
    .name = "uint16",
977 9ed7d6ae Juan Quintela
    .get  = get_uint16,
978 9ed7d6ae Juan Quintela
    .put  = put_uint16,
979 9ed7d6ae Juan Quintela
};
980 9ed7d6ae Juan Quintela
981 9ed7d6ae Juan Quintela
/* 32 bit unsigned int */
982 9ed7d6ae Juan Quintela
983 9ed7d6ae Juan Quintela
static int get_uint32(QEMUFile *f, void *pv, size_t size)
984 9ed7d6ae Juan Quintela
{
985 9ed7d6ae Juan Quintela
    uint32_t *v = pv;
986 9ed7d6ae Juan Quintela
    qemu_get_be32s(f, v);
987 9ed7d6ae Juan Quintela
    return 0;
988 9ed7d6ae Juan Quintela
}
989 9ed7d6ae Juan Quintela
990 84e2e3eb Juan Quintela
static void put_uint32(QEMUFile *f, void *pv, size_t size)
991 9ed7d6ae Juan Quintela
{
992 84e2e3eb Juan Quintela
    uint32_t *v = pv;
993 9ed7d6ae Juan Quintela
    qemu_put_be32s(f, v);
994 9ed7d6ae Juan Quintela
}
995 9ed7d6ae Juan Quintela
996 9ed7d6ae Juan Quintela
const VMStateInfo vmstate_info_uint32 = {
997 9ed7d6ae Juan Quintela
    .name = "uint32",
998 9ed7d6ae Juan Quintela
    .get  = get_uint32,
999 9ed7d6ae Juan Quintela
    .put  = put_uint32,
1000 9ed7d6ae Juan Quintela
};
1001 9ed7d6ae Juan Quintela
1002 9122a8fe Juan Quintela
/* 32 bit uint. See that the received value is the same than the one
1003 9122a8fe Juan Quintela
   in the field */
1004 9122a8fe Juan Quintela
1005 9122a8fe Juan Quintela
static int get_uint32_equal(QEMUFile *f, void *pv, size_t size)
1006 9122a8fe Juan Quintela
{
1007 9122a8fe Juan Quintela
    uint32_t *v = pv;
1008 9122a8fe Juan Quintela
    uint32_t v2;
1009 9122a8fe Juan Quintela
    qemu_get_be32s(f, &v2);
1010 9122a8fe Juan Quintela
1011 9122a8fe Juan Quintela
    if (*v == v2) {
1012 9122a8fe Juan Quintela
        return 0;
1013 9122a8fe Juan Quintela
    }
1014 9122a8fe Juan Quintela
    return -EINVAL;
1015 9122a8fe Juan Quintela
}
1016 9122a8fe Juan Quintela
1017 9122a8fe Juan Quintela
const VMStateInfo vmstate_info_uint32_equal = {
1018 9122a8fe Juan Quintela
    .name = "uint32 equal",
1019 9122a8fe Juan Quintela
    .get  = get_uint32_equal,
1020 9122a8fe Juan Quintela
    .put  = put_uint32,
1021 9122a8fe Juan Quintela
};
1022 9122a8fe Juan Quintela
1023 9ed7d6ae Juan Quintela
/* 64 bit unsigned int */
1024 9ed7d6ae Juan Quintela
1025 9ed7d6ae Juan Quintela
static int get_uint64(QEMUFile *f, void *pv, size_t size)
1026 9ed7d6ae Juan Quintela
{
1027 9ed7d6ae Juan Quintela
    uint64_t *v = pv;
1028 9ed7d6ae Juan Quintela
    qemu_get_be64s(f, v);
1029 9ed7d6ae Juan Quintela
    return 0;
1030 9ed7d6ae Juan Quintela
}
1031 9ed7d6ae Juan Quintela
1032 84e2e3eb Juan Quintela
static void put_uint64(QEMUFile *f, void *pv, size_t size)
1033 9ed7d6ae Juan Quintela
{
1034 84e2e3eb Juan Quintela
    uint64_t *v = pv;
1035 9ed7d6ae Juan Quintela
    qemu_put_be64s(f, v);
1036 9ed7d6ae Juan Quintela
}
1037 9ed7d6ae Juan Quintela
1038 9ed7d6ae Juan Quintela
const VMStateInfo vmstate_info_uint64 = {
1039 9ed7d6ae Juan Quintela
    .name = "uint64",
1040 9ed7d6ae Juan Quintela
    .get  = get_uint64,
1041 9ed7d6ae Juan Quintela
    .put  = put_uint64,
1042 9ed7d6ae Juan Quintela
};
1043 9ed7d6ae Juan Quintela
1044 80cd83e7 Juan Quintela
/* 8 bit int. See that the received value is the same than the one
1045 80cd83e7 Juan Quintela
   in the field */
1046 80cd83e7 Juan Quintela
1047 80cd83e7 Juan Quintela
static int get_uint8_equal(QEMUFile *f, void *pv, size_t size)
1048 80cd83e7 Juan Quintela
{
1049 80cd83e7 Juan Quintela
    uint8_t *v = pv;
1050 80cd83e7 Juan Quintela
    uint8_t v2;
1051 80cd83e7 Juan Quintela
    qemu_get_8s(f, &v2);
1052 80cd83e7 Juan Quintela
1053 80cd83e7 Juan Quintela
    if (*v == v2)
1054 80cd83e7 Juan Quintela
        return 0;
1055 80cd83e7 Juan Quintela
    return -EINVAL;
1056 80cd83e7 Juan Quintela
}
1057 80cd83e7 Juan Quintela
1058 80cd83e7 Juan Quintela
const VMStateInfo vmstate_info_uint8_equal = {
1059 aa1cce69 Juan Quintela
    .name = "uint8 equal",
1060 80cd83e7 Juan Quintela
    .get  = get_uint8_equal,
1061 80cd83e7 Juan Quintela
    .put  = put_uint8,
1062 80cd83e7 Juan Quintela
};
1063 80cd83e7 Juan Quintela
1064 dc3b83a0 Juan Quintela
/* 16 bit unsigned int int. See that the received value is the same than the one
1065 dc3b83a0 Juan Quintela
   in the field */
1066 dc3b83a0 Juan Quintela
1067 dc3b83a0 Juan Quintela
static int get_uint16_equal(QEMUFile *f, void *pv, size_t size)
1068 dc3b83a0 Juan Quintela
{
1069 dc3b83a0 Juan Quintela
    uint16_t *v = pv;
1070 dc3b83a0 Juan Quintela
    uint16_t v2;
1071 dc3b83a0 Juan Quintela
    qemu_get_be16s(f, &v2);
1072 dc3b83a0 Juan Quintela
1073 dc3b83a0 Juan Quintela
    if (*v == v2)
1074 dc3b83a0 Juan Quintela
        return 0;
1075 dc3b83a0 Juan Quintela
    return -EINVAL;
1076 dc3b83a0 Juan Quintela
}
1077 dc3b83a0 Juan Quintela
1078 dc3b83a0 Juan Quintela
const VMStateInfo vmstate_info_uint16_equal = {
1079 dc3b83a0 Juan Quintela
    .name = "uint16 equal",
1080 dc3b83a0 Juan Quintela
    .get  = get_uint16_equal,
1081 dc3b83a0 Juan Quintela
    .put  = put_uint16,
1082 dc3b83a0 Juan Quintela
};
1083 dc3b83a0 Juan Quintela
1084 dde0463b Juan Quintela
/* timers  */
1085 dde0463b Juan Quintela
1086 dde0463b Juan Quintela
static int get_timer(QEMUFile *f, void *pv, size_t size)
1087 dde0463b Juan Quintela
{
1088 dde0463b Juan Quintela
    QEMUTimer *v = pv;
1089 dde0463b Juan Quintela
    qemu_get_timer(f, v);
1090 dde0463b Juan Quintela
    return 0;
1091 dde0463b Juan Quintela
}
1092 dde0463b Juan Quintela
1093 84e2e3eb Juan Quintela
static void put_timer(QEMUFile *f, void *pv, size_t size)
1094 dde0463b Juan Quintela
{
1095 84e2e3eb Juan Quintela
    QEMUTimer *v = pv;
1096 dde0463b Juan Quintela
    qemu_put_timer(f, v);
1097 dde0463b Juan Quintela
}
1098 dde0463b Juan Quintela
1099 dde0463b Juan Quintela
const VMStateInfo vmstate_info_timer = {
1100 dde0463b Juan Quintela
    .name = "timer",
1101 dde0463b Juan Quintela
    .get  = get_timer,
1102 dde0463b Juan Quintela
    .put  = put_timer,
1103 dde0463b Juan Quintela
};
1104 dde0463b Juan Quintela
1105 6f67c50f Juan Quintela
/* uint8_t buffers */
1106 6f67c50f Juan Quintela
1107 6f67c50f Juan Quintela
static int get_buffer(QEMUFile *f, void *pv, size_t size)
1108 6f67c50f Juan Quintela
{
1109 6f67c50f Juan Quintela
    uint8_t *v = pv;
1110 6f67c50f Juan Quintela
    qemu_get_buffer(f, v, size);
1111 6f67c50f Juan Quintela
    return 0;
1112 6f67c50f Juan Quintela
}
1113 6f67c50f Juan Quintela
1114 84e2e3eb Juan Quintela
static void put_buffer(QEMUFile *f, void *pv, size_t size)
1115 6f67c50f Juan Quintela
{
1116 84e2e3eb Juan Quintela
    uint8_t *v = pv;
1117 6f67c50f Juan Quintela
    qemu_put_buffer(f, v, size);
1118 6f67c50f Juan Quintela
}
1119 6f67c50f Juan Quintela
1120 6f67c50f Juan Quintela
const VMStateInfo vmstate_info_buffer = {
1121 6f67c50f Juan Quintela
    .name = "buffer",
1122 6f67c50f Juan Quintela
    .get  = get_buffer,
1123 6f67c50f Juan Quintela
    .put  = put_buffer,
1124 6f67c50f Juan Quintela
};
1125 6f67c50f Juan Quintela
1126 76507c75 Juan Quintela
/* unused buffers: space that was used for some fields that are
1127 61cc8701 Stefan Weil
   not useful anymore */
1128 76507c75 Juan Quintela
1129 76507c75 Juan Quintela
static int get_unused_buffer(QEMUFile *f, void *pv, size_t size)
1130 76507c75 Juan Quintela
{
1131 21174c34 Jan Kiszka
    uint8_t buf[1024];
1132 21174c34 Jan Kiszka
    int block_len;
1133 21174c34 Jan Kiszka
1134 21174c34 Jan Kiszka
    while (size > 0) {
1135 21174c34 Jan Kiszka
        block_len = MIN(sizeof(buf), size);
1136 21174c34 Jan Kiszka
        size -= block_len;
1137 21174c34 Jan Kiszka
        qemu_get_buffer(f, buf, block_len);
1138 21174c34 Jan Kiszka
    }
1139 21174c34 Jan Kiszka
   return 0;
1140 76507c75 Juan Quintela
}
1141 76507c75 Juan Quintela
1142 76507c75 Juan Quintela
static void put_unused_buffer(QEMUFile *f, void *pv, size_t size)
1143 76507c75 Juan Quintela
{
1144 21174c34 Jan Kiszka
    static const uint8_t buf[1024];
1145 21174c34 Jan Kiszka
    int block_len;
1146 21174c34 Jan Kiszka
1147 21174c34 Jan Kiszka
    while (size > 0) {
1148 21174c34 Jan Kiszka
        block_len = MIN(sizeof(buf), size);
1149 21174c34 Jan Kiszka
        size -= block_len;
1150 21174c34 Jan Kiszka
        qemu_put_buffer(f, buf, block_len);
1151 21174c34 Jan Kiszka
    }
1152 76507c75 Juan Quintela
}
1153 76507c75 Juan Quintela
1154 76507c75 Juan Quintela
const VMStateInfo vmstate_info_unused_buffer = {
1155 76507c75 Juan Quintela
    .name = "unused_buffer",
1156 76507c75 Juan Quintela
    .get  = get_unused_buffer,
1157 76507c75 Juan Quintela
    .put  = put_unused_buffer,
1158 76507c75 Juan Quintela
};
1159 76507c75 Juan Quintela
1160 7685ee6a Alex Williamson
typedef struct CompatEntry {
1161 7685ee6a Alex Williamson
    char idstr[256];
1162 7685ee6a Alex Williamson
    int instance_id;
1163 7685ee6a Alex Williamson
} CompatEntry;
1164 7685ee6a Alex Williamson
1165 a672b469 aliguori
typedef struct SaveStateEntry {
1166 72cf2d4f Blue Swirl
    QTAILQ_ENTRY(SaveStateEntry) entry;
1167 a672b469 aliguori
    char idstr[256];
1168 a672b469 aliguori
    int instance_id;
1169 4d2ffa08 Jan Kiszka
    int alias_id;
1170 a672b469 aliguori
    int version_id;
1171 a672b469 aliguori
    int section_id;
1172 c163b5ca lirans@il.ibm.com
    SaveSetParamsHandler *set_params;
1173 a672b469 aliguori
    SaveLiveStateHandler *save_live_state;
1174 a672b469 aliguori
    SaveStateHandler *save_state;
1175 a672b469 aliguori
    LoadStateHandler *load_state;
1176 9ed7d6ae Juan Quintela
    const VMStateDescription *vmsd;
1177 a672b469 aliguori
    void *opaque;
1178 7685ee6a Alex Williamson
    CompatEntry *compat;
1179 24312968 Cam Macdonell
    int no_migrate;
1180 a672b469 aliguori
} SaveStateEntry;
1181 a672b469 aliguori
1182 c163b5ca lirans@il.ibm.com
1183 72cf2d4f Blue Swirl
static QTAILQ_HEAD(savevm_handlers, SaveStateEntry) savevm_handlers =
1184 72cf2d4f Blue Swirl
    QTAILQ_HEAD_INITIALIZER(savevm_handlers);
1185 9ed7d6ae Juan Quintela
static int global_section_id;
1186 a672b469 aliguori
1187 8718e999 Juan Quintela
static int calculate_new_instance_id(const char *idstr)
1188 8718e999 Juan Quintela
{
1189 8718e999 Juan Quintela
    SaveStateEntry *se;
1190 8718e999 Juan Quintela
    int instance_id = 0;
1191 8718e999 Juan Quintela
1192 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1193 8718e999 Juan Quintela
        if (strcmp(idstr, se->idstr) == 0
1194 8718e999 Juan Quintela
            && instance_id <= se->instance_id) {
1195 8718e999 Juan Quintela
            instance_id = se->instance_id + 1;
1196 8718e999 Juan Quintela
        }
1197 8718e999 Juan Quintela
    }
1198 8718e999 Juan Quintela
    return instance_id;
1199 8718e999 Juan Quintela
}
1200 8718e999 Juan Quintela
1201 7685ee6a Alex Williamson
static int calculate_compat_instance_id(const char *idstr)
1202 7685ee6a Alex Williamson
{
1203 7685ee6a Alex Williamson
    SaveStateEntry *se;
1204 7685ee6a Alex Williamson
    int instance_id = 0;
1205 7685ee6a Alex Williamson
1206 7685ee6a Alex Williamson
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1207 7685ee6a Alex Williamson
        if (!se->compat)
1208 7685ee6a Alex Williamson
            continue;
1209 7685ee6a Alex Williamson
1210 7685ee6a Alex Williamson
        if (strcmp(idstr, se->compat->idstr) == 0
1211 7685ee6a Alex Williamson
            && instance_id <= se->compat->instance_id) {
1212 7685ee6a Alex Williamson
            instance_id = se->compat->instance_id + 1;
1213 7685ee6a Alex Williamson
        }
1214 7685ee6a Alex Williamson
    }
1215 7685ee6a Alex Williamson
    return instance_id;
1216 7685ee6a Alex Williamson
}
1217 7685ee6a Alex Williamson
1218 a672b469 aliguori
/* TODO: Individual devices generally have very little idea about the rest
1219 a672b469 aliguori
   of the system, so instance_id should be removed/replaced.
1220 a672b469 aliguori
   Meanwhile pass -1 as instance_id if you do not already have a clearly
1221 a672b469 aliguori
   distinguishing id for all instances of your device class. */
1222 0be71e32 Alex Williamson
int register_savevm_live(DeviceState *dev,
1223 0be71e32 Alex Williamson
                         const char *idstr,
1224 a672b469 aliguori
                         int instance_id,
1225 a672b469 aliguori
                         int version_id,
1226 c163b5ca lirans@il.ibm.com
                         SaveSetParamsHandler *set_params,
1227 a672b469 aliguori
                         SaveLiveStateHandler *save_live_state,
1228 a672b469 aliguori
                         SaveStateHandler *save_state,
1229 a672b469 aliguori
                         LoadStateHandler *load_state,
1230 a672b469 aliguori
                         void *opaque)
1231 a672b469 aliguori
{
1232 8718e999 Juan Quintela
    SaveStateEntry *se;
1233 a672b469 aliguori
1234 7267c094 Anthony Liguori
    se = g_malloc0(sizeof(SaveStateEntry));
1235 a672b469 aliguori
    se->version_id = version_id;
1236 a672b469 aliguori
    se->section_id = global_section_id++;
1237 c163b5ca lirans@il.ibm.com
    se->set_params = set_params;
1238 a672b469 aliguori
    se->save_live_state = save_live_state;
1239 a672b469 aliguori
    se->save_state = save_state;
1240 a672b469 aliguori
    se->load_state = load_state;
1241 a672b469 aliguori
    se->opaque = opaque;
1242 9ed7d6ae Juan Quintela
    se->vmsd = NULL;
1243 24312968 Cam Macdonell
    se->no_migrate = 0;
1244 a672b469 aliguori
1245 7685ee6a Alex Williamson
    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
1246 7685ee6a Alex Williamson
        char *id = dev->parent_bus->info->get_dev_path(dev);
1247 7685ee6a Alex Williamson
        if (id) {
1248 7685ee6a Alex Williamson
            pstrcpy(se->idstr, sizeof(se->idstr), id);
1249 7685ee6a Alex Williamson
            pstrcat(se->idstr, sizeof(se->idstr), "/");
1250 7267c094 Anthony Liguori
            g_free(id);
1251 7685ee6a Alex Williamson
1252 7267c094 Anthony Liguori
            se->compat = g_malloc0(sizeof(CompatEntry));
1253 7685ee6a Alex Williamson
            pstrcpy(se->compat->idstr, sizeof(se->compat->idstr), idstr);
1254 7685ee6a Alex Williamson
            se->compat->instance_id = instance_id == -1 ?
1255 7685ee6a Alex Williamson
                         calculate_compat_instance_id(idstr) : instance_id;
1256 7685ee6a Alex Williamson
            instance_id = -1;
1257 7685ee6a Alex Williamson
        }
1258 7685ee6a Alex Williamson
    }
1259 7685ee6a Alex Williamson
    pstrcat(se->idstr, sizeof(se->idstr), idstr);
1260 7685ee6a Alex Williamson
1261 8718e999 Juan Quintela
    if (instance_id == -1) {
1262 7685ee6a Alex Williamson
        se->instance_id = calculate_new_instance_id(se->idstr);
1263 8718e999 Juan Quintela
    } else {
1264 8718e999 Juan Quintela
        se->instance_id = instance_id;
1265 a672b469 aliguori
    }
1266 7685ee6a Alex Williamson
    assert(!se->compat || se->instance_id == 0);
1267 8718e999 Juan Quintela
    /* add at the end of list */
1268 72cf2d4f Blue Swirl
    QTAILQ_INSERT_TAIL(&savevm_handlers, se, entry);
1269 a672b469 aliguori
    return 0;
1270 a672b469 aliguori
}
1271 a672b469 aliguori
1272 0be71e32 Alex Williamson
int register_savevm(DeviceState *dev,
1273 0be71e32 Alex Williamson
                    const char *idstr,
1274 a672b469 aliguori
                    int instance_id,
1275 a672b469 aliguori
                    int version_id,
1276 a672b469 aliguori
                    SaveStateHandler *save_state,
1277 a672b469 aliguori
                    LoadStateHandler *load_state,
1278 a672b469 aliguori
                    void *opaque)
1279 a672b469 aliguori
{
1280 0be71e32 Alex Williamson
    return register_savevm_live(dev, idstr, instance_id, version_id,
1281 c163b5ca lirans@il.ibm.com
                                NULL, NULL, save_state, load_state, opaque);
1282 a672b469 aliguori
}
1283 a672b469 aliguori
1284 0be71e32 Alex Williamson
void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
1285 41bd13af aliguori
{
1286 8718e999 Juan Quintela
    SaveStateEntry *se, *new_se;
1287 7685ee6a Alex Williamson
    char id[256] = "";
1288 7685ee6a Alex Williamson
1289 7685ee6a Alex Williamson
    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
1290 7685ee6a Alex Williamson
        char *path = dev->parent_bus->info->get_dev_path(dev);
1291 7685ee6a Alex Williamson
        if (path) {
1292 7685ee6a Alex Williamson
            pstrcpy(id, sizeof(id), path);
1293 7685ee6a Alex Williamson
            pstrcat(id, sizeof(id), "/");
1294 7267c094 Anthony Liguori
            g_free(path);
1295 7685ee6a Alex Williamson
        }
1296 7685ee6a Alex Williamson
    }
1297 7685ee6a Alex Williamson
    pstrcat(id, sizeof(id), idstr);
1298 41bd13af aliguori
1299 72cf2d4f Blue Swirl
    QTAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) {
1300 7685ee6a Alex Williamson
        if (strcmp(se->idstr, id) == 0 && se->opaque == opaque) {
1301 72cf2d4f Blue Swirl
            QTAILQ_REMOVE(&savevm_handlers, se, entry);
1302 69e58af9 Alex Williamson
            if (se->compat) {
1303 7267c094 Anthony Liguori
                g_free(se->compat);
1304 69e58af9 Alex Williamson
            }
1305 7267c094 Anthony Liguori
            g_free(se);
1306 41bd13af aliguori
        }
1307 41bd13af aliguori
    }
1308 41bd13af aliguori
}
1309 41bd13af aliguori
1310 0be71e32 Alex Williamson
int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
1311 4d2ffa08 Jan Kiszka
                                   const VMStateDescription *vmsd,
1312 4d2ffa08 Jan Kiszka
                                   void *opaque, int alias_id,
1313 4d2ffa08 Jan Kiszka
                                   int required_for_version)
1314 9ed7d6ae Juan Quintela
{
1315 8718e999 Juan Quintela
    SaveStateEntry *se;
1316 9ed7d6ae Juan Quintela
1317 4d2ffa08 Jan Kiszka
    /* If this triggers, alias support can be dropped for the vmsd. */
1318 4d2ffa08 Jan Kiszka
    assert(alias_id == -1 || required_for_version >= vmsd->minimum_version_id);
1319 4d2ffa08 Jan Kiszka
1320 7267c094 Anthony Liguori
    se = g_malloc0(sizeof(SaveStateEntry));
1321 9ed7d6ae Juan Quintela
    se->version_id = vmsd->version_id;
1322 9ed7d6ae Juan Quintela
    se->section_id = global_section_id++;
1323 9ed7d6ae Juan Quintela
    se->save_live_state = NULL;
1324 9ed7d6ae Juan Quintela
    se->save_state = NULL;
1325 9ed7d6ae Juan Quintela
    se->load_state = NULL;
1326 9ed7d6ae Juan Quintela
    se->opaque = opaque;
1327 9ed7d6ae Juan Quintela
    se->vmsd = vmsd;
1328 4d2ffa08 Jan Kiszka
    se->alias_id = alias_id;
1329 2837c8ea Gerd Hoffmann
    se->no_migrate = vmsd->unmigratable;
1330 9ed7d6ae Juan Quintela
1331 7685ee6a Alex Williamson
    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
1332 7685ee6a Alex Williamson
        char *id = dev->parent_bus->info->get_dev_path(dev);
1333 7685ee6a Alex Williamson
        if (id) {
1334 7685ee6a Alex Williamson
            pstrcpy(se->idstr, sizeof(se->idstr), id);
1335 7685ee6a Alex Williamson
            pstrcat(se->idstr, sizeof(se->idstr), "/");
1336 7267c094 Anthony Liguori
            g_free(id);
1337 7685ee6a Alex Williamson
1338 7267c094 Anthony Liguori
            se->compat = g_malloc0(sizeof(CompatEntry));
1339 7685ee6a Alex Williamson
            pstrcpy(se->compat->idstr, sizeof(se->compat->idstr), vmsd->name);
1340 7685ee6a Alex Williamson
            se->compat->instance_id = instance_id == -1 ?
1341 7685ee6a Alex Williamson
                         calculate_compat_instance_id(vmsd->name) : instance_id;
1342 7685ee6a Alex Williamson
            instance_id = -1;
1343 7685ee6a Alex Williamson
        }
1344 7685ee6a Alex Williamson
    }
1345 7685ee6a Alex Williamson
    pstrcat(se->idstr, sizeof(se->idstr), vmsd->name);
1346 7685ee6a Alex Williamson
1347 8718e999 Juan Quintela
    if (instance_id == -1) {
1348 7685ee6a Alex Williamson
        se->instance_id = calculate_new_instance_id(se->idstr);
1349 8718e999 Juan Quintela
    } else {
1350 8718e999 Juan Quintela
        se->instance_id = instance_id;
1351 9ed7d6ae Juan Quintela
    }
1352 7685ee6a Alex Williamson
    assert(!se->compat || se->instance_id == 0);
1353 8718e999 Juan Quintela
    /* add at the end of list */
1354 72cf2d4f Blue Swirl
    QTAILQ_INSERT_TAIL(&savevm_handlers, se, entry);
1355 9ed7d6ae Juan Quintela
    return 0;
1356 9ed7d6ae Juan Quintela
}
1357 9ed7d6ae Juan Quintela
1358 0be71e32 Alex Williamson
int vmstate_register(DeviceState *dev, int instance_id,
1359 0be71e32 Alex Williamson
                     const VMStateDescription *vmsd, void *opaque)
1360 4d2ffa08 Jan Kiszka
{
1361 0be71e32 Alex Williamson
    return vmstate_register_with_alias_id(dev, instance_id, vmsd,
1362 0be71e32 Alex Williamson
                                          opaque, -1, 0);
1363 4d2ffa08 Jan Kiszka
}
1364 4d2ffa08 Jan Kiszka
1365 0be71e32 Alex Williamson
void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
1366 0be71e32 Alex Williamson
                        void *opaque)
1367 9ed7d6ae Juan Quintela
{
1368 1eb7538b Juan Quintela
    SaveStateEntry *se, *new_se;
1369 1eb7538b Juan Quintela
1370 72cf2d4f Blue Swirl
    QTAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) {
1371 1eb7538b Juan Quintela
        if (se->vmsd == vmsd && se->opaque == opaque) {
1372 72cf2d4f Blue Swirl
            QTAILQ_REMOVE(&savevm_handlers, se, entry);
1373 69e58af9 Alex Williamson
            if (se->compat) {
1374 7267c094 Anthony Liguori
                g_free(se->compat);
1375 69e58af9 Alex Williamson
            }
1376 7267c094 Anthony Liguori
            g_free(se);
1377 1eb7538b Juan Quintela
        }
1378 1eb7538b Juan Quintela
    }
1379 9ed7d6ae Juan Quintela
}
1380 9ed7d6ae Juan Quintela
1381 811814bd Juan Quintela
static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
1382 811814bd Juan Quintela
                                    void *opaque);
1383 811814bd Juan Quintela
static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
1384 811814bd Juan Quintela
                                   void *opaque);
1385 811814bd Juan Quintela
1386 9ed7d6ae Juan Quintela
int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
1387 9ed7d6ae Juan Quintela
                       void *opaque, int version_id)
1388 9ed7d6ae Juan Quintela
{
1389 9ed7d6ae Juan Quintela
    VMStateField *field = vmsd->fields;
1390 811814bd Juan Quintela
    int ret;
1391 9ed7d6ae Juan Quintela
1392 9ed7d6ae Juan Quintela
    if (version_id > vmsd->version_id) {
1393 9ed7d6ae Juan Quintela
        return -EINVAL;
1394 9ed7d6ae Juan Quintela
    }
1395 9ed7d6ae Juan Quintela
    if (version_id < vmsd->minimum_version_id_old) {
1396 9ed7d6ae Juan Quintela
        return -EINVAL;
1397 9ed7d6ae Juan Quintela
    }
1398 9ed7d6ae Juan Quintela
    if  (version_id < vmsd->minimum_version_id) {
1399 9ed7d6ae Juan Quintela
        return vmsd->load_state_old(f, opaque, version_id);
1400 9ed7d6ae Juan Quintela
    }
1401 fd4d52de Juan Quintela
    if (vmsd->pre_load) {
1402 fd4d52de Juan Quintela
        int ret = vmsd->pre_load(opaque);
1403 fd4d52de Juan Quintela
        if (ret)
1404 fd4d52de Juan Quintela
            return ret;
1405 fd4d52de Juan Quintela
    }
1406 9ed7d6ae Juan Quintela
    while(field->name) {
1407 f11f6a5f Juan Quintela
        if ((field->field_exists &&
1408 f11f6a5f Juan Quintela
             field->field_exists(opaque, version_id)) ||
1409 f11f6a5f Juan Quintela
            (!field->field_exists &&
1410 f11f6a5f Juan Quintela
             field->version_id <= version_id)) {
1411 f752a6aa Juan Quintela
            void *base_addr = opaque + field->offset;
1412 811814bd Juan Quintela
            int i, n_elems = 1;
1413 e61a1e0a Juan Quintela
            int size = field->size;
1414 9ed7d6ae Juan Quintela
1415 e61a1e0a Juan Quintela
            if (field->flags & VMS_VBUFFER) {
1416 e61a1e0a Juan Quintela
                size = *(int32_t *)(opaque+field->size_offset);
1417 33599e2a Juan Quintela
                if (field->flags & VMS_MULTIPLY) {
1418 33599e2a Juan Quintela
                    size *= field->size;
1419 33599e2a Juan Quintela
                }
1420 e61a1e0a Juan Quintela
            }
1421 f752a6aa Juan Quintela
            if (field->flags & VMS_ARRAY) {
1422 f752a6aa Juan Quintela
                n_elems = field->num;
1423 d6698281 Juan Quintela
            } else if (field->flags & VMS_VARRAY_INT32) {
1424 d6698281 Juan Quintela
                n_elems = *(int32_t *)(opaque+field->num_offset);
1425 a624b086 Juan Quintela
            } else if (field->flags & VMS_VARRAY_UINT32) {
1426 a624b086 Juan Quintela
                n_elems = *(uint32_t *)(opaque+field->num_offset);
1427 bdb4941d Juan Quintela
            } else if (field->flags & VMS_VARRAY_UINT16) {
1428 bdb4941d Juan Quintela
                n_elems = *(uint16_t *)(opaque+field->num_offset);
1429 82fa39b7 Juan Quintela
            } else if (field->flags & VMS_VARRAY_UINT8) {
1430 82fa39b7 Juan Quintela
                n_elems = *(uint8_t *)(opaque+field->num_offset);
1431 f752a6aa Juan Quintela
            }
1432 dde0463b Juan Quintela
            if (field->flags & VMS_POINTER) {
1433 e61a1e0a Juan Quintela
                base_addr = *(void **)base_addr + field->start;
1434 dde0463b Juan Quintela
            }
1435 f752a6aa Juan Quintela
            for (i = 0; i < n_elems; i++) {
1436 e61a1e0a Juan Quintela
                void *addr = base_addr + size * i;
1437 ec245e21 Juan Quintela
1438 19df438b Juan Quintela
                if (field->flags & VMS_ARRAY_OF_POINTER) {
1439 19df438b Juan Quintela
                    addr = *(void **)addr;
1440 19df438b Juan Quintela
                }
1441 ec245e21 Juan Quintela
                if (field->flags & VMS_STRUCT) {
1442 fa3aad24 Juan Quintela
                    ret = vmstate_load_state(f, field->vmsd, addr, field->vmsd->version_id);
1443 ec245e21 Juan Quintela
                } else {
1444 e61a1e0a Juan Quintela
                    ret = field->info->get(f, addr, size);
1445 ec245e21 Juan Quintela
1446 ec245e21 Juan Quintela
                }
1447 f752a6aa Juan Quintela
                if (ret < 0) {
1448 f752a6aa Juan Quintela
                    return ret;
1449 f752a6aa Juan Quintela
                }
1450 9ed7d6ae Juan Quintela
            }
1451 9ed7d6ae Juan Quintela
        }
1452 9ed7d6ae Juan Quintela
        field++;
1453 9ed7d6ae Juan Quintela
    }
1454 811814bd Juan Quintela
    ret = vmstate_subsection_load(f, vmsd, opaque);
1455 811814bd Juan Quintela
    if (ret != 0) {
1456 811814bd Juan Quintela
        return ret;
1457 811814bd Juan Quintela
    }
1458 752ff2fa Juan Quintela
    if (vmsd->post_load) {
1459 e59fb374 Juan Quintela
        return vmsd->post_load(opaque, version_id);
1460 752ff2fa Juan Quintela
    }
1461 9ed7d6ae Juan Quintela
    return 0;
1462 9ed7d6ae Juan Quintela
}
1463 9ed7d6ae Juan Quintela
1464 9ed7d6ae Juan Quintela
void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
1465 84e2e3eb Juan Quintela
                        void *opaque)
1466 9ed7d6ae Juan Quintela
{
1467 9ed7d6ae Juan Quintela
    VMStateField *field = vmsd->fields;
1468 9ed7d6ae Juan Quintela
1469 8fb0791d Juan Quintela
    if (vmsd->pre_save) {
1470 8fb0791d Juan Quintela
        vmsd->pre_save(opaque);
1471 8fb0791d Juan Quintela
    }
1472 9ed7d6ae Juan Quintela
    while(field->name) {
1473 f11f6a5f Juan Quintela
        if (!field->field_exists ||
1474 f11f6a5f Juan Quintela
            field->field_exists(opaque, vmsd->version_id)) {
1475 f11f6a5f Juan Quintela
            void *base_addr = opaque + field->offset;
1476 f11f6a5f Juan Quintela
            int i, n_elems = 1;
1477 e61a1e0a Juan Quintela
            int size = field->size;
1478 dde0463b Juan Quintela
1479 e61a1e0a Juan Quintela
            if (field->flags & VMS_VBUFFER) {
1480 e61a1e0a Juan Quintela
                size = *(int32_t *)(opaque+field->size_offset);
1481 33599e2a Juan Quintela
                if (field->flags & VMS_MULTIPLY) {
1482 33599e2a Juan Quintela
                    size *= field->size;
1483 33599e2a Juan Quintela
                }
1484 e61a1e0a Juan Quintela
            }
1485 f11f6a5f Juan Quintela
            if (field->flags & VMS_ARRAY) {
1486 f11f6a5f Juan Quintela
                n_elems = field->num;
1487 d6698281 Juan Quintela
            } else if (field->flags & VMS_VARRAY_INT32) {
1488 d6698281 Juan Quintela
                n_elems = *(int32_t *)(opaque+field->num_offset);
1489 bdb4941d Juan Quintela
            } else if (field->flags & VMS_VARRAY_UINT16) {
1490 bdb4941d Juan Quintela
                n_elems = *(uint16_t *)(opaque+field->num_offset);
1491 b784421c Juan Quintela
            } else if (field->flags & VMS_VARRAY_UINT8) {
1492 b784421c Juan Quintela
                n_elems = *(uint8_t *)(opaque+field->num_offset);
1493 f11f6a5f Juan Quintela
            }
1494 f11f6a5f Juan Quintela
            if (field->flags & VMS_POINTER) {
1495 e61a1e0a Juan Quintela
                base_addr = *(void **)base_addr + field->start;
1496 f11f6a5f Juan Quintela
            }
1497 f11f6a5f Juan Quintela
            for (i = 0; i < n_elems; i++) {
1498 e61a1e0a Juan Quintela
                void *addr = base_addr + size * i;
1499 ec245e21 Juan Quintela
1500 8595387e Juan Quintela
                if (field->flags & VMS_ARRAY_OF_POINTER) {
1501 8595387e Juan Quintela
                    addr = *(void **)addr;
1502 8595387e Juan Quintela
                }
1503 f11f6a5f Juan Quintela
                if (field->flags & VMS_STRUCT) {
1504 f11f6a5f Juan Quintela
                    vmstate_save_state(f, field->vmsd, addr);
1505 f11f6a5f Juan Quintela
                } else {
1506 e61a1e0a Juan Quintela
                    field->info->put(f, addr, size);
1507 f11f6a5f Juan Quintela
                }
1508 ec245e21 Juan Quintela
            }
1509 dde0463b Juan Quintela
        }
1510 9ed7d6ae Juan Quintela
        field++;
1511 9ed7d6ae Juan Quintela
    }
1512 811814bd Juan Quintela
    vmstate_subsection_save(f, vmsd, opaque);
1513 9ed7d6ae Juan Quintela
}
1514 9ed7d6ae Juan Quintela
1515 4082be4d Juan Quintela
static int vmstate_load(QEMUFile *f, SaveStateEntry *se, int version_id)
1516 4082be4d Juan Quintela
{
1517 9ed7d6ae Juan Quintela
    if (!se->vmsd) {         /* Old style */
1518 9ed7d6ae Juan Quintela
        return se->load_state(f, se->opaque, version_id);
1519 9ed7d6ae Juan Quintela
    }
1520 9ed7d6ae Juan Quintela
    return vmstate_load_state(f, se->vmsd, se->opaque, version_id);
1521 4082be4d Juan Quintela
}
1522 4082be4d Juan Quintela
1523 dc912121 Alex Williamson
static void vmstate_save(QEMUFile *f, SaveStateEntry *se)
1524 4082be4d Juan Quintela
{
1525 9ed7d6ae Juan Quintela
    if (!se->vmsd) {         /* Old style */
1526 9ed7d6ae Juan Quintela
        se->save_state(f, se->opaque);
1527 dc912121 Alex Williamson
        return;
1528 9ed7d6ae Juan Quintela
    }
1529 9ed7d6ae Juan Quintela
    vmstate_save_state(f,se->vmsd, se->opaque);
1530 4082be4d Juan Quintela
}
1531 4082be4d Juan Quintela
1532 a672b469 aliguori
#define QEMU_VM_FILE_MAGIC           0x5145564d
1533 a672b469 aliguori
#define QEMU_VM_FILE_VERSION_COMPAT  0x00000002
1534 a672b469 aliguori
#define QEMU_VM_FILE_VERSION         0x00000003
1535 a672b469 aliguori
1536 a672b469 aliguori
#define QEMU_VM_EOF                  0x00
1537 a672b469 aliguori
#define QEMU_VM_SECTION_START        0x01
1538 a672b469 aliguori
#define QEMU_VM_SECTION_PART         0x02
1539 a672b469 aliguori
#define QEMU_VM_SECTION_END          0x03
1540 a672b469 aliguori
#define QEMU_VM_SECTION_FULL         0x04
1541 811814bd Juan Quintela
#define QEMU_VM_SUBSECTION           0x05
1542 a672b469 aliguori
1543 dc912121 Alex Williamson
bool qemu_savevm_state_blocked(Monitor *mon)
1544 dc912121 Alex Williamson
{
1545 dc912121 Alex Williamson
    SaveStateEntry *se;
1546 dc912121 Alex Williamson
1547 dc912121 Alex Williamson
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1548 dc912121 Alex Williamson
        if (se->no_migrate) {
1549 dc912121 Alex Williamson
            monitor_printf(mon, "state blocked by non-migratable device '%s'\n",
1550 dc912121 Alex Williamson
                           se->idstr);
1551 dc912121 Alex Williamson
            return true;
1552 dc912121 Alex Williamson
        }
1553 dc912121 Alex Williamson
    }
1554 dc912121 Alex Williamson
    return false;
1555 dc912121 Alex Williamson
}
1556 dc912121 Alex Williamson
1557 f327aa0c Jan Kiszka
int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
1558 f327aa0c Jan Kiszka
                            int shared)
1559 a672b469 aliguori
{
1560 a672b469 aliguori
    SaveStateEntry *se;
1561 39346385 Juan Quintela
    int ret;
1562 a672b469 aliguori
1563 c163b5ca lirans@il.ibm.com
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1564 c163b5ca lirans@il.ibm.com
        if(se->set_params == NULL) {
1565 c163b5ca lirans@il.ibm.com
            continue;
1566 c163b5ca lirans@il.ibm.com
        }
1567 c163b5ca lirans@il.ibm.com
        se->set_params(blk_enable, shared, se->opaque);
1568 c163b5ca lirans@il.ibm.com
    }
1569 c163b5ca lirans@il.ibm.com
    
1570 a672b469 aliguori
    qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
1571 a672b469 aliguori
    qemu_put_be32(f, QEMU_VM_FILE_VERSION);
1572 a672b469 aliguori
1573 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1574 a672b469 aliguori
        int len;
1575 a672b469 aliguori
1576 a672b469 aliguori
        if (se->save_live_state == NULL)
1577 a672b469 aliguori
            continue;
1578 a672b469 aliguori
1579 a672b469 aliguori
        /* Section type */
1580 a672b469 aliguori
        qemu_put_byte(f, QEMU_VM_SECTION_START);
1581 a672b469 aliguori
        qemu_put_be32(f, se->section_id);
1582 a672b469 aliguori
1583 a672b469 aliguori
        /* ID string */
1584 a672b469 aliguori
        len = strlen(se->idstr);
1585 a672b469 aliguori
        qemu_put_byte(f, len);
1586 a672b469 aliguori
        qemu_put_buffer(f, (uint8_t *)se->idstr, len);
1587 a672b469 aliguori
1588 a672b469 aliguori
        qemu_put_be32(f, se->instance_id);
1589 a672b469 aliguori
        qemu_put_be32(f, se->version_id);
1590 a672b469 aliguori
1591 2975725f Juan Quintela
        ret = se->save_live_state(mon, f, QEMU_VM_SECTION_START, se->opaque);
1592 2975725f Juan Quintela
        if (ret < 0) {
1593 2975725f Juan Quintela
            qemu_savevm_state_cancel(mon, f);
1594 2975725f Juan Quintela
            return ret;
1595 2975725f Juan Quintela
        }
1596 a672b469 aliguori
    }
1597 624b9cc2 Juan Quintela
    ret = qemu_file_get_error(f);
1598 39346385 Juan Quintela
    if (ret != 0) {
1599 f327aa0c Jan Kiszka
        qemu_savevm_state_cancel(mon, f);
1600 4ec7fcc7 Jan Kiszka
    }
1601 a672b469 aliguori
1602 39346385 Juan Quintela
    return ret;
1603 39346385 Juan Quintela
1604 a672b469 aliguori
}
1605 a672b469 aliguori
1606 39346385 Juan Quintela
/*
1607 07f35073 Dong Xu Wang
 * this function has three return values:
1608 39346385 Juan Quintela
 *   negative: there was one error, and we have -errno.
1609 39346385 Juan Quintela
 *   0 : We haven't finished, caller have to go again
1610 39346385 Juan Quintela
 *   1 : We have finished, we can go to complete phase
1611 39346385 Juan Quintela
 */
1612 f327aa0c Jan Kiszka
int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
1613 a672b469 aliguori
{
1614 a672b469 aliguori
    SaveStateEntry *se;
1615 a672b469 aliguori
    int ret = 1;
1616 a672b469 aliguori
1617 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1618 a672b469 aliguori
        if (se->save_live_state == NULL)
1619 a672b469 aliguori
            continue;
1620 a672b469 aliguori
1621 a672b469 aliguori
        /* Section type */
1622 a672b469 aliguori
        qemu_put_byte(f, QEMU_VM_SECTION_PART);
1623 a672b469 aliguori
        qemu_put_be32(f, se->section_id);
1624 a672b469 aliguori
1625 90697be8 Jan Kiszka
        ret = se->save_live_state(mon, f, QEMU_VM_SECTION_PART, se->opaque);
1626 2975725f Juan Quintela
        if (ret <= 0) {
1627 90697be8 Jan Kiszka
            /* Do not proceed to the next vmstate before this one reported
1628 90697be8 Jan Kiszka
               completion of the current stage. This serializes the migration
1629 90697be8 Jan Kiszka
               and reduces the probability that a faster changing state is
1630 90697be8 Jan Kiszka
               synchronized over and over again. */
1631 90697be8 Jan Kiszka
            break;
1632 90697be8 Jan Kiszka
        }
1633 a672b469 aliguori
    }
1634 39346385 Juan Quintela
    if (ret != 0) {
1635 39346385 Juan Quintela
        return ret;
1636 39346385 Juan Quintela
    }
1637 624b9cc2 Juan Quintela
    ret = qemu_file_get_error(f);
1638 39346385 Juan Quintela
    if (ret != 0) {
1639 f327aa0c Jan Kiszka
        qemu_savevm_state_cancel(mon, f);
1640 4ec7fcc7 Jan Kiszka
    }
1641 39346385 Juan Quintela
    return ret;
1642 a672b469 aliguori
}
1643 a672b469 aliguori
1644 f327aa0c Jan Kiszka
int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
1645 a672b469 aliguori
{
1646 a672b469 aliguori
    SaveStateEntry *se;
1647 2975725f Juan Quintela
    int ret;
1648 a672b469 aliguori
1649 ea375f9a Jan Kiszka
    cpu_synchronize_all_states();
1650 ea375f9a Jan Kiszka
1651 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1652 a672b469 aliguori
        if (se->save_live_state == NULL)
1653 a672b469 aliguori
            continue;
1654 a672b469 aliguori
1655 a672b469 aliguori
        /* Section type */
1656 a672b469 aliguori
        qemu_put_byte(f, QEMU_VM_SECTION_END);
1657 a672b469 aliguori
        qemu_put_be32(f, se->section_id);
1658 a672b469 aliguori
1659 2975725f Juan Quintela
        ret = se->save_live_state(mon, f, QEMU_VM_SECTION_END, se->opaque);
1660 2975725f Juan Quintela
        if (ret < 0) {
1661 2975725f Juan Quintela
            return ret;
1662 2975725f Juan Quintela
        }
1663 a672b469 aliguori
    }
1664 a672b469 aliguori
1665 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1666 a672b469 aliguori
        int len;
1667 a672b469 aliguori
1668 9ed7d6ae Juan Quintela
        if (se->save_state == NULL && se->vmsd == NULL)
1669 a672b469 aliguori
            continue;
1670 a672b469 aliguori
1671 a672b469 aliguori
        /* Section type */
1672 a672b469 aliguori
        qemu_put_byte(f, QEMU_VM_SECTION_FULL);
1673 a672b469 aliguori
        qemu_put_be32(f, se->section_id);
1674 a672b469 aliguori
1675 a672b469 aliguori
        /* ID string */
1676 a672b469 aliguori
        len = strlen(se->idstr);
1677 a672b469 aliguori
        qemu_put_byte(f, len);
1678 a672b469 aliguori
        qemu_put_buffer(f, (uint8_t *)se->idstr, len);
1679 a672b469 aliguori
1680 a672b469 aliguori
        qemu_put_be32(f, se->instance_id);
1681 a672b469 aliguori
        qemu_put_be32(f, se->version_id);
1682 a672b469 aliguori
1683 dc912121 Alex Williamson
        vmstate_save(f, se);
1684 a672b469 aliguori
    }
1685 a672b469 aliguori
1686 a672b469 aliguori
    qemu_put_byte(f, QEMU_VM_EOF);
1687 a672b469 aliguori
1688 624b9cc2 Juan Quintela
    return qemu_file_get_error(f);
1689 a672b469 aliguori
}
1690 a672b469 aliguori
1691 f327aa0c Jan Kiszka
void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f)
1692 4ec7fcc7 Jan Kiszka
{
1693 4ec7fcc7 Jan Kiszka
    SaveStateEntry *se;
1694 4ec7fcc7 Jan Kiszka
1695 4ec7fcc7 Jan Kiszka
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1696 4ec7fcc7 Jan Kiszka
        if (se->save_live_state) {
1697 f327aa0c Jan Kiszka
            se->save_live_state(mon, f, -1, se->opaque);
1698 4ec7fcc7 Jan Kiszka
        }
1699 4ec7fcc7 Jan Kiszka
    }
1700 4ec7fcc7 Jan Kiszka
}
1701 4ec7fcc7 Jan Kiszka
1702 f327aa0c Jan Kiszka
static int qemu_savevm_state(Monitor *mon, QEMUFile *f)
1703 a672b469 aliguori
{
1704 a672b469 aliguori
    int ret;
1705 a672b469 aliguori
1706 dc912121 Alex Williamson
    if (qemu_savevm_state_blocked(mon)) {
1707 dc912121 Alex Williamson
        ret = -EINVAL;
1708 dc912121 Alex Williamson
        goto out;
1709 dc912121 Alex Williamson
    }
1710 dc912121 Alex Williamson
1711 f327aa0c Jan Kiszka
    ret = qemu_savevm_state_begin(mon, f, 0, 0);
1712 a672b469 aliguori
    if (ret < 0)
1713 a672b469 aliguori
        goto out;
1714 a672b469 aliguori
1715 a672b469 aliguori
    do {
1716 f327aa0c Jan Kiszka
        ret = qemu_savevm_state_iterate(mon, f);
1717 a672b469 aliguori
        if (ret < 0)
1718 a672b469 aliguori
            goto out;
1719 a672b469 aliguori
    } while (ret == 0);
1720 a672b469 aliguori
1721 f327aa0c Jan Kiszka
    ret = qemu_savevm_state_complete(mon, f);
1722 a672b469 aliguori
1723 a672b469 aliguori
out:
1724 39346385 Juan Quintela
    if (ret == 0) {
1725 624b9cc2 Juan Quintela
        ret = qemu_file_get_error(f);
1726 39346385 Juan Quintela
    }
1727 a672b469 aliguori
1728 a672b469 aliguori
    return ret;
1729 a672b469 aliguori
}
1730 a672b469 aliguori
1731 a672b469 aliguori
static SaveStateEntry *find_se(const char *idstr, int instance_id)
1732 a672b469 aliguori
{
1733 a672b469 aliguori
    SaveStateEntry *se;
1734 a672b469 aliguori
1735 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1736 a672b469 aliguori
        if (!strcmp(se->idstr, idstr) &&
1737 4d2ffa08 Jan Kiszka
            (instance_id == se->instance_id ||
1738 4d2ffa08 Jan Kiszka
             instance_id == se->alias_id))
1739 a672b469 aliguori
            return se;
1740 7685ee6a Alex Williamson
        /* Migrating from an older version? */
1741 7685ee6a Alex Williamson
        if (strstr(se->idstr, idstr) && se->compat) {
1742 7685ee6a Alex Williamson
            if (!strcmp(se->compat->idstr, idstr) &&
1743 7685ee6a Alex Williamson
                (instance_id == se->compat->instance_id ||
1744 7685ee6a Alex Williamson
                 instance_id == se->alias_id))
1745 7685ee6a Alex Williamson
                return se;
1746 7685ee6a Alex Williamson
        }
1747 a672b469 aliguori
    }
1748 a672b469 aliguori
    return NULL;
1749 a672b469 aliguori
}
1750 a672b469 aliguori
1751 811814bd Juan Quintela
static const VMStateDescription *vmstate_get_subsection(const VMStateSubsection *sub, char *idstr)
1752 811814bd Juan Quintela
{
1753 811814bd Juan Quintela
    while(sub && sub->needed) {
1754 811814bd Juan Quintela
        if (strcmp(idstr, sub->vmsd->name) == 0) {
1755 811814bd Juan Quintela
            return sub->vmsd;
1756 811814bd Juan Quintela
        }
1757 811814bd Juan Quintela
        sub++;
1758 811814bd Juan Quintela
    }
1759 811814bd Juan Quintela
    return NULL;
1760 811814bd Juan Quintela
}
1761 811814bd Juan Quintela
1762 811814bd Juan Quintela
static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
1763 811814bd Juan Quintela
                                   void *opaque)
1764 811814bd Juan Quintela
{
1765 c6380724 Juan Quintela
    while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) {
1766 811814bd Juan Quintela
        char idstr[256];
1767 811814bd Juan Quintela
        int ret;
1768 c6380724 Juan Quintela
        uint8_t version_id, len, size;
1769 811814bd Juan Quintela
        const VMStateDescription *sub_vmsd;
1770 811814bd Juan Quintela
1771 c6380724 Juan Quintela
        len = qemu_peek_byte(f, 1);
1772 c6380724 Juan Quintela
        if (len < strlen(vmsd->name) + 1) {
1773 c6380724 Juan Quintela
            /* subsection name has be be "section_name/a" */
1774 c6380724 Juan Quintela
            return 0;
1775 c6380724 Juan Quintela
        }
1776 c6380724 Juan Quintela
        size = qemu_peek_buffer(f, (uint8_t *)idstr, len, 2);
1777 c6380724 Juan Quintela
        if (size != len) {
1778 c6380724 Juan Quintela
            return 0;
1779 c6380724 Juan Quintela
        }
1780 c6380724 Juan Quintela
        idstr[size] = 0;
1781 811814bd Juan Quintela
1782 c6380724 Juan Quintela
        if (strncmp(vmsd->name, idstr, strlen(vmsd->name)) != 0) {
1783 c6380724 Juan Quintela
            /* it don't have a valid subsection name */
1784 c6380724 Juan Quintela
            return 0;
1785 c6380724 Juan Quintela
        }
1786 3da9eebd Juan Quintela
        sub_vmsd = vmstate_get_subsection(vmsd->subsections, idstr);
1787 811814bd Juan Quintela
        if (sub_vmsd == NULL) {
1788 811814bd Juan Quintela
            return -ENOENT;
1789 811814bd Juan Quintela
        }
1790 c6380724 Juan Quintela
        qemu_file_skip(f, 1); /* subsection */
1791 c6380724 Juan Quintela
        qemu_file_skip(f, 1); /* len */
1792 c6380724 Juan Quintela
        qemu_file_skip(f, len); /* idstr */
1793 c6380724 Juan Quintela
        version_id = qemu_get_be32(f);
1794 c6380724 Juan Quintela
1795 811814bd Juan Quintela
        ret = vmstate_load_state(f, sub_vmsd, opaque, version_id);
1796 811814bd Juan Quintela
        if (ret) {
1797 811814bd Juan Quintela
            return ret;
1798 811814bd Juan Quintela
        }
1799 811814bd Juan Quintela
    }
1800 811814bd Juan Quintela
    return 0;
1801 811814bd Juan Quintela
}
1802 811814bd Juan Quintela
1803 811814bd Juan Quintela
static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
1804 811814bd Juan Quintela
                                    void *opaque)
1805 811814bd Juan Quintela
{
1806 811814bd Juan Quintela
    const VMStateSubsection *sub = vmsd->subsections;
1807 811814bd Juan Quintela
1808 811814bd Juan Quintela
    while (sub && sub->needed) {
1809 811814bd Juan Quintela
        if (sub->needed(opaque)) {
1810 811814bd Juan Quintela
            const VMStateDescription *vmsd = sub->vmsd;
1811 811814bd Juan Quintela
            uint8_t len;
1812 811814bd Juan Quintela
1813 811814bd Juan Quintela
            qemu_put_byte(f, QEMU_VM_SUBSECTION);
1814 811814bd Juan Quintela
            len = strlen(vmsd->name);
1815 811814bd Juan Quintela
            qemu_put_byte(f, len);
1816 811814bd Juan Quintela
            qemu_put_buffer(f, (uint8_t *)vmsd->name, len);
1817 811814bd Juan Quintela
            qemu_put_be32(f, vmsd->version_id);
1818 811814bd Juan Quintela
            vmstate_save_state(f, vmsd, opaque);
1819 811814bd Juan Quintela
        }
1820 811814bd Juan Quintela
        sub++;
1821 811814bd Juan Quintela
    }
1822 811814bd Juan Quintela
}
1823 811814bd Juan Quintela
1824 a672b469 aliguori
typedef struct LoadStateEntry {
1825 72cf2d4f Blue Swirl
    QLIST_ENTRY(LoadStateEntry) entry;
1826 a672b469 aliguori
    SaveStateEntry *se;
1827 a672b469 aliguori
    int section_id;
1828 a672b469 aliguori
    int version_id;
1829 a672b469 aliguori
} LoadStateEntry;
1830 a672b469 aliguori
1831 a672b469 aliguori
int qemu_loadvm_state(QEMUFile *f)
1832 a672b469 aliguori
{
1833 72cf2d4f Blue Swirl
    QLIST_HEAD(, LoadStateEntry) loadvm_handlers =
1834 72cf2d4f Blue Swirl
        QLIST_HEAD_INITIALIZER(loadvm_handlers);
1835 f4dbb8dd Juan Quintela
    LoadStateEntry *le, *new_le;
1836 a672b469 aliguori
    uint8_t section_type;
1837 a672b469 aliguori
    unsigned int v;
1838 a672b469 aliguori
    int ret;
1839 a672b469 aliguori
1840 dc912121 Alex Williamson
    if (qemu_savevm_state_blocked(default_mon)) {
1841 dc912121 Alex Williamson
        return -EINVAL;
1842 dc912121 Alex Williamson
    }
1843 dc912121 Alex Williamson
1844 a672b469 aliguori
    v = qemu_get_be32(f);
1845 a672b469 aliguori
    if (v != QEMU_VM_FILE_MAGIC)
1846 a672b469 aliguori
        return -EINVAL;
1847 a672b469 aliguori
1848 a672b469 aliguori
    v = qemu_get_be32(f);
1849 bbfe1408 Juan Quintela
    if (v == QEMU_VM_FILE_VERSION_COMPAT) {
1850 bbfe1408 Juan Quintela
        fprintf(stderr, "SaveVM v2 format is obsolete and don't work anymore\n");
1851 bbfe1408 Juan Quintela
        return -ENOTSUP;
1852 bbfe1408 Juan Quintela
    }
1853 a672b469 aliguori
    if (v != QEMU_VM_FILE_VERSION)
1854 a672b469 aliguori
        return -ENOTSUP;
1855 a672b469 aliguori
1856 a672b469 aliguori
    while ((section_type = qemu_get_byte(f)) != QEMU_VM_EOF) {
1857 a672b469 aliguori
        uint32_t instance_id, version_id, section_id;
1858 a672b469 aliguori
        SaveStateEntry *se;
1859 a672b469 aliguori
        char idstr[257];
1860 a672b469 aliguori
        int len;
1861 a672b469 aliguori
1862 a672b469 aliguori
        switch (section_type) {
1863 a672b469 aliguori
        case QEMU_VM_SECTION_START:
1864 a672b469 aliguori
        case QEMU_VM_SECTION_FULL:
1865 a672b469 aliguori
            /* Read section start */
1866 a672b469 aliguori
            section_id = qemu_get_be32(f);
1867 a672b469 aliguori
            len = qemu_get_byte(f);
1868 a672b469 aliguori
            qemu_get_buffer(f, (uint8_t *)idstr, len);
1869 a672b469 aliguori
            idstr[len] = 0;
1870 a672b469 aliguori
            instance_id = qemu_get_be32(f);
1871 a672b469 aliguori
            version_id = qemu_get_be32(f);
1872 a672b469 aliguori
1873 a672b469 aliguori
            /* Find savevm section */
1874 a672b469 aliguori
            se = find_se(idstr, instance_id);
1875 a672b469 aliguori
            if (se == NULL) {
1876 a672b469 aliguori
                fprintf(stderr, "Unknown savevm section or instance '%s' %d\n", idstr, instance_id);
1877 a672b469 aliguori
                ret = -EINVAL;
1878 a672b469 aliguori
                goto out;
1879 a672b469 aliguori
            }
1880 a672b469 aliguori
1881 a672b469 aliguori
            /* Validate version */
1882 a672b469 aliguori
            if (version_id > se->version_id) {
1883 a672b469 aliguori
                fprintf(stderr, "savevm: unsupported version %d for '%s' v%d\n",
1884 a672b469 aliguori
                        version_id, idstr, se->version_id);
1885 a672b469 aliguori
                ret = -EINVAL;
1886 a672b469 aliguori
                goto out;
1887 a672b469 aliguori
            }
1888 a672b469 aliguori
1889 a672b469 aliguori
            /* Add entry */
1890 7267c094 Anthony Liguori
            le = g_malloc0(sizeof(*le));
1891 a672b469 aliguori
1892 a672b469 aliguori
            le->se = se;
1893 a672b469 aliguori
            le->section_id = section_id;
1894 a672b469 aliguori
            le->version_id = version_id;
1895 72cf2d4f Blue Swirl
            QLIST_INSERT_HEAD(&loadvm_handlers, le, entry);
1896 a672b469 aliguori
1897 4082be4d Juan Quintela
            ret = vmstate_load(f, le->se, le->version_id);
1898 b5a22e4a Juan Quintela
            if (ret < 0) {
1899 b5a22e4a Juan Quintela
                fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n",
1900 b5a22e4a Juan Quintela
                        instance_id, idstr);
1901 b5a22e4a Juan Quintela
                goto out;
1902 b5a22e4a Juan Quintela
            }
1903 a672b469 aliguori
            break;
1904 a672b469 aliguori
        case QEMU_VM_SECTION_PART:
1905 a672b469 aliguori
        case QEMU_VM_SECTION_END:
1906 a672b469 aliguori
            section_id = qemu_get_be32(f);
1907 a672b469 aliguori
1908 72cf2d4f Blue Swirl
            QLIST_FOREACH(le, &loadvm_handlers, entry) {
1909 f4dbb8dd Juan Quintela
                if (le->section_id == section_id) {
1910 f4dbb8dd Juan Quintela
                    break;
1911 f4dbb8dd Juan Quintela
                }
1912 f4dbb8dd Juan Quintela
            }
1913 a672b469 aliguori
            if (le == NULL) {
1914 a672b469 aliguori
                fprintf(stderr, "Unknown savevm section %d\n", section_id);
1915 a672b469 aliguori
                ret = -EINVAL;
1916 a672b469 aliguori
                goto out;
1917 a672b469 aliguori
            }
1918 a672b469 aliguori
1919 4082be4d Juan Quintela
            ret = vmstate_load(f, le->se, le->version_id);
1920 b5a22e4a Juan Quintela
            if (ret < 0) {
1921 b5a22e4a Juan Quintela
                fprintf(stderr, "qemu: warning: error while loading state section id %d\n",
1922 b5a22e4a Juan Quintela
                        section_id);
1923 b5a22e4a Juan Quintela
                goto out;
1924 b5a22e4a Juan Quintela
            }
1925 a672b469 aliguori
            break;
1926 a672b469 aliguori
        default:
1927 a672b469 aliguori
            fprintf(stderr, "Unknown savevm section type %d\n", section_type);
1928 a672b469 aliguori
            ret = -EINVAL;
1929 a672b469 aliguori
            goto out;
1930 a672b469 aliguori
        }
1931 a672b469 aliguori
    }
1932 a672b469 aliguori
1933 ea375f9a Jan Kiszka
    cpu_synchronize_all_post_init();
1934 ea375f9a Jan Kiszka
1935 a672b469 aliguori
    ret = 0;
1936 a672b469 aliguori
1937 a672b469 aliguori
out:
1938 72cf2d4f Blue Swirl
    QLIST_FOREACH_SAFE(le, &loadvm_handlers, entry, new_le) {
1939 72cf2d4f Blue Swirl
        QLIST_REMOVE(le, entry);
1940 7267c094 Anthony Liguori
        g_free(le);
1941 a672b469 aliguori
    }
1942 a672b469 aliguori
1943 42802d47 Juan Quintela
    if (ret == 0) {
1944 42802d47 Juan Quintela
        ret = qemu_file_get_error(f);
1945 624b9cc2 Juan Quintela
    }
1946 a672b469 aliguori
1947 a672b469 aliguori
    return ret;
1948 a672b469 aliguori
}
1949 a672b469 aliguori
1950 a672b469 aliguori
static int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
1951 a672b469 aliguori
                              const char *name)
1952 a672b469 aliguori
{
1953 a672b469 aliguori
    QEMUSnapshotInfo *sn_tab, *sn;
1954 a672b469 aliguori
    int nb_sns, i, ret;
1955 a672b469 aliguori
1956 a672b469 aliguori
    ret = -ENOENT;
1957 a672b469 aliguori
    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
1958 a672b469 aliguori
    if (nb_sns < 0)
1959 a672b469 aliguori
        return ret;
1960 a672b469 aliguori
    for(i = 0; i < nb_sns; i++) {
1961 a672b469 aliguori
        sn = &sn_tab[i];
1962 a672b469 aliguori
        if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) {
1963 a672b469 aliguori
            *sn_info = *sn;
1964 a672b469 aliguori
            ret = 0;
1965 a672b469 aliguori
            break;
1966 a672b469 aliguori
        }
1967 a672b469 aliguori
    }
1968 7267c094 Anthony Liguori
    g_free(sn_tab);
1969 a672b469 aliguori
    return ret;
1970 a672b469 aliguori
}
1971 a672b469 aliguori
1972 cb499fb2 Kevin Wolf
/*
1973 cb499fb2 Kevin Wolf
 * Deletes snapshots of a given name in all opened images.
1974 cb499fb2 Kevin Wolf
 */
1975 cb499fb2 Kevin Wolf
static int del_existing_snapshots(Monitor *mon, const char *name)
1976 cb499fb2 Kevin Wolf
{
1977 cb499fb2 Kevin Wolf
    BlockDriverState *bs;
1978 cb499fb2 Kevin Wolf
    QEMUSnapshotInfo sn1, *snapshot = &sn1;
1979 cb499fb2 Kevin Wolf
    int ret;
1980 cb499fb2 Kevin Wolf
1981 dbc13590 Markus Armbruster
    bs = NULL;
1982 dbc13590 Markus Armbruster
    while ((bs = bdrv_next(bs))) {
1983 cb499fb2 Kevin Wolf
        if (bdrv_can_snapshot(bs) &&
1984 cb499fb2 Kevin Wolf
            bdrv_snapshot_find(bs, snapshot, name) >= 0)
1985 cb499fb2 Kevin Wolf
        {
1986 cb499fb2 Kevin Wolf
            ret = bdrv_snapshot_delete(bs, name);
1987 cb499fb2 Kevin Wolf
            if (ret < 0) {
1988 cb499fb2 Kevin Wolf
                monitor_printf(mon,
1989 cb499fb2 Kevin Wolf
                               "Error while deleting snapshot on '%s'\n",
1990 cb499fb2 Kevin Wolf
                               bdrv_get_device_name(bs));
1991 cb499fb2 Kevin Wolf
                return -1;
1992 cb499fb2 Kevin Wolf
            }
1993 cb499fb2 Kevin Wolf
        }
1994 cb499fb2 Kevin Wolf
    }
1995 cb499fb2 Kevin Wolf
1996 cb499fb2 Kevin Wolf
    return 0;
1997 cb499fb2 Kevin Wolf
}
1998 cb499fb2 Kevin Wolf
1999 d54908a5 Luiz Capitulino
void do_savevm(Monitor *mon, const QDict *qdict)
2000 a672b469 aliguori
{
2001 a672b469 aliguori
    BlockDriverState *bs, *bs1;
2002 a672b469 aliguori
    QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
2003 cb499fb2 Kevin Wolf
    int ret;
2004 a672b469 aliguori
    QEMUFile *f;
2005 a672b469 aliguori
    int saved_vm_running;
2006 c2c9a466 Kevin Wolf
    uint64_t vm_state_size;
2007 a672b469 aliguori
#ifdef _WIN32
2008 a672b469 aliguori
    struct _timeb tb;
2009 7d631a11 Miguel Di Ciurcio Filho
    struct tm *ptm;
2010 a672b469 aliguori
#else
2011 a672b469 aliguori
    struct timeval tv;
2012 7d631a11 Miguel Di Ciurcio Filho
    struct tm tm;
2013 a672b469 aliguori
#endif
2014 d54908a5 Luiz Capitulino
    const char *name = qdict_get_try_str(qdict, "name");
2015 a672b469 aliguori
2016 feeee5ac Miguel Di Ciurcio Filho
    /* Verify if there is a device that doesn't support snapshots and is writable */
2017 dbc13590 Markus Armbruster
    bs = NULL;
2018 dbc13590 Markus Armbruster
    while ((bs = bdrv_next(bs))) {
2019 feeee5ac Miguel Di Ciurcio Filho
2020 07b70bfb Markus Armbruster
        if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
2021 feeee5ac Miguel Di Ciurcio Filho
            continue;
2022 feeee5ac Miguel Di Ciurcio Filho
        }
2023 feeee5ac Miguel Di Ciurcio Filho
2024 feeee5ac Miguel Di Ciurcio Filho
        if (!bdrv_can_snapshot(bs)) {
2025 feeee5ac Miguel Di Ciurcio Filho
            monitor_printf(mon, "Device '%s' is writable but does not support snapshots.\n",
2026 feeee5ac Miguel Di Ciurcio Filho
                               bdrv_get_device_name(bs));
2027 feeee5ac Miguel Di Ciurcio Filho
            return;
2028 feeee5ac Miguel Di Ciurcio Filho
        }
2029 feeee5ac Miguel Di Ciurcio Filho
    }
2030 feeee5ac Miguel Di Ciurcio Filho
2031 f9092b10 Markus Armbruster
    bs = bdrv_snapshots();
2032 a672b469 aliguori
    if (!bs) {
2033 376253ec aliguori
        monitor_printf(mon, "No block device can accept snapshots\n");
2034 a672b469 aliguori
        return;
2035 a672b469 aliguori
    }
2036 a672b469 aliguori
2037 1354869c Luiz Capitulino
    saved_vm_running = runstate_is_running();
2038 0461d5a6 Luiz Capitulino
    vm_stop(RUN_STATE_SAVE_VM);
2039 a672b469 aliguori
2040 cb499fb2 Kevin Wolf
    memset(sn, 0, sizeof(*sn));
2041 a672b469 aliguori
2042 a672b469 aliguori
    /* fill auxiliary fields */
2043 a672b469 aliguori
#ifdef _WIN32
2044 a672b469 aliguori
    _ftime(&tb);
2045 a672b469 aliguori
    sn->date_sec = tb.time;
2046 a672b469 aliguori
    sn->date_nsec = tb.millitm * 1000000;
2047 a672b469 aliguori
#else
2048 a672b469 aliguori
    gettimeofday(&tv, NULL);
2049 a672b469 aliguori
    sn->date_sec = tv.tv_sec;
2050 a672b469 aliguori
    sn->date_nsec = tv.tv_usec * 1000;
2051 a672b469 aliguori
#endif
2052 74475455 Paolo Bonzini
    sn->vm_clock_nsec = qemu_get_clock_ns(vm_clock);
2053 a672b469 aliguori
2054 7d631a11 Miguel Di Ciurcio Filho
    if (name) {
2055 7d631a11 Miguel Di Ciurcio Filho
        ret = bdrv_snapshot_find(bs, old_sn, name);
2056 7d631a11 Miguel Di Ciurcio Filho
        if (ret >= 0) {
2057 7d631a11 Miguel Di Ciurcio Filho
            pstrcpy(sn->name, sizeof(sn->name), old_sn->name);
2058 7d631a11 Miguel Di Ciurcio Filho
            pstrcpy(sn->id_str, sizeof(sn->id_str), old_sn->id_str);
2059 7d631a11 Miguel Di Ciurcio Filho
        } else {
2060 7d631a11 Miguel Di Ciurcio Filho
            pstrcpy(sn->name, sizeof(sn->name), name);
2061 7d631a11 Miguel Di Ciurcio Filho
        }
2062 7d631a11 Miguel Di Ciurcio Filho
    } else {
2063 7d631a11 Miguel Di Ciurcio Filho
#ifdef _WIN32
2064 7d631a11 Miguel Di Ciurcio Filho
        ptm = localtime(&tb.time);
2065 7d631a11 Miguel Di Ciurcio Filho
        strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", ptm);
2066 7d631a11 Miguel Di Ciurcio Filho
#else
2067 d7d9b528 Blue Swirl
        /* cast below needed for OpenBSD where tv_sec is still 'long' */
2068 d7d9b528 Blue Swirl
        localtime_r((const time_t *)&tv.tv_sec, &tm);
2069 7d631a11 Miguel Di Ciurcio Filho
        strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", &tm);
2070 7d631a11 Miguel Di Ciurcio Filho
#endif
2071 7d631a11 Miguel Di Ciurcio Filho
    }
2072 7d631a11 Miguel Di Ciurcio Filho
2073 cb499fb2 Kevin Wolf
    /* Delete old snapshots of the same name */
2074 f139a412 Marcelo Tosatti
    if (name && del_existing_snapshots(mon, name) < 0) {
2075 cb499fb2 Kevin Wolf
        goto the_end;
2076 cb499fb2 Kevin Wolf
    }
2077 cb499fb2 Kevin Wolf
2078 a672b469 aliguori
    /* save the VM state */
2079 45566e9c Christoph Hellwig
    f = qemu_fopen_bdrv(bs, 1);
2080 a672b469 aliguori
    if (!f) {
2081 376253ec aliguori
        monitor_printf(mon, "Could not open VM state file\n");
2082 a672b469 aliguori
        goto the_end;
2083 a672b469 aliguori
    }
2084 f327aa0c Jan Kiszka
    ret = qemu_savevm_state(mon, f);
2085 2d22b18f aliguori
    vm_state_size = qemu_ftell(f);
2086 a672b469 aliguori
    qemu_fclose(f);
2087 a672b469 aliguori
    if (ret < 0) {
2088 376253ec aliguori
        monitor_printf(mon, "Error %d while writing VM\n", ret);
2089 a672b469 aliguori
        goto the_end;
2090 a672b469 aliguori
    }
2091 a672b469 aliguori
2092 a672b469 aliguori
    /* create the snapshots */
2093 a672b469 aliguori
2094 dbc13590 Markus Armbruster
    bs1 = NULL;
2095 dbc13590 Markus Armbruster
    while ((bs1 = bdrv_next(bs1))) {
2096 feeee5ac Miguel Di Ciurcio Filho
        if (bdrv_can_snapshot(bs1)) {
2097 2d22b18f aliguori
            /* Write VM state size only to the image that contains the state */
2098 2d22b18f aliguori
            sn->vm_state_size = (bs == bs1 ? vm_state_size : 0);
2099 a672b469 aliguori
            ret = bdrv_snapshot_create(bs1, sn);
2100 a672b469 aliguori
            if (ret < 0) {
2101 376253ec aliguori
                monitor_printf(mon, "Error while creating snapshot on '%s'\n",
2102 376253ec aliguori
                               bdrv_get_device_name(bs1));
2103 a672b469 aliguori
            }
2104 a672b469 aliguori
        }
2105 a672b469 aliguori
    }
2106 a672b469 aliguori
2107 a672b469 aliguori
 the_end:
2108 a672b469 aliguori
    if (saved_vm_running)
2109 a672b469 aliguori
        vm_start();
2110 a672b469 aliguori
}
2111 a672b469 aliguori
2112 03cd4655 Markus Armbruster
int load_vmstate(const char *name)
2113 a672b469 aliguori
{
2114 f0aa7a8b Miguel Di Ciurcio Filho
    BlockDriverState *bs, *bs_vm_state;
2115 2d22b18f aliguori
    QEMUSnapshotInfo sn;
2116 a672b469 aliguori
    QEMUFile *f;
2117 751c6a17 Gerd Hoffmann
    int ret;
2118 a672b469 aliguori
2119 f0aa7a8b Miguel Di Ciurcio Filho
    bs_vm_state = bdrv_snapshots();
2120 f0aa7a8b Miguel Di Ciurcio Filho
    if (!bs_vm_state) {
2121 f0aa7a8b Miguel Di Ciurcio Filho
        error_report("No block device supports snapshots");
2122 f0aa7a8b Miguel Di Ciurcio Filho
        return -ENOTSUP;
2123 f0aa7a8b Miguel Di Ciurcio Filho
    }
2124 f0aa7a8b Miguel Di Ciurcio Filho
2125 f0aa7a8b Miguel Di Ciurcio Filho
    /* Don't even try to load empty VM states */
2126 f0aa7a8b Miguel Di Ciurcio Filho
    ret = bdrv_snapshot_find(bs_vm_state, &sn, name);
2127 f0aa7a8b Miguel Di Ciurcio Filho
    if (ret < 0) {
2128 f0aa7a8b Miguel Di Ciurcio Filho
        return ret;
2129 f0aa7a8b Miguel Di Ciurcio Filho
    } else if (sn.vm_state_size == 0) {
2130 e11480db Kevin Wolf
        error_report("This is a disk-only snapshot. Revert to it offline "
2131 e11480db Kevin Wolf
            "using qemu-img.");
2132 f0aa7a8b Miguel Di Ciurcio Filho
        return -EINVAL;
2133 f0aa7a8b Miguel Di Ciurcio Filho
    }
2134 f0aa7a8b Miguel Di Ciurcio Filho
2135 f0aa7a8b Miguel Di Ciurcio Filho
    /* Verify if there is any device that doesn't support snapshots and is
2136 f0aa7a8b Miguel Di Ciurcio Filho
    writable and check if the requested snapshot is available too. */
2137 dbc13590 Markus Armbruster
    bs = NULL;
2138 dbc13590 Markus Armbruster
    while ((bs = bdrv_next(bs))) {
2139 feeee5ac Miguel Di Ciurcio Filho
2140 07b70bfb Markus Armbruster
        if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
2141 feeee5ac Miguel Di Ciurcio Filho
            continue;
2142 feeee5ac Miguel Di Ciurcio Filho
        }
2143 feeee5ac Miguel Di Ciurcio Filho
2144 feeee5ac Miguel Di Ciurcio Filho
        if (!bdrv_can_snapshot(bs)) {
2145 feeee5ac Miguel Di Ciurcio Filho
            error_report("Device '%s' is writable but does not support snapshots.",
2146 feeee5ac Miguel Di Ciurcio Filho
                               bdrv_get_device_name(bs));
2147 feeee5ac Miguel Di Ciurcio Filho
            return -ENOTSUP;
2148 feeee5ac Miguel Di Ciurcio Filho
        }
2149 feeee5ac Miguel Di Ciurcio Filho
2150 f0aa7a8b Miguel Di Ciurcio Filho
        ret = bdrv_snapshot_find(bs, &sn, name);
2151 f0aa7a8b Miguel Di Ciurcio Filho
        if (ret < 0) {
2152 f0aa7a8b Miguel Di Ciurcio Filho
            error_report("Device '%s' does not have the requested snapshot '%s'",
2153 f0aa7a8b Miguel Di Ciurcio Filho
                           bdrv_get_device_name(bs), name);
2154 f0aa7a8b Miguel Di Ciurcio Filho
            return ret;
2155 f0aa7a8b Miguel Di Ciurcio Filho
        }
2156 a672b469 aliguori
    }
2157 a672b469 aliguori
2158 a672b469 aliguori
    /* Flush all IO requests so they don't interfere with the new state.  */
2159 922453bc Stefan Hajnoczi
    bdrv_drain_all();
2160 a672b469 aliguori
2161 f0aa7a8b Miguel Di Ciurcio Filho
    bs = NULL;
2162 f0aa7a8b Miguel Di Ciurcio Filho
    while ((bs = bdrv_next(bs))) {
2163 f0aa7a8b Miguel Di Ciurcio Filho
        if (bdrv_can_snapshot(bs)) {
2164 f0aa7a8b Miguel Di Ciurcio Filho
            ret = bdrv_snapshot_goto(bs, name);
2165 a672b469 aliguori
            if (ret < 0) {
2166 f0aa7a8b Miguel Di Ciurcio Filho
                error_report("Error %d while activating snapshot '%s' on '%s'",
2167 f0aa7a8b Miguel Di Ciurcio Filho
                             ret, name, bdrv_get_device_name(bs));
2168 f0aa7a8b Miguel Di Ciurcio Filho
                return ret;
2169 a672b469 aliguori
            }
2170 a672b469 aliguori
        }
2171 a672b469 aliguori
    }
2172 a672b469 aliguori
2173 a672b469 aliguori
    /* restore the VM state */
2174 f0aa7a8b Miguel Di Ciurcio Filho
    f = qemu_fopen_bdrv(bs_vm_state, 0);
2175 a672b469 aliguori
    if (!f) {
2176 1ecda02b Markus Armbruster
        error_report("Could not open VM state file");
2177 05f2401e Juan Quintela
        return -EINVAL;
2178 a672b469 aliguori
    }
2179 f0aa7a8b Miguel Di Ciurcio Filho
2180 5a8a49d7 Jan Kiszka
    qemu_system_reset(VMRESET_SILENT);
2181 a672b469 aliguori
    ret = qemu_loadvm_state(f);
2182 f0aa7a8b Miguel Di Ciurcio Filho
2183 a672b469 aliguori
    qemu_fclose(f);
2184 a672b469 aliguori
    if (ret < 0) {
2185 1ecda02b Markus Armbruster
        error_report("Error %d while loading VM state", ret);
2186 05f2401e Juan Quintela
        return ret;
2187 a672b469 aliguori
    }
2188 f0aa7a8b Miguel Di Ciurcio Filho
2189 05f2401e Juan Quintela
    return 0;
2190 7b630349 Juan Quintela
}
2191 7b630349 Juan Quintela
2192 d54908a5 Luiz Capitulino
void do_delvm(Monitor *mon, const QDict *qdict)
2193 a672b469 aliguori
{
2194 a672b469 aliguori
    BlockDriverState *bs, *bs1;
2195 751c6a17 Gerd Hoffmann
    int ret;
2196 d54908a5 Luiz Capitulino
    const char *name = qdict_get_str(qdict, "name");
2197 a672b469 aliguori
2198 f9092b10 Markus Armbruster
    bs = bdrv_snapshots();
2199 a672b469 aliguori
    if (!bs) {
2200 376253ec aliguori
        monitor_printf(mon, "No block device supports snapshots\n");
2201 a672b469 aliguori
        return;
2202 a672b469 aliguori
    }
2203 a672b469 aliguori
2204 dbc13590 Markus Armbruster
    bs1 = NULL;
2205 dbc13590 Markus Armbruster
    while ((bs1 = bdrv_next(bs1))) {
2206 feeee5ac Miguel Di Ciurcio Filho
        if (bdrv_can_snapshot(bs1)) {
2207 a672b469 aliguori
            ret = bdrv_snapshot_delete(bs1, name);
2208 a672b469 aliguori
            if (ret < 0) {
2209 a672b469 aliguori
                if (ret == -ENOTSUP)
2210 376253ec aliguori
                    monitor_printf(mon,
2211 376253ec aliguori
                                   "Snapshots not supported on device '%s'\n",
2212 376253ec aliguori
                                   bdrv_get_device_name(bs1));
2213 a672b469 aliguori
                else
2214 376253ec aliguori
                    monitor_printf(mon, "Error %d while deleting snapshot on "
2215 376253ec aliguori
                                   "'%s'\n", ret, bdrv_get_device_name(bs1));
2216 a672b469 aliguori
            }
2217 a672b469 aliguori
        }
2218 a672b469 aliguori
    }
2219 a672b469 aliguori
}
2220 a672b469 aliguori
2221 376253ec aliguori
void do_info_snapshots(Monitor *mon)
2222 a672b469 aliguori
{
2223 a672b469 aliguori
    BlockDriverState *bs, *bs1;
2224 f9209915 Miguel Di Ciurcio Filho
    QEMUSnapshotInfo *sn_tab, *sn, s, *sn_info = &s;
2225 f9209915 Miguel Di Ciurcio Filho
    int nb_sns, i, ret, available;
2226 f9209915 Miguel Di Ciurcio Filho
    int total;
2227 f9209915 Miguel Di Ciurcio Filho
    int *available_snapshots;
2228 a672b469 aliguori
    char buf[256];
2229 a672b469 aliguori
2230 f9092b10 Markus Armbruster
    bs = bdrv_snapshots();
2231 a672b469 aliguori
    if (!bs) {
2232 376253ec aliguori
        monitor_printf(mon, "No available block device supports snapshots\n");
2233 a672b469 aliguori
        return;
2234 a672b469 aliguori
    }
2235 a672b469 aliguori
2236 a672b469 aliguori
    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
2237 a672b469 aliguori
    if (nb_sns < 0) {
2238 376253ec aliguori
        monitor_printf(mon, "bdrv_snapshot_list: error %d\n", nb_sns);
2239 a672b469 aliguori
        return;
2240 a672b469 aliguori
    }
2241 f9209915 Miguel Di Ciurcio Filho
2242 f9209915 Miguel Di Ciurcio Filho
    if (nb_sns == 0) {
2243 f9209915 Miguel Di Ciurcio Filho
        monitor_printf(mon, "There is no snapshot available.\n");
2244 f9209915 Miguel Di Ciurcio Filho
        return;
2245 f9209915 Miguel Di Ciurcio Filho
    }
2246 f9209915 Miguel Di Ciurcio Filho
2247 7267c094 Anthony Liguori
    available_snapshots = g_malloc0(sizeof(int) * nb_sns);
2248 f9209915 Miguel Di Ciurcio Filho
    total = 0;
2249 f9209915 Miguel Di Ciurcio Filho
    for (i = 0; i < nb_sns; i++) {
2250 a672b469 aliguori
        sn = &sn_tab[i];
2251 f9209915 Miguel Di Ciurcio Filho
        available = 1;
2252 f9209915 Miguel Di Ciurcio Filho
        bs1 = NULL;
2253 f9209915 Miguel Di Ciurcio Filho
2254 f9209915 Miguel Di Ciurcio Filho
        while ((bs1 = bdrv_next(bs1))) {
2255 f9209915 Miguel Di Ciurcio Filho
            if (bdrv_can_snapshot(bs1) && bs1 != bs) {
2256 f9209915 Miguel Di Ciurcio Filho
                ret = bdrv_snapshot_find(bs1, sn_info, sn->id_str);
2257 f9209915 Miguel Di Ciurcio Filho
                if (ret < 0) {
2258 f9209915 Miguel Di Ciurcio Filho
                    available = 0;
2259 f9209915 Miguel Di Ciurcio Filho
                    break;
2260 f9209915 Miguel Di Ciurcio Filho
                }
2261 f9209915 Miguel Di Ciurcio Filho
            }
2262 f9209915 Miguel Di Ciurcio Filho
        }
2263 f9209915 Miguel Di Ciurcio Filho
2264 f9209915 Miguel Di Ciurcio Filho
        if (available) {
2265 f9209915 Miguel Di Ciurcio Filho
            available_snapshots[total] = i;
2266 f9209915 Miguel Di Ciurcio Filho
            total++;
2267 f9209915 Miguel Di Ciurcio Filho
        }
2268 a672b469 aliguori
    }
2269 f9209915 Miguel Di Ciurcio Filho
2270 f9209915 Miguel Di Ciurcio Filho
    if (total > 0) {
2271 f9209915 Miguel Di Ciurcio Filho
        monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
2272 f9209915 Miguel Di Ciurcio Filho
        for (i = 0; i < total; i++) {
2273 f9209915 Miguel Di Ciurcio Filho
            sn = &sn_tab[available_snapshots[i]];
2274 f9209915 Miguel Di Ciurcio Filho
            monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
2275 f9209915 Miguel Di Ciurcio Filho
        }
2276 f9209915 Miguel Di Ciurcio Filho
    } else {
2277 f9209915 Miguel Di Ciurcio Filho
        monitor_printf(mon, "There is no suitable snapshot available\n");
2278 f9209915 Miguel Di Ciurcio Filho
    }
2279 f9209915 Miguel Di Ciurcio Filho
2280 7267c094 Anthony Liguori
    g_free(sn_tab);
2281 7267c094 Anthony Liguori
    g_free(available_snapshots);
2282 f9209915 Miguel Di Ciurcio Filho
2283 a672b469 aliguori
}
2284 c5705a77 Avi Kivity
2285 c5705a77 Avi Kivity
void vmstate_register_ram(MemoryRegion *mr, DeviceState *dev)
2286 c5705a77 Avi Kivity
{
2287 1ddde087 Avi Kivity
    qemu_ram_set_idstr(memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK,
2288 c5705a77 Avi Kivity
                       memory_region_name(mr), dev);
2289 c5705a77 Avi Kivity
}
2290 c5705a77 Avi Kivity
2291 c5705a77 Avi Kivity
void vmstate_unregister_ram(MemoryRegion *mr, DeviceState *dev)
2292 c5705a77 Avi Kivity
{
2293 c5705a77 Avi Kivity
    /* Nothing do to while the implementation is in RAMBlock */
2294 c5705a77 Avi Kivity
}
2295 c5705a77 Avi Kivity
2296 c5705a77 Avi Kivity
void vmstate_register_ram_global(MemoryRegion *mr)
2297 c5705a77 Avi Kivity
{
2298 c5705a77 Avi Kivity
    vmstate_register_ram(mr, NULL);
2299 c5705a77 Avi Kivity
}