1 /*
2 * hvm/save.c: Save and restore HVM guest's emulated hardware state.
3 *
4 * Copyright (c) 2004, Intel Corporation.
5 * Copyright (c) 2007, XenSource Inc.
6 * Copyright (c) 2007, Isaku Yamahata <yamahata at valinux co jp>
7 * VA Linux Systems Japan K.K.
8 * split x86 specific part
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms and conditions of the GNU General Public License,
12 * version 2, as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program; If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include <xen/guest_access.h>
24 #include <xen/version.h>
25
26 #include <asm/hvm/support.h>
27
28 #include <public/hvm/save.h>
29
arch_hvm_save(struct domain * d,struct hvm_save_header * hdr)30 void arch_hvm_save(struct domain *d, struct hvm_save_header *hdr)
31 {
32 uint32_t eax, ebx, ecx, edx;
33
34 /* Save some CPUID bits */
35 cpuid(1, &eax, &ebx, &ecx, &edx);
36 hdr->cpuid = eax;
37
38 /* Save guest's preferred TSC. */
39 hdr->gtsc_khz = d->arch.tsc_khz;
40
41 /* Time when saving started */
42 d->arch.hvm.sync_tsc = rdtsc();
43 }
44
arch_hvm_load(struct domain * d,struct hvm_save_header * hdr)45 int arch_hvm_load(struct domain *d, struct hvm_save_header *hdr)
46 {
47 uint32_t eax, ebx, ecx, edx;
48
49 if ( hdr->magic != HVM_FILE_MAGIC )
50 {
51 printk(XENLOG_G_ERR "HVM%d restore: bad magic number %#"PRIx32"\n",
52 d->domain_id, hdr->magic);
53 return -1;
54 }
55
56 if ( hdr->version != HVM_FILE_VERSION )
57 {
58 printk(XENLOG_G_ERR "HVM%d restore: unsupported version %u\n",
59 d->domain_id, hdr->version);
60 return -1;
61 }
62
63 cpuid(1, &eax, &ebx, &ecx, &edx);
64 /* CPUs ought to match but with feature-masking they might not */
65 if ( (hdr->cpuid & ~0x0fUL) != (eax & ~0x0fUL) )
66 printk(XENLOG_G_INFO "HVM%d restore: VM saved on one CPU "
67 "(%#"PRIx32") and restored on another (%#"PRIx32").\n",
68 d->domain_id, hdr->cpuid, eax);
69
70 /* Restore guest's preferred TSC frequency. */
71 if ( hdr->gtsc_khz )
72 d->arch.tsc_khz = hdr->gtsc_khz;
73 if ( d->arch.vtsc )
74 hvm_set_rdtsc_exiting(d, 1);
75
76 /* Time when restore started */
77 d->arch.hvm.sync_tsc = rdtsc();
78
79 /* VGA state is not saved/restored, so we nobble the cache. */
80 d->arch.hvm.stdvga.cache = STDVGA_CACHE_DISABLED;
81
82 return 0;
83 }
84
85 /* List of handlers for various HVM save and restore types */
86 static struct {
87 hvm_save_handler save;
88 hvm_load_handler load;
89 const char *name;
90 size_t size;
91 int kind;
92 } hvm_sr_handlers[HVM_SAVE_CODE_MAX + 1];
93
94 /* Init-time function to add entries to that list */
hvm_register_savevm(uint16_t typecode,const char * name,hvm_save_handler save_state,hvm_load_handler load_state,size_t size,int kind)95 void __init hvm_register_savevm(uint16_t typecode,
96 const char *name,
97 hvm_save_handler save_state,
98 hvm_load_handler load_state,
99 size_t size, int kind)
100 {
101 ASSERT(typecode <= HVM_SAVE_CODE_MAX);
102 ASSERT(hvm_sr_handlers[typecode].save == NULL);
103 ASSERT(hvm_sr_handlers[typecode].load == NULL);
104 hvm_sr_handlers[typecode].save = save_state;
105 hvm_sr_handlers[typecode].load = load_state;
106 hvm_sr_handlers[typecode].name = name;
107 hvm_sr_handlers[typecode].size = size;
108 hvm_sr_handlers[typecode].kind = kind;
109 }
110
hvm_save_size(struct domain * d)111 size_t hvm_save_size(struct domain *d)
112 {
113 struct vcpu *v;
114 size_t sz;
115 int i;
116
117 /* Basic overhead for header and footer */
118 sz = (2 * sizeof (struct hvm_save_descriptor)) + HVM_SAVE_LENGTH(HEADER);
119
120 /* Plus space for each thing we will be saving */
121 for ( i = 0; i <= HVM_SAVE_CODE_MAX; i++ )
122 if ( hvm_sr_handlers[i].kind == HVMSR_PER_VCPU )
123 for_each_vcpu(d, v)
124 sz += hvm_sr_handlers[i].size;
125 else
126 sz += hvm_sr_handlers[i].size;
127
128 return sz;
129 }
130
131 /*
132 * Extract a single instance of a save record, by marshalling all records of
133 * that type and copying out the one we need.
134 */
hvm_save_one(struct domain * d,unsigned int typecode,unsigned int instance,XEN_GUEST_HANDLE_64 (uint8)handle,uint64_t * bufsz)135 int hvm_save_one(struct domain *d, unsigned int typecode, unsigned int instance,
136 XEN_GUEST_HANDLE_64(uint8) handle, uint64_t *bufsz)
137 {
138 int rv;
139 hvm_domain_context_t ctxt = { };
140 const struct hvm_save_descriptor *desc;
141 struct vcpu *v;
142
143 if ( d->is_dying ||
144 typecode > HVM_SAVE_CODE_MAX ||
145 hvm_sr_handlers[typecode].size < sizeof(*desc) ||
146 !hvm_sr_handlers[typecode].save )
147 return -EINVAL;
148
149 if ( hvm_sr_handlers[typecode].kind != HVMSR_PER_VCPU )
150 v = d->vcpu[0];
151 else if ( instance >= d->max_vcpus || !d->vcpu[instance] )
152 return -ENOENT;
153 else
154 v = d->vcpu[instance];
155 ctxt.size = hvm_sr_handlers[typecode].size;
156 ctxt.data = xmalloc_bytes(ctxt.size);
157 if ( !ctxt.data )
158 return -ENOMEM;
159
160 if ( hvm_sr_handlers[typecode].kind == HVMSR_PER_VCPU )
161 vcpu_pause(v);
162 else
163 domain_pause(d);
164
165 if ( (rv = hvm_sr_handlers[typecode].save(v, &ctxt)) != 0 )
166 printk(XENLOG_G_ERR "HVM%d save: failed to save type %"PRIu16" (%d)\n",
167 d->domain_id, typecode, rv);
168 else if ( (rv = hvm_sr_handlers[typecode].kind == HVMSR_PER_VCPU ?
169 -ENODATA : -ENOENT), ctxt.cur >= sizeof(*desc) )
170 {
171 uint32_t off;
172
173 for ( off = 0; off <= (ctxt.cur - sizeof(*desc)); off += desc->length )
174 {
175 desc = (void *)(ctxt.data + off);
176 /* Move past header */
177 off += sizeof(*desc);
178 if ( ctxt.cur < desc->length ||
179 off > ctxt.cur - desc->length )
180 break;
181 if ( instance == desc->instance )
182 {
183 rv = 0;
184 if ( guest_handle_is_null(handle) )
185 *bufsz = desc->length;
186 else if ( *bufsz < desc->length )
187 rv = -ENOBUFS;
188 else if ( copy_to_guest(handle, ctxt.data + off, desc->length) )
189 rv = -EFAULT;
190 else
191 *bufsz = desc->length;
192 break;
193 }
194 }
195 }
196
197 if ( hvm_sr_handlers[typecode].kind == HVMSR_PER_VCPU )
198 vcpu_unpause(v);
199 else
200 domain_unpause(d);
201
202 xfree(ctxt.data);
203 return rv;
204 }
205
hvm_save(struct domain * d,hvm_domain_context_t * h)206 int hvm_save(struct domain *d, hvm_domain_context_t *h)
207 {
208 char *c;
209 struct hvm_save_header hdr;
210 struct hvm_save_end end;
211 unsigned int i;
212
213 if ( d->is_dying )
214 return -EINVAL;
215
216 hdr.magic = HVM_FILE_MAGIC;
217 hdr.version = HVM_FILE_VERSION;
218
219 /* Save xen changeset */
220 c = strrchr(xen_changeset(), ':');
221 if ( c )
222 hdr.changeset = simple_strtoll(c, NULL, 16);
223 else
224 hdr.changeset = -1ULL; /* Unknown */
225
226 arch_hvm_save(d, &hdr);
227
228 if ( hvm_save_entry(HEADER, 0, h, &hdr) != 0 )
229 {
230 printk(XENLOG_G_ERR "HVM%d save: failed to write header\n",
231 d->domain_id);
232 return -EFAULT;
233 }
234
235 /* Save all available kinds of state */
236 for ( i = 0; i <= HVM_SAVE_CODE_MAX; i++ )
237 {
238 hvm_save_handler handler = hvm_sr_handlers[i].save;
239
240 if ( !handler )
241 continue;
242
243 if ( hvm_sr_handlers[i].kind == HVMSR_PER_VCPU )
244 {
245 struct vcpu *v;
246
247 for_each_vcpu ( d, v )
248 {
249 printk(XENLOG_G_INFO "HVM %pv save: %s\n",
250 v, hvm_sr_handlers[i].name);
251 if ( handler(v, h) != 0 )
252 {
253 printk(XENLOG_G_ERR
254 "HVM %pv save: failed to save type %"PRIu16"\n",
255 v, i);
256 return -ENODATA;
257 }
258 }
259 }
260 else
261 {
262 printk(XENLOG_G_INFO "HVM d%d save: %s\n",
263 d->domain_id, hvm_sr_handlers[i].name);
264 if ( handler(d->vcpu[0], h) != 0 )
265 {
266 printk(XENLOG_G_ERR
267 "HVM d%d save: failed to save type %"PRIu16"\n",
268 d->domain_id, i);
269 return -ENODATA;
270 }
271 }
272 }
273
274 /* Save an end-of-file marker */
275 if ( hvm_save_entry(END, 0, h, &end) != 0 )
276 {
277 /* Run out of data */
278 printk(XENLOG_G_ERR "HVM%d save: no room for end marker\n",
279 d->domain_id);
280 return -EFAULT;
281 }
282
283 /* Save macros should not have let us overrun */
284 ASSERT(h->cur <= h->size);
285 return 0;
286 }
287
hvm_load(struct domain * d,hvm_domain_context_t * h)288 int hvm_load(struct domain *d, hvm_domain_context_t *h)
289 {
290 struct hvm_save_header hdr;
291 struct hvm_save_descriptor *desc;
292 hvm_load_handler handler;
293 struct vcpu *v;
294
295 if ( d->is_dying )
296 return -EINVAL;
297
298 /* Read the save header, which must be first */
299 if ( hvm_load_entry(HEADER, h, &hdr) != 0 )
300 return -1;
301
302 if ( arch_hvm_load(d, &hdr) )
303 return -1;
304
305 /* Down all the vcpus: we only re-enable the ones that had state saved. */
306 for_each_vcpu(d, v)
307 if ( !test_and_set_bit(_VPF_down, &v->pause_flags) )
308 vcpu_sleep_nosync(v);
309
310 for ( ; ; )
311 {
312 if ( h->size - h->cur < sizeof(struct hvm_save_descriptor) )
313 {
314 /* Run out of data */
315 printk(XENLOG_G_ERR
316 "HVM%d restore: save did not end with a null entry\n",
317 d->domain_id);
318 return -1;
319 }
320
321 /* Read the typecode of the next entry and check for the end-marker */
322 desc = (struct hvm_save_descriptor *)(&h->data[h->cur]);
323 if ( desc->typecode == 0 )
324 return 0;
325
326 /* Find the handler for this entry */
327 if ( (desc->typecode > HVM_SAVE_CODE_MAX) ||
328 ((handler = hvm_sr_handlers[desc->typecode].load) == NULL) )
329 {
330 printk(XENLOG_G_ERR "HVM%d restore: unknown entry typecode %u\n",
331 d->domain_id, desc->typecode);
332 return -1;
333 }
334
335 /* Load the entry */
336 printk(XENLOG_G_INFO "HVM%d restore: %s %"PRIu16"\n", d->domain_id,
337 hvm_sr_handlers[desc->typecode].name, desc->instance);
338 if ( handler(d, h) != 0 )
339 {
340 printk(XENLOG_G_ERR "HVM%d restore: failed to load entry %u/%u\n",
341 d->domain_id, desc->typecode, desc->instance);
342 return -1;
343 }
344 }
345
346 /* Not reached */
347 }
348
_hvm_init_entry(struct hvm_domain_context * h,uint16_t tc,uint16_t inst,uint32_t len)349 int _hvm_init_entry(struct hvm_domain_context *h, uint16_t tc, uint16_t inst,
350 uint32_t len)
351 {
352 struct hvm_save_descriptor *d
353 = (struct hvm_save_descriptor *)&h->data[h->cur];
354
355 if ( h->size - h->cur < len + sizeof (*d) )
356 {
357 printk(XENLOG_G_WARNING "HVM save: no room for"
358 " %"PRIu32" + %zu bytes for typecode %"PRIu16"\n",
359 len, sizeof(*d), tc);
360 return -1;
361 }
362
363 d->typecode = tc;
364 d->instance = inst;
365 d->length = len;
366 h->cur += sizeof(*d);
367
368 return 0;
369 }
370
_hvm_write_entry(struct hvm_domain_context * h,void * src,uint32_t src_len)371 void _hvm_write_entry(struct hvm_domain_context *h, void *src,
372 uint32_t src_len)
373 {
374 memcpy(&h->data[h->cur], src, src_len);
375 h->cur += src_len;
376 }
377
_hvm_check_entry(struct hvm_domain_context * h,uint16_t type,uint32_t len,bool strict_length)378 int _hvm_check_entry(struct hvm_domain_context *h, uint16_t type, uint32_t len,
379 bool strict_length)
380 {
381 struct hvm_save_descriptor *d
382 = (struct hvm_save_descriptor *)&h->data[h->cur];
383
384 if ( sizeof(*d) > h->size - h->cur)
385 {
386 printk(XENLOG_G_WARNING
387 "HVM restore: not enough data left to read %zu bytes "
388 "for type %u header\n", sizeof(*d), type);
389 return -1;
390 }
391
392 if ( (type != d->typecode) ||
393 (strict_length ? (len != d->length) : (len < d->length)) ||
394 (d->length > (h->size - h->cur - sizeof(*d))) )
395 {
396 printk(XENLOG_G_WARNING
397 "HVM restore mismatch: expected %s type %u length %u, "
398 "saw type %u length %u. %zu bytes remaining\n",
399 strict_length ? "strict" : "zeroextended", type, len,
400 d->typecode, d->length, h->size - h->cur - sizeof(*d));
401 return -1;
402 }
403
404 h->cur += sizeof(*d);
405
406 return 0;
407 }
408
_hvm_read_entry(struct hvm_domain_context * h,void * dest,uint32_t dest_len)409 void _hvm_read_entry(struct hvm_domain_context *h, void *dest,
410 uint32_t dest_len)
411 {
412 struct hvm_save_descriptor *d
413 = (struct hvm_save_descriptor *)&h->data[h->cur - sizeof(*d)];
414
415 BUG_ON(d->length > dest_len);
416
417 memcpy(dest, &h->data[h->cur], d->length);
418
419 if ( d->length < dest_len )
420 memset(dest + d->length, 0, dest_len - d->length);
421
422 h->cur += d->length;
423 }
424
425 /*
426 * Local variables:
427 * mode: C
428 * c-file-style: "BSD"
429 * c-basic-offset: 4
430 * tab-width: 4
431 * indent-tabs-mode: nil
432 * End:
433 */
434