direct-io.hg

view tools/libxc/powerpc64/xc_linux_build.c @ 11362:1bbb88b5dfeb

[POWERPC][TOOLS] sync with start_info_t changes
Signed-off-by: Jimi Xenidis <jimix@watson.ibm.com>
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author Hollis Blanchard <hollisb@us.ibm.com>
date Tue Aug 29 14:18:23 2006 -0500 (2006-08-29)
parents 86d26e6ec89b
children caba587e6656
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/memory.h>
31 #include <xc_private.h>
32 #include <xg_private.h>
33 #include <xenctrl.h>
35 /* XXX 64M hack */
36 #define MEMSIZE (64UL << 20)
37 #define INITRD_ADDR (24UL << 20)
39 #define ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1)))
41 #define max(x,y) ({ \
42 const typeof(x) _x = (x); \
43 const typeof(y) _y = (y); \
44 (void) (&_x == &_y); \
45 _x > _y ? _x : _y; })
47 static void *load_file(const char *path, unsigned long *filesize)
48 {
49 void *img;
50 ssize_t size;
51 int fd;
53 DPRINTF("load_file(%s)\n", path);
55 fd = open(path, O_RDONLY);
56 if (fd < 0) {
57 perror(path);
58 return NULL;
59 }
61 size = lseek(fd, 0, SEEK_END);
62 if (size < 0) {
63 perror(path);
64 close(fd);
65 return NULL;
66 }
67 lseek(fd, 0, SEEK_SET);
69 img = malloc(size);
70 if (img == NULL) {
71 perror(path);
72 close(fd);
73 return NULL;
74 }
76 size = read(fd, img, size);
77 if (size <= 0) {
78 perror(path);
79 close(fd);
80 free(img);
81 return NULL;
82 }
84 if (filesize)
85 *filesize = size;
86 close(fd);
87 return img;
88 }
90 static int init_boot_vcpu(
91 int xc_handle,
92 int domid,
93 struct domain_setup_info *dsi,
94 unsigned long dtb,
95 unsigned long kaddr)
96 {
97 vcpu_guest_context_t ctxt;
98 int rc;
100 memset(&ctxt.user_regs, 0x55, sizeof(ctxt.user_regs));
101 ctxt.user_regs.pc = dsi->v_kernentry;
102 ctxt.user_regs.msr = 0;
103 ctxt.user_regs.gprs[1] = 0; /* Linux uses its own stack */
104 ctxt.user_regs.gprs[3] = dtb;
105 ctxt.user_regs.gprs[4] = kaddr;
106 ctxt.user_regs.gprs[5] = 0;
107 /* There is a buggy kernel that does not zero the "local_paca", so
108 * we must make sure this register is 0 */
109 ctxt.user_regs.gprs[13] = 0;
111 DPRINTF("xc_vcpu_setvcpucontext:\n"
112 " pc 0x%"PRIx64", msr 0x016%"PRIx64"\n"
113 " r1-5 %016"PRIx64" %016"PRIx64" %016"PRIx64" %016"PRIx64
114 " %016"PRIx64"\n",
115 ctxt.user_regs.pc, ctxt.user_regs.msr,
116 ctxt.user_regs.gprs[1],
117 ctxt.user_regs.gprs[2],
118 ctxt.user_regs.gprs[3],
119 ctxt.user_regs.gprs[4],
120 ctxt.user_regs.gprs[5]);
121 rc = xc_vcpu_setcontext(xc_handle, domid, 0, &ctxt);
122 if (rc < 0)
123 perror("setdomaininfo");
125 return rc;
126 }
128 static int install_image(
129 int xc_handle,
130 int domid,
131 xen_pfn_t *page_array,
132 void *image,
133 unsigned long paddr,
134 unsigned long size)
135 {
136 uint8_t *img = image;
137 int i;
138 int rc = 0;
140 if (paddr & ~PAGE_MASK) {
141 printf("*** unaligned address\n");
142 return -1;
143 }
145 for (i = 0; i < size; i += PAGE_SIZE) {
146 void *page = img + i;
147 xen_pfn_t pfn = (paddr + i) >> PAGE_SHIFT;
148 xen_pfn_t mfn = page_array[pfn];
150 rc = xc_copy_to_domain_page(xc_handle, domid, mfn, page);
151 if (rc < 0) {
152 perror("xc_copy_to_domain_page");
153 break;
154 }
155 }
156 return rc;
157 }
159 /* XXX be more flexible about placement in memory */
160 static int load_dtb(
161 int xc_handle,
162 int domid,
163 const char *dtb_path,
164 unsigned long dtb_addr,
165 struct domain_setup_info *dsi,
166 xen_pfn_t *page_array)
167 {
168 uint8_t *img;
169 unsigned long dtb_size;
170 int rc = 0;
172 img = load_file(dtb_path, &dtb_size);
173 if (img == NULL) {
174 rc = -1;
175 goto out;
176 }
178 DPRINTF("copying device tree to 0x%lx[0x%lx]\n", dtb_addr, dtb_size);
179 rc = install_image(xc_handle, domid, page_array, img, dtb_addr, dtb_size);
181 out:
182 free(img);
183 return rc;
184 }
186 unsigned long spin_list[] = {
187 #if 0
188 0x100,
189 0x200,
190 0x300,
191 0x380,
192 0x400,
193 0x480,
194 0x500,
195 0x700,
196 0x900,
197 0xc00,
198 #endif
199 0
200 };
202 /* XXX yes, this is a hack */
203 static void hack_kernel_img(char *img)
204 {
205 const off_t file_offset = 0x10000;
206 unsigned long *addr = spin_list;
208 while (*addr) {
209 uint32_t *instruction = (uint32_t *)(img + *addr + file_offset);
210 printf("installing spin loop at %lx (%x)\n", *addr, *instruction);
211 *instruction = 0x48000000;
212 addr++;
213 }
214 }
216 static int load_kernel(
217 int xc_handle,
218 int domid,
219 const char *kernel_path,
220 struct domain_setup_info *dsi,
221 xen_pfn_t *page_array)
222 {
223 struct load_funcs load_funcs;
224 char *kernel_img;
225 unsigned long kernel_size;
226 int rc;
228 /* load the kernel ELF file */
229 kernel_img = load_file(kernel_path, &kernel_size);
230 if (kernel_img == NULL) {
231 rc = -1;
232 goto out;
233 }
235 hack_kernel_img(kernel_img);
237 DPRINTF("probe_elf\n");
238 rc = probe_elf(kernel_img, kernel_size, &load_funcs);
239 if (rc < 0) {
240 rc = -1;
241 printf("%s is not an ELF file\n", kernel_path);
242 goto out;
243 }
245 DPRINTF("parseimage\n");
246 rc = (load_funcs.parseimage)(kernel_img, kernel_size, dsi);
247 if (rc < 0) {
248 rc = -1;
249 goto out;
250 }
252 DPRINTF("loadimage\n");
253 (load_funcs.loadimage)(kernel_img, kernel_size, xc_handle, domid,
254 page_array, dsi);
256 DPRINTF(" v_start %016"PRIx64"\n", dsi->v_start);
257 DPRINTF(" v_end %016"PRIx64"\n", dsi->v_end);
258 DPRINTF(" v_kernstart %016"PRIx64"\n", dsi->v_kernstart);
259 DPRINTF(" v_kernend %016"PRIx64"\n", dsi->v_kernend);
260 DPRINTF(" v_kernentry %016"PRIx64"\n", dsi->v_kernentry);
262 out:
263 free(kernel_img);
264 return rc;
265 }
267 static int load_initrd(
268 int xc_handle,
269 int domid,
270 xen_pfn_t *page_array,
271 const char *initrd_path,
272 unsigned long *base,
273 unsigned long *len)
274 {
275 uint8_t *initrd_img;
276 int rc = -1;
278 /* load the initrd file */
279 initrd_img = load_file(initrd_path, len);
280 if (initrd_img == NULL)
281 return -1;
283 DPRINTF("copying initrd to 0x%lx[0x%lx]\n", INITRD_ADDR, *len);
284 if (install_image(xc_handle, domid, page_array, initrd_img, INITRD_ADDR,
285 *len))
286 goto out;
288 *base = INITRD_ADDR;
289 rc = 0;
291 out:
292 free(initrd_img);
293 return rc;
294 }
296 static unsigned long create_start_info(start_info_t *si,
297 unsigned int console_evtchn, unsigned int store_evtchn)
298 {
299 unsigned long eomem;
300 unsigned long si_addr;
302 memset(si, 0, sizeof(*si));
303 snprintf(si->magic, sizeof(si->magic), "xen-%d.%d-powerpc64HV", 3, 0);
305 eomem = MEMSIZE;
306 si->nr_pages = eomem >> PAGE_SHIFT;
307 si->shared_info = eomem - (PAGE_SIZE * 1);
308 si->store_mfn = si->nr_pages - 2;
309 si->store_evtchn = store_evtchn;
310 si->console.domU.mfn = si->nr_pages - 3;
311 si->console.domU.evtchn = console_evtchn;
312 si_addr = si->nr_pages - 4;
314 return si_addr;
315 }
317 static int get_page_array(int xc_handle, int domid, xen_pfn_t **page_array)
318 {
319 int nr_pages;
320 int rc;
322 DPRINTF("xc_get_tot_pages\n");
323 nr_pages = xc_get_tot_pages(xc_handle, domid);
324 DPRINTF(" 0x%x\n", nr_pages);
326 *page_array = malloc(nr_pages * sizeof(xen_pfn_t));
327 if (*page_array == NULL) {
328 perror("malloc");
329 return -1;
330 }
332 DPRINTF("xc_get_pfn_list\n");
333 rc = xc_get_pfn_list(xc_handle, domid, *page_array, nr_pages);
334 if (rc != nr_pages) {
335 perror("Could not get the page frame list");
336 return -1;
337 }
339 return 0;
340 }
344 int xc_linux_build(int xc_handle,
345 uint32_t domid,
346 const char *image_name,
347 const char *initrd_name,
348 const char *cmdline,
349 const char *features,
350 unsigned long flags,
351 unsigned int store_evtchn,
352 unsigned long *store_mfn,
353 unsigned int console_evtchn,
354 unsigned long *console_mfn)
355 {
356 struct domain_setup_info dsi;
357 xen_pfn_t *page_array = NULL;
358 unsigned long kern_addr;
359 unsigned long dtb_addr;
360 unsigned long si_addr;
361 unsigned long initrd_base = 0;
362 unsigned long initrd_len = 0;
363 start_info_t si;
364 int rc = 0;
366 if (get_page_array(xc_handle, domid, &page_array)) {
367 rc = -1;
368 goto out;
369 }
371 if (load_kernel(xc_handle, domid, image_name, &dsi, page_array)) {
372 rc = -1;
373 goto out;
374 }
375 kern_addr = 0;
377 if (initrd_name && initrd_name[0] != '\0' &&
378 load_initrd(xc_handle, domid, page_array, initrd_name, &initrd_base,
379 &initrd_len)) {
380 rc = -1;
381 goto out;
382 }
383 /* XXX install initrd addr/len into device tree */
385 dtb_addr = (16 << 20);
386 if (load_dtb(xc_handle, domid, "/root/DomU.dtb", dtb_addr, &dsi, page_array)) {
387 dtb_addr = 0;
388 }
390 si_addr = create_start_info(&si, console_evtchn, store_evtchn);
391 *console_mfn = page_array[si.console.domU.mfn];
392 *store_mfn = page_array[si.store_mfn];
394 if (install_image(xc_handle, domid, page_array, &si, si_addr,
395 sizeof(start_info_t))) {
396 rc = -1;
397 goto out;
398 }
400 if (init_boot_vcpu(xc_handle, domid, &dsi, dtb_addr, kern_addr)) {
401 rc = -1;
402 goto out;
403 }
405 out:
406 return rc;
407 }