debuggers.hg

view xen/common/hvm/save.c @ 22848:6341fe0f4e5a

Added tag 4.1.0-rc2 for changeset 9dca60d88c63
author Keir Fraser <keir@xen.org>
date Tue Jan 25 14:06:55 2011 +0000 (2011-01-25)
parents 1f08b2932a52
children
line source
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 arch generic 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, write to the Free Software Foundation, Inc., 59 Temple
21 * Place - Suite 330, Boston, MA 02111-1307 USA.
22 */
24 #include <xen/config.h>
25 #include <xen/lib.h>
26 #include <xen/version.h>
27 #include <public/version.h>
28 #include <xen/sched.h>
29 #include <xen/guest_access.h>
31 #include <asm/hvm/support.h>
33 /* List of handlers for various HVM save and restore types */
34 static struct {
35 hvm_save_handler save;
36 hvm_load_handler load;
37 const char *name;
38 size_t size;
39 int kind;
40 } hvm_sr_handlers [HVM_SAVE_CODE_MAX + 1] = {{NULL, NULL, "<?>"},};
42 /* Init-time function to add entries to that list */
43 void hvm_register_savevm(uint16_t typecode,
44 const char *name,
45 hvm_save_handler save_state,
46 hvm_load_handler load_state,
47 size_t size, int kind)
48 {
49 ASSERT(typecode <= HVM_SAVE_CODE_MAX);
50 ASSERT(hvm_sr_handlers[typecode].save == NULL);
51 ASSERT(hvm_sr_handlers[typecode].load == NULL);
52 hvm_sr_handlers[typecode].save = save_state;
53 hvm_sr_handlers[typecode].load = load_state;
54 hvm_sr_handlers[typecode].name = name;
55 hvm_sr_handlers[typecode].size = size;
56 hvm_sr_handlers[typecode].kind = kind;
57 }
59 size_t hvm_save_size(struct domain *d)
60 {
61 struct vcpu *v;
62 size_t sz;
63 int i;
65 /* Basic overhead for header and footer */
66 sz = (2 * sizeof (struct hvm_save_descriptor)) + HVM_SAVE_LENGTH(HEADER);
68 /* Plus space for each thing we will be saving */
69 for ( i = 0; i <= HVM_SAVE_CODE_MAX; i++ )
70 if ( hvm_sr_handlers[i].kind == HVMSR_PER_VCPU )
71 for_each_vcpu(d, v)
72 sz += hvm_sr_handlers[i].size;
73 else
74 sz += hvm_sr_handlers[i].size;
76 return sz;
77 }
79 /* Extract a single instance of a save record, by marshalling all
80 * records of that type and copying out the one we need. */
81 int hvm_save_one(struct domain *d, uint16_t typecode, uint16_t instance,
82 XEN_GUEST_HANDLE_64(uint8) handle)
83 {
84 int rv = 0;
85 size_t sz = 0;
86 struct vcpu *v;
87 hvm_domain_context_t ctxt = { 0, };
89 if ( d->is_dying
90 || typecode > HVM_SAVE_CODE_MAX
91 || hvm_sr_handlers[typecode].size < sizeof(struct hvm_save_descriptor)
92 || hvm_sr_handlers[typecode].save == NULL )
93 return -EINVAL;
95 if ( hvm_sr_handlers[typecode].kind == HVMSR_PER_VCPU )
96 for_each_vcpu(d, v)
97 sz += hvm_sr_handlers[typecode].size;
98 else
99 sz = hvm_sr_handlers[typecode].size;
101 if ( (instance + 1) * hvm_sr_handlers[typecode].size > sz )
102 return -EINVAL;
104 ctxt.size = sz;
105 ctxt.data = xmalloc_bytes(sz);
106 if ( !ctxt.data )
107 return -ENOMEM;
109 if ( hvm_sr_handlers[typecode].save(d, &ctxt) != 0 )
110 {
111 gdprintk(XENLOG_ERR,
112 "HVM save: failed to save type %"PRIu16"\n", typecode);
113 rv = -EFAULT;
114 }
115 else if ( copy_to_guest(handle,
116 ctxt.data
117 + (instance * hvm_sr_handlers[typecode].size)
118 + sizeof (struct hvm_save_descriptor),
119 hvm_sr_handlers[typecode].size
120 - sizeof (struct hvm_save_descriptor)) )
121 rv = -EFAULT;
123 xfree(ctxt.data);
124 return rv;
125 }
127 int hvm_save(struct domain *d, hvm_domain_context_t *h)
128 {
129 char *c;
130 struct hvm_save_header hdr;
131 struct hvm_save_end end;
132 hvm_save_handler handler;
133 uint16_t i;
135 if ( d->is_dying )
136 return -EINVAL;
138 hdr.magic = HVM_FILE_MAGIC;
139 hdr.version = HVM_FILE_VERSION;
141 /* Save xen changeset */
142 c = strrchr(xen_changeset(), ':');
143 if ( c )
144 hdr.changeset = simple_strtoll(c, NULL, 16);
145 else
146 hdr.changeset = -1ULL; /* Unknown */
148 arch_hvm_save(d, &hdr);
150 if ( hvm_save_entry(HEADER, 0, h, &hdr) != 0 )
151 {
152 gdprintk(XENLOG_ERR, "HVM save: failed to write header\n");
153 return -EFAULT;
154 }
156 /* Save all available kinds of state */
157 for ( i = 0; i <= HVM_SAVE_CODE_MAX; i++ )
158 {
159 handler = hvm_sr_handlers[i].save;
160 if ( handler != NULL )
161 {
162 gdprintk(XENLOG_INFO, "HVM save: %s\n", hvm_sr_handlers[i].name);
163 if ( handler(d, h) != 0 )
164 {
165 gdprintk(XENLOG_ERR,
166 "HVM save: failed to save type %"PRIu16"\n", i);
167 return -EFAULT;
168 }
169 }
170 }
172 /* Save an end-of-file marker */
173 if ( hvm_save_entry(END, 0, h, &end) != 0 )
174 {
175 /* Run out of data */
176 gdprintk(XENLOG_ERR, "HVM save: no room for end marker.\n");
177 return -EFAULT;
178 }
180 /* Save macros should not have let us overrun */
181 ASSERT(h->cur <= h->size);
182 return 0;
183 }
185 int hvm_load(struct domain *d, hvm_domain_context_t *h)
186 {
187 struct hvm_save_header hdr;
188 struct hvm_save_descriptor *desc;
189 hvm_load_handler handler;
190 struct vcpu *v;
192 if ( d->is_dying )
193 return -EINVAL;
195 /* Read the save header, which must be first */
196 if ( hvm_load_entry(HEADER, h, &hdr) != 0 )
197 return -1;
199 if ( arch_hvm_load(d, &hdr) )
200 return -1;
202 /* Down all the vcpus: we only re-enable the ones that had state saved. */
203 for_each_vcpu(d, v)
204 if ( test_and_set_bit(_VPF_down, &v->pause_flags) )
205 vcpu_sleep_nosync(v);
207 for ( ; ; )
208 {
209 if ( h->size - h->cur < sizeof(struct hvm_save_descriptor) )
210 {
211 /* Run out of data */
212 gdprintk(XENLOG_ERR,
213 "HVM restore: save did not end with a null entry\n");
214 return -1;
215 }
217 /* Read the typecode of the next entry and check for the end-marker */
218 desc = (struct hvm_save_descriptor *)(&h->data[h->cur]);
219 if ( desc->typecode == 0 )
220 return 0;
222 /* Find the handler for this entry */
223 if ( (desc->typecode > HVM_SAVE_CODE_MAX) ||
224 ((handler = hvm_sr_handlers[desc->typecode].load) == NULL) )
225 {
226 gdprintk(XENLOG_ERR,
227 "HVM restore: unknown entry typecode %u\n",
228 desc->typecode);
229 return -1;
230 }
232 /* Load the entry */
233 gdprintk(XENLOG_INFO, "HVM restore: %s %"PRIu16"\n",
234 hvm_sr_handlers[desc->typecode].name, desc->instance);
235 if ( handler(d, h) != 0 )
236 {
237 gdprintk(XENLOG_ERR,
238 "HVM restore: failed to load entry %u/%u\n",
239 desc->typecode, desc->instance);
240 return -1;
241 }
242 }
244 /* Not reached */
245 }
247 int _hvm_init_entry(struct hvm_domain_context *h,
248 uint16_t tc, uint16_t inst, uint32_t len)
249 {
250 struct hvm_save_descriptor *d
251 = (struct hvm_save_descriptor *)&h->data[h->cur];
252 if ( h->size - h->cur < len + sizeof (*d) )
253 {
254 gdprintk(XENLOG_WARNING,
255 "HVM save: no room for %"PRIu32" + %u bytes "
256 "for typecode %"PRIu16"\n",
257 len, (unsigned) sizeof (*d), tc);
258 return -1;
259 }
260 d->typecode = tc;
261 d->instance = inst;
262 d->length = len;
263 h->cur += sizeof(*d);
264 return 0;
265 }
267 void _hvm_write_entry(struct hvm_domain_context *h,
268 void *src, uint32_t src_len)
269 {
270 memcpy(&h->data[h->cur], src, src_len);
271 h->cur += src_len;
272 }
274 int _hvm_check_entry(struct hvm_domain_context *h,
275 uint16_t type, uint32_t len, bool_t strict_length)
276 {
277 struct hvm_save_descriptor *d
278 = (struct hvm_save_descriptor *)&h->data[h->cur];
279 if ( len + sizeof (*d) > h->size - h->cur)
280 {
281 gdprintk(XENLOG_WARNING,
282 "HVM restore: not enough data left to read %u bytes "
283 "for type %u\n", len, type);
284 return -1;
285 }
286 if ( (type != d->typecode) || (len < d->length) ||
287 (strict_length && (len != d->length)) )
288 {
289 gdprintk(XENLOG_WARNING,
290 "HVM restore mismatch: expected type %u length %u, "
291 "saw type %u length %u\n", type, len, d->typecode, d->length);
292 return -1;
293 }
294 h->cur += sizeof(*d);
295 return 0;
296 }
298 void _hvm_read_entry(struct hvm_domain_context *h,
299 void *dest, uint32_t dest_len)
300 {
301 struct hvm_save_descriptor *d
302 = (struct hvm_save_descriptor *)&h->data[h->cur - sizeof(*d)];
303 BUG_ON(d->length > dest_len);
304 memcpy(dest, &h->data[h->cur], d->length);
305 if ( d->length < dest_len )
306 memset((char *)dest + d->length, 0, dest_len - d->length);
307 h->cur += d->length;
308 }
310 /*
311 * Local variables:
312 * mode: C
313 * c-set-style: "BSD"
314 * c-basic-offset: 4
315 * tab-width: 4
316 * indent-tabs-mode: nil
317 * End:
318 */