ia64/xen-unstable

view xen/arch/powerpc/domain_build.c @ 13943:4ce0b332b572

[POWERPC][XEN] Move shared page location to public header to share with libxc.
Signed-off-by: Ryan Harper <ryanh@us.ibm.com>
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author Hollis Blanchard <hollisb@us.ibm.com>
date Tue Feb 06 13:42:19 2007 -0600 (2007-02-06)
parents cc1eb0689bcf
children 978ff6fad81f
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/domain.h>
30 #include <xen/version.h>
31 #include <asm/processor.h>
32 #include <asm/papr.h>
33 #include <public/arch-powerpc.h>
34 #include "oftree.h"
36 extern int parseelfimage_32(struct domain_setup_info *dsi);
37 extern int loadelfimage_32(struct domain_setup_info *dsi);
39 /* opt_dom0_mem: memory allocated to domain 0. */
40 static unsigned int dom0_nrpages;
41 static void parse_dom0_mem(char *s)
42 {
43 unsigned long long bytes;
45 bytes = parse_size_and_unit(s, NULL);
46 dom0_nrpages = bytes >> PAGE_SHIFT;
47 }
48 custom_param("dom0_mem", parse_dom0_mem);
50 static unsigned int opt_dom0_max_vcpus;
51 integer_param("dom0_max_vcpus", opt_dom0_max_vcpus);
53 static unsigned int opt_dom0_shadow;
54 boolean_param("dom0_shadow", opt_dom0_shadow);
56 int elf_sanity_check(const Elf_Ehdr *ehdr)
57 {
58 if (IS_ELF(*ehdr))
59 /* we are happy with either */
60 if ((ehdr->e_ident[EI_CLASS] == ELFCLASS32
61 && ehdr->e_machine == EM_PPC)
62 || (ehdr->e_ident[EI_CLASS] == ELFCLASS64
63 && ehdr->e_machine == EM_PPC64)) {
64 if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB
65 && ehdr->e_type == ET_EXEC)
66 return 1;
67 }
68 printk("DOM0 image is not a Xen-compatible Elf image.\n");
69 return 0;
70 }
72 /* adapted from common/elf.c */
73 #define RM_MASK(a,l) ((a) & ((1UL << (l)) - 1))
75 static int rm_loadelfimage_64(struct domain_setup_info *dsi, ulong rma)
76 {
77 char *elfbase = (char *)dsi->image_addr;
78 Elf64_Ehdr *ehdr = (Elf64_Ehdr *)dsi->image_addr;
79 Elf64_Phdr *phdr;
80 int h;
82 for (h = 0; h < ehdr->e_phnum; h++ )
83 {
84 phdr = (Elf64_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
85 if (!((phdr->p_type == PT_LOAD) &&
86 ((phdr->p_flags & (PF_W|PF_X)) != 0)))
87 continue;
89 if (phdr->p_filesz != 0)
90 memcpy((char *)(rma + RM_MASK(phdr->p_paddr, 42)),
91 elfbase + phdr->p_offset,
92 phdr->p_filesz);
93 if (phdr->p_memsz > phdr->p_filesz)
94 memset((char *)(rma + RM_MASK(phdr->p_paddr, 42) + phdr->p_filesz),
95 0, phdr->p_memsz - phdr->p_filesz);
96 }
98 #ifdef NOT_YET
99 loadelfsymtab(dsi, 1);
100 #endif
102 return 0;
103 }
105 int construct_dom0(struct domain *d,
106 unsigned long image_start, unsigned long image_len,
107 unsigned long initrd_start, unsigned long initrd_len,
108 char *cmdline)
109 {
110 int rc;
111 struct vcpu *v = d->vcpu[0];
112 struct domain_setup_info dsi;
113 ulong dst;
114 u64 *ofh_tree;
115 uint rma_nrpages = 1 << d->arch.rma_order;
116 ulong rma_sz = rma_size(d->arch.rma_order);
117 ulong rma = page_to_maddr(d->arch.rma_page);
118 start_info_t *si;
119 ulong eomem;
120 int am64 = 1;
121 int preempt = 0;
122 ulong msr;
123 ulong pc;
124 ulong r2;
125 int vcpu;
127 /* Sanity! */
128 BUG_ON(d->domain_id != 0);
129 BUG_ON(d->vcpu[0] == NULL);
131 if (image_len == 0)
132 panic("No Dom0 image supplied\n");
134 cpu_init_vcpu(v);
136 memset(&dsi, 0, sizeof(struct domain_setup_info));
137 dsi.image_addr = image_start;
138 dsi.image_len = image_len;
140 printk("Trying Dom0 as 64bit ELF\n");
141 if ((rc = parseelfimage(&dsi)) != 0) {
142 printk("Trying Dom0 as 32bit ELF\n");
143 if ((rc = parseelfimage_32(&dsi)) != 0)
144 return rc;
145 am64 = 0;
146 }
148 /* elf contains virtual addresses that can have the upper bits
149 * masked while running in real mode, so we do the masking as well
150 * as well */
151 dsi.v_kernstart = RM_MASK(dsi.v_kernstart, 42);
152 dsi.v_kernend = RM_MASK(dsi.v_kernend, 42);
153 dsi.v_kernentry = RM_MASK(dsi.v_kernentry, 42);
155 printk("*** LOADING DOMAIN 0 ***\n");
157 /* By default DOM0 is allocated all available memory. */
158 d->max_pages = ~0U;
160 /* default is the max(1/16th of memory, CONFIG_MIN_DOM0_PAGES) */
161 if (dom0_nrpages == 0) {
162 dom0_nrpages = total_pages >> 4;
164 if (dom0_nrpages < CONFIG_MIN_DOM0_PAGES)
165 dom0_nrpages = CONFIG_MIN_DOM0_PAGES;
166 }
168 /* make sure we are at least as big as the RMA */
169 if (dom0_nrpages > rma_nrpages)
170 dom0_nrpages = allocate_extents(d, dom0_nrpages, rma_nrpages);
172 ASSERT(d->tot_pages == dom0_nrpages);
173 ASSERT(d->tot_pages >= rma_nrpages);
175 if (opt_dom0_shadow == 0) {
176 /* 1/64 of memory */
177 opt_dom0_shadow = (d->tot_pages >> 6) >> (20 - PAGE_SHIFT);
178 }
180 do {
181 shadow_set_allocation(d, opt_dom0_shadow, &preempt);
182 } while (preempt);
183 if (shadow_get_allocation(d) == 0)
184 panic("shadow allocation failed: %dMib\n", opt_dom0_shadow);
186 ASSERT( image_len < rma_sz );
188 si = (start_info_t *)(rma_addr(&d->arch, RMA_START_INFO) + rma);
189 printk("xen_start_info: %p\n", si);
191 sprintf(si->magic, "xen-%i.%i-powerpc%d%s",
192 xen_major_version(), xen_minor_version(), BITS_PER_LONG, "HV");
193 si->flags = SIF_PRIVILEGED | SIF_INITDOMAIN;
195 si->shared_info = ((ulong)d->shared_info) - rma;
196 printk("shared_info: 0x%lx,%p\n", si->shared_info, d->shared_info);
198 eomem = si->shared_info;
200 /* number of pages accessible */
201 si->nr_pages = rma_sz >> PAGE_SHIFT;
203 si->pt_base = 0;
204 si->nr_pt_frames = 0;
205 si->mfn_list = 0;
207 /* OF usually sits here:
208 * - Linux needs it to be loaded before the vmlinux or initrd
209 * - AIX demands it to be @ 32M.
210 */
211 dst = (32 << 20);
213 /* put stack below everything */
214 v->arch.ctxt.gprs[1] = dst - STACK_FRAME_OVERHEAD;
216 /* startup secondary processors */
217 if ( opt_dom0_max_vcpus == 0 )
218 opt_dom0_max_vcpus = num_online_cpus();
219 if ( opt_dom0_max_vcpus > num_online_cpus() )
220 opt_dom0_max_vcpus = num_online_cpus();
221 if ( opt_dom0_max_vcpus > MAX_VIRT_CPUS )
222 opt_dom0_max_vcpus = MAX_VIRT_CPUS;
223 #ifdef BITS_PER_GUEST_LONG
224 if ( opt_dom0_max_vcpus > BITS_PER_GUEST_LONG(d) )
225 opt_dom0_max_vcpus = BITS_PER_GUEST_LONG(d);
226 #endif
227 printk("Dom0 has maximum %u VCPUs\n", opt_dom0_max_vcpus);
229 for (vcpu = 1; vcpu < opt_dom0_max_vcpus; vcpu++) {
230 if (NULL == alloc_vcpu(dom0, vcpu, vcpu))
231 panic("Error creating domain 0 vcpu %d\n", vcpu);
232 /* for now we pin Dom0 VCPUs to their coresponding CPUs */
233 if (cpu_isset(vcpu, cpu_online_map))
234 dom0->vcpu[vcpu]->cpu_affinity = cpumask_of_cpu(vcpu);
235 }
237 /* copy relative to Xen */
238 dst += rma;
240 ASSERT((dst - rma) + (ulong)firmware_image_size < eomem);
241 printk("loading OFH: 0x%lx, RMA: 0x%lx\n", dst, dst - rma);
242 memcpy((void *)dst, firmware_image_start, (ulong)firmware_image_size);
244 v->arch.ctxt.gprs[5] = (dst - rma);
245 ofh_tree = (u64 *)(dst + 0x10);
246 ASSERT(*ofh_tree == 0xdeadbeef00000000);
248 /* accomodate for a modest bss section */
249 dst = ALIGN_UP(dst + (ulong)firmware_image_size + PAGE_SIZE, PAGE_SIZE);
250 ASSERT((dst - rma) + oftree_len < eomem);
252 *ofh_tree = dst - rma;
253 printk("loading OFD: 0x%lx RMA: 0x%lx, 0x%lx\n", dst, dst - rma,
254 oftree_len);
255 memcpy((void *)dst, (void *)oftree, oftree_len);
257 dst = ALIGN_UP(dst + oftree_len, PAGE_SIZE);
259 if (am64) {
260 ulong kbase;
261 ulong *fdesc;
263 printk("loading 64-bit Dom0: 0x%lx, in RMA:0x%lx\n", dst, dst - rma);
264 rm_loadelfimage_64(&dsi, dst);
266 kbase = dst;
267 /* move dst to end of bss */
268 dst = ALIGN_UP(dsi.v_kernend + dst, PAGE_SIZE);
270 if ( initrd_len > 0 ) {
271 ASSERT( (dst - rma) + image_len < eomem );
273 printk("loading initrd: 0x%lx, 0x%lx\n", dst, initrd_len);
274 memcpy((void *)dst, (void *)initrd_start, initrd_len);
276 si->mod_start = dst - rma;
277 si->mod_len = image_len;
279 dst = ALIGN_UP(dst + initrd_len, PAGE_SIZE);
280 } else {
281 printk("no initrd\n");
282 si->mod_start = 0;
283 si->mod_len = 0;
284 }
285 /* it may be a function descriptor */
286 fdesc = (ulong *)(dsi.v_kernstart + dsi.v_kernentry + kbase);
288 if (fdesc[2] == 0
289 && ((fdesc[0] >= dsi.v_kernstart)
290 && (fdesc[0] < dsi.v_kernend)) /* text entry is in range */
291 && ((fdesc[1] >= dsi.v_kernstart) /* toc can be > image */
292 && (fdesc[1] < (dsi.v_kernend + (0x7fff * sizeof (ulong)))))) {
293 /* it is almost certainly a function descriptor */
294 pc = RM_MASK(fdesc[0], 42) + kbase - rma;
295 r2 = RM_MASK(fdesc[1], 42) + kbase - rma;
296 } else {
297 pc = ((ulong)fdesc) - rma;
298 r2 = 0;
299 }
300 msr = MSR_SF;
301 } else {
302 printk("loading 32-bit Dom0: 0x%lx, in RMA:0x%lx\n",
303 dsi.v_kernstart + rma, dsi.v_kernstart);
304 dsi.v_start = rma;
305 loadelfimage_32(&dsi);
307 pc = dsi.v_kernentry;
308 r2 = 0;
309 msr = 0;
310 }
312 v->arch.ctxt.gprs[3] = si->mod_start;
313 v->arch.ctxt.gprs[4] = si->mod_len;
315 memset(si->cmd_line, 0, sizeof(si->cmd_line));
316 if ( cmdline != NULL )
317 strncpy((char *)si->cmd_line, cmdline, sizeof(si->cmd_line)-1);
319 v->arch.ctxt.msr = msr;
320 v->arch.ctxt.pc = pc;
321 v->arch.ctxt.gprs[2] = r2;
323 printk("DOM: pc = 0x%lx, r2 = 0x%lx\n", pc, r2);
325 ofd_dom0_fixup(d, *ofh_tree + rma, si);
327 set_bit(_VCPUF_initialised, &v->vcpu_flags);
329 rc = 0;
331 /* DOM0 is permitted full I/O capabilities. */
332 rc |= iomem_permit_access(dom0, 0UL, ~0UL);
333 rc |= irqs_permit_access(dom0, 0, NR_IRQS-1);
335 BUG_ON(rc != 0);
337 return 0;
338 }