]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/bhyve/snapshot.c
zfs: merge OpenZFS master-bedbc13da
[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 "inout.h"
83 #include "fwctl.h"
84 #include "ioapic.h"
85 #include "mem.h"
86 #include "mevent.h"
87 #include "mptbl.h"
88 #include "pci_emul.h"
89 #include "pci_irq.h"
90 #include "pci_lpc.h"
91 #include "smbiostbl.h"
92 #include "snapshot.h"
93 #include "xmsr.h"
94 #include "spinup_ap.h"
95 #include "rtc.h"
96
97 #include <libxo/xo.h>
98 #include <ucl.h>
99
100 struct spinner_info {
101         const size_t *crtval;
102         const size_t maxval;
103         const size_t total;
104 };
105
106 extern int guest_ncpus;
107
108 static struct winsize winsize;
109 static sig_t old_winch_handler;
110
111 #define KB              (1024UL)
112 #define MB              (1024UL * KB)
113 #define GB              (1024UL * MB)
114
115 #define SNAPSHOT_CHUNK  (4 * MB)
116 #define PROG_BUF_SZ     (8192)
117
118 #define MAX_VMNAME 100
119
120 #define MAX_MSG_SIZE 1024
121
122 #define SNAPSHOT_BUFFER_SIZE (20 * MB)
123
124 #define JSON_STRUCT_ARR_KEY             "structs"
125 #define JSON_DEV_ARR_KEY                "devices"
126 #define JSON_BASIC_METADATA_KEY         "basic metadata"
127 #define JSON_SNAPSHOT_REQ_KEY           "snapshot_req"
128 #define JSON_SIZE_KEY                   "size"
129 #define JSON_FILE_OFFSET_KEY            "file_offset"
130
131 #define JSON_NCPUS_KEY                  "ncpus"
132 #define JSON_VMNAME_KEY                 "vmname"
133 #define JSON_MEMSIZE_KEY                "memsize"
134 #define JSON_MEMFLAGS_KEY               "memflags"
135
136 #define min(a,b)                \
137 ({                              \
138  __typeof__ (a) _a = (a);       \
139  __typeof__ (b) _b = (b);       \
140  _a < _b ? _a : _b;             \
141  })
142
143 const struct vm_snapshot_dev_info snapshot_devs[] = {
144         { "atkbdc",     atkbdc_snapshot,        NULL,           NULL            },
145         { "virtio-net", pci_snapshot,           pci_pause,      pci_resume      },
146         { "virtio-blk", pci_snapshot,           pci_pause,      pci_resume      },
147         { "virtio-rnd", pci_snapshot,           NULL,           NULL            },
148         { "lpc",        pci_snapshot,           NULL,           NULL            },
149         { "fbuf",       pci_snapshot,           NULL,           NULL            },
150         { "xhci",       pci_snapshot,           NULL,           NULL            },
151         { "e1000",      pci_snapshot,           NULL,           NULL            },
152         { "ahci",       pci_snapshot,           pci_pause,      pci_resume      },
153         { "ahci-hd",    pci_snapshot,           pci_pause,      pci_resume      },
154         { "ahci-cd",    pci_snapshot,           pci_pause,      pci_resume      },
155 };
156
157 const struct vm_snapshot_kern_info snapshot_kern_structs[] = {
158         { "vhpet",      STRUCT_VHPET    },
159         { "vm",         STRUCT_VM       },
160         { "vmx",        STRUCT_VMX      },
161         { "vioapic",    STRUCT_VIOAPIC  },
162         { "vlapic",     STRUCT_VLAPIC   },
163         { "vmcx",       STRUCT_VMCX     },
164         { "vatpit",     STRUCT_VATPIT   },
165         { "vatpic",     STRUCT_VATPIC   },
166         { "vpmtmr",     STRUCT_VPMTMR   },
167         { "vrtc",       STRUCT_VRTC     },
168 };
169
170 static cpuset_t vcpus_active, vcpus_suspended;
171 static pthread_mutex_t vcpu_lock;
172 static pthread_cond_t vcpus_idle, vcpus_can_run;
173 static bool checkpoint_active;
174
175 /*
176  * TODO: Harden this function and all of its callers since 'base_str' is a user
177  * provided string.
178  */
179 static char *
180 strcat_extension(const char *base_str, const char *ext)
181 {
182         char *res;
183         size_t base_len, ext_len;
184
185         base_len = strnlen(base_str, MAX_VMNAME);
186         ext_len = strnlen(ext, MAX_VMNAME);
187
188         if (base_len + ext_len > MAX_VMNAME) {
189                 fprintf(stderr, "Filename exceeds maximum length.\n");
190                 return (NULL);
191         }
192
193         res = malloc(base_len + ext_len + 1);
194         if (res == NULL) {
195                 perror("Failed to allocate memory.");
196                 return (NULL);
197         }
198
199         memcpy(res, base_str, base_len);
200         memcpy(res + base_len, ext, ext_len);
201         res[base_len + ext_len] = 0;
202
203         return (res);
204 }
205
206 void
207 destroy_restore_state(struct restore_state *rstate)
208 {
209         if (rstate == NULL) {
210                 fprintf(stderr, "Attempting to destroy NULL restore struct.\n");
211                 return;
212         }
213
214         if (rstate->kdata_map != MAP_FAILED)
215                 munmap(rstate->kdata_map, rstate->kdata_len);
216
217         if (rstate->kdata_fd > 0)
218                 close(rstate->kdata_fd);
219         if (rstate->vmmem_fd > 0)
220                 close(rstate->vmmem_fd);
221
222         if (rstate->meta_root_obj != NULL)
223                 ucl_object_unref(rstate->meta_root_obj);
224         if (rstate->meta_parser != NULL)
225                 ucl_parser_free(rstate->meta_parser);
226 }
227
228 static int
229 load_vmmem_file(const char *filename, struct restore_state *rstate)
230 {
231         struct stat sb;
232         int err;
233
234         rstate->vmmem_fd = open(filename, O_RDONLY);
235         if (rstate->vmmem_fd < 0) {
236                 perror("Failed to open restore file");
237                 return (-1);
238         }
239
240         err = fstat(rstate->vmmem_fd, &sb);
241         if (err < 0) {
242                 perror("Failed to stat restore file");
243                 goto err_load_vmmem;
244         }
245
246         if (sb.st_size == 0) {
247                 fprintf(stderr, "Restore file is empty.\n");
248                 goto err_load_vmmem;
249         }
250
251         rstate->vmmem_len = sb.st_size;
252
253         return (0);
254
255 err_load_vmmem:
256         if (rstate->vmmem_fd > 0)
257                 close(rstate->vmmem_fd);
258         return (-1);
259 }
260
261 static int
262 load_kdata_file(const char *filename, struct restore_state *rstate)
263 {
264         struct stat sb;
265         int err;
266
267         rstate->kdata_fd = open(filename, O_RDONLY);
268         if (rstate->kdata_fd < 0) {
269                 perror("Failed to open kernel data file");
270                 return (-1);
271         }
272
273         err = fstat(rstate->kdata_fd, &sb);
274         if (err < 0) {
275                 perror("Failed to stat kernel data file");
276                 goto err_load_kdata;
277         }
278
279         if (sb.st_size == 0) {
280                 fprintf(stderr, "Kernel data file is empty.\n");
281                 goto err_load_kdata;
282         }
283
284         rstate->kdata_len = sb.st_size;
285         rstate->kdata_map = mmap(NULL, rstate->kdata_len, PROT_READ,
286                                  MAP_SHARED, rstate->kdata_fd, 0);
287         if (rstate->kdata_map == MAP_FAILED) {
288                 perror("Failed to map restore file");
289                 goto err_load_kdata;
290         }
291
292         return (0);
293
294 err_load_kdata:
295         if (rstate->kdata_fd > 0)
296                 close(rstate->kdata_fd);
297         return (-1);
298 }
299
300 static int
301 load_metadata_file(const char *filename, struct restore_state *rstate)
302 {
303         const ucl_object_t *obj;
304         struct ucl_parser *parser;
305         int err;
306
307         parser = ucl_parser_new(UCL_PARSER_DEFAULT);
308         if (parser == NULL) {
309                 fprintf(stderr, "Failed to initialize UCL parser.\n");
310                 goto err_load_metadata;
311         }
312
313         err = ucl_parser_add_file(parser, filename);
314         if (err == 0) {
315                 fprintf(stderr, "Failed to parse metadata file: '%s'\n",
316                         filename);
317                 err = -1;
318                 goto err_load_metadata;
319         }
320
321         obj = ucl_parser_get_object(parser);
322         if (obj == NULL) {
323                 fprintf(stderr, "Failed to parse object.\n");
324                 err = -1;
325                 goto err_load_metadata;
326         }
327
328         rstate->meta_parser = parser;
329         rstate->meta_root_obj = (ucl_object_t *)obj;
330
331         return (0);
332
333 err_load_metadata:
334         if (parser != NULL)
335                 ucl_parser_free(parser);
336         return (err);
337 }
338
339 int
340 load_restore_file(const char *filename, struct restore_state *rstate)
341 {
342         int err = 0;
343         char *kdata_filename = NULL, *meta_filename = NULL;
344
345         assert(filename != NULL);
346         assert(rstate != NULL);
347
348         memset(rstate, 0, sizeof(*rstate));
349         rstate->kdata_map = MAP_FAILED;
350
351         err = load_vmmem_file(filename, rstate);
352         if (err != 0) {
353                 fprintf(stderr, "Failed to load guest RAM file.\n");
354                 goto err_restore;
355         }
356
357         kdata_filename = strcat_extension(filename, ".kern");
358         if (kdata_filename == NULL) {
359                 fprintf(stderr, "Failed to construct kernel data filename.\n");
360                 goto err_restore;
361         }
362
363         err = load_kdata_file(kdata_filename, rstate);
364         if (err != 0) {
365                 fprintf(stderr, "Failed to load guest kernel data file.\n");
366                 goto err_restore;
367         }
368
369         meta_filename = strcat_extension(filename, ".meta");
370         if (meta_filename == NULL) {
371                 fprintf(stderr, "Failed to construct kernel metadata filename.\n");
372                 goto err_restore;
373         }
374
375         err = load_metadata_file(meta_filename, rstate);
376         if (err != 0) {
377                 fprintf(stderr, "Failed to load guest metadata file.\n");
378                 goto err_restore;
379         }
380
381         return (0);
382
383 err_restore:
384         destroy_restore_state(rstate);
385         if (kdata_filename != NULL)
386                 free(kdata_filename);
387         if (meta_filename != NULL)
388                 free(meta_filename);
389         return (-1);
390 }
391
392 #define JSON_GET_INT_OR_RETURN(key, obj, result_ptr, ret)                       \
393 do {                                                                            \
394         const ucl_object_t *obj__;                                              \
395         obj__ = ucl_object_lookup(obj, key);                                    \
396         if (obj__ == NULL) {                                                    \
397                 fprintf(stderr, "Missing key: '%s'", key);                      \
398                 return (ret);                                                   \
399         }                                                                       \
400         if (!ucl_object_toint_safe(obj__, result_ptr)) {                        \
401                 fprintf(stderr, "Cannot convert '%s' value to int.", key);      \
402                 return (ret);                                                   \
403         }                                                                       \
404 } while(0)
405
406 #define JSON_GET_STRING_OR_RETURN(key, obj, result_ptr, ret)                    \
407 do {                                                                            \
408         const ucl_object_t *obj__;                                              \
409         obj__ = ucl_object_lookup(obj, key);                                    \
410         if (obj__ == NULL) {                                                    \
411                 fprintf(stderr, "Missing key: '%s'", key);                      \
412                 return (ret);                                                   \
413         }                                                                       \
414         if (!ucl_object_tostring_safe(obj__, result_ptr)) {                     \
415                 fprintf(stderr, "Cannot convert '%s' value to string.", key);   \
416                 return (ret);                                                   \
417         }                                                                       \
418 } while(0)
419
420 static void *
421 lookup_struct(enum snapshot_req struct_id, struct restore_state *rstate,
422               size_t *struct_size)
423 {
424         const ucl_object_t *structs = NULL, *obj = NULL;
425         ucl_object_iter_t it = NULL;
426         int64_t snapshot_req, size, file_offset;
427
428         structs = ucl_object_lookup(rstate->meta_root_obj, JSON_STRUCT_ARR_KEY);
429         if (structs == NULL) {
430                 fprintf(stderr, "Failed to find '%s' object.\n",
431                         JSON_STRUCT_ARR_KEY);
432                 return (NULL);
433         }
434
435         if (ucl_object_type((ucl_object_t *)structs) != UCL_ARRAY) {
436                 fprintf(stderr, "Object '%s' is not an array.\n",
437                 JSON_STRUCT_ARR_KEY);
438                 return (NULL);
439         }
440
441         while ((obj = ucl_object_iterate(structs, &it, true)) != NULL) {
442                 snapshot_req = -1;
443                 JSON_GET_INT_OR_RETURN(JSON_SNAPSHOT_REQ_KEY, obj,
444                                        &snapshot_req, NULL);
445                 assert(snapshot_req >= 0);
446                 if ((enum snapshot_req) snapshot_req == struct_id) {
447                         JSON_GET_INT_OR_RETURN(JSON_SIZE_KEY, obj,
448                                                &size, NULL);
449                         assert(size >= 0);
450
451                         JSON_GET_INT_OR_RETURN(JSON_FILE_OFFSET_KEY, obj,
452                                                &file_offset, NULL);
453                         assert(file_offset >= 0);
454                         assert(file_offset + size <= rstate->kdata_len);
455
456                         *struct_size = (size_t)size;
457                         return (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(file_offset + size <= rstate->kdata_len);
484
485                 *data_size = (size_t)size;
486                 return (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((ucl_object_t *)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((ucl_object_t *)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)
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 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 += 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         int ret;
918         int i;
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 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         int ret;
981         int i;
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(struct vmctx *ctx)
994 {
995         const struct vm_snapshot_dev_info *info;
996         int ret;
997         int i;
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(ctx, info->dev_name);
1005                 if (ret != 0)
1006                         return (ret);
1007         }
1008
1009         return (0);
1010 }
1011
1012 int
1013 vm_resume_user_devs(struct vmctx *ctx)
1014 {
1015         const struct vm_snapshot_dev_info *info;
1016         int ret;
1017         int i;
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(ctx, 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         write_cnt = write(data_fd, meta->buffer.buf_start, data_size);
1051         if (write_cnt != data_size) {
1052                 perror("Failed to write all snapshotted data.");
1053                 ret = -1;
1054                 goto done;
1055         }
1056
1057         /* Write metadata. */
1058         xo_open_instance_h(xop, array_key);
1059         xo_emit_h(xop, "{:debug_name/%s}\n", meta->dev_name);
1060         xo_emit_h(xop, "{:" JSON_SNAPSHOT_REQ_KEY "/%d}\n",
1061                   meta->dev_req);
1062         xo_emit_h(xop, "{:" JSON_SIZE_KEY "/%lu}\n", data_size);
1063         xo_emit_h(xop, "{:" JSON_FILE_OFFSET_KEY "/%lu}\n", *offset);
1064         xo_close_instance_h(xop, JSON_STRUCT_ARR_KEY);
1065
1066         *offset += data_size;
1067
1068 done:
1069         return (ret);
1070 }
1071
1072 static int
1073 vm_snapshot_kern_structs(struct vmctx *ctx, int data_fd, xo_handle_t *xop)
1074 {
1075         int ret, i, error;
1076         size_t offset, buf_size;
1077         char *buffer;
1078         struct vm_snapshot_meta *meta;
1079
1080         error = 0;
1081         offset = 0;
1082         buf_size = SNAPSHOT_BUFFER_SIZE;
1083
1084         buffer = malloc(SNAPSHOT_BUFFER_SIZE * sizeof(char));
1085         if (buffer == NULL) {
1086                 error = ENOMEM;
1087                 perror("Failed to allocate memory for snapshot buffer");
1088                 goto err_vm_snapshot_kern_data;
1089         }
1090
1091         meta = &(struct vm_snapshot_meta) {
1092                 .ctx = ctx,
1093
1094                 .buffer.buf_start = buffer,
1095                 .buffer.buf_size = buf_size,
1096
1097                 .op = VM_SNAPSHOT_SAVE,
1098         };
1099
1100         xo_open_list_h(xop, JSON_STRUCT_ARR_KEY);
1101         for (i = 0; i < nitems(snapshot_kern_structs); i++) {
1102                 meta->dev_name = snapshot_kern_structs[i].struct_name;
1103                 meta->dev_req  = snapshot_kern_structs[i].req;
1104
1105                 memset(meta->buffer.buf_start, 0, meta->buffer.buf_size);
1106                 meta->buffer.buf = meta->buffer.buf_start;
1107                 meta->buffer.buf_rem = meta->buffer.buf_size;
1108
1109                 ret = vm_snapshot_kern_struct(data_fd, xop, JSON_DEV_ARR_KEY,
1110                                               meta, &offset);
1111                 if (ret != 0) {
1112                         error = -1;
1113                         goto err_vm_snapshot_kern_data;
1114                 }
1115         }
1116         xo_close_list_h(xop, JSON_STRUCT_ARR_KEY);
1117
1118 err_vm_snapshot_kern_data:
1119         if (buffer != NULL)
1120                 free(buffer);
1121         return (error);
1122 }
1123
1124 static int
1125 vm_snapshot_basic_metadata(struct vmctx *ctx, xo_handle_t *xop, size_t memsz)
1126 {
1127         int error;
1128         int memflags;
1129         char vmname_buf[MAX_VMNAME];
1130
1131         memset(vmname_buf, 0, MAX_VMNAME);
1132         error = vm_get_name(ctx, vmname_buf, MAX_VMNAME - 1);
1133         if (error != 0) {
1134                 perror("Failed to get VM name");
1135                 goto err;
1136         }
1137
1138         memflags = vm_get_memflags(ctx);
1139
1140         xo_open_container_h(xop, JSON_BASIC_METADATA_KEY);
1141         xo_emit_h(xop, "{:" JSON_NCPUS_KEY "/%ld}\n", guest_ncpus);
1142         xo_emit_h(xop, "{:" JSON_VMNAME_KEY "/%s}\n", vmname_buf);
1143         xo_emit_h(xop, "{:" JSON_MEMSIZE_KEY "/%lu}\n", memsz);
1144         xo_emit_h(xop, "{:" JSON_MEMFLAGS_KEY "/%d}\n", memflags);
1145         xo_close_container_h(xop, JSON_BASIC_METADATA_KEY);
1146
1147 err:
1148         return (error);
1149 }
1150
1151 static int
1152 vm_snapshot_dev_write_data(int data_fd, xo_handle_t *xop, const char *array_key,
1153                            struct vm_snapshot_meta *meta, off_t *offset)
1154 {
1155         int ret;
1156         size_t data_size;
1157
1158         data_size = vm_get_snapshot_size(meta);
1159
1160         ret = write(data_fd, meta->buffer.buf_start, data_size);
1161         if (ret != data_size) {
1162                 perror("Failed to write all snapshotted data.");
1163                 return (-1);
1164         }
1165
1166         /* Write metadata. */
1167         xo_open_instance_h(xop, array_key);
1168         xo_emit_h(xop, "{:" JSON_SNAPSHOT_REQ_KEY "/%s}\n", meta->dev_name);
1169         xo_emit_h(xop, "{:" JSON_SIZE_KEY "/%lu}\n", data_size);
1170         xo_emit_h(xop, "{:" JSON_FILE_OFFSET_KEY "/%lu}\n", *offset);
1171         xo_close_instance_h(xop, array_key);
1172
1173         *offset += data_size;
1174
1175         return (0);
1176 }
1177
1178 static int
1179 vm_snapshot_user_dev(const struct vm_snapshot_dev_info *info,
1180                      int data_fd, xo_handle_t *xop,
1181                      struct vm_snapshot_meta *meta, off_t *offset)
1182 {
1183         int ret;
1184
1185         ret = (*info->snapshot_cb)(meta);
1186         if (ret != 0) {
1187                 fprintf(stderr, "Failed to snapshot %s; ret=%d\r\n",
1188                         meta->dev_name, ret);
1189                 return (ret);
1190         }
1191
1192         ret = vm_snapshot_dev_write_data(data_fd, xop, JSON_DEV_ARR_KEY, meta,
1193                                          offset);
1194         if (ret != 0)
1195                 return (ret);
1196
1197         return (0);
1198 }
1199
1200 static int
1201 vm_snapshot_user_devs(struct vmctx *ctx, int data_fd, xo_handle_t *xop)
1202 {
1203         int ret, i;
1204         off_t offset;
1205         void *buffer;
1206         size_t buf_size;
1207         struct vm_snapshot_meta *meta;
1208
1209         buf_size = SNAPSHOT_BUFFER_SIZE;
1210
1211         offset = lseek(data_fd, 0, SEEK_CUR);
1212         if (offset < 0) {
1213                 perror("Failed to get data file current offset.");
1214                 return (-1);
1215         }
1216
1217         buffer = malloc(buf_size);
1218         if (buffer == NULL) {
1219                 perror("Failed to allocate memory for snapshot buffer");
1220                 ret = ENOSPC;
1221                 goto snapshot_err;
1222         }
1223
1224         meta = &(struct vm_snapshot_meta) {
1225                 .ctx = ctx,
1226
1227                 .buffer.buf_start = buffer,
1228                 .buffer.buf_size = buf_size,
1229
1230                 .op = VM_SNAPSHOT_SAVE,
1231         };
1232
1233         xo_open_list_h(xop, JSON_DEV_ARR_KEY);
1234
1235         /* Restore other devices that support this feature */
1236         for (i = 0; i < nitems(snapshot_devs); i++) {
1237                 meta->dev_name = snapshot_devs[i].dev_name;
1238
1239                 memset(meta->buffer.buf_start, 0, meta->buffer.buf_size);
1240                 meta->buffer.buf = meta->buffer.buf_start;
1241                 meta->buffer.buf_rem = meta->buffer.buf_size;
1242
1243                 ret = vm_snapshot_user_dev(&snapshot_devs[i], data_fd, xop,
1244                                            meta, &offset);
1245                 if (ret != 0)
1246                         goto snapshot_err;
1247         }
1248
1249         xo_close_list_h(xop, JSON_DEV_ARR_KEY);
1250
1251 snapshot_err:
1252         if (buffer != NULL)
1253                 free(buffer);
1254         return (ret);
1255 }
1256
1257 void
1258 checkpoint_cpu_add(int vcpu)
1259 {
1260
1261         pthread_mutex_lock(&vcpu_lock);
1262         CPU_SET(vcpu, &vcpus_active);
1263
1264         if (checkpoint_active) {
1265                 CPU_SET(vcpu, &vcpus_suspended);
1266                 while (checkpoint_active)
1267                         pthread_cond_wait(&vcpus_can_run, &vcpu_lock);
1268                 CPU_CLR(vcpu, &vcpus_suspended);
1269         }
1270         pthread_mutex_unlock(&vcpu_lock);
1271 }
1272
1273 /*
1274  * When a vCPU is suspended for any reason, it calls
1275  * checkpoint_cpu_suspend().  This records that the vCPU is idle.
1276  * Before returning from suspension, checkpoint_cpu_resume() is
1277  * called.  In suspend we note that the vCPU is idle.  In resume we
1278  * pause the vCPU thread until the checkpoint is complete.  The reason
1279  * for the two-step process is that vCPUs might already be stopped in
1280  * the debug server when a checkpoint is requested.  This approach
1281  * allows us to account for and handle those vCPUs.
1282  */
1283 void
1284 checkpoint_cpu_suspend(int vcpu)
1285 {
1286
1287         pthread_mutex_lock(&vcpu_lock);
1288         CPU_SET(vcpu, &vcpus_suspended);
1289         if (checkpoint_active && CPU_CMP(&vcpus_active, &vcpus_suspended) == 0)
1290                 pthread_cond_signal(&vcpus_idle);
1291         pthread_mutex_unlock(&vcpu_lock);
1292 }
1293
1294 void
1295 checkpoint_cpu_resume(int vcpu)
1296 {
1297
1298         pthread_mutex_lock(&vcpu_lock);
1299         while (checkpoint_active)
1300                 pthread_cond_wait(&vcpus_can_run, &vcpu_lock);
1301         CPU_CLR(vcpu, &vcpus_suspended);
1302         pthread_mutex_unlock(&vcpu_lock);
1303 }
1304
1305 static void
1306 vm_vcpu_pause(struct vmctx *ctx)
1307 {
1308
1309         pthread_mutex_lock(&vcpu_lock);
1310         checkpoint_active = true;
1311         vm_suspend_cpu(ctx, -1);
1312         while (CPU_CMP(&vcpus_active, &vcpus_suspended) != 0)
1313                 pthread_cond_wait(&vcpus_idle, &vcpu_lock);
1314         pthread_mutex_unlock(&vcpu_lock);
1315 }
1316
1317 static void
1318 vm_vcpu_resume(struct vmctx *ctx)
1319 {
1320
1321         pthread_mutex_lock(&vcpu_lock);
1322         checkpoint_active = false;
1323         pthread_mutex_unlock(&vcpu_lock);
1324         vm_resume_cpu(ctx, -1);
1325         pthread_cond_broadcast(&vcpus_can_run);
1326 }
1327
1328 static int
1329 vm_checkpoint(struct vmctx *ctx, char *checkpoint_file, bool stop_vm)
1330 {
1331         int fd_checkpoint = 0, kdata_fd = 0;
1332         int ret = 0;
1333         int error = 0;
1334         size_t memsz;
1335         xo_handle_t *xop = NULL;
1336         char *meta_filename = NULL;
1337         char *kdata_filename = NULL;
1338         FILE *meta_file = NULL;
1339
1340         kdata_filename = strcat_extension(checkpoint_file, ".kern");
1341         if (kdata_filename == NULL) {
1342                 fprintf(stderr, "Failed to construct kernel data filename.\n");
1343                 return (-1);
1344         }
1345
1346         kdata_fd = open(kdata_filename, O_WRONLY | O_CREAT | O_TRUNC, 0700);
1347         if (kdata_fd < 0) {
1348                 perror("Failed to open kernel data snapshot file.");
1349                 error = -1;
1350                 goto done;
1351         }
1352
1353         fd_checkpoint = open(checkpoint_file, O_RDWR | O_CREAT | O_TRUNC, 0700);
1354
1355         if (fd_checkpoint < 0) {
1356                 perror("Failed to create checkpoint file");
1357                 error = -1;
1358                 goto done;
1359         }
1360
1361         meta_filename = strcat_extension(checkpoint_file, ".meta");
1362         if (meta_filename == NULL) {
1363                 fprintf(stderr, "Failed to construct vm metadata filename.\n");
1364                 goto done;
1365         }
1366
1367         meta_file = fopen(meta_filename, "w");
1368         if (meta_file == NULL) {
1369                 perror("Failed to open vm metadata snapshot file.");
1370                 goto done;
1371         }
1372
1373         xop = xo_create_to_file(meta_file, XO_STYLE_JSON, XOF_PRETTY);
1374         if (xop == NULL) {
1375                 perror("Failed to get libxo handle on metadata file.");
1376                 goto done;
1377         }
1378
1379         vm_vcpu_pause(ctx);
1380
1381         ret = vm_pause_user_devs(ctx);
1382         if (ret != 0) {
1383                 fprintf(stderr, "Could not pause devices\r\n");
1384                 error = ret;
1385                 goto done;
1386         }
1387
1388         memsz = vm_snapshot_mem(ctx, fd_checkpoint, 0, true);
1389         if (memsz == 0) {
1390                 perror("Could not write guest memory to file");
1391                 error = -1;
1392                 goto done;
1393         }
1394
1395         ret = vm_snapshot_basic_metadata(ctx, xop, memsz);
1396         if (ret != 0) {
1397                 fprintf(stderr, "Failed to snapshot vm basic metadata.\n");
1398                 error = -1;
1399                 goto done;
1400         }
1401
1402
1403         ret = vm_snapshot_kern_structs(ctx, kdata_fd, xop);
1404         if (ret != 0) {
1405                 fprintf(stderr, "Failed to snapshot vm kernel data.\n");
1406                 error = -1;
1407                 goto done;
1408         }
1409
1410         ret = vm_snapshot_user_devs(ctx, kdata_fd, xop);
1411         if (ret != 0) {
1412                 fprintf(stderr, "Failed to snapshot device state.\n");
1413                 error = -1;
1414                 goto done;
1415         }
1416
1417         xo_finish_h(xop);
1418
1419         if (stop_vm) {
1420                 vm_destroy(ctx);
1421                 exit(0);
1422         }
1423
1424 done:
1425         ret = vm_resume_user_devs(ctx);
1426         if (ret != 0)
1427                 fprintf(stderr, "Could not resume devices\r\n");
1428         vm_vcpu_resume(ctx);
1429         if (fd_checkpoint > 0)
1430                 close(fd_checkpoint);
1431         if (meta_filename != NULL)
1432                 free(meta_filename);
1433         if (kdata_filename != NULL)
1434                 free(kdata_filename);
1435         if (xop != NULL)
1436                 xo_destroy(xop);
1437         if (meta_file != NULL)
1438                 fclose(meta_file);
1439         if (kdata_fd > 0)
1440                 close(kdata_fd);
1441         return (error);
1442 }
1443
1444 int
1445 get_checkpoint_msg(int conn_fd, struct vmctx *ctx)
1446 {
1447         unsigned char buf[MAX_MSG_SIZE];
1448         struct checkpoint_op *checkpoint_op;
1449         int len, recv_len, total_recv = 0;
1450         int err = 0;
1451
1452         len = sizeof(struct checkpoint_op); /* expected length */
1453         while ((recv_len = recv(conn_fd, buf + total_recv, len - total_recv, 0)) > 0) {
1454                 total_recv += recv_len;
1455         }
1456         if (recv_len < 0) {
1457                 perror("Error while receiving data from bhyvectl");
1458                 err = -1;
1459                 goto done;
1460         }
1461
1462         checkpoint_op = (struct checkpoint_op *)buf;
1463         switch (checkpoint_op->op) {
1464                 case START_CHECKPOINT:
1465                         err = vm_checkpoint(ctx, checkpoint_op->snapshot_filename, false);
1466                         break;
1467                 case START_SUSPEND:
1468                         err = vm_checkpoint(ctx, checkpoint_op->snapshot_filename, true);
1469                         break;
1470                 default:
1471                         fprintf(stderr, "Unrecognized checkpoint operation.\n");
1472                         err = -1;
1473         }
1474
1475 done:
1476         close(conn_fd);
1477         return (err);
1478 }
1479
1480 /*
1481  * Listen for commands from bhyvectl
1482  */
1483 void *
1484 checkpoint_thread(void *param)
1485 {
1486         struct checkpoint_thread_info *thread_info;
1487         int conn_fd, ret;
1488
1489         pthread_set_name_np(pthread_self(), "checkpoint thread");
1490         thread_info = (struct checkpoint_thread_info *)param;
1491
1492         while ((conn_fd = accept(thread_info->socket_fd, NULL, NULL)) > -1) {
1493                 ret = get_checkpoint_msg(conn_fd, thread_info->ctx);
1494                 if (ret != 0) {
1495                         fprintf(stderr, "Failed to read message on checkpoint "
1496                                         "socket. Retrying.\n");
1497                 }
1498         }
1499         if (conn_fd < -1) {
1500                 perror("Failed to accept connection");
1501         }
1502
1503         return (NULL);
1504 }
1505
1506 /*
1507  * Create the listening socket for IPC with bhyvectl
1508  */
1509 int
1510 init_checkpoint_thread(struct vmctx *ctx)
1511 {
1512         struct checkpoint_thread_info *checkpoint_info = NULL;
1513         struct sockaddr_un addr;
1514         int socket_fd;
1515         pthread_t checkpoint_pthread;
1516         char vmname_buf[MAX_VMNAME];
1517         int ret, err = 0;
1518
1519         memset(&addr, 0, sizeof(addr));
1520
1521         err = pthread_mutex_init(&vcpu_lock, NULL);
1522         if (err != 0)
1523                 errc(1, err, "checkpoint mutex init");
1524         err = pthread_cond_init(&vcpus_idle, NULL);
1525         if (err == 0)
1526                 err = pthread_cond_init(&vcpus_can_run, NULL);
1527         if (err != 0)
1528                 errc(1, err, "checkpoint cv init");
1529
1530         socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
1531         if (socket_fd < 0) {
1532                 perror("Socket creation failed (IPC with bhyvectl");
1533                 err = -1;
1534                 goto fail;
1535         }
1536
1537         addr.sun_family = AF_UNIX;
1538
1539         err = vm_get_name(ctx, vmname_buf, MAX_VMNAME - 1);
1540         if (err != 0) {
1541                 perror("Failed to get VM name");
1542                 goto fail;
1543         }
1544
1545         snprintf(addr.sun_path, sizeof(addr.sun_path), "%s%s",
1546                  BHYVE_RUN_DIR, vmname_buf);
1547         addr.sun_len = SUN_LEN(&addr);
1548         unlink(addr.sun_path);
1549
1550         if (bind(socket_fd, (struct sockaddr *)&addr, addr.sun_len) != 0) {
1551                 perror("Failed to bind socket (IPC with bhyvectl)");
1552                 err = -1;
1553                 goto fail;
1554         }
1555
1556         if (listen(socket_fd, 10) < 0) {
1557                 perror("Failed to listen on socket (IPC with bhyvectl)");
1558                 err = -1;
1559                 goto fail;
1560         }
1561
1562         checkpoint_info = calloc(1, sizeof(*checkpoint_info));
1563         checkpoint_info->ctx = ctx;
1564         checkpoint_info->socket_fd = socket_fd;
1565
1566         ret = pthread_create(&checkpoint_pthread, NULL, checkpoint_thread,
1567                 checkpoint_info);
1568         if (ret < 0) {
1569                 err = ret;
1570                 goto fail;
1571         }
1572
1573         return (0);
1574 fail:
1575         free(checkpoint_info);
1576         if (socket_fd > 0)
1577                 close(socket_fd);
1578         unlink(addr.sun_path);
1579
1580         return (err);
1581 }
1582
1583 void
1584 vm_snapshot_buf_err(const char *bufname, const enum vm_snapshot_op op)
1585 {
1586         const char *__op;
1587
1588         if (op == VM_SNAPSHOT_SAVE)
1589                 __op = "save";
1590         else if (op == VM_SNAPSHOT_RESTORE)
1591                 __op = "restore";
1592         else
1593                 __op = "unknown";
1594
1595         fprintf(stderr, "%s: snapshot-%s failed for %s\r\n",
1596                 __func__, __op, bufname);
1597 }
1598
1599 int
1600 vm_snapshot_buf(volatile void *data, size_t data_size,
1601                 struct vm_snapshot_meta *meta)
1602 {
1603         struct vm_snapshot_buffer *buffer;
1604         int op;
1605
1606         buffer = &meta->buffer;
1607         op = meta->op;
1608
1609         if (buffer->buf_rem < data_size) {
1610                 fprintf(stderr, "%s: buffer too small\r\n", __func__);
1611                 return (E2BIG);
1612         }
1613
1614         if (op == VM_SNAPSHOT_SAVE)
1615                 memcpy(buffer->buf, (uint8_t *) data, data_size);
1616         else if (op == VM_SNAPSHOT_RESTORE)
1617                 memcpy((uint8_t *) data, buffer->buf, data_size);
1618         else
1619                 return (EINVAL);
1620
1621         buffer->buf += data_size;
1622         buffer->buf_rem -= data_size;
1623
1624         return (0);
1625 }
1626
1627 size_t
1628 vm_get_snapshot_size(struct vm_snapshot_meta *meta)
1629 {
1630         size_t length;
1631         struct vm_snapshot_buffer *buffer;
1632
1633         buffer = &meta->buffer;
1634
1635         if (buffer->buf_size < buffer->buf_rem) {
1636                 fprintf(stderr, "%s: Invalid buffer: size = %zu, rem = %zu\r\n",
1637                         __func__, buffer->buf_size, buffer->buf_rem);
1638                 length = 0;
1639         } else {
1640                 length = buffer->buf_size - buffer->buf_rem;
1641         }
1642
1643         return (length);
1644 }
1645
1646 int
1647 vm_snapshot_guest2host_addr(void **addrp, size_t len, bool restore_null,
1648                             struct vm_snapshot_meta *meta)
1649 {
1650         int ret;
1651         vm_paddr_t gaddr;
1652
1653         if (meta->op == VM_SNAPSHOT_SAVE) {
1654                 gaddr = paddr_host2guest(meta->ctx, *addrp);
1655                 if (gaddr == (vm_paddr_t) -1) {
1656                         if (!restore_null ||
1657                             (restore_null && (*addrp != NULL))) {
1658                                 ret = EFAULT;
1659                                 goto done;
1660                         }
1661                 }
1662
1663                 SNAPSHOT_VAR_OR_LEAVE(gaddr, meta, ret, done);
1664         } else if (meta->op == VM_SNAPSHOT_RESTORE) {
1665                 SNAPSHOT_VAR_OR_LEAVE(gaddr, meta, ret, done);
1666                 if (gaddr == (vm_paddr_t) -1) {
1667                         if (!restore_null) {
1668                                 ret = EFAULT;
1669                                 goto done;
1670                         }
1671                 }
1672
1673                 *addrp = paddr_guest2host(meta->ctx, gaddr, len);
1674         } else {
1675                 ret = EINVAL;
1676         }
1677
1678 done:
1679         return (ret);
1680 }
1681
1682 int
1683 vm_snapshot_buf_cmp(volatile void *data, size_t data_size,
1684                     struct vm_snapshot_meta *meta)
1685 {
1686         struct vm_snapshot_buffer *buffer;
1687         int op;
1688         int ret;
1689
1690         buffer = &meta->buffer;
1691         op = meta->op;
1692
1693         if (buffer->buf_rem < data_size) {
1694                 fprintf(stderr, "%s: buffer too small\r\n", __func__);
1695                 ret = E2BIG;
1696                 goto done;
1697         }
1698
1699         if (op == VM_SNAPSHOT_SAVE) {
1700                 ret = 0;
1701                 memcpy(buffer->buf, (uint8_t *) data, data_size);
1702         } else if (op == VM_SNAPSHOT_RESTORE) {
1703                 ret = memcmp((uint8_t *) data, buffer->buf, data_size);
1704         } else {
1705                 ret = EINVAL;
1706                 goto done;
1707         }
1708
1709         buffer->buf += data_size;
1710         buffer->buf_rem -= data_size;
1711
1712 done:
1713         return (ret);
1714 }