[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [XEN][POWERPC] Allow Xen to use RTAS if available
# HG changeset patch # User Jimi Xenidis <jimix@xxxxxxxxxxxxxx> # Node ID 5b0e0c93a5bfb5d719dac0c2fb36e3f6731bd180 # Parent 97e1d0fd7def382ff521d2997eadc942ee831445 [XEN][POWERPC] Allow Xen to use RTAS if available If FW provides an RTAS layer, it will be instantiated and Xen will try to use it for power control (halt, reboot, power-off, etc). Xen will also communicate to Dom0 (using /xen/power-control in the devtree) when Xen cannot control power and it is hoped that the domain can, especially useful for Maple boards running non-RTAS versions of PIBS. Signed-off-by: Jimi Xenidis <jimix@xxxxxxxxxxxxxx> Signed-off-by: Hollis Blanchard <hollisb@xxxxxxxxxx> --- xen/arch/powerpc/boot_of.c | 210 ++++++++++++++++++++++++++----------- xen/arch/powerpc/domain.c | 18 ++- xen/arch/powerpc/memory.c | 26 +++- xen/arch/powerpc/ofd_fixup.c | 5 xen/arch/powerpc/rtas.c | 84 ++++++++++++++ xen/arch/powerpc/rtas.h | 34 +++++ xen/arch/powerpc/setup.c | 15 +- xen/include/asm-powerpc/debugger.h | 10 + 8 files changed, 322 insertions(+), 80 deletions(-) diff -r 97e1d0fd7def -r 5b0e0c93a5bf xen/arch/powerpc/boot_of.c --- a/xen/arch/powerpc/boot_of.c Tue Sep 26 14:01:11 2006 -0400 +++ b/xen/arch/powerpc/boot_of.c Thu Sep 28 12:34:01 2006 -0400 @@ -32,6 +32,7 @@ #include "exceptions.h" #include "of-devtree.h" #include "oftree.h" +#include "rtas.h" /* Secondary processors use this for handshaking with main processor. */ volatile unsigned int __spin_ack; @@ -68,7 +69,6 @@ static int bof_chosen; static int bof_chosen; static struct of_service s; -extern s32 prom_call(void *arg, ulong rtas_base, ulong func, ulong msr); static int __init of_call( const char *service, u32 nargs, u32 nrets, s32 rets[], ...) @@ -359,6 +359,14 @@ static int __init of_getparent(int ph) of_call("parent", 1, 1, rets, ph); DBG("getparent 0x%x -> 0x%x\n", ph, rets[0]); + return rets[0]; +} + +static int __init of_open(const char *devspec) +{ + int rets[1] = { OF_FAILURE }; + + of_call("open", 1, 1, rets, devspec); return rets[0]; } @@ -500,7 +508,8 @@ static int save_props(void *m, ofdn_t n, of_panic("obj array not big enough for 0x%x\n", sz); } actual = of_getprop(pkg, name, obj, sz); - if (actual > sz) of_panic("obj too small"); + if (actual > sz) + of_panic("obj too small"); } if (strncmp(name, name_str, sizeof(name_str)) == 0) { @@ -512,7 +521,8 @@ static int save_props(void *m, ofdn_t n, } pos = ofd_prop_add(m, n, name, obj, actual); - if (pos == 0) of_panic("prop_create"); + if (pos == 0) + of_panic("prop_create"); } result = of_nextprop(pkg, name, name); @@ -536,10 +546,12 @@ retry: if (pnext != 0) { sz = of_package_to_path(pnext, path, psz); - if (sz == OF_FAILURE) of_panic("bad path\n"); + if (sz == OF_FAILURE) + of_panic("bad path\n"); nnext = ofd_node_child_create(m, n, path, sz); - if (nnext == 0) of_panic("out of mem\n"); + if (nnext == 0) + of_panic("out of mem\n"); do_pkg(m, nnext, pnext, path, psz); } @@ -551,7 +563,8 @@ retry: sz = of_package_to_path(pnext, path, psz); nnext = ofd_node_peer_create(m, n, path, sz); - if (nnext <= 0) of_panic("out of space in OFD tree.\n"); + if (nnext <= 0) + of_panic("out of space in OFD tree.\n"); n = nnext; p = pnext; @@ -570,7 +583,8 @@ static int pkg_save(void *mem) /* get root */ root = of_getpeer(0); - if (root == OF_FAILURE) of_panic("no root package\n"); + if (root == OF_FAILURE) + of_panic("no root package\n"); do_pkg(mem, OFD_ROOT, root, path, sizeof(path)); @@ -604,7 +618,8 @@ static int boot_of_fixup_refs(void *mem) char ofpath[256]; path = ofd_node_path(mem, c); - if (path == NULL) of_panic("no path to found prop: %s\n", name); + if (path == NULL) + of_panic("no path to found prop: %s\n", name); rp = of_finddevice(path); if (rp == OF_FAILURE) @@ -629,13 +644,15 @@ static int boot_of_fixup_refs(void *mem) "ref 0x%x\n", name, path, rp, ref); dp = ofd_node_find(mem, ofpath); - if (dp <= 0) of_panic("no ofd node for OF node[0x%x]: %s\n", - ref, ofpath); + if (dp <= 0) + of_panic("no ofd node for OF node[0x%x]: %s\n", + ref, ofpath); ref = dp; upd = ofd_prop_add(mem, c, name, &ref, sizeof(ref)); - if (upd <= 0) of_panic("update failed: %s\n", name); + if (upd <= 0) + of_panic("update failed: %s\n", name); #ifdef DEBUG of_printf("%s: %s/%s -> %s\n", __func__, @@ -658,7 +675,8 @@ static int boot_of_fixup_chosen(void *me char ofpath[256]; ch = of_finddevice("/chosen"); - if (ch == OF_FAILURE) of_panic("/chosen not found\n"); + if (ch == OF_FAILURE) + of_panic("/chosen not found\n"); rc = of_getprop(ch, "cpu", &val, sizeof (val)); @@ -667,16 +685,19 @@ static int boot_of_fixup_chosen(void *me if (rc > 0) { dn = ofd_node_find(mem, ofpath); - if (dn <= 0) of_panic("no node for: %s\n", ofpath); + if (dn <= 0) + of_panic("no node for: %s\n", ofpath); ofd_boot_cpu = dn; val = dn; dn = ofd_node_find(mem, "/chosen"); - if (dn <= 0) of_panic("no /chosen node\n"); + if (dn <= 0) + of_panic("no /chosen node\n"); dc = ofd_prop_add(mem, dn, "cpu", &val, sizeof (val)); - if (dc <= 0) of_panic("could not fix /chosen/cpu\n"); + if (dc <= 0) + of_panic("could not fix /chosen/cpu\n"); rc = 1; } else { of_printf("*** can't find path to booting cpu, " @@ -855,17 +876,101 @@ static int __init boot_of_serial(void *o return 1; } -static void boot_of_module(ulong r3, ulong r4, multiboot_info_t *mbi) -{ - static module_t mods[3]; +static int __init boot_of_rtas(module_t *mod, multiboot_info_t *mbi) +{ + int rtas_node; + int rtas_instance; + uint size = 0; + int res[2]; + int mem; + int ret; + + rtas_node = of_finddevice("/rtas"); + + if (rtas_node <= 0) { + of_printf("No RTAS, Xen has no power control\n"); + return 0; + } + of_getprop(rtas_node, "rtas-size", &size, sizeof (size)); + if (size == 0) { + of_printf("RTAS, has no size\n"); + return 0; + } + + rtas_instance = of_open("/rtas"); + if (rtas_instance == OF_FAILURE) { + of_printf("RTAS, could not open\n"); + return 0; + } + + size = ALIGN_UP(size, PAGE_SIZE); + + mem = find_space(size, PAGE_SIZE, mbi); + if (mem == 0) + of_panic("Could not allocate RTAS tree\n"); + + ret = of_call("call-method", 3, 2, res, + "instantiate-rtas", rtas_instance, mem); + if (ret == OF_FAILURE) { + of_printf("RTAS, could not open\n"); + return 0; + } + + rtas_entry = res[1]; + rtas_base = mem; + rtas_end = mem + size; + rtas_msr = of_msr; + + mod->mod_start = rtas_base; + mod->mod_end = rtas_end; + return 1; +} + +static void * __init boot_of_devtree(module_t *mod, multiboot_info_t *mbi) +{ void *oft; ulong oft_sz = 48 * PAGE_SIZE; + + /* snapshot the tree */ + oft = (void*)find_space(oft_sz, PAGE_SIZE, mbi); + if (oft == 0) + of_panic("Could not allocate OFD tree\n"); + + of_printf("creating oftree\n"); + of_test("package-to-path"); + oft = ofd_create(oft, oft_sz); + pkg_save(oft); + + if (ofd_size(oft) > oft_sz) + of_panic("Could not fit all of native devtree\n"); + + boot_of_fixup_refs(oft); + boot_of_fixup_chosen(oft); + + if (ofd_size(oft) > oft_sz) + of_panic("Could not fit all devtree fixups\n"); + + ofd_walk(oft, OFD_ROOT, /* add_hype_props */ NULL, 2); + + mod->mod_start = (ulong)oft; + mod->mod_end = mod->mod_start + oft_sz; + of_printf("%s: devtree mod @ 0x%016x[0x%x]\n", __func__, + mod->mod_start, mod->mod_end); + + return oft; +} + +static void * __init boot_of_module(ulong r3, ulong r4, multiboot_info_t *mbi) +{ + static module_t mods[4]; ulong mod0_start; ulong mod0_size; static const char sepr[] = " -- "; extern char dom0_start[] __attribute__ ((weak)); extern char dom0_size[] __attribute__ ((weak)); const char *p; + int mod; + void *oft; if ((r3 > 0) && (r4 > 0)) { /* was it handed to us in registers ? */ @@ -909,50 +1014,35 @@ static void boot_of_module(ulong r3, ulo } space_base = (ulong)_end; - mods[0].mod_start = mod0_start; - mods[0].mod_end = mod0_start + mod0_size; - - of_printf("%s: mod[0] @ 0x%016x[0x%x]\n", __func__, - mods[0].mod_start, mods[0].mod_end); + + mod = 0; + mods[mod].mod_start = mod0_start; + mods[mod].mod_end = mod0_start + mod0_size; + + of_printf("%s: dom0 mod @ 0x%016x[0x%x]\n", __func__, + mods[mod].mod_start, mods[mod].mod_end); p = strstr((char *)(ulong)mbi->cmdline, sepr); if (p != NULL) { p += sizeof (sepr) - 1; - mods[0].string = (u32)(ulong)p; - of_printf("%s: mod[0].string: %s\n", __func__, p); - } - - /* snapshot the tree */ - oft = (void*)find_space(oft_sz, PAGE_SIZE, mbi); - if (oft == 0) - of_panic("Could not allocate OFD tree\n"); - - of_printf("creating oft\n"); - of_test("package-to-path"); - oft = ofd_create(oft, oft_sz); - pkg_save(oft); - - if (ofd_size(oft) > oft_sz) - of_panic("Could not fit all of native devtree\n"); - - boot_of_fixup_refs(oft); - boot_of_fixup_chosen(oft); - - if (ofd_size(oft) > oft_sz) - of_panic("Could not fit all devtree fixups\n"); - - ofd_walk(oft, OFD_ROOT, /* add_hype_props */ NULL, 2); - - mods[1].mod_start = (ulong)oft; - mods[1].mod_end = mods[1].mod_start + oft_sz; - of_printf("%s: mod[1] @ 0x%016x[0x%x]\n", __func__, - mods[1].mod_start, mods[1].mod_end); - + mods[mod].string = (u32)(ulong)p; + of_printf("%s: dom0 mod string: %s\n", __func__, p); + } + + ++mod; + if (boot_of_rtas(&mods[mod], mbi)) + ++mod; + + oft = boot_of_devtree(&mods[mod], mbi); + if (oft == NULL) + of_panic("%s: boot_of_devtree failed\n", __func__); + + ++mod; mbi->flags |= MBI_MODULES; - mbi->mods_count = 2; + mbi->mods_count = mod; mbi->mods_addr = (u32)mods; - boot_of_serial(oft); + return oft; } static int __init boot_of_cpus(void) @@ -1075,15 +1165,11 @@ static int __init boot_of_cpus(void) return 1; } -static int __init boot_of_rtas(void) -{ - return 1; -} - multiboot_info_t __init *boot_of_init( ulong r3, ulong r4, ulong vec, ulong r6, ulong r7, ulong orig_msr) { static multiboot_info_t mbi; + void *oft; of_vec = vec; of_msr = orig_msr; @@ -1112,9 +1198,9 @@ multiboot_info_t __init *boot_of_init( boot_of_fix_maple(); boot_of_probemem(&mbi); boot_of_bootargs(&mbi); - boot_of_module(r3, r4, &mbi); + oft = boot_of_module(r3, r4, &mbi); boot_of_cpus(); - boot_of_rtas(); + boot_of_serial(oft); /* end of OF */ of_printf("Quiescing Open Firmware ...\n"); diff -r 97e1d0fd7def -r 5b0e0c93a5bf xen/arch/powerpc/domain.c --- a/xen/arch/powerpc/domain.c Tue Sep 26 14:01:11 2006 -0400 +++ b/xen/arch/powerpc/domain.c Thu Sep 28 12:34:01 2006 -0400 @@ -33,6 +33,7 @@ #include <asm/htab.h> #include <asm/current.h> #include <asm/hcalls.h> +#include "rtas.h" #define next_arg(fmt, args) ({ \ unsigned long __arg; \ @@ -95,18 +96,27 @@ void arch_domain_destroy(struct domain * shadow_teardown(d); } +static void machine_fail(const char *s) +{ + printf("%s failed, manual powercycle required!\n", s); + while(1); +} + void machine_halt(void) { - printk("machine_halt called: spinning....\n"); console_start_sync(); - while(1); + printf("%s called\n", __func__); + rtas_halt(); + + machine_fail(__func__); } void machine_restart(char * __unused) { - printk("machine_restart called: spinning....\n"); console_start_sync(); - while(1); + printf("%s called\n", __func__); + rtas_reboot(); + machine_fail(__func__); } struct vcpu *alloc_vcpu_struct(void) diff -r 97e1d0fd7def -r 5b0e0c93a5bf xen/arch/powerpc/memory.c --- a/xen/arch/powerpc/memory.c Tue Sep 26 14:01:11 2006 -0400 +++ b/xen/arch/powerpc/memory.c Thu Sep 28 12:34:01 2006 -0400 @@ -22,6 +22,7 @@ #include <xen/mm.h> #include "of-devtree.h" #include "oftree.h" +#include "rtas.h" unsigned long xenheap_phys_end; struct membuf { @@ -33,16 +34,29 @@ typedef void (*walk_mem_fn)(struct membu static ulong free_xenheap(ulong start, ulong end) { + ulong save_start; + ulong save_end; + start = ALIGN_UP(start, PAGE_SIZE); end = ALIGN_DOWN(end, PAGE_SIZE); printk("%s: 0x%lx - 0x%lx\n", __func__, start, end); - if (oftree <= end && oftree >= start) { - printk("%s: Go around the devtree: 0x%lx - 0x%lx\n", - __func__, oftree, oftree_end); - init_xenheap_pages(start, ALIGN_DOWN(oftree, PAGE_SIZE)); - init_xenheap_pages(ALIGN_UP(oftree_end, PAGE_SIZE), end); + save_start = oftree; + save_end = oftree_end; + if (rtas_base) { + if (save_start > rtas_base) + save_start = rtas_base; + if (save_end < rtas_end) + save_end = rtas_end; + } + + /* need to do this better */ + if (save_start <= end && save_start >= start) { + printk("%s: Go around the saved area: 0x%lx - 0x%lx\n", + __func__, save_start, save_end); + init_xenheap_pages(start, ALIGN_DOWN(save_start, PAGE_SIZE)); + init_xenheap_pages(ALIGN_UP(save_end, PAGE_SIZE), end); } else { init_xenheap_pages(start, end); } @@ -123,7 +137,7 @@ static void setup_xenheap(module_t *mod, for (i = 0; i < mcount; i++) { u32 s; - if(mod[i].mod_end == mod[i].mod_start) + if (mod[i].mod_end == mod[i].mod_start) continue; s = ALIGN_DOWN(mod[i].mod_start, PAGE_SIZE); diff -r 97e1d0fd7def -r 5b0e0c93a5bf xen/arch/powerpc/ofd_fixup.c --- a/xen/arch/powerpc/ofd_fixup.c Tue Sep 26 14:01:11 2006 -0400 +++ b/xen/arch/powerpc/ofd_fixup.c Thu Sep 28 12:34:01 2006 -0400 @@ -25,6 +25,7 @@ #include <public/xen.h> #include "of-devtree.h" #include "oftree.h" +#include "rtas.h" #undef RTAS @@ -347,6 +348,10 @@ static ofdn_t ofd_xen_props(void *m, str val[0] = rma_size(d->arch.rma_order) - val[1]; ofd_prop_add(m, n, "reserved", val, sizeof (val)); + /* tell dom0 that Xen depends on it to have power control */ + if (!rtas_entry) + ofd_prop_add(m, n, "power-control", NULL, 0); + n = ofd_node_add(m, n, console, sizeof (console)); if (n > 0) { val[0] = 0; diff -r 97e1d0fd7def -r 5b0e0c93a5bf xen/arch/powerpc/rtas.c --- a/xen/arch/powerpc/rtas.c Tue Sep 26 14:01:11 2006 -0400 +++ b/xen/arch/powerpc/rtas.c Thu Sep 28 12:34:01 2006 -0400 @@ -13,12 +13,90 @@ * along with this program; if not, write to the Free Software * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Copyright (C) IBM Corp. 2005 + * Copyright (C) IBM Corp. 2006 * * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx> */ #include <xen/config.h> +#include <xen/init.h> +#include <xen/lib.h> +#include <xen/errno.h> +#include "of-devtree.h" +#include "rtas.h" -int rtas_halt = -1; -int rtas_reboot = -1; +static int rtas_halt_token = -1; +static int rtas_reboot_token = -1; +int rtas_entry; +unsigned long rtas_msr; +unsigned long rtas_base; +unsigned long rtas_end; + +struct rtas_args { + int ra_token; + int ra_nargs; + int ra_nrets; + int ra_args[10]; +} __attribute__ ((aligned(8))); + +static int rtas_call(struct rtas_args *r) +{ + if (rtas_entry == 0) + return -ENOSYS; + + return prom_call(r, rtas_base, rtas_entry, rtas_msr); +} + +int __init rtas_init(void *m) +{ + static const char halt[] = "power-off"; + static const char reboot[] = "system-reboot"; + ofdn_t n; + + if (rtas_entry == 0) + return -ENOSYS; + + n = ofd_node_find(m, "/rtas"); + if (n <= 0) + return -ENOSYS; + + ofd_getprop(m, n, halt, + &rtas_halt_token, sizeof (rtas_halt_token)); + ofd_getprop(m, n, reboot, + &rtas_reboot_token, sizeof (rtas_reboot_token)); + return 1; +} + +int +rtas_halt(void) +{ + struct rtas_args r; + + if (rtas_halt_token == -1) + return -1; + + r.ra_token = rtas_halt_token; + r.ra_nargs = 2; + r.ra_nrets = 1; + r.ra_args[0] = 0; + r.ra_args[1] = 0; + + return rtas_call(&r); +} + +int +rtas_reboot(void) +{ + struct rtas_args r; + + if (rtas_reboot_token == -1) + return -ENOSYS; + + r.ra_token = rtas_reboot_token; + r.ra_nargs = 2; + r.ra_nrets = 1; + r.ra_args[0] = 0; + r.ra_args[1] = 0; + + return rtas_call(&r); +} diff -r 97e1d0fd7def -r 5b0e0c93a5bf xen/arch/powerpc/setup.c --- a/xen/arch/powerpc/setup.c Tue Sep 26 14:01:11 2006 -0400 +++ b/xen/arch/powerpc/setup.c Thu Sep 28 12:34:01 2006 -0400 @@ -47,6 +47,7 @@ #include "exceptions.h" #include "of-devtree.h" #include "oftree.h" +#include "rtas.h" #define DEBUG @@ -286,9 +287,8 @@ static void __init __start_xen(multiboot serial_init_preirq(); init_console(); -#ifdef CONSOLE_SYNC + /* let synchronize until we really get going */ console_start_sync(); -#endif /* we give the first RMA to the hypervisor */ xenheap_phys_end = rma_size(cpu_default_rma_order_pages()); @@ -312,6 +312,13 @@ static void __init __start_xen(multiboot mod[mbi->mods_count-1].mod_end = 0; --mbi->mods_count; + if (rtas_entry) { + rtas_init((void *)oftree); + /* remove rtas module from consideration */ + mod[mbi->mods_count-1].mod_start = 0; + mod[mbi->mods_count-1].mod_end = 0; + --mbi->mods_count; + } memory_init(mod, mbi->mods_count); #ifdef OF_DEBUG @@ -319,7 +326,6 @@ static void __init __start_xen(multiboot /* make sure the OF devtree is good */ ofd_walk((void *)oftree, OFD_ROOT, ofd_dump_props, OFD_DUMP_ALL); #endif - percpu_init_areas(); init_parea(0); @@ -395,8 +401,9 @@ static void __init __start_xen(multiboot /* Hide UART from DOM0 if we're using it */ serial_endboot(); + console_end_sync(); + domain_unpause_by_systemcontroller(dom0); - startup_cpu_idle_loop(); } diff -r 97e1d0fd7def -r 5b0e0c93a5bf xen/include/asm-powerpc/debugger.h --- a/xen/include/asm-powerpc/debugger.h Tue Sep 26 14:01:11 2006 -0400 +++ b/xen/include/asm-powerpc/debugger.h Thu Sep 28 12:34:01 2006 -0400 @@ -35,10 +35,18 @@ static inline void dump_execution_state( show_backtrace(sp, lr, lr); } +static inline void __force_crash(void) +{ + dump_execution_state(); + __builtin_trap(); +} + static inline void debugger_trap_immediate(void) { dump_execution_state(); +#ifdef CRASH_DEBUG __builtin_trap(); +#endif } static inline void unimplemented(void) @@ -57,7 +65,7 @@ extern void __warn(char *file, int line) #define WARN() __warn(__FILE__, __LINE__) #define WARN_ON(_p) do { if (_p) WARN(); } while ( 0 ) -#define FORCE_CRASH() debugger_trap_immediate() +#define FORCE_CRASH() __force_crash() #ifdef CRASH_DEBUG diff -r 97e1d0fd7def -r 5b0e0c93a5bf xen/arch/powerpc/rtas.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/powerpc/rtas.h Thu Sep 28 12:34:01 2006 -0400 @@ -0,0 +1,34 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright (C) IBM Corp. 2006 + * + * Authors: Jimi Xenidis <jimix@xxxxxxxxxx> + */ + +#ifndef _ARCH_POWERPC_RTAS_H_ +#define _ARCH_POWERPC_RTAS_H_ + +extern int rtas_entry; +extern unsigned long rtas_msr; +extern unsigned long rtas_base; +extern unsigned long rtas_end; + +extern int prom_call(void *arg, unsigned rtas_base, + unsigned long func, unsigned long msr); +extern int rtas_init(void *); +extern int rtas_halt(void); +extern int rtas_reboot(void); +#endif _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |