direct-io.hg

view xen/arch/powerpc/boot_of.c @ 11526:ce9c34c049c5

[POWERPC][XEN] Track the Hard CPUID as configured by the FW

This patch correctly implements and supports hard_smp_processor_id().

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 Sep 18 09:23:51 2006 -0400 (2006-09-18)
parents 4fdf5151b187
children 776efe262006
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, 2006
17 *
18 * Authors: Jimi Xenidis <jimix@watson.ibm.com>
19 */
21 #include <xen/config.h>
22 #include <xen/init.h>
23 #include <xen/lib.h>
24 #include <xen/multiboot.h>
25 #include <xen/version.h>
26 #include <xen/spinlock.h>
27 #include <xen/serial.h>
28 #include <xen/time.h>
29 #include <xen/sched.h>
30 #include <asm/page.h>
31 #include <asm/io.h>
32 #include "exceptions.h"
33 #include "of-devtree.h"
34 #include "oftree.h"
36 /* Secondary processors use this for handshaking with main processor. */
37 volatile unsigned int __spin_ack;
39 static ulong of_vec;
40 static ulong of_msr;
41 static int of_out;
42 static char bootargs[256];
44 #define COMMAND_LINE_SIZE 512
45 static char builtin_cmdline[COMMAND_LINE_SIZE]
46 __attribute__((section("__builtin_cmdline"))) = CMDLINE;
48 extern struct ns16550_defaults ns16550;
50 #undef OF_DEBUG
52 #ifdef OF_DEBUG
53 #define DBG(args...) of_printf(args)
54 #else
55 #define DBG(args...)
56 #endif
58 #define of_panic(MSG...) \
59 do { of_printf(MSG); of_printf("\nHANG\n"); for (;;); } while (0)
61 struct of_service {
62 u32 ofs_service;
63 u32 ofs_nargs;
64 u32 ofs_nrets;
65 u32 ofs_args[10];
66 };
68 static int bof_chosen;
70 static struct of_service s;
71 extern s32 prom_call(void *arg, ulong rtas_base, ulong func, ulong msr);
73 static int __init of_call(
74 const char *service, u32 nargs, u32 nrets, s32 rets[], ...)
75 {
76 int rc;
78 if (of_vec != 0) {
79 va_list args;
80 int i;
82 memset(&s, 0, sizeof (s));
83 s.ofs_service = (ulong)service;
84 s.ofs_nargs = nargs;
85 s.ofs_nrets = nrets;
86 s.ofs_nargs = nargs;
88 /* copy all the params into the args array */
89 va_start(args, rets);
91 for (i = 0; i < nargs; i++) {
92 s.ofs_args[i] = va_arg(args, u32);
93 }
95 va_end(args);
97 rc = prom_call(&s, 0, of_vec, of_msr);
99 /* yes always to the copy, just in case */
100 for (i = 0; i < nrets; i++) {
101 rets[i] = s.ofs_args[i + nargs];
102 }
103 } else {
104 rc = OF_FAILURE;
105 }
106 return rc;
107 }
109 /* popular OF methods */
110 static int __init _of_write(int ih, const char *addr, u32 len)
111 {
112 int rets[1] = { OF_FAILURE };
113 if (of_call("write", 3, 1, rets, ih, addr, len) == OF_FAILURE) {
114 return OF_FAILURE;
115 }
116 return rets[0];
117 }
119 /* popular OF methods */
120 static int __init of_write(int ih, const char *addr, u32 len)
121 {
122 int rc;
123 int i = 0;
124 int sum = 0;
126 while (i < len) {
127 if (addr[i] == '\n') {
128 if (i > 0) {
129 rc = _of_write(ih, addr, i);
130 if (rc == OF_FAILURE)
131 return rc;
132 sum += rc;
133 }
134 rc = _of_write(ih, "\r\n", 2);
135 if (rc == OF_FAILURE)
136 return rc;
137 sum += rc;
138 i++;
139 addr += i;
140 len -= i;
141 i = 0;
142 continue;
143 }
144 i++;
145 }
146 if (len > 0) {
147 rc = _of_write(ih, addr, len);
148 if (rc == OF_FAILURE)
149 return rc;
150 sum += rc;
151 }
153 return sum;
154 }
156 static int of_printf(const char *fmt, ...)
157 __attribute__ ((format (printf, 1, 2)));
158 static int __init of_printf(const char *fmt, ...)
159 {
160 static char buf[1024];
161 va_list args;
162 int sz;
164 if (of_out == 0) {
165 return OF_FAILURE;
166 }
168 va_start(args, fmt);
170 sz = vsnprintf(buf, sizeof (buf), fmt, args);
171 if (sz <= sizeof (buf)) {
172 of_write(of_out, buf, sz);
173 } else {
174 static const char trunc[] = "\n(TRUNCATED)\n";
176 sz = sizeof (buf);
177 of_write(of_out, buf, sz);
178 of_write(of_out, trunc, sizeof (trunc));
179 }
180 return sz;
181 }
183 static int __init of_finddevice(const char *devspec)
184 {
185 int rets[1] = { OF_FAILURE };
187 of_call("finddevice", 1, 1, rets, devspec);
188 if (rets[0] == OF_FAILURE) {
189 DBG("finddevice %s -> FAILURE %d\n",devspec,rets[0]);
190 return OF_FAILURE;
191 }
192 DBG("finddevice %s -> %d\n",devspec, rets[0]);
193 return rets[0];
194 }
196 static int __init of_getprop(int ph, const char *name, void *buf, u32 buflen)
197 {
198 int rets[1] = { OF_FAILURE };
200 of_call("getprop", 4, 1, rets, ph, name, buf, buflen);
202 if (rets[0] == OF_FAILURE) {
203 DBG("getprop 0x%x %s -> FAILURE\n", ph, name);
204 return OF_FAILURE;
205 }
207 DBG("getprop 0x%x %s -> 0x%x (%s)\n", ph, name, rets[0], (char *)buf);
208 return rets[0];
209 }
211 static int __init of_setprop(
212 int ph, const char *name, const void *buf, u32 buflen)
213 {
214 int rets[1] = { OF_FAILURE };
216 of_call("setprop", 4, 1, rets, ph, name, buf, buflen);
218 if (rets[0] == OF_FAILURE) {
219 DBG("setprop 0x%x %s -> FAILURE\n", ph, name);
220 return OF_FAILURE;
221 }
223 DBG("setprop 0x%x %s -> %s\n", ph, name, (char *)buf);
224 return rets[0];
225 }
227 /*
228 * returns 0 if there are no children (of spec)
229 */
230 static int __init of_getchild(int ph)
231 {
232 int rets[1] = { OF_FAILURE };
234 of_call("child", 1, 1, rets, ph);
235 DBG("getchild 0x%x -> 0x%x\n", ph, rets[0]);
237 return rets[0];
238 }
240 /*
241 * returns 0 is there are no peers
242 */
243 static int __init of_getpeer(int ph)
244 {
245 int rets[1] = { OF_FAILURE };
247 of_call("peer", 1, 1, rets, ph);
248 DBG("getpeer 0x%x -> 0x%x\n", ph, rets[0]);
250 return rets[0];
251 }
253 static int __init of_getproplen(int ph, const char *name)
254 {
255 int rets[1] = { OF_FAILURE };
257 of_call("getproplen", 2, 1, rets, ph, name);
258 if (rets[0] == OF_FAILURE) {
259 DBG("getproplen 0x%x %s -> FAILURE\n", ph, name);
260 return OF_FAILURE;
261 }
262 DBG("getproplen 0x%x %s -> 0x%x\n", ph, name, rets[0]);
263 return rets[0];
264 }
266 static int __init of_package_to_path(int ph, char *buffer, u32 buflen)
267 {
268 int rets[1] = { OF_FAILURE };
270 of_call("package-to-path", 3, 1, rets, ph, buffer, buflen);
271 if (rets[0] == OF_FAILURE) {
272 DBG("%s 0x%x -> FAILURE\n", __func__, ph);
273 return OF_FAILURE;
274 }
275 DBG("%s 0x%x %s -> 0x%x\n", __func__, ph, buffer, rets[0]);
276 if (rets[0] <= buflen)
277 buffer[rets[0]] = '\0';
278 return rets[0];
279 }
281 static int __init of_nextprop(int ph, const char *name, void *buf)
282 {
283 int rets[1] = { OF_FAILURE };
285 of_call("nextprop", 3, 1, rets, ph, name, buf);
287 if (rets[0] == OF_FAILURE) {
288 DBG("nextprop 0x%x %s -> FAILURE\n", ph, name);
289 return OF_FAILURE;
290 }
292 DBG("nextprop 0x%x %s -> %s\n", ph, name, (char *)buf);
293 return rets[0];
294 }
296 static int __init of_instance_to_path(int ih, char *buffer, u32 buflen)
297 {
298 int rets[1] = { OF_FAILURE };
300 if (of_call("instance-to-path", 3, 1, rets, ih, buffer, buflen)
301 == OF_FAILURE)
302 return OF_FAILURE;
304 if (rets[0] <= buflen)
305 buffer[rets[0]] = '\0';
306 return rets[0];
307 }
309 static int __init of_start_cpu(int cpu, u32 pc, u32 reg)
310 {
311 int ret;
313 ret = of_call("start-cpu", 3, 0, NULL, cpu, pc, reg);
315 return ret;
316 }
318 static void __init of_test(const char *of_method_name)
319 {
320 int rets[1] = { OF_FAILURE };
322 of_call("test", 1, 1, rets, of_method_name);
323 if (rets[0] == OF_FAILURE ) {
324 of_printf("Warning: possibly no OF method %s.\n"
325 "(Ignore this warning on PIBS.)\n", of_method_name);
326 }
327 }
329 static int __init of_claim(u32 virt, u32 size, u32 align)
330 {
331 int rets[1] = { OF_FAILURE };
333 of_call("claim", 3, 1, rets, virt, size, align);
334 if (rets[0] == OF_FAILURE) {
335 DBG("%s 0x%08x 0x%08x 0x%08x -> FAIL\n", __func__, virt, size, align);
336 return OF_FAILURE;
337 }
339 DBG("%s 0x%08x 0x%08x 0x%08x -> 0x%08x\n", __func__, virt, size, align,
340 rets[0]);
341 return rets[0];
342 }
344 static int __init of_instance_to_package(int ih)
345 {
346 int rets[1] = { OF_FAILURE };
348 of_call("instance-to-package", 1, 1, rets, ih);
349 if (rets[0] == OF_FAILURE)
350 return OF_FAILURE;
352 return rets[0];
353 }
355 static int __init of_getparent(int ph)
356 {
357 int rets[1] = { OF_FAILURE };
359 of_call("parent", 1, 1, rets, ph);
361 DBG("getparent 0x%x -> 0x%x\n", ph, rets[0]);
362 return rets[0];
363 }
365 static void boot_of_probemem(multiboot_info_t *mbi)
366 {
367 int root;
368 int p;
369 u32 addr_cells = 1;
370 u32 size_cells = 1;
371 int rc;
372 int mcount = 0;
373 static memory_map_t mmap[16];
375 root = of_finddevice("/");
376 p = of_getchild(root);
378 /* code is writen to assume sizes of 1 */
379 of_getprop(root, "#address-cells", &addr_cells, sizeof (addr_cells));
380 of_getprop(root, "#size-cells", &size_cells, sizeof (size_cells));
381 DBG("%s: address_cells=%d size_cells=%d\n",
382 __func__, addr_cells, size_cells);
384 do {
385 const char memory[] = "memory";
386 char type[32];
388 type[0] = '\0';
390 of_getprop(p, "device_type", type, sizeof (type));
391 if (strncmp(type, memory, sizeof (memory)) == 0) {
392 u32 reg[48];
393 u32 al, ah, ll, lh;
394 int r;
396 rc = of_getprop(p, "reg", reg, sizeof (reg));
397 if (rc == OF_FAILURE) {
398 of_panic("no reg property for memory node: 0x%x.\n", p);
399 }
400 int l = rc/sizeof(u32); /* number reg element */
401 DBG("%s: number of bytes in property 'reg' %d\n",
402 __func__, rc);
404 r = 0;
405 while (r < l) {
406 al = ah = ll = lh = 0;
407 if (addr_cells == 2) {
408 ah = reg[r++];
409 if (r >= l)
410 break; /* partial line. Skip */
411 al = reg[r++];
412 if (r >= l)
413 break; /* partial line. Skip */
414 } else {
415 al = reg[r++];
416 if (r >= l)
417 break; /* partial line. Skip */
418 }
419 if (size_cells == 2) {
420 lh = reg[r++];
421 if (r >= l)
422 break; /* partial line. Skip */
423 ll = reg[r++];
424 } else {
425 ll = reg[r++];
426 }
428 if ((ll != 0) || (lh != 0)) {
429 mmap[mcount].size = 20; /* - size field */
430 mmap[mcount].type = 1; /* Regular ram */
431 mmap[mcount].length_high = lh;
432 mmap[mcount].length_low = ll;
433 mmap[mcount].base_addr_high = ah;
434 mmap[mcount].base_addr_low = al;
435 of_printf("%s: memory 0x%016lx[0x%08lx]\n",
436 __func__,
437 (u64)(((u64)mmap[mcount].base_addr_high << 32)
438 | mmap[mcount].base_addr_low),
439 (u64)(((u64)mmap[mcount].length_high << 32)
440 | mmap[mcount].length_low));
441 ++mcount;
442 }
443 }
444 }
445 p = of_getpeer(p);
446 } while (p != OF_FAILURE && p != 0);
448 if (mcount > 0) {
449 mbi->flags |= MBI_MEMMAP;
450 mbi->mmap_length = sizeof (mmap[0]) * mcount;
451 mbi->mmap_addr = (ulong)mmap;
452 }
453 }
455 static void boot_of_bootargs(multiboot_info_t *mbi)
456 {
457 int rc;
459 rc = of_getprop(bof_chosen, "bootargs", &bootargs, sizeof (bootargs));
460 if (rc == OF_FAILURE || bootargs[0] == '\0') {
461 strlcpy(bootargs, builtin_cmdline, sizeof(bootargs));
462 }
464 mbi->flags |= MBI_CMDLINE;
465 mbi->cmdline = (u32)bootargs;
467 of_printf("bootargs = %s\n", bootargs);
468 }
470 static int save_props(void *m, ofdn_t n, int pkg)
471 {
472 int ret;
473 char name[128];
474 int result = 1;
475 int found_name = 0;
476 int found_device_type = 0;
477 const char name_str[] = "name";
478 const char devtype_str[] = "device_type";
480 /* get first */
481 result = of_nextprop(pkg, 0, name);
483 while (result > 0) {
484 int sz;
485 u64 obj[1024];
487 sz = of_getproplen(pkg, name);
488 if (sz >= 0) {
489 ret = OF_SUCCESS;
490 } else {
491 ret = OF_FAILURE;
492 }
494 if (ret == OF_SUCCESS) {
495 int actual = 0;
496 ofdn_t pos;
498 if (sz > 0) {
499 if (sz > sizeof (obj)) {
500 of_panic("obj array not big enough for 0x%x\n", sz);
501 }
502 actual = of_getprop(pkg, name, obj, sz);
503 if (actual > sz) of_panic("obj too small");
504 }
506 if (strncmp(name, name_str, sizeof(name_str)) == 0) {
507 found_name = 1;
508 }
510 if (strncmp(name, devtype_str, sizeof(devtype_str)) == 0) {
511 found_device_type = 1;
512 }
514 pos = ofd_prop_add(m, n, name, obj, actual);
515 if (pos == 0) of_panic("prop_create");
516 }
518 result = of_nextprop(pkg, name, name);
519 }
521 return 1;
522 }
525 static void do_pkg(void *m, ofdn_t n, int p, char *path, size_t psz)
526 {
527 int pnext;
528 ofdn_t nnext;
529 int sz;
531 retry:
532 save_props(m, n, p);
534 /* do children first */
535 pnext = of_getchild(p);
537 if (pnext != 0) {
538 sz = of_package_to_path(pnext, path, psz);
539 if (sz == OF_FAILURE) of_panic("bad path\n");
541 nnext = ofd_node_child_create(m, n, path, sz);
542 if (nnext == 0) of_panic("out of mem\n");
544 do_pkg(m, nnext, pnext, path, psz);
545 }
547 /* do peer */
548 pnext = of_getpeer(p);
550 if (pnext != 0) {
551 sz = of_package_to_path(pnext, path, psz);
553 nnext = ofd_node_peer_create(m, n, path, sz);
554 if (nnext <= 0) of_panic("out of space in OFD tree.\n");
556 n = nnext;
557 p = pnext;
558 goto retry;
559 }
560 }
562 static int pkg_save(void *mem)
563 {
564 int root;
565 char path[256];
566 int r;
568 path[0]='/';
569 path[1]='\0';
571 /* get root */
572 root = of_getpeer(0);
573 if (root == OF_FAILURE) of_panic("no root package\n");
575 do_pkg(mem, OFD_ROOT, root, path, sizeof(path));
577 r = (((ofdn_t *)mem)[1] + 1) * sizeof (u64);
579 of_printf("%s: saved device tree in 0x%x bytes\n", __func__, r);
581 return r;
582 }
584 static int boot_of_fixup_refs(void *mem)
585 {
586 static const char *fixup_props[] = {
587 "interrupt-parent",
588 };
589 int i;
590 int count = 0;
592 for (i = 0; i < ARRAY_SIZE(fixup_props); i++) {
593 ofdn_t c;
594 const char *name = fixup_props[i];
596 c = ofd_node_find_by_prop(mem, OFD_ROOT, name, NULL, 0);
597 while (c > 0) {
598 const char *path;
599 int rp;
600 int ref;
601 ofdn_t dp;
602 int rc;
603 ofdn_t upd;
604 char ofpath[256];
606 path = ofd_node_path(mem, c);
607 if (path == NULL) of_panic("no path to found prop: %s\n", name);
609 rp = of_finddevice(path);
610 if (rp == OF_FAILURE)
611 of_panic("no real device for: name %s, path %s\n",
612 name, path);
613 /* Note: In theory 0 is a valid node handle but it is highly
614 * unlikely.
615 */
616 if (rp == 0) {
617 of_panic("%s: of_finddevice returns 0 for path %s\n",
618 __func__, path);
619 }
621 rc = of_getprop(rp, name, &ref, sizeof(ref));
622 if ((rc == OF_FAILURE) || (rc == 0))
623 of_panic("no prop: name %s, path %s, device 0x%x\n",
624 name, path, rp);
626 rc = of_package_to_path(ref, ofpath, sizeof (ofpath));
627 if (rc == OF_FAILURE)
628 of_panic("no package: name %s, path %s, device 0x%x,\n"
629 "ref 0x%x\n", name, path, rp, ref);
631 dp = ofd_node_find(mem, ofpath);
632 if (dp <= 0) of_panic("no ofd node for OF node[0x%x]: %s\n",
633 ref, ofpath);
635 ref = dp;
637 upd = ofd_prop_add(mem, c, name, &ref, sizeof(ref));
638 if (upd <= 0) of_panic("update failed: %s\n", name);
640 #ifdef DEBUG
641 of_printf("%s: %s/%s -> %s\n", __func__,
642 path, name, ofpath);
643 #endif
644 ++count;
645 c = ofd_node_find_next(mem, c);
646 }
647 }
648 return count;
649 }
651 static int boot_of_fixup_chosen(void *mem)
652 {
653 int ch;
654 ofdn_t dn;
655 ofdn_t dc;
656 int val;
657 int rc;
658 char ofpath[256];
660 ch = of_finddevice("/chosen");
661 if (ch == OF_FAILURE) of_panic("/chosen not found\n");
663 rc = of_getprop(ch, "cpu", &val, sizeof (val));
665 if (rc != OF_FAILURE) {
666 rc = of_instance_to_path(val, ofpath, sizeof (ofpath));
668 if (rc > 0) {
669 dn = ofd_node_find(mem, ofpath);
670 if (dn <= 0) of_panic("no node for: %s\n", ofpath);
672 ofd_boot_cpu = dn;
673 val = dn;
675 dn = ofd_node_find(mem, "/chosen");
676 if (dn <= 0) of_panic("no /chosen node\n");
678 dc = ofd_prop_add(mem, dn, "cpu", &val, sizeof (val));
679 if (dc <= 0) of_panic("could not fix /chosen/cpu\n");
680 rc = 1;
681 } else {
682 of_printf("*** can't find path to booting cpu, "
683 "SMP is disabled\n");
684 ofd_boot_cpu = -1;
685 }
686 }
687 return rc;
688 }
690 static ulong space_base;
692 /*
693 * The following function is necessary because we cannot depend on all
694 * FW to actually allocate us any space, so we look for it _hoping_
695 * that at least is will fail if we try to claim something that
696 * belongs to FW. This hope does not seem to be true on some version
697 * of PIBS.
698 */
699 static ulong find_space(u32 size, u32 align, multiboot_info_t *mbi)
700 {
701 memory_map_t *map = (memory_map_t *)((ulong)mbi->mmap_addr);
702 ulong eomem = ((u64)map->length_high << 32) | (u64)map->length_low;
703 ulong base;
705 if (size == 0)
706 return 0;
708 if (align == 0)
709 of_panic("cannot call %s() with align of 0\n", __func__);
711 #ifdef BROKEN_CLAIM_WORKAROUND
712 {
713 static int broken_claim;
714 if (!broken_claim) {
715 /* just try and claim it to the FW chosen address */
716 base = of_claim(0, size, align);
717 if (base != OF_FAILURE)
718 return base;
719 of_printf("%s: Firmware does not allocate memory for you\n",
720 __func__);
721 broken_claim = 1;
722 }
723 }
724 #endif
726 of_printf("%s base=0x%016lx eomem=0x%016lx size=0x%08x align=0x%x\n",
727 __func__, space_base, eomem, size, align);
728 base = ALIGN_UP(space_base, PAGE_SIZE);
730 while ((base + size) < rma_size(cpu_default_rma_order_pages())) {
731 if (of_claim(base, size, 0) != OF_FAILURE) {
732 space_base = base + size;
733 return base;
734 }
735 base += (PAGE_SIZE > align) ? PAGE_SIZE : align;
736 }
737 of_panic("Cannot find memory in the RMA\n");
738 }
740 /* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges
741 * property. The values are bad, and it doesn't even have the
742 * right number of cells. */
744 static void __init boot_of_fix_maple(void)
745 {
746 int isa;
747 const char *ranges = "ranges";
748 u32 isa_ranges[3];
749 const u32 isa_test[] = { 0x00000001, 0xf4000000, 0x00010000 };
750 const u32 isa_fixed[] = {
751 0x00000001,
752 0x00000000,
753 0x00000000, /* 0xf4000000, matt says this */
754 0x00000000,
755 0x00000000,
756 0x00010000
757 };
759 isa = of_finddevice("/ht@0/isa@4");
760 if (isa != OF_FAILURE) {
761 if (of_getproplen(isa, ranges) == sizeof (isa_test)) {
762 of_getprop(isa, ranges, isa_ranges, sizeof (isa_ranges));
763 if (memcmp(isa_ranges, isa_test, sizeof (isa_test)) == 0) {
764 int rc;
766 of_printf("OF: fixing bogus ISA range on maple\n");
767 rc = of_setprop(isa, ranges, isa_fixed, sizeof (isa_fixed));
768 if (rc == OF_FAILURE) {
769 of_panic("of_setprop() failed\n");
770 }
771 }
772 }
773 }
774 }
776 static int __init boot_of_serial(void *oft)
777 {
778 int n;
779 int p;
780 int rc;
781 u32 val[3];
782 char buf[128];
784 n = of_instance_to_package(of_out);
785 if (n == OF_FAILURE) {
786 of_panic("instance-to-package of /chosen/stdout: failed\n");
787 }
789 /* Prune all serial devices from the device tree, including the
790 * one pointed to by /chosen/stdout, because a guest domain can
791 * initialize them and in so doing corrupt our console output.
792 */
793 for (p = n; p > 0; p = of_getpeer(p)) {
794 char type[32];
796 rc = of_package_to_path(p, buf, sizeof(buf));
797 if (rc == OF_FAILURE)
798 of_panic("package-to-path failed\n");
800 rc = of_getprop(p, "device_type", type, sizeof (type));
801 if (rc == OF_FAILURE)
802 of_panic("fetching device type failed\n");
804 if (strcmp(type, "serial") != 0)
805 continue;
807 of_printf("pruning `%s' from devtree\n", buf);
808 rc = ofd_prune_path(oft, buf);
809 if (rc < 0)
810 of_panic("prune of `%s' failed\n", buf);
811 }
813 p = of_getparent(n);
814 if (p == OF_FAILURE) {
815 of_panic("no parent for: 0x%x\n", n);
816 }
818 buf[0] = '\0';
819 of_getprop(p, "device_type", buf, sizeof (buf));
820 if (strstr(buf, "isa") == NULL) {
821 of_panic("only ISA UARTS supported\n");
822 }
824 /* should get this from devtree */
825 isa_io_base = 0xf4000000;
826 of_printf("%s: ISA base: 0x%lx\n", __func__, isa_io_base);
828 buf[0] = '\0';
829 of_getprop(n, "device_type", buf, sizeof (buf));
830 if (strstr(buf, "serial") == NULL) {
831 of_panic("only UARTS supported\n");
832 }
834 rc = of_getprop(n, "reg", val, sizeof (val));
835 if (rc == OF_FAILURE) {
836 of_panic("%s: no location for serial port\n", __func__);
837 }
839 ns16550.baud = BAUD_AUTO;
840 ns16550.data_bits = 8;
841 ns16550.parity = 'n';
842 ns16550.stop_bits = 1;
844 rc = of_getprop(n, "interrupts", val, sizeof (val));
845 if (rc == OF_FAILURE) {
846 of_printf("%s: no ISRC, forcing poll mode\n", __func__);
847 ns16550.irq = 0;
848 } else {
849 ns16550.irq = val[0];
850 of_printf("%s: ISRC=0x%x, but forcing poll mode\n",
851 __func__, ns16550.irq);
852 ns16550.irq = 0;
853 }
855 return 1;
856 }
858 static void boot_of_module(ulong r3, ulong r4, multiboot_info_t *mbi)
859 {
860 static module_t mods[3];
861 void *oft;
862 ulong oft_sz = 48 * PAGE_SIZE;
863 ulong mod0_start;
864 ulong mod0_size;
865 static const char sepr[] = " -- ";
866 extern char dom0_start[] __attribute__ ((weak));
867 extern char dom0_size[] __attribute__ ((weak));
868 const char *p;
870 if ((r3 > 0) && (r4 > 0)) {
871 /* was it handed to us in registers ? */
872 mod0_start = r3;
873 mod0_size = r4;
874 of_printf("%s: Dom0 was loaded and found using r3/r4:"
875 "0x%lx[size 0x%lx]\n",
876 __func__, mod0_start, mod0_size);
877 } else {
878 /* see if it is in the boot params */
879 p = strstr((char *)((ulong)mbi->cmdline), "dom0_start=");
880 if ( p != NULL) {
881 p += 11;
882 mod0_start = simple_strtoul(p, NULL, 0);
884 p = strstr((char *)((ulong)mbi->cmdline), "dom0_size=");
885 p += 10;
886 mod0_size = simple_strtoul(p, NULL, 0);
887 of_printf("%s: Dom0 was loaded and found using cmdline:"
888 "0x%lx[size 0x%lx]\n",
889 __func__, mod0_start, mod0_size);
890 } else if ( ((ulong)dom0_start != 0) && ((ulong)dom0_size != 0) ) {
891 /* was it linked in ? */
893 mod0_start = (ulong)dom0_start;
894 mod0_size = (ulong)dom0_size;
895 of_printf("%s: Dom0 is linked in: 0x%lx[size 0x%lx]\n",
896 __func__, mod0_start, mod0_size);
897 } else {
898 mod0_start = (ulong)_end;
899 mod0_size = 0;
900 of_printf("%s: FYI Dom0 is unknown, will be caught later\n",
901 __func__);
902 }
903 }
905 if (mod0_size > 0) {
906 const char *c = (const char *)mod0_start;
908 of_printf("mod0: %o %c %c %c\n", c[0], c[1], c[2], c[3]);
909 }
911 space_base = (ulong)_end;
912 mods[0].mod_start = mod0_start;
913 mods[0].mod_end = mod0_start + mod0_size;
915 of_printf("%s: mod[0] @ 0x%016x[0x%x]\n", __func__,
916 mods[0].mod_start, mods[0].mod_end);
917 p = strstr((char *)(ulong)mbi->cmdline, sepr);
918 if (p != NULL) {
919 p += sizeof (sepr) - 1;
920 mods[0].string = (u32)(ulong)p;
921 of_printf("%s: mod[0].string: %s\n", __func__, p);
922 }
924 /* snapshot the tree */
925 oft = (void*)find_space(oft_sz, PAGE_SIZE, mbi);
926 if (oft == 0)
927 of_panic("Could not allocate OFD tree\n");
929 of_printf("creating oft\n");
930 of_test("package-to-path");
931 oft = ofd_create(oft, oft_sz);
932 pkg_save(oft);
934 if (ofd_size(oft) > oft_sz)
935 of_panic("Could not fit all of native devtree\n");
937 boot_of_fixup_refs(oft);
938 boot_of_fixup_chosen(oft);
940 if (ofd_size(oft) > oft_sz)
941 of_panic("Could not fit all devtree fixups\n");
943 ofd_walk(oft, OFD_ROOT, /* add_hype_props */ NULL, 2);
945 mods[1].mod_start = (ulong)oft;
946 mods[1].mod_end = mods[1].mod_start + oft_sz;
947 of_printf("%s: mod[1] @ 0x%016x[0x%x]\n", __func__,
948 mods[1].mod_start, mods[1].mod_end);
951 mbi->flags |= MBI_MODULES;
952 mbi->mods_count = 2;
953 mbi->mods_addr = (u32)mods;
955 boot_of_serial(oft);
956 }
958 static int __init boot_of_cpus(void)
959 {
960 int cpus_node;
961 int cpu_node, bootcpu_node, logical;
962 int result;
963 s32 cpuid;
964 u32 cpu_clock[2];
965 extern uint cpu_hard_id[NR_CPUS];
967 /* Look up which CPU we are running on right now and get all info
968 * from there */
969 result = of_getprop(bof_chosen, "cpu",
970 &bootcpu_node, sizeof (bootcpu_node));
971 if (result == OF_FAILURE)
972 of_panic("Failed to look up boot cpu\n");
974 cpu_node = bootcpu_node;
976 result = of_getprop(cpu_node, "timebase-frequency", &timebase_freq,
977 sizeof(timebase_freq));
978 if (result == OF_FAILURE) {
979 of_panic("Couldn't get timebase frequency!\n");
980 }
981 of_printf("OF: timebase-frequency = %d Hz\n", timebase_freq);
983 result = of_getprop(cpu_node, "clock-frequency",
984 &cpu_clock, sizeof(cpu_clock));
985 if (result == OF_FAILURE || (result !=4 && result != 8)) {
986 of_panic("Couldn't get clock frequency!\n");
987 }
988 cpu_khz = cpu_clock[0];
989 if (result == 8) {
990 cpu_khz <<= 32;
991 cpu_khz |= cpu_clock[1];
992 }
993 cpu_khz /= 1000;
994 of_printf("OF: clock-frequency = %ld KHz\n", cpu_khz);
996 /* We want a continuous logical cpu number space and we'll make
997 * the booting CPU logical 0. */
998 cpu_set(0, cpu_present_map);
999 cpu_set(0, cpu_online_map);
1000 cpu_set(0, cpu_possible_map);
1002 result = of_getprop(cpu_node, "reg", &cpuid, sizeof(cpuid));
1003 cpu_hard_id[0] = cpuid;
1005 /* Spin up all CPUS, even if there are more than NR_CPUS or we are
1006 * runnign nosmp, because Open Firmware has them spinning on cache
1007 * lines which will eventually be scrubbed, which could lead to
1008 * random CPU activation.
1009 */
1011 /* Find the base of the multi-CPU package node */
1012 cpus_node = of_finddevice("/cpus");
1013 if (cpus_node <= 0) {
1014 of_printf("Single Processor System\n");
1015 return 1;
1017 /* Start with the first child */
1018 cpu_node = of_getchild(cpus_node);
1020 for (logical = 1; cpu_node > 0; logical++) {
1021 unsigned int ping, pong;
1022 unsigned long now, then, timeout;
1024 if (cpu_node == bootcpu_node) {
1025 /* same CPU as boot CPU shich we have already made 0 so
1026 * reduce the logical count */
1027 --logical;
1028 } else {
1029 result = of_getprop(cpu_node, "reg", &cpuid, sizeof(cpuid));
1030 if (result == OF_FAILURE)
1031 of_panic("cpuid lookup failed\n");
1033 cpu_hard_id[logical] = cpuid;
1035 of_printf("spinning up secondary processor #%d: ", logical);
1037 __spin_ack = ~0x0;
1038 ping = __spin_ack;
1039 pong = __spin_ack;
1040 of_printf("ping = 0x%x: ", ping);
1042 mb();
1043 result = of_start_cpu(cpu_node, (ulong)spin_start, logical);
1044 if (result == OF_FAILURE)
1045 of_panic("start cpu failed\n");
1047 /* We will give the secondary processor five seconds to reply. */
1048 then = mftb();
1049 timeout = then + (5 * timebase_freq);
1051 do {
1052 now = mftb();
1053 if (now >= timeout) {
1054 of_printf("BROKEN: ");
1055 break;
1058 mb();
1059 pong = __spin_ack;
1060 } while (pong == ping);
1061 of_printf("pong = 0x%x\n", pong);
1063 if (pong != ping) {
1064 cpu_set(logical, cpu_present_map);
1065 cpu_set(logical, cpu_possible_map);
1068 cpu_node = of_getpeer(cpu_node);
1070 return 1;
1073 static int __init boot_of_rtas(void)
1075 return 1;
1078 multiboot_info_t __init *boot_of_init(
1079 ulong r3, ulong r4, ulong vec, ulong r6, ulong r7, ulong orig_msr)
1081 static multiboot_info_t mbi;
1083 of_vec = vec;
1084 of_msr = orig_msr;
1086 bof_chosen = of_finddevice("/chosen");
1087 of_getprop(bof_chosen, "stdout", &of_out, sizeof (of_out));
1089 of_printf("%s\n", "---------------------------------------------------");
1090 of_printf("OF: Xen/PPC version %d.%d%s (%s@%s) (%s) %s\n",
1091 xen_major_version(), xen_minor_version(), xen_extra_version(),
1092 xen_compile_by(), xen_compile_domain(),
1093 xen_compiler(), xen_compile_date());
1095 of_printf("%s args: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n"
1096 "boot msr: 0x%lx\n",
1097 __func__,
1098 r3, r4, vec, r6, r7, orig_msr);
1100 if ((vec >= (ulong)_start) && (vec <= (ulong)_end)) {
1101 of_printf("Hmm.. OF[0x%lx] seems to have stepped on our image "
1102 "that ranges: %p .. %p.\n HANG!\n",
1103 vec, _start, _end);
1105 of_printf("%s: _start %p _end %p 0x%lx\n", __func__, _start, _end, r6);
1107 boot_of_fix_maple();
1108 boot_of_probemem(&mbi);
1109 boot_of_bootargs(&mbi);
1110 boot_of_module(r3, r4, &mbi);
1111 boot_of_cpus();
1112 boot_of_rtas();
1114 /* end of OF */
1115 of_printf("Quiescing Open Firmware ...\n");
1116 of_call("quiesce", 0, 0, NULL);
1118 return &mbi;
1121 /*
1122 * Local variables:
1123 * mode: C
1124 * c-set-style: "BSD"
1125 * c-basic-offset: 4
1126 * tab-width: 4
1127 * indent-tabs-mode: nil
1128 * End:
1129 */