ia64/xen-unstable

view tools/libxc/xc_ppc_linux_build.c @ 11057:c8870f1aa5ca

[TOOLS] use standard DPRINTF macro in PPC builder
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author Hollis Blanchard <hollisb@us.ibm.com>
date Wed Aug 02 13:56:41 2006 -0500 (2006-08-02)
parents 80e2c1b3f9b1
children ecd673684ec8
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 */
21 #include <stdio.h>
22 #include <stdint.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <sys/types.h>
28 #include <inttypes.h>
30 #include <xen/dom0_ops.h>
31 #include <xen/memory.h>
32 #include <xc_private.h>
33 #include <xg_private.h>
34 #include <xenctrl.h>
36 /* XXX 64M hack */
37 #define MEMSIZE (64UL << 20)
38 #define INITRD_ADDR (24UL << 20)
40 #define ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1)))
42 #define max(x,y) ({ \
43 const typeof(x) _x = (x); \
44 const typeof(y) _y = (y); \
45 (void) (&_x == &_y); \
46 _x > _y ? _x : _y; })
48 static void *load_file(const char *path, unsigned long *filesize)
49 {
50 void *img;
51 ssize_t size;
52 int fd;
54 DPRINTF("load_file(%s)\n", path);
56 fd = open(path, O_RDONLY);
57 if (fd < 0) {
58 perror(path);
59 return NULL;
60 }
62 size = lseek(fd, 0, SEEK_END);
63 if (size < 0) {
64 perror(path);
65 close(fd);
66 return NULL;
67 }
68 lseek(fd, 0, SEEK_SET);
70 img = malloc(size);
71 if (img == NULL) {
72 perror(path);
73 close(fd);
74 return NULL;
75 }
77 size = read(fd, img, size);
78 if (size <= 0) {
79 perror(path);
80 close(fd);
81 free(img);
82 return NULL;
83 }
85 if (filesize)
86 *filesize = size;
87 close(fd);
88 return img;
89 }
91 static int init_boot_vcpu(
92 int xc_handle,
93 int domid,
94 struct domain_setup_info *dsi,
95 unsigned long dtb,
96 unsigned long kaddr)
97 {
98 vcpu_guest_context_t ctxt;
99 int rc;
101 memset(&ctxt.user_regs, 0x55, sizeof(ctxt.user_regs));
102 ctxt.user_regs.pc = dsi->v_kernentry;
103 ctxt.user_regs.msr = 0;
104 ctxt.user_regs.gprs[1] = 0; /* Linux uses its own stack */
105 ctxt.user_regs.gprs[3] = dtb;
106 ctxt.user_regs.gprs[4] = kaddr;
107 ctxt.user_regs.gprs[5] = 0;
108 /* There is a buggy kernel that does not zero the "local_paca", so
109 * we must make sure this register is 0 */
110 ctxt.user_regs.gprs[13] = 0;
112 DPRINTF("xc_vcpu_setvcpucontext:\n"
113 " pc 0x%"PRIx64", msr 0x016%"PRIx64"\n"
114 " r1-5 %016"PRIx64" %016"PRIx64" %016"PRIx64" %016"PRIx64
115 " %016"PRIx64"\n",
116 ctxt.user_regs.pc, ctxt.user_regs.msr,
117 ctxt.user_regs.gprs[1],
118 ctxt.user_regs.gprs[2],
119 ctxt.user_regs.gprs[3],
120 ctxt.user_regs.gprs[4],
121 ctxt.user_regs.gprs[5]);
122 rc = xc_vcpu_setcontext(xc_handle, domid, 0, &ctxt);
123 if (rc < 0)
124 perror("setdomaininfo");
126 return rc;
127 }
129 static int install_image(
130 int xc_handle,
131 int domid,
132 xen_pfn_t *page_array,
133 void *image,
134 unsigned long paddr,
135 unsigned long size)
136 {
137 uint8_t *img = image;
138 int i;
139 int rc = 0;
141 if (paddr & ~PAGE_MASK) {
142 printf("*** unaligned address\n");
143 return -1;
144 }
146 for (i = 0; i < size; i += PAGE_SIZE) {
147 void *page = img + i;
148 xen_pfn_t pfn = (paddr + i) >> PAGE_SHIFT;
149 xen_pfn_t mfn = page_array[pfn];
151 rc = xc_copy_to_domain_page(xc_handle, domid, mfn, page);
152 if (rc < 0) {
153 perror("xc_copy_to_domain_page");
154 break;
155 }
156 }
157 return rc;
158 }
160 /* XXX be more flexible about placement in memory */
161 static int load_dtb(
162 int xc_handle,
163 int domid,
164 const char *dtb_path,
165 unsigned long dtb_addr,
166 struct domain_setup_info *dsi,
167 xen_pfn_t *page_array)
168 {
169 uint8_t *img;
170 unsigned long dtb_size;
171 int rc = 0;
173 img = load_file(dtb_path, &dtb_size);
174 if (img == NULL) {
175 rc = -1;
176 goto out;
177 }
179 DPRINTF("copying device tree to 0x%lx[0x%lx]\n", dtb_addr, dtb_size);
180 rc = install_image(xc_handle, domid, page_array, img, dtb_addr, dtb_size);
182 out:
183 free(img);
184 return rc;
185 }
187 unsigned long spin_list[] = {
188 #if 0
189 0x100,
190 0x200,
191 0x300,
192 0x380,
193 0x400,
194 0x480,
195 0x500,
196 0x700,
197 0x900,
198 0xc00,
199 #endif
200 0
201 };
203 /* XXX yes, this is a hack */
204 static void hack_kernel_img(char *img)
205 {
206 const off_t file_offset = 0x10000;
207 unsigned long *addr = spin_list;
209 while (*addr) {
210 uint32_t *instruction = (uint32_t *)(img + *addr + file_offset);
211 printf("installing spin loop at %lx (%x)\n", *addr, *instruction);
212 *instruction = 0x48000000;
213 addr++;
214 }
215 }
217 static int load_kernel(
218 int xc_handle,
219 int domid,
220 const char *kernel_path,
221 struct domain_setup_info *dsi,
222 xen_pfn_t *page_array)
223 {
224 struct load_funcs load_funcs;
225 char *kernel_img;
226 unsigned long kernel_size;
227 int rc;
229 /* load the kernel ELF file */
230 kernel_img = load_file(kernel_path, &kernel_size);
231 if (kernel_img == NULL) {
232 rc = -1;
233 goto out;
234 }
236 hack_kernel_img(kernel_img);
238 DPRINTF("probe_elf\n");
239 rc = probe_elf(kernel_img, kernel_size, &load_funcs);
240 if (rc < 0) {
241 rc = -1;
242 printf("%s is not an ELF file\n", kernel_path);
243 goto out;
244 }
246 DPRINTF("parseimage\n");
247 rc = (load_funcs.parseimage)(kernel_img, kernel_size, dsi);
248 if (rc < 0) {
249 rc = -1;
250 goto out;
251 }
253 DPRINTF("loadimage\n");
254 (load_funcs.loadimage)(kernel_img, kernel_size, xc_handle, domid,
255 page_array, dsi);
257 DPRINTF(" v_start %016"PRIx64"\n", dsi->v_start);
258 DPRINTF(" v_end %016"PRIx64"\n", dsi->v_end);
259 DPRINTF(" v_kernstart %016"PRIx64"\n", dsi->v_kernstart);
260 DPRINTF(" v_kernend %016"PRIx64"\n", dsi->v_kernend);
261 DPRINTF(" v_kernentry %016"PRIx64"\n", dsi->v_kernentry);
263 out:
264 free(kernel_img);
265 return rc;
266 }
268 static int load_initrd(
269 int xc_handle,
270 int domid,
271 xen_pfn_t *page_array,
272 const char *initrd_path,
273 unsigned long *base,
274 unsigned long *len)
275 {
276 uint8_t *initrd_img;
277 int rc = -1;
279 /* load the initrd file */
280 initrd_img = load_file(initrd_path, len);
281 if (initrd_img == NULL)
282 return -1;
284 DPRINTF("copying initrd to 0x%lx[0x%lx]\n", INITRD_ADDR, *len);
285 if (install_image(xc_handle, domid, page_array, initrd_img, INITRD_ADDR,
286 *len))
287 goto out;
289 *base = INITRD_ADDR;
290 rc = 0;
292 out:
293 free(initrd_img);
294 return rc;
295 }
297 static unsigned long create_start_info(start_info_t *si,
298 unsigned int console_evtchn, unsigned int store_evtchn)
299 {
300 unsigned long eomem;
301 unsigned long si_addr;
303 memset(si, 0, sizeof(*si));
304 snprintf(si->magic, sizeof(si->magic), "xen-%d.%d-powerpc64HV", 3, 0);
306 eomem = MEMSIZE;
307 si->nr_pages = eomem >> PAGE_SHIFT;
308 si->shared_info = eomem - (PAGE_SIZE * 1);
309 si->store_mfn = si->nr_pages - 2;
310 si->store_evtchn = store_evtchn;
311 si->console_mfn = si->nr_pages - 3;
312 si->console_evtchn = console_evtchn;
313 si_addr = eomem - (PAGE_SIZE * 4);
315 return si_addr;
316 }
318 static int get_page_array(int xc_handle, int domid, xen_pfn_t **page_array)
319 {
320 int nr_pages;
321 int rc;
323 DPRINTF("xc_get_tot_pages\n");
324 nr_pages = xc_get_tot_pages(xc_handle, domid);
325 DPRINTF(" 0x%x\n", nr_pages);
327 *page_array = malloc(nr_pages * sizeof(xen_pfn_t));
328 if (*page_array == NULL) {
329 perror("malloc");
330 return -1;
331 }
333 DPRINTF("xc_get_pfn_list\n");
334 rc = xc_get_pfn_list(xc_handle, domid, *page_array, nr_pages);
335 if (rc != nr_pages) {
336 perror("Could not get the page frame list");
337 return -1;
338 }
340 return 0;
341 }
345 int xc_linux_build(int xc_handle,
346 uint32_t domid,
347 const char *image_name,
348 const char *initrd_name,
349 const char *cmdline,
350 const char *features,
351 unsigned long flags,
352 unsigned int store_evtchn,
353 unsigned long *store_mfn,
354 unsigned int console_evtchn,
355 unsigned long *console_mfn)
356 {
357 struct domain_setup_info dsi;
358 xen_pfn_t *page_array = NULL;
359 unsigned long kern_addr;
360 unsigned long dtb_addr;
361 unsigned long si_addr;
362 unsigned long initrd_base = 0;
363 unsigned long initrd_len = 0;
364 start_info_t si;
365 int rc = 0;
367 if (get_page_array(xc_handle, domid, &page_array)) {
368 rc = -1;
369 goto out;
370 }
372 if (load_kernel(xc_handle, domid, image_name, &dsi, page_array)) {
373 rc = -1;
374 goto out;
375 }
376 kern_addr = 0;
378 if (initrd_name && initrd_name[0] != '\0' &&
379 load_initrd(xc_handle, domid, page_array, initrd_name, &initrd_base,
380 &initrd_len)) {
381 rc = -1;
382 goto out;
383 }
384 /* XXX install initrd addr/len into device tree */
386 dtb_addr = (16 << 20);
387 if (load_dtb(xc_handle, domid, "/root/DomU.dtb", dtb_addr, &dsi, page_array)) {
388 dtb_addr = 0;
389 }
391 si_addr = create_start_info(&si, store_evtchn, console_evtchn);
392 *console_mfn = page_array[si.console_mfn];
393 *store_mfn = page_array[si.store_mfn];
395 if (install_image(xc_handle, domid, page_array, &si, si_addr,
396 sizeof(start_info_t))) {
397 rc = -1;
398 goto out;
399 }
401 if (init_boot_vcpu(xc_handle, domid, &dsi, dtb_addr, kern_addr)) {
402 rc = -1;
403 goto out;
404 }
406 out:
407 return rc;
408 }