ia64/xen-unstable

view xen/arch/powerpc/ofd_fixup.c @ 10890:b786bfb058eb

[XEN] Hide compile-time information values behind a
functional interface, so that the values are contained
within a single object file.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Tue Aug 01 15:28:09 2006 +0100 (2006-08-01)
parents 050de6b53961
children 552d50b3abf2
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/sched.h>
24 #include <xen/version.h>
25 #include <public/xen.h>
26 #include "of-devtree.h"
28 #undef RTAS
30 #ifdef PAPR_VTERM
31 static ofdn_t ofd_vdevice_vty(void *m, ofdn_t p, struct domain *d)
32 {
33 ofdn_t n;
34 static const char pathfmt[] = "/vdevice/vty@%x";
35 static const char name[] = "vty";
36 static const char compatible[] = "hvterm1";
37 static const char device_type[] = "serial";
38 char path[sizeof (pathfmt) + 8 - 2];
39 int client = 0;
41 snprintf(path, sizeof (path), pathfmt, client);
42 n = ofd_node_add(m, p, path, sizeof (path));
44 if (n > 0) {
45 u32 val32;
47 val32 = client;
48 ofd_prop_add(m, n, "name", name, sizeof (name));
49 ofd_prop_add(m, n, "reg", &val32, sizeof (val32));
50 ofd_prop_add(m, n, "compatible",
51 compatible, sizeof (compatible));
52 ofd_prop_add(m, n, "device_type",
53 device_type, sizeof (device_type));
54 }
56 return n;
57 }
58 #endif
60 #ifdef PAPR_VDEVICE
61 static ofdn_t ofd_vdevice(void *m, struct domain *d)
62 {
63 ofdn_t n;
64 static const char path[] = "/vdevice";
65 static const char name[] = "vdevice";
66 static const char compatible[] = "IBM,vdevice";
67 u32 val;
69 n = ofd_node_add(m, OFD_ROOT, path, sizeof (path));
71 if (n > 0) {
73 ofd_prop_add(m, n, "name", name, sizeof (name));
74 val = 1;
75 ofd_prop_add(m, n, "#address-cells", &val, sizeof (val));
76 val = 0;
77 ofd_prop_add(m, n, "#size-cells", &val, sizeof (val));
78 ofd_prop_add(m, n, "compatible",
79 compatible, sizeof (compatible));
80 ofd_prop_add(m, n, "device_type", name, sizeof (name));
81 ofd_prop_add(m, n, "interupt-controller", NULL, 0);
83 #ifdef PAPR_VDEVICE
84 ofdn_t r;
86 /* add vty */
87 r = ofd_vdevice_vty(m, n, d);
88 printk("vdevice r: %x\n", r);
89 n = r;
90 #endif
91 }
92 return n;
93 }
94 #endif
96 static ofdn_t ofd_openprom_props(void *m)
97 {
98 static const char path[] = "/openprom";
99 static const char vernum[] = "IBM,XenOF0.1";
100 ofdn_t n;
102 n = ofd_node_find(m, path);
103 if (n == 0) {
104 n = ofd_node_add(m, OFD_ROOT, path, sizeof (path));
105 ofd_prop_add(m, n, "name",
106 &path[1], sizeof (path) - 1);
107 }
108 /* I want to override */
109 ofd_prop_add(m, n, "model", vernum, sizeof(vernum));
110 ofd_prop_add(m, n, "ibm,fw-vernum_encoded", vernum, sizeof(vernum));
111 ofd_prop_add(m, n, "relative-addressing", NULL, 0);
112 return n;
114 }
116 #ifdef PAPR_VTERM
117 static ofdn_t ofd_aliases_props(void *m)
118 {
119 static const char path[] = "/aliases";
120 static const char screen[] = "/vdevice/vty@0";
121 ofdn_t n;
123 n = ofd_node_find(m, path);
124 if (n == 0) {
125 n = ofd_node_add(m, OFD_ROOT, path, sizeof (path));
126 ofd_prop_add(m, n, "name",
127 &path[1], sizeof (path) - 1);
128 }
129 ofd_prop_add(m, n, "screen", screen, sizeof(screen));
130 return n;
131 }
132 #endif
134 static ofdn_t ofd_options_props(void *m)
135 {
136 static const char path[] = "/options";
137 static const char boot[] = "true";
138 ofdn_t n;
140 n = ofd_node_find(m, path);
141 if (n == 0) {
142 n = ofd_node_add(m, OFD_ROOT, path, sizeof (path));
143 ofd_prop_add(m, n, "name",
144 &path[1], sizeof (path) - 1);
145 }
146 ofd_prop_add(m, n, "auto-boot?", boot, sizeof(boot));
147 return n;
148 }
150 static ofdn_t ofd_cpus_props(void *m, struct domain *d)
151 {
152 static const char path[] = "/cpus";
153 static const char cpu[] = "cpu";
154 u32 val = 1;
155 ofdn_t n;
156 ofdn_t c;
157 static u32 ibm_pft_size[] = { 0x0, 0x0 };
159 n = ofd_node_find(m, path);
160 if (n == 0) {
161 n = ofd_node_add(m, OFD_ROOT, path, sizeof (path));
162 ofd_prop_add(m, n, "name",
163 &path[1], sizeof (path) - 1);
164 }
165 ofd_prop_add(m, n, "#address-cells", &val, sizeof(val));
166 ofd_prop_add(m, n, "#size-cells", &val, sizeof(val));
167 ofd_prop_add(m, n, "smp-enabled", NULL, 0);
169 #ifdef HV_EXPOSE_PERFORMANCE_MONITOR
170 ofd_prop_add(m, n, "performance-monitor", NULL, 0);
171 #endif
173 c = ofd_node_find_by_prop(m, n, "device_type", cpu, sizeof (cpu));
174 while (c > 0) {
175 ibm_pft_size[1] = d->arch.htab.log_num_ptes + LOG_PTE_SIZE;
176 ofd_prop_add(m, c, "ibm,pft-size",
177 ibm_pft_size, sizeof (ibm_pft_size));
179 /* FIXME: Check the the "l2-cache" property who's
180 * contents is an orphaned phandle? */
181 c = ofd_node_find_next(m, c);
183 /* Since we are not MP yet we can prune the rest of the CPUs */
184 while (c > 0) {
185 ofdn_t nc;
187 nc = ofd_node_find_next(m, c);
188 ofd_node_prune(m, c);
190 c = nc;
191 }
192 }
194 return n;
195 }
197 #ifdef ADD_XICS
198 static ofdn_t ofd_xics_props(void *m)
199 {
200 ofdn_t n;
201 static const char path[] = "/interrupt-controller";
202 static const char compat[] = "IBM,ppc-xicp";
203 static const char model[] = "IBM, BoaC, PowerPC-PIC, 00";
204 static const char dtype[] =
205 "PowerPC-External-Interrupt-Presentation";
206 /*
207 * I don't think these are used for anything but linux wants
208 * it. I seems to describe some per processor location for
209 * IPIs but that is a complete guess.
210 */
211 static const u32 reg[] = {
212 0x000003e0, 0x0f000000, 0x00000000, 0x00001000,
213 0x000003e0, 0x0f001000, 0x00000000, 0x00001000,
214 0x000003e0, 0x0f002000, 0x00000000, 0x00001000,
215 0x000003e0, 0x0f003000, 0x00000000, 0x00001000,
216 0x000003e0, 0x0f004000, 0x00000000, 0x00001000,
217 0x000003e0, 0x0f005000, 0x00000000, 0x00001000,
218 0x000003e0, 0x0f006000, 0x00000000, 0x00001000,
219 0x000003e0, 0x0f007000, 0x00000000, 0x00001000,
220 0x000003e0, 0x0f008000, 0x00000000, 0x00001000,
221 0x000003e0, 0x0f009000, 0x00000000, 0x00001000,
222 0x000003e0, 0x0f00a000, 0x00000000, 0x00001000,
223 0x000003e0, 0x0f00b000, 0x00000000, 0x00001000,
224 0x000003e0, 0x0f00c000, 0x00000000, 0x00001000,
225 0x000003e0, 0x0f00d000, 0x00000000, 0x00001000,
226 0x000003e0, 0x0f00e000, 0x00000000, 0x00001000,
227 0x000003e0, 0x0f00f000, 0x00000000, 0x00001000,
228 };
230 n = ofd_node_find(m, path);
231 if (n == 0) {
232 n = ofd_node_add(m, OFD_ROOT, path, sizeof (path));
233 ofd_prop_add(m, n, "name",
234 &path[1], sizeof (path) - 1);
235 }
236 ofd_prop_add(m, n, "built-in", NULL, 0);
237 ofd_prop_add(m, n, "compatible", compat, sizeof(compat));
238 ofd_prop_add(m, n, "device_type", dtype, sizeof(dtype));
239 ofd_prop_add(m, n, "model", model, sizeof(model));
240 ofd_prop_add(m, n, "reg", reg, sizeof(reg));
242 return n;
243 }
244 #endif
246 /*
247 * Good things you can stick here:
248 * init=/bin/bash ip=dhcp root=/dev/hda2 ide=nodma
249 */
250 static char default_bootargs[] = "";
252 static ofdn_t ofd_chosen_props(void *m, const char *cmdline)
253 {
254 ofdn_t n;
255 ofdn_t p;
256 static const char path[] = "/chosen";
257 char bootargs[256];
258 int bsz;
259 int sz;
260 int rm;
262 n = ofd_node_find(m, path);
263 if (n == 0) {
264 n = ofd_node_add(m, OFD_ROOT, path, sizeof (path));
265 ofd_prop_add(m, n, "name",
266 &path[1], sizeof (path) - 1);
267 }
269 strcpy(bootargs, cmdline);
270 bsz = strlen(bootargs) + 1;
271 rm = sizeof (bootargs) - bsz;
273 if (default_bootargs != NULL) {
274 sz = strlen(default_bootargs);
275 if (sz > rm) {
276 panic("default_bootargs is too big: 0x%x > 0x%x\n",
277 sz, rm);
278 } else if (sz > 0) {
279 memcpy(&bootargs[bsz - 1], default_bootargs, sz + 1);
280 bsz += sz;
281 rm -= sz;
282 }
283 }
285 printk("DOM0 bootargs: %s\n", bootargs);
286 ofd_prop_add(m, n, "bootargs", bootargs, bsz);
288 ofd_prop_add(m, n, "bootpath", NULL, 0);
290 printk("Remove /chosen/mmu, stub will replace\n");
291 p = ofd_prop_find(m, n, "mmu");
292 if (p > 0) {
293 ofd_prop_remove(m, n, p);
294 }
296 return n;
297 }
299 #ifdef RTAS
300 static ofdn_t ofd_rtas_props(void *m)
301 {
302 static const char path[] = "/rtas";
303 static const char hypertas[] = "dummy";
304 ofdn_t p;
305 ofdn_t n;
307 /* just enough to make linux think its on LPAR */
309 p = ofd_node_find(m, "/");
311 n = ofd_node_add(m, p, path, sizeof(path));
312 ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1);
313 ofd_prop_add(m, n, "ibm,hypertas-functions", hypertas, sizeof (hypertas));
315 return n;
316 }
317 #endif
319 struct mem_reg {
320 u64 addr;
321 u64 sz;
322 };
324 static ofdn_t ofd_memory_chunk_create(void *m, ofdn_t p,
325 const char *ppath,
326 const char *name,
327 const char *dt,
328 ulong start, ulong size)
329 {
330 struct mem_reg reg;
331 char path[128];
332 ulong l;
333 u32 v;
334 ofdn_t n;
335 ulong nl = strlen(name) + 1;
336 ulong dtl = strlen(dt) + 1;
338 l = snprintf(path, sizeof (path), "%s/%s@%lx", ppath, name, start);
339 n = ofd_node_add(m, p, path, l + 1);
340 ofd_prop_add(m, n, "name", name, nl);
342 v = 1;
343 ofd_prop_add(m, n, "#address-cells", &v, sizeof (v));
344 v = 0;
345 ofd_prop_add(m, n, "#size-cells", &v, sizeof (v));
347 ofd_prop_add(m, n, "device_type", dt, dtl);
349 /* physical addresses usable without regard to OF */
350 reg.addr = start;
351 reg.sz = size;
352 ofd_prop_add(m, n, "reg", &reg, sizeof (reg));
354 return n;
355 }
357 static ofdn_t ofd_memory_props(void *m, struct domain *d, ulong eoload)
358 {
359 ofdn_t n = -1;
360 ulong start = 0;
361 static char name[] = "memory";
362 ulong mem_size = d->arch.rma_size;
363 ulong chunk_size = d->arch.rma_size;
365 /* Remove all old memory props */
366 do {
367 ofdn_t old;
369 old = ofd_node_find_by_prop(m, OFD_ROOT, "device_type",
370 name, sizeof(name));
371 if (old <= 0) break;
373 ofd_node_prune(m, old);
374 } while (1);
376 while (start < mem_size) {
377 ulong size = (mem_size < chunk_size) ? mem_size : chunk_size;
379 n = ofd_memory_chunk_create(m, OFD_ROOT, "", "memory", "memory",
380 start, size);
382 if (start == 0) {
383 /* We are processing the first and RMA chunk */
385 /* free list of physical addresses available after OF and
386 * client program have been accounted for */
387 struct mem_reg avail[] = {
388 /* 0 til OF @ 32MiB - 16KiB stack */
389 { .addr = 0, .sz = ((32 << 20) - (16 << 10)) },
390 /* end of loaded material to the end the chunk - 1 page */
391 { .addr = eoload, .sz = chunk_size - eoload - PAGE_SIZE },
392 /* the last page is reserved for xen_start_info */
393 };
394 ofd_prop_add(m, n, "available", &avail,
395 sizeof (avail));
396 }
398 start += size;
399 mem_size -= size;
400 }
401 return n;
402 }
404 static ofdn_t ofd_xen_props(void *m, struct domain *d, start_info_t *si)
405 {
406 ofdn_t n;
407 static const char path[] = "/xen";
408 static const char console[] = "/xen/console";
410 n = ofd_node_add(m, OFD_ROOT, path, sizeof (path));
411 if (n > 0) {
412 char xen[256];
413 int xl;
414 u64 val[2];
415 s32 dom_id;
417 dom_id = d->domain_id;
419 ofd_prop_add(m, n, "reg", &dom_id, sizeof (dom_id));
420 ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1);
422 xl = snprintf(xen, sizeof (xen), "Xen-%d.%d%s",
423 xen_major_version(), xen_minor_version(), xen_extra_version());
424 ASSERT(xl < sizeof (xen));
425 ofd_prop_add(m, n, "version", xen, xl + 1);
427 val[0] = (ulong)si - d->arch.rma_base;
428 val[1] = PAGE_SIZE;
429 ofd_prop_add(m, n, "start-info", val, sizeof (val));
431 val[1] = RMA_LAST_DOM0 * PAGE_SIZE;
432 val[0] = d->arch.rma_size - val[1];
433 ofd_prop_add(m, n, "reserved", val, sizeof (val));
435 n = ofd_node_add(m, n, console, sizeof (console));
436 if (n > 0) {
437 val[0] = 0;
438 ofd_prop_add(m, n, "interrupts", &val[0], sizeof (val[0]));
439 }
440 }
441 return n;
442 }
443 extern int ofd_dom0_fixup(
444 struct domain *d, ulong oftree, start_info_t *si, ulong dst);
445 int ofd_dom0_fixup(struct domain *d, ulong mem, start_info_t *si, ulong eoload)
446 {
447 void *m;
448 const ofdn_t n = OFD_ROOT;
449 ofdn_t r;
451 m = (void *)mem;
453 #ifdef PAPR_VDEVICE
454 printk("Add /vdevice\n");
455 ofd_vdevice(m, d);
457 printk("Add /aliases props\n");
458 ofd_aliases_props(m);
459 #endif
461 printk("Add /openprom props\n");
462 ofd_openprom_props(m);
464 printk("Add /options props\n");
465 ofd_options_props(m);
467 printk("Add /cpus props\n");
468 ofd_cpus_props(m, d);
470 printk("Add /chosen props\n");
471 ofd_chosen_props(m, (char *)si->cmd_line);
473 printk("fix /memory@0 props\n");
474 ofd_memory_props(m, d, eoload);
476 printk("fix /xen props\n");
477 ofd_xen_props(m, d, si);
479 printk("Remove original /dart\n");
480 ofd_prune_path(m, "/dart");
482 printk("Remove original /rtas\n");
483 ofd_prune_path(m, "/rtas");
485 #ifdef RTAS
486 printk("Create a new RTAS with just enough stuff to convince "
487 "Linux that its on LPAR\n");
488 ofd_rtas_props(m);
489 #endif
490 #ifdef FIX_COMPAT
491 const char compat[] = "Hypervisor,Maple";
492 r = ofd_prop_add(m, n, "compatible", compat, sizeof (compat));
493 ASSERT( r > 0 );
494 #endif
496 u32 did = d->domain_id;
497 r = ofd_prop_add(m, n, "ibm,partition-no", &did, sizeof(did));
498 ASSERT( r > 0 );
500 const char dom0[] = "dom0";
501 r = ofd_prop_add(m, n, "ibm,partition-name", dom0, sizeof (dom0));
502 ASSERT( r > 0 );
505 #ifdef DEBUG
506 ofd_walk(m, OFD_ROOT, ofd_dump_props, OFD_DUMP_ALL);
507 #endif
508 return 1;
509 }