debuggers.hg

view xen/common/hvm/save.c @ 0:7d21f7218375

Exact replica of unstable on 051908 + README-this
author Mukesh Rathor
date Mon May 19 15:34:57 2008 -0700 (2008-05-19)
parents
children 5c0bf00e371d
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>
30 #include <asm/hvm/support.h>
32 /* List of handlers for various HVM save and restore types */
33 static struct {
34 hvm_save_handler save;
35 hvm_load_handler load;
36 const char *name;
37 size_t size;
38 int kind;
39 } hvm_sr_handlers [HVM_SAVE_CODE_MAX + 1] = {{NULL, NULL, "<?>"},};
41 /* Init-time function to add entries to that list */
42 void hvm_register_savevm(uint16_t typecode,
43 const char *name,
44 hvm_save_handler save_state,
45 hvm_load_handler load_state,
46 size_t size, int kind)
47 {
48 ASSERT(typecode <= HVM_SAVE_CODE_MAX);
49 ASSERT(hvm_sr_handlers[typecode].save == NULL);
50 ASSERT(hvm_sr_handlers[typecode].load == NULL);
51 hvm_sr_handlers[typecode].save = save_state;
52 hvm_sr_handlers[typecode].load = load_state;
53 hvm_sr_handlers[typecode].name = name;
54 hvm_sr_handlers[typecode].size = size;
55 hvm_sr_handlers[typecode].kind = kind;
56 }
58 size_t hvm_save_size(struct domain *d)
59 {
60 struct vcpu *v;
61 size_t sz;
62 int i;
64 /* Basic overhead for header and footer */
65 sz = (2 * sizeof (struct hvm_save_descriptor)) + HVM_SAVE_LENGTH(HEADER);
67 /* Plus space for each thing we will be saving */
68 for ( i = 0; i <= HVM_SAVE_CODE_MAX; i++ )
69 if ( hvm_sr_handlers[i].kind == HVMSR_PER_VCPU )
70 for_each_vcpu(d, v)
71 sz += hvm_sr_handlers[i].size;
72 else
73 sz += hvm_sr_handlers[i].size;
75 return sz;
76 }
79 int hvm_save(struct domain *d, hvm_domain_context_t *h)
80 {
81 char *c;
82 struct hvm_save_header hdr;
83 struct hvm_save_end end;
84 hvm_save_handler handler;
85 uint16_t i;
87 hdr.magic = HVM_FILE_MAGIC;
88 hdr.version = HVM_FILE_VERSION;
90 /* Save xen changeset */
91 c = strrchr(xen_changeset(), ':');
92 if ( c )
93 hdr.changeset = simple_strtoll(c, NULL, 16);
94 else
95 hdr.changeset = -1ULL; /* Unknown */
97 arch_hvm_save(d, &hdr);
99 if ( hvm_save_entry(HEADER, 0, h, &hdr) != 0 )
100 {
101 gdprintk(XENLOG_ERR, "HVM save: failed to write header\n");
102 return -EFAULT;
103 }
105 /* Save all available kinds of state */
106 for ( i = 0; i <= HVM_SAVE_CODE_MAX; i++ )
107 {
108 handler = hvm_sr_handlers[i].save;
109 if ( handler != NULL )
110 {
111 gdprintk(XENLOG_INFO, "HVM save: %s\n", hvm_sr_handlers[i].name);
112 if ( handler(d, h) != 0 )
113 {
114 gdprintk(XENLOG_ERR,
115 "HVM save: failed to save type %"PRIu16"\n", i);
116 return -EFAULT;
117 }
118 }
119 }
121 /* Save an end-of-file marker */
122 if ( hvm_save_entry(END, 0, h, &end) != 0 )
123 {
124 /* Run out of data */
125 gdprintk(XENLOG_ERR, "HVM save: no room for end marker.\n");
126 return -EFAULT;
127 }
129 /* Save macros should not have let us overrun */
130 ASSERT(h->cur <= h->size);
131 return 0;
132 }
134 int hvm_load(struct domain *d, hvm_domain_context_t *h)
135 {
136 char *c;
137 uint64_t cset;
138 struct hvm_save_header hdr;
139 struct hvm_save_descriptor *desc;
140 hvm_load_handler handler;
141 struct vcpu *v;
143 /* Read the save header, which must be first */
144 if ( hvm_load_entry(HEADER, h, &hdr) != 0 )
145 return -1;
147 if ( arch_hvm_load(d, &hdr) )
148 return -1;
150 c = strrchr(xen_changeset(), ':');
151 if ( hdr.changeset == -1ULL )
152 gdprintk(XENLOG_WARNING,
153 "HVM restore: Xen changeset was not saved.\n");
154 else if ( c == NULL )
155 gdprintk(XENLOG_WARNING,
156 "HVM restore: Xen changeset is not available.\n");
157 else
158 {
159 cset = simple_strtoll(c, NULL, 16);
160 if ( hdr.changeset != cset )
161 gdprintk(XENLOG_WARNING, "HVM restore: saved Xen changeset (%#"PRIx64
162 ") does not match host (%#"PRIx64").\n", hdr.changeset, cset);
163 }
165 /* Down all the vcpus: we only re-enable the ones that had state saved. */
166 for_each_vcpu(d, v)
167 if ( test_and_set_bit(_VPF_down, &v->pause_flags) )
168 vcpu_sleep_nosync(v);
170 for ( ; ; )
171 {
172 if ( h->size - h->cur < sizeof(struct hvm_save_descriptor) )
173 {
174 /* Run out of data */
175 gdprintk(XENLOG_ERR,
176 "HVM restore: save did not end with a null entry\n");
177 return -1;
178 }
180 /* Read the typecode of the next entry and check for the end-marker */
181 desc = (struct hvm_save_descriptor *)(&h->data[h->cur]);
182 if ( desc->typecode == 0 )
183 return 0;
185 /* Find the handler for this entry */
186 if ( (desc->typecode > HVM_SAVE_CODE_MAX) ||
187 ((handler = hvm_sr_handlers[desc->typecode].load) == NULL) )
188 {
189 gdprintk(XENLOG_ERR,
190 "HVM restore: unknown entry typecode %u\n",
191 desc->typecode);
192 return -1;
193 }
195 /* Load the entry */
196 gdprintk(XENLOG_INFO, "HVM restore: %s %"PRIu16"\n",
197 hvm_sr_handlers[desc->typecode].name, desc->instance);
198 if ( handler(d, h) != 0 )
199 {
200 gdprintk(XENLOG_ERR,
201 "HVM restore: failed to load entry %u/%u\n",
202 desc->typecode, desc->instance);
203 return -1;
204 }
205 }
207 /* Not reached */
208 }
210 /*
211 * Local variables:
212 * mode: C
213 * c-set-style: "BSD"
214 * c-basic-offset: 4
215 * tab-width: 4
216 * indent-tabs-mode: nil
217 * End:
218 */