xref: /freebsd/sys/amd64/vmm/vmm_snapshot.c (revision 483d953a86a2507355f8287c5107dc827a0ff516)
1*483d953aSJohn Baldwin /*-
2*483d953aSJohn Baldwin  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*483d953aSJohn Baldwin  *
4*483d953aSJohn Baldwin  * Copyright (c) 2016 Flavius Anton
5*483d953aSJohn Baldwin  * Copyright (c) 2016 Mihai Tiganus
6*483d953aSJohn Baldwin  * Copyright (c) 2016-2019 Mihai Carabas
7*483d953aSJohn Baldwin  * Copyright (c) 2017-2019 Darius Mihai
8*483d953aSJohn Baldwin  * Copyright (c) 2017-2019 Elena Mihailescu
9*483d953aSJohn Baldwin  * Copyright (c) 2018-2019 Sergiu Weisz
10*483d953aSJohn Baldwin  * All rights reserved.
11*483d953aSJohn Baldwin  * The bhyve-snapshot feature was developed under sponsorships
12*483d953aSJohn Baldwin  * from Matthew Grooms.
13*483d953aSJohn Baldwin  *
14*483d953aSJohn Baldwin  * Redistribution and use in source and binary forms, with or without
15*483d953aSJohn Baldwin  * modification, are permitted provided that the following conditions
16*483d953aSJohn Baldwin  * are met:
17*483d953aSJohn Baldwin  * 1. Redistributions of source code must retain the above copyright
18*483d953aSJohn Baldwin  *    notice, this list of conditions and the following disclaimer.
19*483d953aSJohn Baldwin  * 2. Redistributions in binary form must reproduce the above copyright
20*483d953aSJohn Baldwin  *    notice, this list of conditions and the following disclaimer in the
21*483d953aSJohn Baldwin  *    documentation and/or other materials provided with the distribution.
22*483d953aSJohn Baldwin  *
23*483d953aSJohn Baldwin  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
24*483d953aSJohn Baldwin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25*483d953aSJohn Baldwin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26*483d953aSJohn Baldwin  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
27*483d953aSJohn Baldwin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28*483d953aSJohn Baldwin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29*483d953aSJohn Baldwin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30*483d953aSJohn Baldwin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31*483d953aSJohn Baldwin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32*483d953aSJohn Baldwin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33*483d953aSJohn Baldwin  * SUCH DAMAGE.
34*483d953aSJohn Baldwin  */
35*483d953aSJohn Baldwin 
36*483d953aSJohn Baldwin #include <sys/cdefs.h>
37*483d953aSJohn Baldwin __FBSDID("$FreeBSD$");
38*483d953aSJohn Baldwin 
39*483d953aSJohn Baldwin #include <sys/types.h>
40*483d953aSJohn Baldwin #include <sys/systm.h>
41*483d953aSJohn Baldwin 
42*483d953aSJohn Baldwin #include <machine/vmm_snapshot.h>
43*483d953aSJohn Baldwin 
44*483d953aSJohn Baldwin void
45*483d953aSJohn Baldwin vm_snapshot_buf_err(const char *bufname, const enum vm_snapshot_op op)
46*483d953aSJohn Baldwin {
47*483d953aSJohn Baldwin 	const char *opstr;
48*483d953aSJohn Baldwin 
49*483d953aSJohn Baldwin 	if (op == VM_SNAPSHOT_SAVE)
50*483d953aSJohn Baldwin 		opstr = "save";
51*483d953aSJohn Baldwin 	else if (op == VM_SNAPSHOT_RESTORE)
52*483d953aSJohn Baldwin 		opstr = "restore";
53*483d953aSJohn Baldwin 	else
54*483d953aSJohn Baldwin 		opstr = "unknown";
55*483d953aSJohn Baldwin 
56*483d953aSJohn Baldwin 	printf("%s: snapshot-%s failed for %s\r\n", __func__, opstr, bufname);
57*483d953aSJohn Baldwin }
58*483d953aSJohn Baldwin 
59*483d953aSJohn Baldwin int
60*483d953aSJohn Baldwin vm_snapshot_buf(volatile void *data, size_t data_size,
61*483d953aSJohn Baldwin 	     struct vm_snapshot_meta *meta)
62*483d953aSJohn Baldwin {
63*483d953aSJohn Baldwin 	struct vm_snapshot_buffer *buffer;
64*483d953aSJohn Baldwin 	int op;
65*483d953aSJohn Baldwin 	void *nv_data;
66*483d953aSJohn Baldwin 
67*483d953aSJohn Baldwin 	nv_data = __DEVOLATILE(void *, data);
68*483d953aSJohn Baldwin 	buffer = &meta->buffer;
69*483d953aSJohn Baldwin 	op = meta->op;
70*483d953aSJohn Baldwin 
71*483d953aSJohn Baldwin 	if (buffer->buf_rem < data_size) {
72*483d953aSJohn Baldwin 		printf("%s: buffer too small\r\n", __func__);
73*483d953aSJohn Baldwin 		return (E2BIG);
74*483d953aSJohn Baldwin 	}
75*483d953aSJohn Baldwin 
76*483d953aSJohn Baldwin 	if (op == VM_SNAPSHOT_SAVE)
77*483d953aSJohn Baldwin 		copyout(nv_data, buffer->buf, data_size);
78*483d953aSJohn Baldwin 	else if (op == VM_SNAPSHOT_RESTORE)
79*483d953aSJohn Baldwin 		copyin(buffer->buf, nv_data, data_size);
80*483d953aSJohn Baldwin 	else
81*483d953aSJohn Baldwin 		return (EINVAL);
82*483d953aSJohn Baldwin 
83*483d953aSJohn Baldwin 	buffer->buf += data_size;
84*483d953aSJohn Baldwin 	buffer->buf_rem -= data_size;
85*483d953aSJohn Baldwin 
86*483d953aSJohn Baldwin 	return (0);
87*483d953aSJohn Baldwin }
88*483d953aSJohn Baldwin 
89*483d953aSJohn Baldwin size_t
90*483d953aSJohn Baldwin vm_get_snapshot_size(struct vm_snapshot_meta *meta)
91*483d953aSJohn Baldwin {
92*483d953aSJohn Baldwin 	size_t length;
93*483d953aSJohn Baldwin 	struct vm_snapshot_buffer *buffer;
94*483d953aSJohn Baldwin 
95*483d953aSJohn Baldwin 	buffer = &meta->buffer;
96*483d953aSJohn Baldwin 
97*483d953aSJohn Baldwin 	if (buffer->buf_size < buffer->buf_rem) {
98*483d953aSJohn Baldwin 		printf("%s: Invalid buffer: size = %zu, rem = %zu\r\n",
99*483d953aSJohn Baldwin 		       __func__, buffer->buf_size, buffer->buf_rem);
100*483d953aSJohn Baldwin 		length = 0;
101*483d953aSJohn Baldwin 	} else {
102*483d953aSJohn Baldwin 		length = buffer->buf_size - buffer->buf_rem;
103*483d953aSJohn Baldwin 	}
104*483d953aSJohn Baldwin 
105*483d953aSJohn Baldwin 	return (length);
106*483d953aSJohn Baldwin }
107*483d953aSJohn Baldwin 
108*483d953aSJohn Baldwin int
109*483d953aSJohn Baldwin vm_snapshot_buf_cmp(volatile void *data, size_t data_size,
110*483d953aSJohn Baldwin 		    struct vm_snapshot_meta *meta)
111*483d953aSJohn Baldwin {
112*483d953aSJohn Baldwin 	struct vm_snapshot_buffer *buffer;
113*483d953aSJohn Baldwin 	int op;
114*483d953aSJohn Baldwin 	int ret;
115*483d953aSJohn Baldwin 	void *_data = *(void **)(void *)&data;
116*483d953aSJohn Baldwin 
117*483d953aSJohn Baldwin 	buffer = &meta->buffer;
118*483d953aSJohn Baldwin 	op = meta->op;
119*483d953aSJohn Baldwin 
120*483d953aSJohn Baldwin 	if (buffer->buf_rem < data_size) {
121*483d953aSJohn Baldwin 		printf("%s: buffer too small\r\n", __func__);
122*483d953aSJohn Baldwin 		ret = E2BIG;
123*483d953aSJohn Baldwin 		goto done;
124*483d953aSJohn Baldwin 	}
125*483d953aSJohn Baldwin 
126*483d953aSJohn Baldwin 	if (op == VM_SNAPSHOT_SAVE) {
127*483d953aSJohn Baldwin 		ret = 0;
128*483d953aSJohn Baldwin 		copyout(_data, buffer->buf, data_size);
129*483d953aSJohn Baldwin 	} else if (op == VM_SNAPSHOT_RESTORE) {
130*483d953aSJohn Baldwin 		ret = memcmp(_data, buffer->buf, data_size);
131*483d953aSJohn Baldwin 	} else {
132*483d953aSJohn Baldwin 		ret = EINVAL;
133*483d953aSJohn Baldwin 		goto done;
134*483d953aSJohn Baldwin 	}
135*483d953aSJohn Baldwin 
136*483d953aSJohn Baldwin 	buffer->buf += data_size;
137*483d953aSJohn Baldwin 	buffer->buf_rem -= data_size;
138*483d953aSJohn Baldwin 
139*483d953aSJohn Baldwin done:
140*483d953aSJohn Baldwin 	return (ret);
141*483d953aSJohn Baldwin }
142