ia64/xen-unstable

view tools/libxc/powerpc64/xc_prose_build.c @ 12976:a510c94ceaa3

[POWERPC] Merge in outstanding changes from xenppc-unstable.hg.
It's a long story, but basically a small divergence in xenppc-unstable meant a
large number of changesets couldn't be directly imported to xen-unstable, so
this changeset includes all of them.
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author Hollis Blanchard <hollisb@us.ibm.com>
date Tue Dec 12 09:56:06 2006 -0600 (2006-12-12)
parents b0293bc59835
children 09b3fd488726
line source
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 *
16 * Copyright (C) IBM Corporation 2006
17 *
18 * Authors: Hollis Blanchard <hollisb@us.ibm.com>
19 * Jonathan Appavoo <jappavoo@us.ibm.com>
20 */
22 #include <stdio.h>
23 #include <stdint.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <sys/types.h>
29 #include <inttypes.h>
31 #include <xen/xen.h>
32 #include <xen/memory.h>
33 #include <xc_private.h>
34 #include <xg_private.h>
35 #include <xenctrl.h>
37 #include "flatdevtree_env.h"
38 #include "flatdevtree.h"
39 #include "utils.h"
41 #define INITRD_ADDR (24UL << 20)
42 #define DEVTREE_ADDR (16UL << 20)
44 static int init_boot_vcpu(
45 int xc_handle,
46 int domid,
47 struct domain_setup_info *dsi,
48 unsigned long devtree_addr,
49 unsigned long kern_addr)
50 {
51 vcpu_guest_context_t ctxt;
52 int rc;
54 memset(&ctxt.user_regs, 0x55, sizeof(ctxt.user_regs));
55 ctxt.user_regs.pc = dsi->v_kernentry;
56 ctxt.user_regs.msr = 0;
57 ctxt.user_regs.gprs[1] = 0; /* Linux uses its own stack */
58 ctxt.user_regs.gprs[3] = devtree_addr;
59 ctxt.user_regs.gprs[4] = kern_addr;
60 ctxt.user_regs.gprs[5] = 0; /* reserved for specifying OF handler */
61 /* There is a buggy kernel that does not zero the "local_paca", so
62 * we must make sure this register is 0 */
63 ctxt.user_regs.gprs[13] = 0;
65 DPRINTF("xc_vcpu_setvcpucontext:\n"
66 " pc 0x%016"PRIx64", msr 0x%016"PRIx64"\n"
67 " r1-5 %016"PRIx64" %016"PRIx64" %016"PRIx64" %016"PRIx64
68 " %016"PRIx64"\n",
69 ctxt.user_regs.pc, ctxt.user_regs.msr,
70 ctxt.user_regs.gprs[1],
71 ctxt.user_regs.gprs[2],
72 ctxt.user_regs.gprs[3],
73 ctxt.user_regs.gprs[4],
74 ctxt.user_regs.gprs[5]);
75 rc = xc_vcpu_setcontext(xc_handle, domid, 0, &ctxt);
76 if (rc < 0)
77 perror("setdomaininfo");
79 return rc;
80 }
82 static int load_devtree(
83 int xc_handle,
84 int domid,
85 xen_pfn_t *page_array,
86 void *devtree,
87 unsigned long devtree_addr,
88 uint64_t initrd_base,
89 unsigned long initrd_len,
90 start_info_t *start_info __attribute__((unused)),
91 unsigned long start_info_addr)
92 {
93 uint32_t si[4] = {0, start_info_addr, 0, 0x1000};
94 struct boot_param_header *header;
95 void *chosen;
96 void *xen;
97 uint64_t initrd_end = initrd_base + initrd_len;
98 unsigned int devtree_size;
99 int rc = 0;
101 DPRINTF("adding initrd props\n");
103 chosen = ft_find_node(devtree, "/chosen");
104 if (chosen == NULL) {
105 DPRINTF("couldn't find /chosen\n");
106 return -1;
107 }
109 xen = ft_find_node(devtree, "/xen");
110 if (xen == NULL) {
111 DPRINTF("couldn't find /xen\n");
112 return -1;
113 }
115 /* initrd-start */
116 rc = ft_set_prop(&devtree, chosen, "linux,initrd-start",
117 &initrd_base, sizeof(initrd_base));
118 if (rc < 0) {
119 DPRINTF("couldn't set /chosen/linux,initrd-start\n");
120 return rc;
121 }
123 /* initrd-end */
124 rc = ft_set_prop(&devtree, chosen, "linux,initrd-end",
125 &initrd_end, sizeof(initrd_end));
126 if (rc < 0) {
127 DPRINTF("couldn't set /chosen/linux,initrd-end\n");
128 return rc;
129 }
131 rc = ft_set_rsvmap(devtree, 1, initrd_base, initrd_len);
132 if (rc < 0) {
133 DPRINTF("couldn't set initrd reservation\n");
134 return ~0UL;
135 }
137 /* start-info (XXX being removed soon) */
138 rc = ft_set_prop(&devtree, xen, "start-info", si, sizeof(si));
139 if (rc < 0) {
140 DPRINTF("couldn't set /xen/start-info\n");
141 return rc;
142 }
144 header = devtree;
145 devtree_size = header->totalsize;
146 {
147 static const char dtb[] = "/tmp/xc_domU.dtb";
148 int dfd = creat(dtb, 0666);
149 if (dfd != -1) {
150 write(dfd, devtree, devtree_size);
151 close(dfd);
152 } else
153 DPRINTF("could not open(\"%s\")\n", dtb);
154 }
156 DPRINTF("copying device tree to 0x%lx[0x%x]\n", DEVTREE_ADDR, devtree_size);
157 return install_image(xc_handle, domid, page_array, devtree, DEVTREE_ADDR,
158 devtree_size);
159 }
161 static int load_initrd(
162 int xc_handle,
163 int domid,
164 xen_pfn_t *page_array,
165 const char *initrd_path,
166 unsigned long *base,
167 unsigned long *len)
168 {
169 uint8_t *initrd_img;
170 int rc = -1;
172 /* load the initrd file */
173 initrd_img = load_file(initrd_path, len);
174 if (initrd_img == NULL)
175 return -1;
177 DPRINTF("copying initrd to 0x%lx[0x%lx]\n", INITRD_ADDR, *len);
178 if (install_image(xc_handle, domid, page_array, initrd_img, INITRD_ADDR,
179 *len))
180 goto out;
182 *base = INITRD_ADDR;
183 rc = 0;
185 out:
186 free(initrd_img);
187 return rc;
188 }
190 static unsigned long create_start_info(
191 void *devtree, start_info_t *start_info,
192 unsigned int console_evtchn, unsigned int store_evtchn,
193 unsigned long nr_pages, unsigned long rma_pages, const char *cmdline)
194 {
195 unsigned long start_info_addr;
196 uint64_t rma_top;
197 int rc;
199 memset(start_info, 0, sizeof(*start_info));
200 snprintf(start_info->magic, sizeof(start_info->magic),
201 "xen-%d.%d-powerpc64HV", 3, 0);
203 rma_top = rma_pages << PAGE_SHIFT;
204 DPRINTF("RMA top = 0x%"PRIX64"\n", rma_top);
206 start_info->nr_pages = nr_pages;
207 start_info->shared_info = rma_top - PAGE_SIZE;
208 start_info->store_mfn = (rma_top >> PAGE_SHIFT) - 2;
209 start_info->store_evtchn = store_evtchn;
210 start_info->console.domU.mfn = (rma_top >> PAGE_SHIFT) - 3;
211 start_info->console.domU.evtchn = console_evtchn;
212 strncpy((char *)start_info->cmd_line, cmdline, MAX_GUEST_CMDLINE);
213 /* just in case we truncated cmdline with strncpy add 0 at the end */
214 start_info->cmd_line[MAX_GUEST_CMDLINE-1]=0;
215 start_info_addr = rma_top - 4*PAGE_SIZE;
217 rc = ft_set_rsvmap(devtree, 0, start_info_addr, 4*PAGE_SIZE);
218 if (rc < 0) {
219 DPRINTF("couldn't set start_info reservation\n");
220 return ~0UL;
221 }
223 return start_info_addr;
224 }
226 static void free_page_array(xen_pfn_t *page_array)
227 {
228 free(page_array);
229 }
231 int xc_prose_build(int xc_handle,
232 uint32_t domid,
233 unsigned int mem_mb,
234 const char *image_name,
235 const char *initrd_name,
236 const char *cmdline,
237 const char *features,
238 unsigned long flags,
239 unsigned int store_evtchn,
240 unsigned long *store_mfn,
241 unsigned int console_evtchn,
242 unsigned long *console_mfn,
243 void *devtree)
244 {
245 start_info_t start_info;
246 struct domain_setup_info dsi;
247 xen_pfn_t *page_array = NULL;
248 unsigned long nr_pages;
249 unsigned long devtree_addr = 0;
250 unsigned long kern_addr;
251 unsigned long initrd_base = 0;
252 unsigned long initrd_len = 0;
253 unsigned long start_info_addr;
254 unsigned long rma_pages;
255 int rc = 0;
257 DPRINTF("%s\n", __func__);
259 DPRINTF("cmdline=%s\n", cmdline);
261 nr_pages = mem_mb << (20 - PAGE_SHIFT);
262 DPRINTF("nr_pages 0x%lx\n", nr_pages);
264 rma_pages = get_rma_pages(devtree);
265 if (rma_pages == 0) {
266 rc = -1;
267 goto out;
268 }
270 if (get_rma_page_array(xc_handle, domid, &page_array, rma_pages)) {
271 rc = -1;
272 goto out;
273 }
275 DPRINTF("loading image '%s'\n", image_name);
276 if (load_elf_kernel(xc_handle, domid, image_name, &dsi, page_array)) {
277 rc = -1;
278 goto out;
279 }
280 kern_addr = 0;
282 if (initrd_name && initrd_name[0] != '\0') {
283 DPRINTF("loading initrd '%s'\n", initrd_name);
284 if (load_initrd(xc_handle, domid, page_array, initrd_name,
285 &initrd_base, &initrd_len)) {
286 rc = -1;
287 goto out;
288 }
289 }
291 /* start_info stuff: about to be removed */
292 start_info_addr = create_start_info(devtree, &start_info, console_evtchn,
293 store_evtchn, nr_pages,
294 rma_pages, cmdline);
295 *console_mfn = page_array[start_info.console.domU.mfn];
296 *store_mfn = page_array[start_info.store_mfn];
297 if (install_image(xc_handle, domid, page_array, &start_info,
298 start_info_addr, sizeof(start_info_t))) {
299 rc = -1;
300 goto out;
301 }
303 if (devtree) {
304 DPRINTF("loading flattened device tree\n");
305 devtree_addr = DEVTREE_ADDR;
306 if (load_devtree(xc_handle, domid, page_array, devtree, devtree_addr,
307 initrd_base, initrd_len, &start_info,
308 start_info_addr)) {
309 DPRINTF("couldn't load flattened device tree.\n");
310 rc = -1;
311 goto out;
312 }
313 }
315 if (init_boot_vcpu(xc_handle, domid, &dsi, devtree_addr, kern_addr)) {
316 rc = -1;
317 goto out;
318 }
320 out:
321 free_page_array(page_array);
322 return rc;
323 }