debuggers.hg

view tools/libxc/xc_dom_boot.c @ 16715:c5deb251b9dc

Update version to 3.2.0-rc4
author Keir Fraser <keir.fraser@citrix.com>
date Sat Dec 29 17:57:37 2007 +0000 (2007-12-29)
parents 8f33d2c6c67c
children 7299346111fb
line source
1 /*
2 * Xen domain builder -- xen booter.
3 *
4 * This is the code which actually boots a fresh
5 * prepared domain image as xen guest domain.
6 *
7 * ==> this is the only domain bilder code piece
8 * where xen hypercalls are allowed <==
9 *
10 * This code is licenced under the GPL.
11 * written 2006 by Gerd Hoffmann <kraxel@suse.de>.
12 *
13 */
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <inttypes.h>
18 #include <zlib.h>
20 #include "xg_private.h"
21 #include "xc_dom.h"
22 #include <xen/hvm/params.h>
24 /* ------------------------------------------------------------------------ */
26 static int setup_hypercall_page(struct xc_dom_image *dom)
27 {
28 DECLARE_DOMCTL;
29 xen_pfn_t pfn;
30 int rc;
32 if ( dom->parms.virt_hypercall == -1 )
33 return 0;
34 pfn = (dom->parms.virt_hypercall - dom->parms.virt_base)
35 >> XC_DOM_PAGE_SHIFT(dom);
37 xc_dom_printf("%s: vaddr=0x%" PRIx64 " pfn=0x%" PRIpfn "\n", __FUNCTION__,
38 dom->parms.virt_hypercall, pfn);
39 domctl.cmd = XEN_DOMCTL_hypercall_init;
40 domctl.domain = dom->guest_domid;
41 domctl.u.hypercall_init.gmfn = xc_dom_p2m_guest(dom, pfn);
42 rc = do_domctl(dom->guest_xc, &domctl);
43 if ( rc != 0 )
44 xc_dom_panic(XC_INTERNAL_ERROR, "%s: HYPERCALL_INIT failed (rc=%d)\n",
45 __FUNCTION__, rc);
46 return rc;
47 }
49 static int launch_vm(int xc, domid_t domid, void *ctxt)
50 {
51 DECLARE_DOMCTL;
52 int rc;
54 xc_dom_printf("%s: called, ctxt=%p\n", __FUNCTION__, ctxt);
55 memset(&domctl, 0, sizeof(domctl));
56 domctl.cmd = XEN_DOMCTL_setvcpucontext;
57 domctl.domain = domid;
58 domctl.u.vcpucontext.vcpu = 0;
59 set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
60 rc = do_domctl(xc, &domctl);
61 if ( rc != 0 )
62 xc_dom_panic(XC_INTERNAL_ERROR,
63 "%s: SETVCPUCONTEXT failed (rc=%d)\n", __FUNCTION__, rc);
64 return rc;
65 }
67 static int clear_page(struct xc_dom_image *dom, xen_pfn_t pfn)
68 {
69 xen_pfn_t dst;
70 int rc;
72 if ( pfn == 0 )
73 return 0;
75 dst = xc_dom_p2m_host(dom, pfn);
76 xc_dom_printf("%s: pfn 0x%" PRIpfn ", mfn 0x%" PRIpfn "\n",
77 __FUNCTION__, pfn, dst);
78 rc = xc_clear_domain_page(dom->guest_xc, dom->guest_domid, dst);
79 if ( rc != 0 )
80 xc_dom_panic(XC_INTERNAL_ERROR,
81 "%s: xc_clear_domain_page failed (pfn 0x%" PRIpfn
82 ", rc=%d)\n", __FUNCTION__, pfn, rc);
83 return rc;
84 }
87 /* ------------------------------------------------------------------------ */
89 int xc_dom_compat_check(struct xc_dom_image *dom)
90 {
91 xen_capabilities_info_t xen_caps;
92 char *item, *ptr;
93 int match, found = 0;
95 strncpy(xen_caps, dom->xen_caps, XEN_CAPABILITIES_INFO_LEN - 1);
96 xen_caps[XEN_CAPABILITIES_INFO_LEN - 1] = '\0';
98 for ( item = strtok_r(xen_caps, " ", &ptr);
99 item != NULL ; item = strtok_r(NULL, " ", &ptr) )
100 {
101 match = !strcmp(dom->guest_type, item);
102 xc_dom_printf("%s: supported guest type: %s%s\n", __FUNCTION__,
103 item, match ? " <= matches" : "");
104 if ( match )
105 found++;
106 }
107 if ( !found )
108 xc_dom_panic(XC_INVALID_KERNEL,
109 "%s: guest type %s not supported by xen kernel, sorry\n",
110 __FUNCTION__, dom->guest_type);
112 return found;
113 }
115 int xc_dom_boot_xen_init(struct xc_dom_image *dom, int xc, domid_t domid)
116 {
117 dom->guest_xc = xc;
118 dom->guest_domid = domid;
120 dom->xen_version = xc_version(dom->guest_xc, XENVER_version, NULL);
121 if ( xc_version(xc, XENVER_capabilities, &dom->xen_caps) < 0 )
122 {
123 xc_dom_panic(XC_INTERNAL_ERROR, "can't get xen capabilities");
124 return -1;
125 }
126 xc_dom_printf("%s: ver %d.%d, caps %s\n", __FUNCTION__,
127 dom->xen_version >> 16, dom->xen_version & 0xff,
128 dom->xen_caps);
129 return 0;
130 }
132 int xc_dom_boot_mem_init(struct xc_dom_image *dom)
133 {
134 long rc;
136 xc_dom_printf("%s: called\n", __FUNCTION__);
138 rc = arch_setup_meminit(dom);
139 if ( rc != 0 )
140 {
141 xc_dom_panic(XC_OUT_OF_MEMORY,
142 "%s: can't allocate low memory for domain\n",
143 __FUNCTION__);
144 return rc;
145 }
147 return 0;
148 }
150 void *xc_dom_boot_domU_map(struct xc_dom_image *dom, xen_pfn_t pfn,
151 xen_pfn_t count)
152 {
153 int page_shift = XC_DOM_PAGE_SHIFT(dom);
154 privcmd_mmap_entry_t *entries;
155 void *ptr;
156 int i, rc;
157 int err;
159 entries = xc_dom_malloc(dom, count * sizeof(privcmd_mmap_entry_t));
160 if ( entries == NULL )
161 {
162 xc_dom_panic(XC_INTERNAL_ERROR,
163 "%s: failed to mmap domU pages 0x%" PRIpfn "+0x%" PRIpfn
164 " [malloc]\n", __FUNCTION__, pfn, count);
165 return NULL;
166 }
168 ptr = mmap(NULL, count << page_shift, PROT_READ | PROT_WRITE,
169 MAP_SHARED, dom->guest_xc, 0);
170 if ( ptr == MAP_FAILED )
171 {
172 err = errno;
173 xc_dom_panic(XC_INTERNAL_ERROR,
174 "%s: failed to mmap domU pages 0x%" PRIpfn "+0x%" PRIpfn
175 " [mmap, errno=%i (%s)]\n", __FUNCTION__, pfn, count,
176 err, strerror(err));
177 return NULL;
178 }
180 for ( i = 0; i < count; i++ )
181 {
182 entries[i].va = (uintptr_t) ptr + (i << page_shift);
183 entries[i].mfn = xc_dom_p2m_host(dom, pfn + i);
184 entries[i].npages = 1;
185 }
187 rc = xc_map_foreign_ranges(dom->guest_xc, dom->guest_domid,
188 entries, count);
189 if ( rc < 0 )
190 {
191 xc_dom_panic(XC_INTERNAL_ERROR,
192 "%s: failed to mmap domU pages 0x%" PRIpfn "+0x%" PRIpfn
193 " [xenctl, rc=%d]\n", __FUNCTION__, pfn, count, rc);
194 return NULL;
195 }
196 return ptr;
197 }
199 int xc_dom_boot_image(struct xc_dom_image *dom)
200 {
201 DECLARE_DOMCTL;
202 void *ctxt;
203 int rc;
205 xc_dom_printf("%s: called\n", __FUNCTION__);
207 /* misc ia64 stuff*/
208 if ( (rc = arch_setup_bootearly(dom)) != 0 )
209 return rc;
211 /* collect some info */
212 domctl.cmd = XEN_DOMCTL_getdomaininfo;
213 domctl.domain = dom->guest_domid;
214 rc = do_domctl(dom->guest_xc, &domctl);
215 if ( rc != 0 )
216 {
217 xc_dom_panic(XC_INTERNAL_ERROR,
218 "%s: getdomaininfo failed (rc=%d)\n", __FUNCTION__, rc);
219 return rc;
220 }
221 if ( domctl.domain != dom->guest_domid )
222 {
223 xc_dom_panic(XC_INTERNAL_ERROR,
224 "%s: Huh? domid mismatch (%d != %d)\n", __FUNCTION__,
225 domctl.domain, dom->guest_domid);
226 return -1;
227 }
228 dom->shared_info_mfn = domctl.u.getdomaininfo.shared_info_frame;
230 /* sanity checks */
231 if ( !xc_dom_compat_check(dom) )
232 return -1;
234 /* initial mm setup */
235 if ( (rc = xc_dom_update_guest_p2m(dom)) != 0 )
236 return rc;
237 if ( dom->arch_hooks->setup_pgtables )
238 if ( (rc = dom->arch_hooks->setup_pgtables(dom)) != 0 )
239 return rc;
241 if ( (rc = clear_page(dom, dom->console_pfn)) != 0 )
242 return rc;
243 if ( (rc = clear_page(dom, dom->xenstore_pfn)) != 0 )
244 return rc;
246 /* start info page */
247 if ( dom->arch_hooks->start_info )
248 dom->arch_hooks->start_info(dom);
250 /* hypercall page */
251 if ( (rc = setup_hypercall_page(dom)) != 0 )
252 return rc;
253 xc_dom_log_memory_footprint(dom);
255 /* misc x86 stuff */
256 if ( (rc = arch_setup_bootlate(dom)) != 0 )
257 return rc;
259 /* let the vm run */
260 ctxt = xc_dom_malloc(dom, PAGE_SIZE * 2 /* FIXME */ );
261 memset(ctxt, 0, PAGE_SIZE * 2);
262 if ( (rc = dom->arch_hooks->vcpu(dom, ctxt)) != 0 )
263 return rc;
264 xc_dom_unmap_all(dom);
265 rc = launch_vm(dom->guest_xc, dom->guest_domid, ctxt);
267 return rc;
268 }
270 /*
271 * Local variables:
272 * mode: C
273 * c-set-style: "BSD"
274 * c-basic-offset: 4
275 * tab-width: 4
276 * indent-tabs-mode: nil
277 * End:
278 */