]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/bhyve/snapshot.c
bhyve: add emulation for qemu's fwcfg data port
[FreeBSD/FreeBSD.git] / usr.sbin / bhyve / snapshot.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2016 Flavius Anton
5  * Copyright (c) 2016 Mihai Tiganus
6  * Copyright (c) 2016-2019 Mihai Carabas
7  * Copyright (c) 2017-2019 Darius Mihai
8  * Copyright (c) 2017-2019 Elena Mihailescu
9  * Copyright (c) 2018-2019 Sergiu Weisz
10  * All rights reserved.
11  * The bhyve-snapshot feature was developed under sponsorships
12  * from Matthew Grooms.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  *
23  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 #include <sys/types.h>
40 #ifndef WITHOUT_CAPSICUM
41 #include <sys/capsicum.h>
42 #endif
43 #include <sys/mman.h>
44 #include <sys/socket.h>
45 #include <sys/stat.h>
46 #include <sys/time.h>
47 #include <sys/un.h>
48
49 #include <machine/atomic.h>
50 #include <machine/segments.h>
51
52 #ifndef WITHOUT_CAPSICUM
53 #include <capsicum_helpers.h>
54 #endif
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <err.h>
59 #include <errno.h>
60 #include <fcntl.h>
61 #include <libgen.h>
62 #include <signal.h>
63 #include <unistd.h>
64 #include <assert.h>
65 #include <errno.h>
66 #include <pthread.h>
67 #include <pthread_np.h>
68 #include <sysexits.h>
69 #include <stdbool.h>
70 #include <sys/ioctl.h>
71
72 #include <machine/vmm.h>
73 #ifndef WITHOUT_CAPSICUM
74 #include <machine/vmm_dev.h>
75 #endif
76 #include <machine/vmm_snapshot.h>
77 #include <vmmapi.h>
78
79 #include "bhyverun.h"
80 #include "acpi.h"
81 #include "atkbdc.h"
82 #include "debug.h"
83 #include "inout.h"
84 #include "ipc.h"
85 #include "fwctl.h"
86 #include "ioapic.h"
87 #include "mem.h"
88 #include "mevent.h"
89 #include "mptbl.h"
90 #include "pci_emul.h"
91 #include "pci_irq.h"
92 #include "pci_lpc.h"
93 #include "smbiostbl.h"
94 #include "snapshot.h"
95 #include "xmsr.h"
96 #include "spinup_ap.h"
97 #include "rtc.h"
98
99 #include <libxo/xo.h>
100 #include <ucl.h>
101
102 struct spinner_info {
103         const size_t *crtval;
104         const size_t maxval;
105         const size_t total;
106 };
107
108 extern int guest_ncpus;
109
110 static struct winsize winsize;
111 static sig_t old_winch_handler;
112
113 #define KB              (1024UL)
114 #define MB              (1024UL * KB)
115 #define GB              (1024UL * MB)
116
117 #define SNAPSHOT_CHUNK  (4 * MB)
118 #define PROG_BUF_SZ     (8192)
119
120 #define SNAPSHOT_BUFFER_SIZE (20 * MB)
121
122 #define JSON_STRUCT_ARR_KEY             "structs"
123 #define JSON_DEV_ARR_KEY                "devices"
124 #define JSON_BASIC_METADATA_KEY         "basic metadata"
125 #define JSON_SNAPSHOT_REQ_KEY           "snapshot_req"
126 #define JSON_SIZE_KEY                   "size"
127 #define JSON_FILE_OFFSET_KEY            "file_offset"
128
129 #define JSON_NCPUS_KEY                  "ncpus"
130 #define JSON_VMNAME_KEY                 "vmname"
131 #define JSON_MEMSIZE_KEY                "memsize"
132 #define JSON_MEMFLAGS_KEY               "memflags"
133
134 #define min(a,b)                \
135 ({                              \
136  __typeof__ (a) _a = (a);       \
137  __typeof__ (b) _b = (b);       \
138  _a < _b ? _a : _b;             \
139  })
140
141 static const struct vm_snapshot_dev_info snapshot_devs[] = {
142         { "atkbdc",     atkbdc_snapshot,        NULL,           NULL            },
143         { "virtio-net", pci_snapshot,           pci_pause,      pci_resume      },
144         { "virtio-blk", pci_snapshot,           pci_pause,      pci_resume      },
145         { "virtio-rnd", pci_snapshot,           NULL,           NULL            },
146         { "lpc",        pci_snapshot,           NULL,           NULL            },
147         { "fbuf",       pci_snapshot,           NULL,           NULL            },
148         { "xhci",       pci_snapshot,           NULL,           NULL            },
149         { "e1000",      pci_snapshot,           NULL,           NULL            },
150         { "ahci",       pci_snapshot,           pci_pause,      pci_resume      },
151         { "ahci-hd",    pci_snapshot,           pci_pause,      pci_resume      },
152         { "ahci-cd",    pci_snapshot,           pci_pause,      pci_resume      },
153 };
154
155 static const struct vm_snapshot_kern_info snapshot_kern_structs[] = {
156         { "vhpet",      STRUCT_VHPET    },
157         { "vm",         STRUCT_VM       },
158         { "vmx",        STRUCT_VMX      },
159         { "vioapic",    STRUCT_VIOAPIC  },
160         { "vlapic",     STRUCT_VLAPIC   },
161         { "vmcx",       STRUCT_VMCX     },
162         { "vatpit",     STRUCT_VATPIT   },
163         { "vatpic",     STRUCT_VATPIC   },
164         { "vpmtmr",     STRUCT_VPMTMR   },
165         { "vrtc",       STRUCT_VRTC     },
166 };
167
168 static cpuset_t vcpus_active, vcpus_suspended;
169 static pthread_mutex_t vcpu_lock;
170 static pthread_cond_t vcpus_idle, vcpus_can_run;
171 static bool checkpoint_active;
172
173 /*
174  * TODO: Harden this function and all of its callers since 'base_str' is a user
175  * provided string.
176  */
177 static char *
178 strcat_extension(const char *base_str, const char *ext)
179 {
180         char *res;
181         size_t base_len, ext_len;
182
183         base_len = strnlen(base_str, NAME_MAX);
184         ext_len = strnlen(ext, NAME_MAX);
185
186         if (base_len + ext_len > NAME_MAX) {
187                 fprintf(stderr, "Filename exceeds maximum length.\n");
188                 return (NULL);
189         }
190
191         res = malloc(base_len + ext_len + 1);
192         if (res == NULL) {
193                 perror("Failed to allocate memory.");
194                 return (NULL);
195         }
196
197         memcpy(res, base_str, base_len);
198         memcpy(res + base_len, ext, ext_len);
199         res[base_len + ext_len] = 0;
200
201         return (res);
202 }
203
204 void
205 destroy_restore_state(struct restore_state *rstate)
206 {
207         if (rstate == NULL) {
208                 fprintf(stderr, "Attempting to destroy NULL restore struct.\n");
209                 return;
210         }
211
212         if (rstate->kdata_map != MAP_FAILED)
213                 munmap(rstate->kdata_map, rstate->kdata_len);
214
215         if (rstate->kdata_fd > 0)
216                 close(rstate->kdata_fd);
217         if (rstate->vmmem_fd > 0)
218                 close(rstate->vmmem_fd);
219
220         if (rstate->meta_root_obj != NULL)
221                 ucl_object_unref(rstate->meta_root_obj);
222         if (rstate->meta_parser != NULL)
223                 ucl_parser_free(rstate->meta_parser);
224 }
225
226 static int
227 load_vmmem_file(const char *filename, struct restore_state *rstate)
228 {
229         struct stat sb;
230         int err;
231
232         rstate->vmmem_fd = open(filename, O_RDONLY);
233         if (rstate->vmmem_fd < 0) {
234                 perror("Failed to open restore file");
235                 return (-1);
236         }
237
238         err = fstat(rstate->vmmem_fd, &sb);
239         if (err < 0) {
240                 perror("Failed to stat restore file");
241                 goto err_load_vmmem;
242         }
243
244         if (sb.st_size == 0) {
245                 fprintf(stderr, "Restore file is empty.\n");
246                 goto err_load_vmmem;
247         }
248
249         rstate->vmmem_len = sb.st_size;
250
251         return (0);
252
253 err_load_vmmem:
254         if (rstate->vmmem_fd > 0)
255                 close(rstate->vmmem_fd);
256         return (-1);
257 }
258
259 static int
260 load_kdata_file(const char *filename, struct restore_state *rstate)
261 {
262         struct stat sb;
263         int err;
264
265         rstate->kdata_fd = open(filename, O_RDONLY);
266         if (rstate->kdata_fd < 0) {
267                 perror("Failed to open kernel data file");
268                 return (-1);
269         }
270
271         err = fstat(rstate->kdata_fd, &sb);
272         if (err < 0) {
273                 perror("Failed to stat kernel data file");
274                 goto err_load_kdata;
275         }
276
277         if (sb.st_size == 0) {
278                 fprintf(stderr, "Kernel data file is empty.\n");
279                 goto err_load_kdata;
280         }
281
282         rstate->kdata_len = sb.st_size;
283         rstate->kdata_map = mmap(NULL, rstate->kdata_len, PROT_READ,
284                                  MAP_SHARED, rstate->kdata_fd, 0);
285         if (rstate->kdata_map == MAP_FAILED) {
286                 perror("Failed to map restore file");
287                 goto err_load_kdata;
288         }
289
290         return (0);
291
292 err_load_kdata:
293         if (rstate->kdata_fd > 0)
294                 close(rstate->kdata_fd);
295         return (-1);
296 }
297
298 static int
299 load_metadata_file(const char *filename, struct restore_state *rstate)
300 {
301         ucl_object_t *obj;
302         struct ucl_parser *parser;
303         int err;
304
305         parser = ucl_parser_new(UCL_PARSER_DEFAULT);
306         if (parser == NULL) {
307                 fprintf(stderr, "Failed to initialize UCL parser.\n");
308                 err = -1;
309                 goto err_load_metadata;
310         }
311
312         err = ucl_parser_add_file(parser, filename);
313         if (err == 0) {
314                 fprintf(stderr, "Failed to parse metadata file: '%s'\n",
315                         filename);
316                 err = -1;
317                 goto err_load_metadata;
318         }
319
320         obj = ucl_parser_get_object(parser);
321         if (obj == NULL) {
322                 fprintf(stderr, "Failed to parse object.\n");
323                 err = -1;
324                 goto err_load_metadata;
325         }
326
327         rstate->meta_parser = parser;
328         rstate->meta_root_obj = (ucl_object_t *)obj;
329
330         return (0);
331
332 err_load_metadata:
333         if (parser != NULL)
334                 ucl_parser_free(parser);
335         return (err);
336 }
337
338 int
339 load_restore_file(const char *filename, struct restore_state *rstate)
340 {
341         int err = 0;
342         char *kdata_filename = NULL, *meta_filename = NULL;
343
344         assert(filename != NULL);
345         assert(rstate != NULL);
346
347         memset(rstate, 0, sizeof(*rstate));
348         rstate->kdata_map = MAP_FAILED;
349
350         err = load_vmmem_file(filename, rstate);
351         if (err != 0) {
352                 fprintf(stderr, "Failed to load guest RAM file.\n");
353                 goto err_restore;
354         }
355
356         kdata_filename = strcat_extension(filename, ".kern");
357         if (kdata_filename == NULL) {
358                 fprintf(stderr, "Failed to construct kernel data filename.\n");
359                 goto err_restore;
360         }
361
362         err = load_kdata_file(kdata_filename, rstate);
363         if (err != 0) {
364                 fprintf(stderr, "Failed to load guest kernel data file.\n");
365                 goto err_restore;
366         }
367
368         meta_filename = strcat_extension(filename, ".meta");
369         if (meta_filename == NULL) {
370                 fprintf(stderr, "Failed to construct kernel metadata filename.\n");
371                 goto err_restore;
372         }
373
374         err = load_metadata_file(meta_filename, rstate);
375         if (err != 0) {
376                 fprintf(stderr, "Failed to load guest metadata file.\n");
377                 goto err_restore;
378         }
379
380         return (0);
381
382 err_restore:
383         destroy_restore_state(rstate);
384         if (kdata_filename != NULL)
385                 free(kdata_filename);
386         if (meta_filename != NULL)
387                 free(meta_filename);
388         return (-1);
389 }
390
391 #define JSON_GET_INT_OR_RETURN(key, obj, result_ptr, ret)                       \
392 do {                                                                            \
393         const ucl_object_t *obj__;                                              \
394         obj__ = ucl_object_lookup(obj, key);                                    \
395         if (obj__ == NULL) {                                                    \
396                 fprintf(stderr, "Missing key: '%s'", key);                      \
397                 return (ret);                                                   \
398         }                                                                       \
399         if (!ucl_object_toint_safe(obj__, result_ptr)) {                        \
400                 fprintf(stderr, "Cannot convert '%s' value to int.", key);      \
401                 return (ret);                                                   \
402         }                                                                       \
403 } while(0)
404
405 #define JSON_GET_STRING_OR_RETURN(key, obj, result_ptr, ret)                    \
406 do {                                                                            \
407         const ucl_object_t *obj__;                                              \
408         obj__ = ucl_object_lookup(obj, key);                                    \
409         if (obj__ == NULL) {                                                    \
410                 fprintf(stderr, "Missing key: '%s'", key);                      \
411                 return (ret);                                                   \
412         }                                                                       \
413         if (!ucl_object_tostring_safe(obj__, result_ptr)) {                     \
414                 fprintf(stderr, "Cannot convert '%s' value to string.", key);   \
415                 return (ret);                                                   \
416         }                                                                       \
417 } while(0)
418
419 static void *
420 lookup_struct(enum snapshot_req struct_id, struct restore_state *rstate,
421               size_t *struct_size)
422 {
423         const ucl_object_t *structs = NULL, *obj = NULL;
424         ucl_object_iter_t it = NULL;
425         int64_t snapshot_req, size, file_offset;
426
427         structs = ucl_object_lookup(rstate->meta_root_obj, JSON_STRUCT_ARR_KEY);
428         if (structs == NULL) {
429                 fprintf(stderr, "Failed to find '%s' object.\n",
430                         JSON_STRUCT_ARR_KEY);
431                 return (NULL);
432         }
433
434         if (ucl_object_type(structs) != UCL_ARRAY) {
435                 fprintf(stderr, "Object '%s' is not an array.\n",
436                 JSON_STRUCT_ARR_KEY);
437                 return (NULL);
438         }
439
440         while ((obj = ucl_object_iterate(structs, &it, true)) != NULL) {
441                 snapshot_req = -1;
442                 JSON_GET_INT_OR_RETURN(JSON_SNAPSHOT_REQ_KEY, obj,
443                                        &snapshot_req, NULL);
444                 assert(snapshot_req >= 0);
445                 if ((enum snapshot_req) snapshot_req == struct_id) {
446                         JSON_GET_INT_OR_RETURN(JSON_SIZE_KEY, obj,
447                                                &size, NULL);
448                         assert(size >= 0);
449
450                         JSON_GET_INT_OR_RETURN(JSON_FILE_OFFSET_KEY, obj,
451                                                &file_offset, NULL);
452                         assert(file_offset >= 0);
453                         assert((uint64_t)file_offset + size <=
454                             rstate->kdata_len);
455
456                         *struct_size = (size_t)size;
457                         return ((uint8_t *)rstate->kdata_map + file_offset);
458                 }
459         }
460
461         return (NULL);
462 }
463
464 static void *
465 lookup_check_dev(const char *dev_name, struct restore_state *rstate,
466                  const ucl_object_t *obj, size_t *data_size)
467 {
468         const char *snapshot_req;
469         int64_t size, file_offset;
470
471         snapshot_req = NULL;
472         JSON_GET_STRING_OR_RETURN(JSON_SNAPSHOT_REQ_KEY, obj,
473                                   &snapshot_req, NULL);
474         assert(snapshot_req != NULL);
475         if (!strcmp(snapshot_req, dev_name)) {
476                 JSON_GET_INT_OR_RETURN(JSON_SIZE_KEY, obj,
477                                        &size, NULL);
478                 assert(size >= 0);
479
480                 JSON_GET_INT_OR_RETURN(JSON_FILE_OFFSET_KEY, obj,
481                                        &file_offset, NULL);
482                 assert(file_offset >= 0);
483                 assert((uint64_t)file_offset + size <= rstate->kdata_len);
484
485                 *data_size = (size_t)size;
486                 return ((uint8_t *)rstate->kdata_map + file_offset);
487         }
488
489         return (NULL);
490 }
491
492 static void*
493 lookup_dev(const char *dev_name, struct restore_state *rstate,
494            size_t *data_size)
495 {
496         const ucl_object_t *devs = NULL, *obj = NULL;
497         ucl_object_iter_t it = NULL;
498         void *ret;
499
500         devs = ucl_object_lookup(rstate->meta_root_obj, JSON_DEV_ARR_KEY);
501         if (devs == NULL) {
502                 fprintf(stderr, "Failed to find '%s' object.\n",
503                         JSON_DEV_ARR_KEY);
504                 return (NULL);
505         }
506
507         if (ucl_object_type(devs) != UCL_ARRAY) {
508                 fprintf(stderr, "Object '%s' is not an array.\n",
509                         JSON_DEV_ARR_KEY);
510                 return (NULL);
511         }
512
513         while ((obj = ucl_object_iterate(devs, &it, true)) != NULL) {
514                 ret = lookup_check_dev(dev_name, rstate, obj, data_size);
515                 if (ret != NULL)
516                         return (ret);
517         }
518
519         return (NULL);
520 }
521
522 static const ucl_object_t *
523 lookup_basic_metadata_object(struct restore_state *rstate)
524 {
525         const ucl_object_t *basic_meta_obj = NULL;
526
527         basic_meta_obj = ucl_object_lookup(rstate->meta_root_obj,
528                                            JSON_BASIC_METADATA_KEY);
529         if (basic_meta_obj == NULL) {
530                 fprintf(stderr, "Failed to find '%s' object.\n",
531                         JSON_BASIC_METADATA_KEY);
532                 return (NULL);
533         }
534
535         if (ucl_object_type(basic_meta_obj) != UCL_OBJECT) {
536                 fprintf(stderr, "Object '%s' is not a JSON object.\n",
537                 JSON_BASIC_METADATA_KEY);
538                 return (NULL);
539         }
540
541         return (basic_meta_obj);
542 }
543
544 const char *
545 lookup_vmname(struct restore_state *rstate)
546 {
547         const char *vmname;
548         const ucl_object_t *obj;
549
550         obj = lookup_basic_metadata_object(rstate);
551         if (obj == NULL)
552                 return (NULL);
553
554         JSON_GET_STRING_OR_RETURN(JSON_VMNAME_KEY, obj, &vmname, NULL);
555         return (vmname);
556 }
557
558 int
559 lookup_memflags(struct restore_state *rstate)
560 {
561         int64_t memflags;
562         const ucl_object_t *obj;
563
564         obj = lookup_basic_metadata_object(rstate);
565         if (obj == NULL)
566                 return (0);
567
568         JSON_GET_INT_OR_RETURN(JSON_MEMFLAGS_KEY, obj, &memflags, 0);
569
570         return ((int)memflags);
571 }
572
573 size_t
574 lookup_memsize(struct restore_state *rstate)
575 {
576         int64_t memsize;
577         const ucl_object_t *obj;
578
579         obj = lookup_basic_metadata_object(rstate);
580         if (obj == NULL)
581                 return (0);
582
583         JSON_GET_INT_OR_RETURN(JSON_MEMSIZE_KEY, obj, &memsize, 0);
584         if (memsize < 0)
585                 memsize = 0;
586
587         return ((size_t)memsize);
588 }
589
590
591 int
592 lookup_guest_ncpus(struct restore_state *rstate)
593 {
594         int64_t ncpus;
595         const ucl_object_t *obj;
596
597         obj = lookup_basic_metadata_object(rstate);
598         if (obj == NULL)
599                 return (0);
600
601         JSON_GET_INT_OR_RETURN(JSON_NCPUS_KEY, obj, &ncpus, 0);
602         return ((int)ncpus);
603 }
604
605 static void
606 winch_handler(int signal __unused)
607 {
608 #ifdef TIOCGWINSZ
609         ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize);
610 #endif /* TIOCGWINSZ */
611 }
612
613 static int
614 print_progress(size_t crtval, const size_t maxval)
615 {
616         size_t rc;
617         double crtval_gb, maxval_gb;
618         size_t i, win_width, prog_start, prog_done, prog_end;
619         int mval_len;
620
621         static char prog_buf[PROG_BUF_SZ];
622         static const size_t len = sizeof(prog_buf);
623
624         static size_t div;
625         static const char *div_str;
626
627         static char wip_bar[] = { '/', '-', '\\', '|' };
628         static int wip_idx = 0;
629
630         if (maxval == 0) {
631                 printf("[0B / 0B]\r\n");
632                 return (0);
633         }
634
635         if (crtval > maxval)
636                 crtval = maxval;
637
638         if (maxval > 10 * GB) {
639                 div = GB;
640                 div_str = "GiB";
641         } else if (maxval > 10 * MB) {
642                 div = MB;
643                 div_str = "MiB";
644         } else {
645                 div = KB;
646                 div_str = "KiB";
647         }
648
649         crtval_gb = (double) crtval / div;
650         maxval_gb = (double) maxval / div;
651
652         rc = snprintf(prog_buf, len, "%.03lf", maxval_gb);
653         if (rc == len) {
654                 fprintf(stderr, "Maxval too big\n");
655                 return (-1);
656         }
657         mval_len = rc;
658
659         rc = snprintf(prog_buf, len, "\r[%*.03lf%s / %.03lf%s] |",
660                 mval_len, crtval_gb, div_str, maxval_gb, div_str);
661
662         if (rc == len) {
663                 fprintf(stderr, "Buffer too small to print progress\n");
664                 return (-1);
665         }
666
667         win_width = min(winsize.ws_col, len);
668         prog_start = rc;
669
670         if (prog_start < (win_width - 2)) {
671                 prog_end = win_width - prog_start - 2;
672                 prog_done = prog_end * (crtval_gb / maxval_gb);
673
674                 for (i = prog_start; i < prog_start + prog_done; i++)
675                         prog_buf[i] = '#';
676
677                 if (crtval != maxval) {
678                         prog_buf[i] = wip_bar[wip_idx];
679                         wip_idx = (wip_idx + 1) % sizeof(wip_bar);
680                         i++;
681                 } else {
682                         prog_buf[i++] = '#';
683                 }
684
685                 for (; i < win_width - 2; i++)
686                         prog_buf[i] = '_';
687
688                 prog_buf[win_width - 2] = '|';
689         }
690
691         prog_buf[win_width - 1] = '\0';
692         write(STDOUT_FILENO, prog_buf, win_width);
693
694         return (0);
695 }
696
697 static void *
698 snapshot_spinner_cb(void *arg)
699 {
700         int rc;
701         size_t crtval, maxval, total;
702         struct spinner_info *si;
703         struct timespec ts;
704
705         si = arg;
706         if (si == NULL)
707                 pthread_exit(NULL);
708
709         ts.tv_sec = 0;
710         ts.tv_nsec = 50 * 1000 * 1000; /* 50 ms sleep time */
711
712         do {
713                 crtval = *si->crtval;
714                 maxval = si->maxval;
715                 total = si->total;
716
717                 rc = print_progress(crtval, total);
718                 if (rc < 0) {
719                         fprintf(stderr, "Failed to parse progress\n");
720                         break;
721                 }
722
723                 nanosleep(&ts, NULL);
724         } while (crtval < maxval);
725
726         pthread_exit(NULL);
727         return NULL;
728 }
729
730 static int
731 vm_snapshot_mem_part(const int snapfd, const size_t foff, void *src,
732                      const size_t len, const size_t totalmem, const bool op_wr)
733 {
734         int rc;
735         size_t part_done, todo, rem;
736         ssize_t done;
737         bool show_progress;
738         pthread_t spinner_th;
739         struct spinner_info *si;
740
741         if (lseek(snapfd, foff, SEEK_SET) < 0) {
742                 perror("Failed to change file offset");
743                 return (-1);
744         }
745
746         show_progress = false;
747         if (isatty(STDIN_FILENO) && (winsize.ws_col != 0))
748                 show_progress = true;
749
750         part_done = foff;
751         rem = len;
752
753         if (show_progress) {
754                 si = &(struct spinner_info) {
755                         .crtval = &part_done,
756                         .maxval = foff + len,
757                         .total = totalmem
758                 };
759
760                 rc = pthread_create(&spinner_th, 0, snapshot_spinner_cb, si);
761                 if (rc) {
762                         perror("Unable to create spinner thread");
763                         show_progress = false;
764                 }
765         }
766
767         while (rem > 0) {
768                 if (show_progress)
769                         todo = min(SNAPSHOT_CHUNK, rem);
770                 else
771                         todo = rem;
772
773                 if (op_wr)
774                         done = write(snapfd, src, todo);
775                 else
776                         done = read(snapfd, src, todo);
777                 if (done < 0) {
778                         perror("Failed to write in file");
779                         return (-1);
780                 }
781
782                 src = (uint8_t *)src + done;
783                 part_done += done;
784                 rem -= done;
785         }
786
787         if (show_progress) {
788                 rc = pthread_join(spinner_th, NULL);
789                 if (rc)
790                         perror("Unable to end spinner thread");
791         }
792
793         return (0);
794 }
795
796 static size_t
797 vm_snapshot_mem(struct vmctx *ctx, int snapfd, size_t memsz, const bool op_wr)
798 {
799         int ret;
800         size_t lowmem, highmem, totalmem;
801         char *baseaddr;
802
803         ret = vm_get_guestmem_from_ctx(ctx, &baseaddr, &lowmem, &highmem);
804         if (ret) {
805                 fprintf(stderr, "%s: unable to retrieve guest memory size\r\n",
806                         __func__);
807                 return (0);
808         }
809         totalmem = lowmem + highmem;
810
811         if ((op_wr == false) && (totalmem != memsz)) {
812                 fprintf(stderr, "%s: mem size mismatch: %ld vs %ld\r\n",
813                         __func__, totalmem, memsz);
814                 return (0);
815         }
816
817         winsize.ws_col = 80;
818 #ifdef TIOCGWINSZ
819         ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize);
820 #endif /* TIOCGWINSZ */
821         old_winch_handler = signal(SIGWINCH, winch_handler);
822
823         ret = vm_snapshot_mem_part(snapfd, 0, baseaddr, lowmem,
824                 totalmem, op_wr);
825         if (ret) {
826                 fprintf(stderr, "%s: Could not %s lowmem\r\n",
827                         __func__, op_wr ? "write" : "read");
828                 totalmem = 0;
829                 goto done;
830         }
831
832         if (highmem == 0)
833                 goto done;
834
835         ret = vm_snapshot_mem_part(snapfd, lowmem, baseaddr + 4*GB,
836                 highmem, totalmem, op_wr);
837         if (ret) {
838                 fprintf(stderr, "%s: Could not %s highmem\r\n",
839                         __func__, op_wr ? "write" : "read");
840                 totalmem = 0;
841                 goto done;
842         }
843
844 done:
845         printf("\r\n");
846         signal(SIGWINCH, old_winch_handler);
847
848         return (totalmem);
849 }
850
851 int
852 restore_vm_mem(struct vmctx *ctx, struct restore_state *rstate)
853 {
854         size_t restored;
855
856         restored = vm_snapshot_mem(ctx, rstate->vmmem_fd, rstate->vmmem_len,
857                                    false);
858
859         if (restored != rstate->vmmem_len)
860                 return (-1);
861
862         return (0);
863 }
864
865 static int
866 vm_restore_kern_struct(struct vmctx *ctx, struct restore_state *rstate,
867                        const struct vm_snapshot_kern_info *info)
868 {
869         void *struct_ptr;
870         size_t struct_size;
871         int ret;
872         struct vm_snapshot_meta *meta;
873
874         struct_ptr = lookup_struct(info->req, rstate, &struct_size);
875         if (struct_ptr == NULL) {
876                 fprintf(stderr, "%s: Failed to lookup struct %s\r\n",
877                         __func__, info->struct_name);
878                 ret = -1;
879                 goto done;
880         }
881
882         if (struct_size == 0) {
883                 fprintf(stderr, "%s: Kernel struct size was 0 for: %s\r\n",
884                         __func__, info->struct_name);
885                 ret = -1;
886                 goto done;
887         }
888
889         meta = &(struct vm_snapshot_meta) {
890                 .ctx = ctx,
891                 .dev_name = info->struct_name,
892                 .dev_req  = info->req,
893
894                 .buffer.buf_start = struct_ptr,
895                 .buffer.buf_size = struct_size,
896
897                 .buffer.buf = struct_ptr,
898                 .buffer.buf_rem = struct_size,
899
900                 .op = VM_SNAPSHOT_RESTORE,
901         };
902
903         ret = vm_snapshot_req(meta);
904         if (ret != 0) {
905                 fprintf(stderr, "%s: Failed to restore struct: %s\r\n",
906                         __func__, info->struct_name);
907                 goto done;
908         }
909
910 done:
911         return (ret);
912 }
913
914 int
915 vm_restore_kern_structs(struct vmctx *ctx, struct restore_state *rstate)
916 {
917         size_t i;
918         int ret;
919
920         for (i = 0; i < nitems(snapshot_kern_structs); i++) {
921                 ret = vm_restore_kern_struct(ctx, rstate,
922                                              &snapshot_kern_structs[i]);
923                 if (ret != 0)
924                         return (ret);
925         }
926
927         return (0);
928 }
929
930 static int
931 vm_restore_user_dev(struct vmctx *ctx, struct restore_state *rstate,
932                     const struct vm_snapshot_dev_info *info)
933 {
934         void *dev_ptr;
935         size_t dev_size;
936         int ret;
937         struct vm_snapshot_meta *meta;
938
939         dev_ptr = lookup_dev(info->dev_name, rstate, &dev_size);
940         if (dev_ptr == NULL) {
941                 fprintf(stderr, "Failed to lookup dev: %s\r\n", info->dev_name);
942                 fprintf(stderr, "Continuing the restore/migration process\r\n");
943                 return (0);
944         }
945
946         if (dev_size == 0) {
947                 fprintf(stderr, "%s: Device size is 0. "
948                         "Assuming %s is not used\r\n",
949                         __func__, info->dev_name);
950                 return (0);
951         }
952
953         meta = &(struct vm_snapshot_meta) {
954                 .ctx = ctx,
955                 .dev_name = info->dev_name,
956
957                 .buffer.buf_start = dev_ptr,
958                 .buffer.buf_size = dev_size,
959
960                 .buffer.buf = dev_ptr,
961                 .buffer.buf_rem = dev_size,
962
963                 .op = VM_SNAPSHOT_RESTORE,
964         };
965
966         ret = (*info->snapshot_cb)(meta);
967         if (ret != 0) {
968                 fprintf(stderr, "Failed to restore dev: %s\r\n",
969                         info->dev_name);
970                 return (-1);
971         }
972
973         return (0);
974 }
975
976
977 int
978 vm_restore_user_devs(struct vmctx *ctx, struct restore_state *rstate)
979 {
980         size_t i;
981         int ret;
982
983         for (i = 0; i < nitems(snapshot_devs); i++) {
984                 ret = vm_restore_user_dev(ctx, rstate, &snapshot_devs[i]);
985                 if (ret != 0)
986                         return (ret);
987         }
988
989         return 0;
990 }
991
992 int
993 vm_pause_user_devs(void)
994 {
995         const struct vm_snapshot_dev_info *info;
996         size_t i;
997         int ret;
998
999         for (i = 0; i < nitems(snapshot_devs); i++) {
1000                 info = &snapshot_devs[i];
1001                 if (info->pause_cb == NULL)
1002                         continue;
1003
1004                 ret = info->pause_cb(info->dev_name);
1005                 if (ret != 0)
1006                         return (ret);
1007         }
1008
1009         return (0);
1010 }
1011
1012 int
1013 vm_resume_user_devs(void)
1014 {
1015         const struct vm_snapshot_dev_info *info;
1016         size_t i;
1017         int ret;
1018
1019         for (i = 0; i < nitems(snapshot_devs); i++) {
1020                 info = &snapshot_devs[i];
1021                 if (info->resume_cb == NULL)
1022                         continue;
1023
1024                 ret = info->resume_cb(info->dev_name);
1025                 if (ret != 0)
1026                         return (ret);
1027         }
1028
1029         return (0);
1030 }
1031
1032 static int
1033 vm_snapshot_kern_struct(int data_fd, xo_handle_t *xop, const char *array_key,
1034                         struct vm_snapshot_meta *meta, off_t *offset)
1035 {
1036         int ret;
1037         size_t data_size;
1038         ssize_t write_cnt;
1039
1040         ret = vm_snapshot_req(meta);
1041         if (ret != 0) {
1042                 fprintf(stderr, "%s: Failed to snapshot struct %s\r\n",
1043                         __func__, meta->dev_name);
1044                 ret = -1;
1045                 goto done;
1046         }
1047
1048         data_size = vm_get_snapshot_size(meta);
1049
1050         /* XXX-MJ no handling for short writes. */
1051         write_cnt = write(data_fd, meta->buffer.buf_start, data_size);
1052         if (write_cnt < 0 || (size_t)write_cnt != data_size) {
1053                 perror("Failed to write all snapshotted data.");
1054                 ret = -1;
1055                 goto done;
1056         }
1057
1058         /* Write metadata. */
1059         xo_open_instance_h(xop, array_key);
1060         xo_emit_h(xop, "{:debug_name/%s}\n", meta->dev_name);
1061         xo_emit_h(xop, "{:" JSON_SNAPSHOT_REQ_KEY "/%d}\n",
1062                   meta->dev_req);
1063         xo_emit_h(xop, "{:" JSON_SIZE_KEY "/%lu}\n", data_size);
1064         xo_emit_h(xop, "{:" JSON_FILE_OFFSET_KEY "/%lu}\n", *offset);
1065         xo_close_instance_h(xop, JSON_STRUCT_ARR_KEY);
1066
1067         *offset += data_size;
1068
1069 done:
1070         return (ret);
1071 }
1072
1073 static int
1074 vm_snapshot_kern_structs(struct vmctx *ctx, int data_fd, xo_handle_t *xop)
1075 {
1076         int ret, error;
1077         size_t buf_size, i, offset;
1078         char *buffer;
1079         struct vm_snapshot_meta *meta;
1080
1081         error = 0;
1082         offset = 0;
1083         buf_size = SNAPSHOT_BUFFER_SIZE;
1084
1085         buffer = malloc(SNAPSHOT_BUFFER_SIZE * sizeof(char));
1086         if (buffer == NULL) {
1087                 error = ENOMEM;
1088                 perror("Failed to allocate memory for snapshot buffer");
1089                 goto err_vm_snapshot_kern_data;
1090         }
1091
1092         meta = &(struct vm_snapshot_meta) {
1093                 .ctx = ctx,
1094
1095                 .buffer.buf_start = buffer,
1096                 .buffer.buf_size = buf_size,
1097
1098                 .op = VM_SNAPSHOT_SAVE,
1099         };
1100
1101         xo_open_list_h(xop, JSON_STRUCT_ARR_KEY);
1102         for (i = 0; i < nitems(snapshot_kern_structs); i++) {
1103                 meta->dev_name = snapshot_kern_structs[i].struct_name;
1104                 meta->dev_req  = snapshot_kern_structs[i].req;
1105
1106                 memset(meta->buffer.buf_start, 0, meta->buffer.buf_size);
1107                 meta->buffer.buf = meta->buffer.buf_start;
1108                 meta->buffer.buf_rem = meta->buffer.buf_size;
1109
1110                 ret = vm_snapshot_kern_struct(data_fd, xop, JSON_DEV_ARR_KEY,
1111                                               meta, &offset);
1112                 if (ret != 0) {
1113                         error = -1;
1114                         goto err_vm_snapshot_kern_data;
1115                 }
1116         }
1117         xo_close_list_h(xop, JSON_STRUCT_ARR_KEY);
1118
1119 err_vm_snapshot_kern_data:
1120         if (buffer != NULL)
1121                 free(buffer);
1122         return (error);
1123 }
1124
1125 static int
1126 vm_snapshot_basic_metadata(struct vmctx *ctx, xo_handle_t *xop, size_t memsz)
1127 {
1128
1129         xo_open_container_h(xop, JSON_BASIC_METADATA_KEY);
1130         xo_emit_h(xop, "{:" JSON_NCPUS_KEY "/%ld}\n", guest_ncpus);
1131         xo_emit_h(xop, "{:" JSON_VMNAME_KEY "/%s}\n", vm_get_name(ctx));
1132         xo_emit_h(xop, "{:" JSON_MEMSIZE_KEY "/%lu}\n", memsz);
1133         xo_emit_h(xop, "{:" JSON_MEMFLAGS_KEY "/%d}\n", vm_get_memflags(ctx));
1134         xo_close_container_h(xop, JSON_BASIC_METADATA_KEY);
1135
1136         return (0);
1137 }
1138
1139 static int
1140 vm_snapshot_dev_write_data(int data_fd, xo_handle_t *xop, const char *array_key,
1141                            struct vm_snapshot_meta *meta, off_t *offset)
1142 {
1143         ssize_t ret;
1144         size_t data_size;
1145
1146         data_size = vm_get_snapshot_size(meta);
1147
1148         /* XXX-MJ no handling for short writes. */
1149         ret = write(data_fd, meta->buffer.buf_start, data_size);
1150         if (ret < 0 || (size_t)ret != data_size) {
1151                 perror("Failed to write all snapshotted data.");
1152                 return (-1);
1153         }
1154
1155         /* Write metadata. */
1156         xo_open_instance_h(xop, array_key);
1157         xo_emit_h(xop, "{:" JSON_SNAPSHOT_REQ_KEY "/%s}\n", meta->dev_name);
1158         xo_emit_h(xop, "{:" JSON_SIZE_KEY "/%lu}\n", data_size);
1159         xo_emit_h(xop, "{:" JSON_FILE_OFFSET_KEY "/%lu}\n", *offset);
1160         xo_close_instance_h(xop, array_key);
1161
1162         *offset += data_size;
1163
1164         return (0);
1165 }
1166
1167 static int
1168 vm_snapshot_user_dev(const struct vm_snapshot_dev_info *info,
1169                      int data_fd, xo_handle_t *xop,
1170                      struct vm_snapshot_meta *meta, off_t *offset)
1171 {
1172         int ret;
1173
1174         ret = (*info->snapshot_cb)(meta);
1175         if (ret != 0) {
1176                 fprintf(stderr, "Failed to snapshot %s; ret=%d\r\n",
1177                         meta->dev_name, ret);
1178                 return (ret);
1179         }
1180
1181         ret = vm_snapshot_dev_write_data(data_fd, xop, JSON_DEV_ARR_KEY, meta,
1182                                          offset);
1183         if (ret != 0)
1184                 return (ret);
1185
1186         return (0);
1187 }
1188
1189 static int
1190 vm_snapshot_user_devs(struct vmctx *ctx, int data_fd, xo_handle_t *xop)
1191 {
1192         int ret;
1193         off_t offset;
1194         void *buffer;
1195         size_t buf_size, i;
1196         struct vm_snapshot_meta *meta;
1197
1198         buf_size = SNAPSHOT_BUFFER_SIZE;
1199
1200         offset = lseek(data_fd, 0, SEEK_CUR);
1201         if (offset < 0) {
1202                 perror("Failed to get data file current offset.");
1203                 return (-1);
1204         }
1205
1206         buffer = malloc(buf_size);
1207         if (buffer == NULL) {
1208                 perror("Failed to allocate memory for snapshot buffer");
1209                 ret = ENOSPC;
1210                 goto snapshot_err;
1211         }
1212
1213         meta = &(struct vm_snapshot_meta) {
1214                 .ctx = ctx,
1215
1216                 .buffer.buf_start = buffer,
1217                 .buffer.buf_size = buf_size,
1218
1219                 .op = VM_SNAPSHOT_SAVE,
1220         };
1221
1222         xo_open_list_h(xop, JSON_DEV_ARR_KEY);
1223
1224         /* Restore other devices that support this feature */
1225         for (i = 0; i < nitems(snapshot_devs); i++) {
1226                 meta->dev_name = snapshot_devs[i].dev_name;
1227
1228                 memset(meta->buffer.buf_start, 0, meta->buffer.buf_size);
1229                 meta->buffer.buf = meta->buffer.buf_start;
1230                 meta->buffer.buf_rem = meta->buffer.buf_size;
1231
1232                 ret = vm_snapshot_user_dev(&snapshot_devs[i], data_fd, xop,
1233                                            meta, &offset);
1234                 if (ret != 0)
1235                         goto snapshot_err;
1236         }
1237
1238         xo_close_list_h(xop, JSON_DEV_ARR_KEY);
1239
1240 snapshot_err:
1241         if (buffer != NULL)
1242                 free(buffer);
1243         return (ret);
1244 }
1245
1246 void
1247 checkpoint_cpu_add(int vcpu)
1248 {
1249
1250         pthread_mutex_lock(&vcpu_lock);
1251         CPU_SET(vcpu, &vcpus_active);
1252
1253         if (checkpoint_active) {
1254                 CPU_SET(vcpu, &vcpus_suspended);
1255                 while (checkpoint_active)
1256                         pthread_cond_wait(&vcpus_can_run, &vcpu_lock);
1257                 CPU_CLR(vcpu, &vcpus_suspended);
1258         }
1259         pthread_mutex_unlock(&vcpu_lock);
1260 }
1261
1262 /*
1263  * When a vCPU is suspended for any reason, it calls
1264  * checkpoint_cpu_suspend().  This records that the vCPU is idle.
1265  * Before returning from suspension, checkpoint_cpu_resume() is
1266  * called.  In suspend we note that the vCPU is idle.  In resume we
1267  * pause the vCPU thread until the checkpoint is complete.  The reason
1268  * for the two-step process is that vCPUs might already be stopped in
1269  * the debug server when a checkpoint is requested.  This approach
1270  * allows us to account for and handle those vCPUs.
1271  */
1272 void
1273 checkpoint_cpu_suspend(int vcpu)
1274 {
1275
1276         pthread_mutex_lock(&vcpu_lock);
1277         CPU_SET(vcpu, &vcpus_suspended);
1278         if (checkpoint_active && CPU_CMP(&vcpus_active, &vcpus_suspended) == 0)
1279                 pthread_cond_signal(&vcpus_idle);
1280         pthread_mutex_unlock(&vcpu_lock);
1281 }
1282
1283 void
1284 checkpoint_cpu_resume(int vcpu)
1285 {
1286
1287         pthread_mutex_lock(&vcpu_lock);
1288         while (checkpoint_active)
1289                 pthread_cond_wait(&vcpus_can_run, &vcpu_lock);
1290         CPU_CLR(vcpu, &vcpus_suspended);
1291         pthread_mutex_unlock(&vcpu_lock);
1292 }
1293
1294 static void
1295 vm_vcpu_pause(struct vmctx *ctx)
1296 {
1297
1298         pthread_mutex_lock(&vcpu_lock);
1299         checkpoint_active = true;
1300         vm_suspend_cpu(ctx, -1);
1301         while (CPU_CMP(&vcpus_active, &vcpus_suspended) != 0)
1302                 pthread_cond_wait(&vcpus_idle, &vcpu_lock);
1303         pthread_mutex_unlock(&vcpu_lock);
1304 }
1305
1306 static void
1307 vm_vcpu_resume(struct vmctx *ctx)
1308 {
1309
1310         pthread_mutex_lock(&vcpu_lock);
1311         checkpoint_active = false;
1312         pthread_mutex_unlock(&vcpu_lock);
1313         vm_resume_cpu(ctx, -1);
1314         pthread_cond_broadcast(&vcpus_can_run);
1315 }
1316
1317 static int
1318 vm_checkpoint(struct vmctx *ctx, const char *checkpoint_file, bool stop_vm)
1319 {
1320         int fd_checkpoint = 0, kdata_fd = 0;
1321         int ret = 0;
1322         int error = 0;
1323         size_t memsz;
1324         xo_handle_t *xop = NULL;
1325         char *meta_filename = NULL;
1326         char *kdata_filename = NULL;
1327         FILE *meta_file = NULL;
1328
1329         kdata_filename = strcat_extension(checkpoint_file, ".kern");
1330         if (kdata_filename == NULL) {
1331                 fprintf(stderr, "Failed to construct kernel data filename.\n");
1332                 return (-1);
1333         }
1334
1335         kdata_fd = open(kdata_filename, O_WRONLY | O_CREAT | O_TRUNC, 0700);
1336         if (kdata_fd < 0) {
1337                 perror("Failed to open kernel data snapshot file.");
1338                 error = -1;
1339                 goto done;
1340         }
1341
1342         fd_checkpoint = open(checkpoint_file, O_RDWR | O_CREAT | O_TRUNC, 0700);
1343
1344         if (fd_checkpoint < 0) {
1345                 perror("Failed to create checkpoint file");
1346                 error = -1;
1347                 goto done;
1348         }
1349
1350         meta_filename = strcat_extension(checkpoint_file, ".meta");
1351         if (meta_filename == NULL) {
1352                 fprintf(stderr, "Failed to construct vm metadata filename.\n");
1353                 goto done;
1354         }
1355
1356         meta_file = fopen(meta_filename, "w");
1357         if (meta_file == NULL) {
1358                 perror("Failed to open vm metadata snapshot file.");
1359                 goto done;
1360         }
1361
1362         xop = xo_create_to_file(meta_file, XO_STYLE_JSON, XOF_PRETTY);
1363         if (xop == NULL) {
1364                 perror("Failed to get libxo handle on metadata file.");
1365                 goto done;
1366         }
1367
1368         vm_vcpu_pause(ctx);
1369
1370         ret = vm_pause_user_devs();
1371         if (ret != 0) {
1372                 fprintf(stderr, "Could not pause devices\r\n");
1373                 error = ret;
1374                 goto done;
1375         }
1376
1377         memsz = vm_snapshot_mem(ctx, fd_checkpoint, 0, true);
1378         if (memsz == 0) {
1379                 perror("Could not write guest memory to file");
1380                 error = -1;
1381                 goto done;
1382         }
1383
1384         ret = vm_snapshot_basic_metadata(ctx, xop, memsz);
1385         if (ret != 0) {
1386                 fprintf(stderr, "Failed to snapshot vm basic metadata.\n");
1387                 error = -1;
1388                 goto done;
1389         }
1390
1391
1392         ret = vm_snapshot_kern_structs(ctx, kdata_fd, xop);
1393         if (ret != 0) {
1394                 fprintf(stderr, "Failed to snapshot vm kernel data.\n");
1395                 error = -1;
1396                 goto done;
1397         }
1398
1399         ret = vm_snapshot_user_devs(ctx, kdata_fd, xop);
1400         if (ret != 0) {
1401                 fprintf(stderr, "Failed to snapshot device state.\n");
1402                 error = -1;
1403                 goto done;
1404         }
1405
1406         xo_finish_h(xop);
1407
1408         if (stop_vm) {
1409                 vm_destroy(ctx);
1410                 exit(0);
1411         }
1412
1413 done:
1414         ret = vm_resume_user_devs();
1415         if (ret != 0)
1416                 fprintf(stderr, "Could not resume devices\r\n");
1417         vm_vcpu_resume(ctx);
1418         if (fd_checkpoint > 0)
1419                 close(fd_checkpoint);
1420         if (meta_filename != NULL)
1421                 free(meta_filename);
1422         if (kdata_filename != NULL)
1423                 free(kdata_filename);
1424         if (xop != NULL)
1425                 xo_destroy(xop);
1426         if (meta_file != NULL)
1427                 fclose(meta_file);
1428         if (kdata_fd > 0)
1429                 close(kdata_fd);
1430         return (error);
1431 }
1432
1433 static int
1434 handle_message(struct vmctx *ctx, nvlist_t *nvl)
1435 {
1436         const char *cmd;
1437         struct ipc_command **ipc_cmd;
1438
1439         if (!nvlist_exists_string(nvl, "cmd"))
1440                 return (EINVAL);
1441
1442         cmd = nvlist_get_string(nvl, "cmd");
1443         IPC_COMMAND_FOREACH(ipc_cmd, ipc_cmd_set) {
1444                 if (strcmp(cmd, (*ipc_cmd)->name) == 0)
1445                         return ((*ipc_cmd)->handler(ctx, nvl));
1446         }
1447
1448         return (EOPNOTSUPP);
1449 }
1450
1451 /*
1452  * Listen for commands from bhyvectl
1453  */
1454 void *
1455 checkpoint_thread(void *param)
1456 {
1457         int fd;
1458         struct checkpoint_thread_info *thread_info;
1459         nvlist_t *nvl;
1460
1461         pthread_set_name_np(pthread_self(), "checkpoint thread");
1462         thread_info = (struct checkpoint_thread_info *)param;
1463
1464         while ((fd = accept(thread_info->socket_fd, NULL, NULL)) != -1) {
1465                 nvl = nvlist_recv(fd, 0);
1466                 if (nvl != NULL)
1467                         handle_message(thread_info->ctx, nvl);
1468                 else
1469                         EPRINTLN("nvlist_recv() failed: %s", strerror(errno));
1470
1471                 close(fd);
1472                 nvlist_destroy(nvl);
1473         }
1474
1475         return (NULL);
1476 }
1477
1478 static int
1479 vm_do_checkpoint(struct vmctx *ctx, const nvlist_t *nvl)
1480 {
1481         int error;
1482
1483         if (!nvlist_exists_string(nvl, "filename") ||
1484             !nvlist_exists_bool(nvl, "suspend"))
1485                 error = EINVAL;
1486         else
1487                 error = vm_checkpoint(ctx, nvlist_get_string(nvl, "filename"),
1488                     nvlist_get_bool(nvl, "suspend"));
1489
1490         return (error);
1491 }
1492 IPC_COMMAND(ipc_cmd_set, checkpoint, vm_do_checkpoint);
1493
1494 void
1495 init_snapshot(void)
1496 {
1497         int err;
1498
1499         err = pthread_mutex_init(&vcpu_lock, NULL);
1500         if (err != 0)
1501                 errc(1, err, "checkpoint mutex init");
1502         err = pthread_cond_init(&vcpus_idle, NULL);
1503         if (err != 0)
1504                 errc(1, err, "checkpoint cv init (vcpus_idle)");
1505         err = pthread_cond_init(&vcpus_can_run, NULL);
1506         if (err != 0)
1507                 errc(1, err, "checkpoint cv init (vcpus_can_run)");
1508 }
1509
1510 /*
1511  * Create the listening socket for IPC with bhyvectl
1512  */
1513 int
1514 init_checkpoint_thread(struct vmctx *ctx)
1515 {
1516         struct checkpoint_thread_info *checkpoint_info = NULL;
1517         struct sockaddr_un addr;
1518         int socket_fd;
1519         pthread_t checkpoint_pthread;
1520         int err;
1521
1522         memset(&addr, 0, sizeof(addr));
1523
1524         socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
1525         if (socket_fd < 0) {
1526                 EPRINTLN("Socket creation failed: %s", strerror(errno));
1527                 err = -1;
1528                 goto fail;
1529         }
1530
1531         addr.sun_family = AF_UNIX;
1532
1533         snprintf(addr.sun_path, sizeof(addr.sun_path), "%s%s",
1534                  BHYVE_RUN_DIR, vm_get_name(ctx));
1535         addr.sun_len = SUN_LEN(&addr);
1536         unlink(addr.sun_path);
1537
1538         if (bind(socket_fd, (struct sockaddr *)&addr, addr.sun_len) != 0) {
1539                 EPRINTLN("Failed to bind socket \"%s\": %s\n",
1540                     addr.sun_path, strerror(errno));
1541                 err = -1;
1542                 goto fail;
1543         }
1544
1545         if (listen(socket_fd, 10) < 0) {
1546                 EPRINTLN("ipc socket listen: %s\n", strerror(errno));
1547                 err = errno;
1548                 goto fail;
1549         }
1550
1551         checkpoint_info = calloc(1, sizeof(*checkpoint_info));
1552         checkpoint_info->ctx = ctx;
1553         checkpoint_info->socket_fd = socket_fd;
1554
1555         err = pthread_create(&checkpoint_pthread, NULL, checkpoint_thread,
1556                 checkpoint_info);
1557         if (err != 0)
1558                 goto fail;
1559
1560         return (0);
1561 fail:
1562         free(checkpoint_info);
1563         if (socket_fd > 0)
1564                 close(socket_fd);
1565         unlink(addr.sun_path);
1566
1567         return (err);
1568 }
1569
1570 void
1571 vm_snapshot_buf_err(const char *bufname, const enum vm_snapshot_op op)
1572 {
1573         const char *__op;
1574
1575         if (op == VM_SNAPSHOT_SAVE)
1576                 __op = "save";
1577         else if (op == VM_SNAPSHOT_RESTORE)
1578                 __op = "restore";
1579         else
1580                 __op = "unknown";
1581
1582         fprintf(stderr, "%s: snapshot-%s failed for %s\r\n",
1583                 __func__, __op, bufname);
1584 }
1585
1586 int
1587 vm_snapshot_buf(void *data, size_t data_size, struct vm_snapshot_meta *meta)
1588 {
1589         struct vm_snapshot_buffer *buffer;
1590         int op;
1591
1592         buffer = &meta->buffer;
1593         op = meta->op;
1594
1595         if (buffer->buf_rem < data_size) {
1596                 fprintf(stderr, "%s: buffer too small\r\n", __func__);
1597                 return (E2BIG);
1598         }
1599
1600         if (op == VM_SNAPSHOT_SAVE)
1601                 memcpy(buffer->buf, data, data_size);
1602         else if (op == VM_SNAPSHOT_RESTORE)
1603                 memcpy(data, buffer->buf, data_size);
1604         else
1605                 return (EINVAL);
1606
1607         buffer->buf += data_size;
1608         buffer->buf_rem -= data_size;
1609
1610         return (0);
1611 }
1612
1613 size_t
1614 vm_get_snapshot_size(struct vm_snapshot_meta *meta)
1615 {
1616         size_t length;
1617         struct vm_snapshot_buffer *buffer;
1618
1619         buffer = &meta->buffer;
1620
1621         if (buffer->buf_size < buffer->buf_rem) {
1622                 fprintf(stderr, "%s: Invalid buffer: size = %zu, rem = %zu\r\n",
1623                         __func__, buffer->buf_size, buffer->buf_rem);
1624                 length = 0;
1625         } else {
1626                 length = buffer->buf_size - buffer->buf_rem;
1627         }
1628
1629         return (length);
1630 }
1631
1632 int
1633 vm_snapshot_guest2host_addr(void **addrp, size_t len, bool restore_null,
1634                             struct vm_snapshot_meta *meta)
1635 {
1636         int ret;
1637         vm_paddr_t gaddr;
1638
1639         if (meta->op == VM_SNAPSHOT_SAVE) {
1640                 gaddr = paddr_host2guest(meta->ctx, *addrp);
1641                 if (gaddr == (vm_paddr_t) -1) {
1642                         if (!restore_null ||
1643                             (restore_null && (*addrp != NULL))) {
1644                                 ret = EFAULT;
1645                                 goto done;
1646                         }
1647                 }
1648
1649                 SNAPSHOT_VAR_OR_LEAVE(gaddr, meta, ret, done);
1650         } else if (meta->op == VM_SNAPSHOT_RESTORE) {
1651                 SNAPSHOT_VAR_OR_LEAVE(gaddr, meta, ret, done);
1652                 if (gaddr == (vm_paddr_t) -1) {
1653                         if (!restore_null) {
1654                                 ret = EFAULT;
1655                                 goto done;
1656                         }
1657                 }
1658
1659                 *addrp = paddr_guest2host(meta->ctx, gaddr, len);
1660         } else {
1661                 ret = EINVAL;
1662         }
1663
1664 done:
1665         return (ret);
1666 }
1667
1668 int
1669 vm_snapshot_buf_cmp(void *data, size_t data_size, struct vm_snapshot_meta *meta)
1670 {
1671         struct vm_snapshot_buffer *buffer;
1672         int op;
1673         int ret;
1674
1675         buffer = &meta->buffer;
1676         op = meta->op;
1677
1678         if (buffer->buf_rem < data_size) {
1679                 fprintf(stderr, "%s: buffer too small\r\n", __func__);
1680                 ret = E2BIG;
1681                 goto done;
1682         }
1683
1684         if (op == VM_SNAPSHOT_SAVE) {
1685                 ret = 0;
1686                 memcpy(buffer->buf, data, data_size);
1687         } else if (op == VM_SNAPSHOT_RESTORE) {
1688                 ret = memcmp(data, buffer->buf, data_size);
1689         } else {
1690                 ret = EINVAL;
1691                 goto done;
1692         }
1693
1694         buffer->buf += data_size;
1695         buffer->buf_rem -= data_size;
1696
1697 done:
1698         return (ret);
1699 }