direct-io.hg

view xen/arch/powerpc/domain_build.c @ 11384:3e144748d36f

[XEN][POWERPC] do not set d->tot_pages, but check it.
Signed-off-by: Jimi Xenidis <jimix@watson.ibm.com>
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author Jimi Xenidis <jimix@watson.ibm.com>
date Mon Aug 28 17:28:55 2006 -0400 (2006-08-28)
parents e07281779b88
children 444496ecb14e
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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * Copyright (C) IBM Corp. 2005
17 *
18 * Authors: Jimi Xenidis <jimix@watson.ibm.com>
19 */
21 #include <xen/config.h>
22 #include <xen/lib.h>
23 #include <xen/elf.h>
24 #include <xen/sched.h>
25 #include <xen/init.h>
26 #include <xen/ctype.h>
27 #include <xen/iocap.h>
28 #include <xen/shadow.h>
29 #include <xen/version.h>
30 #include <asm/processor.h>
31 #include <asm/papr.h>
32 #include "oftree.h"
34 extern int parseelfimage_32(struct domain_setup_info *dsi);
35 extern int loadelfimage_32(struct domain_setup_info *dsi);
37 /* opt_dom0_mem: memory allocated to domain 0. */
38 static unsigned int dom0_nrpages;
39 static void parse_dom0_mem(char *s)
40 {
41 unsigned long long bytes;
43 bytes = parse_size_and_unit(s);
44 dom0_nrpages = bytes >> PAGE_SHIFT;
45 }
46 custom_param("dom0_mem", parse_dom0_mem);
48 static unsigned int opt_dom0_max_vcpus;
49 integer_param("dom0_max_vcpus", opt_dom0_max_vcpus);
51 static unsigned int opt_dom0_shadow;
52 boolean_param("dom0_shadow", opt_dom0_shadow);
54 int elf_sanity_check(Elf_Ehdr *ehdr)
55 {
56 if (IS_ELF(*ehdr))
57 /* we are happy with either */
58 if ((ehdr->e_ident[EI_CLASS] == ELFCLASS32
59 && ehdr->e_machine == EM_PPC)
60 || (ehdr->e_ident[EI_CLASS] == ELFCLASS64
61 && ehdr->e_machine == EM_PPC64)) {
62 if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB
63 && ehdr->e_type == ET_EXEC)
64 return 1;
65 }
66 printk("DOM0 image is not a Xen-compatible Elf image.\n");
67 return 0;
68 }
70 /* adapted from common/elf.c */
71 #define RM_MASK(a,l) ((a) & ((1UL << (l)) - 1))
73 static int rm_loadelfimage_64(struct domain_setup_info *dsi, ulong rma)
74 {
75 char *elfbase = (char *)dsi->image_addr;
76 Elf64_Ehdr *ehdr = (Elf64_Ehdr *)dsi->image_addr;
77 Elf64_Phdr *phdr;
78 int h;
80 for (h = 0; h < ehdr->e_phnum; h++ )
81 {
82 phdr = (Elf64_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
83 if (!((phdr->p_type == PT_LOAD) &&
84 ((phdr->p_flags & (PF_W|PF_X)) != 0)))
85 continue;
87 if (phdr->p_filesz != 0)
88 memcpy((char *)(rma + RM_MASK(phdr->p_paddr, 42)),
89 elfbase + phdr->p_offset,
90 phdr->p_filesz);
91 if (phdr->p_memsz > phdr->p_filesz)
92 memset((char *)(rma + RM_MASK(phdr->p_paddr, 42) + phdr->p_filesz),
93 0, phdr->p_memsz - phdr->p_filesz);
94 }
96 #ifdef NOT_YET
97 loadelfsymtab(dsi, 1);
98 #endif
100 return 0;
101 }
103 int construct_dom0(struct domain *d,
104 unsigned long image_start, unsigned long image_len,
105 unsigned long initrd_start, unsigned long initrd_len,
106 char *cmdline)
107 {
108 int rc;
109 struct vcpu *v = d->vcpu[0];
110 struct domain_setup_info dsi;
111 ulong dst;
112 u64 *ofh_tree;
113 uint rma_nrpages = 1 << d->arch.rma_order;
114 ulong rma_sz = rma_size(d->arch.rma_order);
115 ulong rma = page_to_maddr(d->arch.rma_page);
116 start_info_t *si;
117 ulong eomem;
118 int am64 = 1;
119 int preempt = 0;
120 ulong msr;
121 ulong pc;
122 ulong r2;
124 /* Sanity! */
125 BUG_ON(d->domain_id != 0);
126 BUG_ON(d->vcpu[0] == NULL);
128 if (image_len == 0)
129 panic("No Dom0 image supplied\n");
131 cpu_init_vcpu(v);
133 memset(&dsi, 0, sizeof(struct domain_setup_info));
134 dsi.image_addr = image_start;
135 dsi.image_len = image_len;
137 printk("Trying Dom0 as 64bit ELF\n");
138 if ((rc = parseelfimage(&dsi)) != 0) {
139 printk("Trying Dom0 as 32bit ELF\n");
140 if ((rc = parseelfimage_32(&dsi)) != 0)
141 return rc;
142 am64 = 0;
143 }
145 /* elf contains virtual addresses that can have the upper bits
146 * masked while running in real mode, so we do the masking as well
147 * as well */
148 dsi.v_kernstart = RM_MASK(dsi.v_kernstart, 42);
149 dsi.v_kernend = RM_MASK(dsi.v_kernend, 42);
150 dsi.v_kernentry = RM_MASK(dsi.v_kernentry, 42);
152 printk("*** LOADING DOMAIN 0 ***\n");
154 /* By default DOM0 is allocated all available memory. */
155 d->max_pages = ~0U;
157 /* default is the max(1/16th of memory, CONFIG_MIN_DOM0_PAGES) */
158 if (dom0_nrpages == 0) {
159 dom0_nrpages = total_pages >> 4;
161 if (dom0_nrpages < CONFIG_MIN_DOM0_PAGES)
162 dom0_nrpages = CONFIG_MIN_DOM0_PAGES;
163 }
165 /* make sure we are at least as big as the RMA */
166 if (dom0_nrpages > rma_nrpages)
167 dom0_nrpages = allocate_extents(d, dom0_nrpages, rma_nrpages);
169 ASSERT(d->tot_pages == dom0_nrpages);
170 ASSERT(d->tot_pages >= rma_nrpages);
172 if (opt_dom0_shadow == 0) {
173 /* 1/64 of memory */
174 opt_dom0_shadow = (d->tot_pages >> 6) >> (20 - PAGE_SHIFT);
175 }
177 do {
178 shadow_set_allocation(d, opt_dom0_shadow, &preempt);
179 } while (preempt);
180 if (shadow_get_allocation(d) == 0)
181 panic("shadow allocation failed 0x%x < 0x%x\n",
182 shadow_get_allocation(d), opt_dom0_shadow);
184 ASSERT( image_len < rma_sz );
186 si = (start_info_t *)(rma_addr(&d->arch, RMA_START_INFO) + rma);
187 printk("xen_start_info: %p\n", si);
189 sprintf(si->magic, "xen-%i.%i-powerpc%d%s",
190 xen_major_version(), xen_minor_version(), BITS_PER_LONG, "HV");
191 si->flags = SIF_PRIVILEGED | SIF_INITDOMAIN;
193 si->shared_info = ((ulong)d->shared_info) - rma;
194 printk("shared_info: 0x%lx,%p\n", si->shared_info, d->shared_info);
196 eomem = si->shared_info;
198 /* number of pages accessible */
199 si->nr_pages = rma_sz >> PAGE_SHIFT;
201 si->pt_base = 0;
202 si->nr_pt_frames = 0;
203 si->mfn_list = 0;
205 /* OF usually sits here:
206 * - Linux needs it to be loaded before the vmlinux or initrd
207 * - AIX demands it to be @ 32M.
208 */
209 dst = (32 << 20);
211 /* put stack below everything */
212 v->arch.ctxt.gprs[1] = dst - STACK_FRAME_OVERHEAD;
214 /* copy relative to Xen */
215 dst += rma;
217 ASSERT((dst - rma) + (ulong)firmware_image_size < eomem);
218 printk("loading OFH: 0x%lx, RMA: 0x%lx\n", dst, dst - rma);
219 memcpy((void *)dst, firmware_image_start, (ulong)firmware_image_size);
221 v->arch.ctxt.gprs[5] = (dst - rma);
222 ofh_tree = (u64 *)(dst + 0x10);
223 ASSERT(*ofh_tree == 0xdeadbeef00000000);
225 /* accomodate for a modest bss section */
226 dst = ALIGN_UP(dst + (ulong)firmware_image_size + PAGE_SIZE, PAGE_SIZE);
227 ASSERT((dst - rma) + oftree_len < eomem);
229 *ofh_tree = dst - rma;
230 printk("loading OFD: 0x%lx RMA: 0x%lx, 0x%lx\n", dst, dst - rma,
231 oftree_len);
232 memcpy((void *)dst, (void *)oftree, oftree_len);
234 dst = ALIGN_UP(dst + oftree_len, PAGE_SIZE);
236 if (am64) {
237 ulong kbase;
238 ulong *fdesc;
240 printk("loading 64-bit Dom0: 0x%lx, in RMA:0x%lx\n", dst, dst - rma);
241 rm_loadelfimage_64(&dsi, dst);
243 kbase = dst;
244 /* move dst to end of bss */
245 dst = ALIGN_UP(dsi.v_kernend + dst, PAGE_SIZE);
247 if ( initrd_len > 0 ) {
248 ASSERT( (dst - rma) + image_len < eomem );
250 printk("loading initrd: 0x%lx, 0x%lx\n", dst, initrd_len);
251 memcpy((void *)dst, (void *)initrd_start, initrd_len);
253 si->mod_start = dst - rma;
254 si->mod_len = image_len;
256 dst = ALIGN_UP(dst + initrd_len, PAGE_SIZE);
257 } else {
258 printk("no initrd\n");
259 si->mod_start = 0;
260 si->mod_len = 0;
261 }
262 /* it may be a function descriptor */
263 fdesc = (ulong *)(dsi.v_kernstart + dsi.v_kernentry + kbase);
265 if (fdesc[2] == 0
266 && ((fdesc[0] >= dsi.v_kernstart)
267 && (fdesc[0] < dsi.v_kernend)) /* text entry is in range */
268 && ((fdesc[1] >= dsi.v_kernstart) /* toc can be > image */
269 && (fdesc[1] < (dsi.v_kernend + (0x7fff * sizeof (ulong)))))) {
270 /* it is almost certainly a function descriptor */
271 pc = RM_MASK(fdesc[0], 42) + kbase - rma;
272 r2 = RM_MASK(fdesc[1], 42) + kbase - rma;
273 } else {
274 pc = ((ulong)fdesc) - rma;
275 r2 = 0;
276 }
277 msr = MSR_SF;
278 } else {
279 printk("loading 32-bit Dom0: 0x%lx, in RMA:0x%lx\n",
280 dsi.v_kernstart + rma, dsi.v_kernstart);
281 dsi.v_start = rma;
282 loadelfimage_32(&dsi);
284 pc = dsi.v_kernentry;
285 r2 = 0;
286 msr = 0;
287 }
289 v->arch.ctxt.gprs[3] = si->mod_start;
290 v->arch.ctxt.gprs[4] = si->mod_len;
292 memset(si->cmd_line, 0, sizeof(si->cmd_line));
293 if ( cmdline != NULL )
294 strncpy((char *)si->cmd_line, cmdline, sizeof(si->cmd_line)-1);
296 v->arch.ctxt.msr = msr;
297 v->arch.ctxt.pc = pc;
298 v->arch.ctxt.gprs[2] = r2;
300 printk("DOM: pc = 0x%lx, r2 = 0x%lx\n", pc, r2);
302 ofd_dom0_fixup(d, *ofh_tree + rma, si);
304 set_bit(_VCPUF_initialised, &v->vcpu_flags);
306 rc = 0;
308 /* DOM0 is permitted full I/O capabilities. */
309 rc |= iomem_permit_access(dom0, 0UL, ~0UL);
310 rc |= irqs_permit_access(dom0, 0, NR_IRQS-1);
312 BUG_ON(rc != 0);
314 return 0;
315 }