ia64/xen-unstable

view xen/arch/powerpc/domain_build.c @ 14239:b75609e1fa81

[POWERPC][XEN] Implement guest_physmap_{add,remove}_page().
- Use p2m array in pfn2mfn() and DOMCTL_getmemlist.
- Remove domain extent list.
- Create and use an m2p array for mfn_to_gmfn().
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 Fri Mar 02 17:07:59 2007 -0600 (2007-03-02)
parents 07066db94d89
children f3f5f2756d75
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 IBM Corp. 2005, 2007
17 *
18 * Authors: Jimi Xenidis <jimix@watson.ibm.com>
19 * Ryan Harper <ryanh@us.ibm.com>
20 * Hollis Blanchard <hollisb@us.ibm.com>
21 */
23 #include <xen/config.h>
24 #include <xen/lib.h>
25 #include <xen/sched.h>
26 #include <xen/init.h>
27 #include <xen/ctype.h>
28 #include <xen/iocap.h>
29 #include <xen/shadow.h>
30 #include <xen/domain.h>
31 #include <xen/version.h>
32 #include <xen/shadow.h>
33 #include <asm/processor.h>
34 #include <asm/platform.h>
35 #include <asm/papr.h>
36 #include <public/arch-powerpc.h>
37 #include <public/libelf.h>
38 #include "oftree.h"
40 /* opt_dom0_mem: memory allocated to domain 0. */
41 static unsigned int dom0_nrpages;
42 static void parse_dom0_mem(char *s)
43 {
44 unsigned long long bytes;
46 bytes = parse_size_and_unit(s, NULL);
47 dom0_nrpages = bytes >> PAGE_SHIFT;
48 }
49 custom_param("dom0_mem", parse_dom0_mem);
51 static unsigned int opt_dom0_max_vcpus;
52 integer_param("dom0_max_vcpus", opt_dom0_max_vcpus);
54 static unsigned int opt_dom0_shadow;
55 boolean_param("dom0_shadow", opt_dom0_shadow);
57 /* adapted from common/elf.c */
58 #define RM_MASK(a,l) ((a) & ((1UL << (l)) - 1))
60 int construct_dom0(struct domain *d,
61 unsigned long image_start, unsigned long image_len,
62 unsigned long initrd_start, unsigned long initrd_len,
63 char *cmdline)
64 {
65 struct elf_binary elf;
66 struct elf_dom_parms parms;
67 int rc;
68 struct vcpu *v;
69 ulong dst;
70 u64 *ofh_tree;
71 uint rma_nrpages = 1 << cpu_default_rma_order_pages();
72 ulong rma_sz;
73 ulong rma;
74 ulong eomem;
75 int preempt = 0;
76 int vcpu;
77 ulong mod_start = 0;
78 ulong mod_len = 0;
79 ulong shared_info_addr;
80 uint extent_size = 1 << cpu_extent_order();
82 /* Sanity! */
83 BUG_ON(d->domain_id != 0);
85 if (image_len == 0)
86 panic("No Dom0 image supplied\n");
88 printk("*** LOADING DOMAIN 0 ***\n");
90 rc = elf_init(&elf, (void *)image_start, image_len);
91 if (rc)
92 return rc;
93 #ifdef VERBOSE
94 elf_set_verbose(&elf);
95 #endif
96 elf_parse_binary(&elf);
97 if (0 != (elf_xen_parse(&elf, &parms)))
98 return rc;
100 printk("Dom0 kernel: %s, paddr 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
101 elf_64bit(&elf) ? "64-bit" : "32-bit",
102 elf.pstart, elf.pend);
104 /* elf contains virtual addresses that can have the upper bits
105 * masked while running in real mode, so we do the masking as well
106 * as well */
107 parms.virt_kend = RM_MASK(parms.virt_kend, 42);
108 parms.virt_entry = RM_MASK(parms.virt_entry, 42);
110 /* default is the max(1/16th of memory, CONFIG_MIN_DOM0_PAGES) */
111 if (dom0_nrpages == 0) {
112 dom0_nrpages = total_pages >> 4;
114 if (dom0_nrpages < CONFIG_MIN_DOM0_PAGES)
115 dom0_nrpages = CONFIG_MIN_DOM0_PAGES;
116 }
118 /* Dom0 has to be at least RMA size. */
119 if (dom0_nrpages < rma_nrpages) {
120 dom0_nrpages = rma_nrpages;
121 printk("Increasing DOM0 memory size to %u MiB for RMA.\n",
122 ((rma_nrpages << PAGE_SHIFT) >> 20));
123 }
125 /* Ensure Dom0 is cpu_extent_order aligned. Round up if
126 not and let user know we did so. */
127 if (dom0_nrpages != ALIGN_UP(dom0_nrpages, extent_size)) {
128 dom0_nrpages = ALIGN_UP(dom0_nrpages, extent_size);
129 printk("Increasing DOM0 memory size to %u MiB for large pages.\n",
130 ((dom0_nrpages << PAGE_SHIFT) >> 20));
131 }
133 /* XXX Dom0 currently can't extend past the IO hole. */
134 if (dom0_nrpages > (platform_iohole_base() >> PAGE_SHIFT)) {
135 dom0_nrpages = (platform_iohole_base() >> PAGE_SHIFT);
136 printk("Limiting DOM0 memory size to %u MiB to avoid IO hole.\n",
137 ((dom0_nrpages << PAGE_SHIFT) >> 20));
138 }
140 /* Set Dom0 max mem, triggering p2m table creation. */
141 if ((guest_physmap_max_mem_pages(d, dom0_nrpages)) != 0)
142 panic("Failed to set DOM0 max mem pages value\n");
144 d->max_pages = dom0_nrpages;
145 if (0 > allocate_rma(d, cpu_default_rma_order_pages()))
146 panic("Error allocating domain 0 RMA\n");
148 rma_sz = rma_size(d->arch.rma_order);
149 rma = page_to_maddr(d->arch.rma_page);
151 /* If we are bigger than RMA, allocate extents. */
152 if (dom0_nrpages > rma_nrpages)
153 dom0_nrpages = allocate_extents(d, dom0_nrpages, rma_nrpages);
155 ASSERT(d->tot_pages == dom0_nrpages);
156 ASSERT(d->tot_pages >= rma_nrpages);
158 if (opt_dom0_shadow == 0) {
159 /* 1/64 of memory */
160 opt_dom0_shadow = (d->tot_pages >> 6) >> (20 - PAGE_SHIFT);
161 }
163 do {
164 shadow_set_allocation(d, opt_dom0_shadow, &preempt);
165 } while (preempt);
166 if (shadow_get_allocation(d) == 0)
167 panic("shadow allocation failed: %dMib\n", opt_dom0_shadow);
169 ASSERT( image_len < rma_sz );
171 eomem = ((ulong)d->shared_info) - rma;
172 printk("shared_info: 0x%lx,%p\n", eomem, d->shared_info);
174 /* startup secondary processors */
175 if ( opt_dom0_max_vcpus == 0 )
176 opt_dom0_max_vcpus = num_online_cpus();
177 if ( opt_dom0_max_vcpus > num_online_cpus() )
178 opt_dom0_max_vcpus = num_online_cpus();
179 if ( opt_dom0_max_vcpus > MAX_VIRT_CPUS )
180 opt_dom0_max_vcpus = MAX_VIRT_CPUS;
181 #ifdef BITS_PER_GUEST_LONG
182 if ( opt_dom0_max_vcpus > BITS_PER_GUEST_LONG(d) )
183 opt_dom0_max_vcpus = BITS_PER_GUEST_LONG(d);
184 #endif
185 printk("Dom0 has maximum %u VCPUs\n", opt_dom0_max_vcpus);
187 for (vcpu = 0; vcpu < opt_dom0_max_vcpus; vcpu++) {
188 if (NULL == alloc_vcpu(dom0, vcpu, vcpu))
189 panic("Error creating domain 0 vcpu %d\n", vcpu);
190 /* for now we pin Dom0 VCPUs to their coresponding CPUs */
191 if (cpu_isset(vcpu, cpu_online_map))
192 dom0->vcpu[vcpu]->cpu_affinity = cpumask_of_cpu(vcpu);
193 }
195 /* Init VCPU0. */
196 v = d->vcpu[0];
197 cpu_init_vcpu(v);
199 /* OF usually sits here:
200 * - Linux needs it to be loaded before the vmlinux or initrd
201 * - AIX demands it to be @ 32M.
202 */
203 dst = (32 << 20);
205 /* Put stack below everything. */
206 v->arch.ctxt.gprs[1] = dst - STACK_FRAME_OVERHEAD;
208 /* copy relative to Xen */
209 dst += rma;
211 ASSERT((dst - rma) + (ulong)firmware_image_size < eomem);
212 printk("loading OFH: 0x%lx, RMA: 0x%lx\n", dst, dst - rma);
213 memcpy((void *)dst, firmware_image_start, (ulong)firmware_image_size);
215 v->arch.ctxt.gprs[5] = (dst - rma);
216 ofh_tree = (u64 *)(dst + 0x10);
217 ASSERT(*ofh_tree == 0xdeadbeef00000000);
219 /* accomodate for a modest bss section */
220 dst = ALIGN_UP(dst + (ulong)firmware_image_size + PAGE_SIZE, PAGE_SIZE);
221 ASSERT((dst - rma) + oftree_len < eomem);
223 *ofh_tree = dst - rma;
224 printk("loading OFD: 0x%lx RMA: 0x%lx, 0x%lx\n", dst, dst - rma,
225 oftree_len);
226 memcpy((void *)dst, (void *)oftree, oftree_len);
227 dst = ALIGN_UP(dst + oftree_len, PAGE_SIZE);
229 /* Load the dom0 kernel. */
230 elf.dest = (void *)dst;
231 elf_load_binary(&elf);
232 v->arch.ctxt.pc = dst - rma;
233 dst = ALIGN_UP(dst + parms.virt_kend, PAGE_SIZE);
235 /* Load the initrd. */
236 if (initrd_len > 0) {
237 ASSERT((dst - rma) + image_len < eomem);
239 printk("loading initrd: 0x%lx, 0x%lx\n", dst, initrd_len);
240 memcpy((void *)dst, (void *)initrd_start, initrd_len);
242 mod_start = dst - rma;
243 mod_len = image_len;
245 dst = ALIGN_UP(dst + initrd_len, PAGE_SIZE);
246 } else {
247 printk("no initrd\n");
248 }
250 if (elf_64bit(&elf)) {
251 v->arch.ctxt.msr = MSR_SF;
252 } else {
253 v->arch.ctxt.msr = 0;
254 }
255 v->arch.ctxt.gprs[2] = 0;
256 v->arch.ctxt.gprs[3] = mod_start;
257 v->arch.ctxt.gprs[4] = mod_len;
259 printk("dom0 initial register state:\n"
260 " pc %016lx msr %016lx\n"
261 " r1 %016lx r2 %016lx r3 %016lx\n"
262 " r4 %016lx r5 %016lx\n",
263 v->arch.ctxt.pc,
264 v->arch.ctxt.msr,
265 v->arch.ctxt.gprs[1],
266 v->arch.ctxt.gprs[2],
267 v->arch.ctxt.gprs[3],
268 v->arch.ctxt.gprs[4],
269 v->arch.ctxt.gprs[5]);
271 /* convert xen pointer shared_info into guest physical */
272 shared_info_addr = (ulong)d->shared_info - page_to_maddr(d->arch.rma_page);
274 ofd_dom0_fixup(d, *ofh_tree + rma, cmdline, shared_info_addr);
276 set_bit(_VCPUF_initialised, &v->vcpu_flags);
278 rc = 0;
280 /* DOM0 is permitted full I/O capabilities. */
281 rc |= iomem_permit_access(dom0, 0UL, ~0UL);
282 rc |= irqs_permit_access(dom0, 0, NR_IRQS-1);
284 BUG_ON(rc != 0);
286 return 0;
287 }