[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [XEN][POWERPC] Merge with xen-unstable.hg.
# HG changeset patch # User Hollis Blanchard <hollisb@xxxxxxxxxx> # Date 1183755664 18000 # Node ID 8a8e6dfa6dea61c1ed07f6579bcb22fad83f0136 # Parent d54d47fc8c6cdea23437476407bec05d85742760 # Parent 6750b1320159458c15fed78ba26d202ada818e57 [XEN][POWERPC] Merge with xen-unstable.hg. Signed-off-by: Hollis Blanchard <hollisb@xxxxxxxxxx> --- .hgignore | 1 xen/arch/powerpc/Makefile | 16 +- xen/arch/powerpc/boot_of.c | 27 ++-- xen/arch/powerpc/domain_build.c | 136 ++++++++++---------- xen/arch/powerpc/of_handler/Makefile | 1 xen/arch/powerpc/of_handler/head.S | 26 ++- xen/arch/powerpc/of_handler/ofh.c | 1 xen/arch/powerpc/of_handler/rtas.c | 82 ++++++++++++ xen/arch/powerpc/of_handler/vdevice.c | 2 xen/arch/powerpc/of_handler/xen_hvcall.S | 26 +++ xen/arch/powerpc/ofd_fixup.c | 37 ----- xen/arch/powerpc/oftree.h | 4 xen/arch/powerpc/powerpc64/hypercall_table.S | 2 xen/arch/powerpc/rtas.c | 151 ++++++++++++++++++---- xen/arch/powerpc/rtas.h | 31 ++++ xen/arch/powerpc/rtas_flash.c | 182 +++++++++++++++++++++++++++ xen/arch/powerpc/rtas_nvram.c | 129 +++++++++++++++++++ 17 files changed, 702 insertions(+), 152 deletions(-) diff -r d54d47fc8c6c -r 8a8e6dfa6dea .hgignore --- a/.hgignore Thu Jul 05 10:19:25 2007 +0100 +++ b/.hgignore Fri Jul 06 16:01:04 2007 -0500 @@ -233,6 +233,7 @@ ^xen/arch/powerpc/dom0\.bin$ ^xen/arch/powerpc/asm-offsets\.s$ ^xen/arch/powerpc/firmware$ +^xen/arch/powerpc/firmware.dbg$ ^xen/arch/powerpc/firmware_image.bin$ ^xen/arch/powerpc/xen\.lds$ ^xen/arch/powerpc/\.xen-syms$ diff -r d54d47fc8c6c -r 8a8e6dfa6dea xen/arch/powerpc/Makefile --- a/xen/arch/powerpc/Makefile Thu Jul 05 10:19:25 2007 +0100 +++ b/xen/arch/powerpc/Makefile Fri Jul 06 16:01:04 2007 -0500 @@ -35,6 +35,8 @@ obj-y += physdev.o obj-y += physdev.o obj-y += platform.o obj-y += rtas.o +obj-y += rtas_nvram.o +obj-y += rtas_flash.o obj-y += setup.o obj-y += shadow.o obj-y += smp.o @@ -63,12 +65,19 @@ CFLAGS += $(PPC_C_WARNINGS) # objects into a single ELF segment and to not link in any additional # objects that gcc would normally like to # -OMAGIC = -nodefaultlibs -nostartfiles +OMAGIC = -nodefaultlibs -nostartfiles -Wl,--omagic firmware: of_handler/built_in.o $(TARGET_SUBARCH)/memcpy.o of-devtree.o $(CC) $(CFLAGS) $(OMAGIC) -e __ofh_start -Wl,-Ttext,0x0 $^ -o $@ -firmware_image.bin: firmware +# +# Link firmware again but this time at the place we expect to load it. +# This makes debugging _way_ easier. +# +firmware.dbg: of_handler/built_in.o $(TARGET_SUBARCH)/memcpy.o of-devtree.o + $(CC) $(CFLAGS) $(OMAGIC) -e __ofh_start -Wl,-Ttext,0x2000000 $^ -o $@ + +firmware_image.bin: firmware firmware.dbg $(CROSS_COMPILE)objcopy --output-target=binary $< $@ # @@ -139,5 +148,6 @@ dom0.bin: $(DOM0_IMAGE) clean:: $(MAKE) -f $(BASEDIR)/Rules.mk -C of_handler clean - rm -f firmware firmware_image.bin dom0.bin .xen-syms xen-syms.S \ + rm -f firmware firmware.dbg firmware_image.bin \ + dom0.bin .xen-syms xen-syms.S \ xen.lds asm-offsets.s cmdline.dep diff -r d54d47fc8c6c -r 8a8e6dfa6dea xen/arch/powerpc/boot_of.c --- a/xen/arch/powerpc/boot_of.c Thu Jul 05 10:19:25 2007 +0100 +++ b/xen/arch/powerpc/boot_of.c Fri Jul 06 16:01:04 2007 -0500 @@ -1073,31 +1073,40 @@ static void * __init boot_of_devtree(mod static void * __init boot_of_devtree(module_t *mod, multiboot_info_t *mbi) { void *oft; - ulong oft_sz = 48 * PAGE_SIZE; + ulong alloc_sz = 32 << 10; /* 32KiB should be plenty */ + ulong sz; /* snapshot the tree */ - oft = (void *)boot_of_alloc(oft_sz); + oft = (void *)boot_of_alloc(alloc_sz); if (oft == NULL) of_panic("Could not allocate OFD tree\n"); of_printf("creating oftree at: 0x%p\n", oft); of_test("package-to-path"); - oft = ofd_create(oft, oft_sz); + oft = ofd_create(oft, alloc_sz); pkg_save(oft); - - if (ofd_size(oft) > oft_sz) - of_panic("Could not fit all of native devtree\n"); + sz = ofd_size(oft); + + if (sz > alloc_sz) + of_panic("Could not fit all of native devtree in 0x%lx of memory\n", + alloc_sz); 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"); + if (sz > alloc_sz) + of_panic("Could not fit all devtree fixupsin 0x%lx of memory\n", + alloc_sz); ofd_walk(oft, __func__, OFD_ROOT, /* add_hype_props */ NULL, 2); mod->mod_start = (ulong)oft; - mod->mod_end = mod->mod_start + oft_sz; + mod->mod_end = ALIGN_UP(mod->mod_start + sz, PAGE_SIZE); + + if (mod->mod_end -mod->mod_start > alloc_sz) + of_panic("Could not fit all devtree module in 0x%lx of memory\n", + alloc_sz); + of_printf("%s: devtree mod @ 0x%016x - 0x%016x\n", __func__, mod->mod_start, mod->mod_end); diff -r d54d47fc8c6c -r 8a8e6dfa6dea xen/arch/powerpc/domain_build.c --- a/xen/arch/powerpc/domain_build.c Thu Jul 05 10:19:25 2007 +0100 +++ b/xen/arch/powerpc/domain_build.c Fri Jul 06 16:01:04 2007 -0500 @@ -68,6 +68,7 @@ int construct_dom0(struct domain *d, struct vcpu *v; ulong dst; u64 *ofh_tree; + ulong firmware_base; uint rma_nrpages = 1 << cpu_default_rma_order_pages(); ulong rma_sz; ulong rma; @@ -78,6 +79,7 @@ int construct_dom0(struct domain *d, ulong mod_len = 0; ulong shared_info_addr; uint extent_size = 1 << cpu_extent_order(); + ulong sz; /* Sanity! */ BUG_ON(d->domain_id != 0); @@ -86,26 +88,6 @@ int construct_dom0(struct domain *d, panic("No Dom0 image supplied\n"); printk("*** LOADING DOMAIN 0 ***\n"); - - rc = elf_init(&elf, (void *)image_start, image_len); - if (rc) - return rc; -#ifdef VERBOSE - elf_set_verbose(&elf); -#endif - elf_parse_binary(&elf); - if (0 != (elf_xen_parse(&elf, &parms))) - return rc; - - printk("Dom0 kernel: %s, paddr 0x%" PRIx64 " -> 0x%" PRIx64 "\n", - elf_64bit(&elf) ? "64-bit" : "32-bit", - elf.pstart, elf.pend); - - /* elf contains virtual addresses that can have the upper bits - * masked while running in real mode, so we do the masking as well - * as well */ - parms.virt_kend = RM_MASK(parms.virt_kend, 42); - parms.virt_entry = RM_MASK(parms.virt_entry, 42); /* default is the max(1/16th of memory, CONFIG_MIN_DOM0_PAGES) */ if (dom0_nrpages == 0) { @@ -196,17 +178,75 @@ int construct_dom0(struct domain *d, v = d->vcpu[0]; cpu_init_vcpu(v); + /* convert xen pointer shared_info into guest physical */ + shared_info_addr = (ulong)d->shared_info - page_to_maddr(d->arch.rma_page); + + /* start loading stuff */ + rc = elf_init(&elf, (void *)image_start, image_len); + if (rc) + return rc; +#ifdef VERBOSE + elf_set_verbose(&elf); +#endif + elf_parse_binary(&elf); + if (0 != (elf_xen_parse(&elf, &parms))) + return rc; + + printk("Dom0 kernel: %s, paddr 0x%" PRIx64 " -> 0x%" PRIx64 "\n", + elf_64bit(&elf) ? "64-bit" : "32-bit", + elf.pstart, elf.pend); + + /* elf contains virtual addresses that can have the upper bits + * masked while running in real mode, so we do the masking as well + * as well */ + parms.virt_kend = RM_MASK(parms.virt_kend, 42); + parms.virt_entry = RM_MASK(parms.virt_entry, 42); + + /* set the MSR bit correctly */ + if (elf_64bit(&elf)) + v->arch.ctxt.msr = MSR_SF; + else + v->arch.ctxt.msr = 0; + + /* Load the dom0 kernel. */ + elf.dest = (void *)(parms.virt_kstart + rma); + + elf_load_binary(&elf); + v->arch.ctxt.pc = parms.virt_entry; + + dst = ALIGN_UP(parms.virt_kend + rma, PAGE_SIZE); + + /* Load the initrd. */ + if (initrd_len > 0) { + ASSERT((dst - rma) + image_len < eomem); + + printk("loading initrd: 0x%lx, 0x%lx\n", dst, initrd_len); + memcpy((void *)dst, (void *)initrd_start, initrd_len); + + mod_start = dst - rma; + mod_len = image_len; + + dst = ALIGN_UP(dst + initrd_len, PAGE_SIZE); + } else { + printk("no initrd\n"); + } + + v->arch.ctxt.gprs[3] = mod_start; + v->arch.ctxt.gprs[4] = mod_len; + /* OF usually sits here: * - Linux needs it to be loaded before the vmlinux or initrd * - AIX demands it to be @ 32M. */ - dst = (32 << 20); - - /* Put stack below everything. */ - v->arch.ctxt.gprs[1] = dst - STACK_FRAME_OVERHEAD; - - /* copy relative to Xen */ - dst += rma; + firmware_base = (32 << 20); + if (dst - rma > firmware_base) + panic("Firmware [0x%lx] will over-write images ending: 0x%lx\n", + firmware_base, dst - rma); + dst = firmware_base + rma; + + /* Put stack below firmware. */ + v->arch.ctxt.gprs[1] = dst - rma - STACK_FRAME_OVERHEAD; + v->arch.ctxt.gprs[2] = 0; ASSERT((dst - rma) + (ulong)firmware_image_size < eomem); printk("loading OFH: 0x%lx, RMA: 0x%lx\n", dst, dst - rma); @@ -218,43 +258,18 @@ int construct_dom0(struct domain *d, /* accomodate for a modest bss section */ dst = ALIGN_UP(dst + (ulong)firmware_image_size + PAGE_SIZE, PAGE_SIZE); + ASSERT((dst - rma) + oftree_len < eomem); *ofh_tree = dst - rma; printk("loading OFD: 0x%lx RMA: 0x%lx, 0x%lx\n", dst, dst - rma, oftree_len); memcpy((void *)dst, (void *)oftree, oftree_len); - dst = ALIGN_UP(dst + oftree_len, PAGE_SIZE); - - /* Load the dom0 kernel. */ - elf.dest = (void *)dst; - elf_load_binary(&elf); - v->arch.ctxt.pc = dst - rma + (parms.virt_entry - parms.virt_kstart); - dst = ALIGN_UP(dst + parms.virt_kend, PAGE_SIZE); - - /* Load the initrd. */ - if (initrd_len > 0) { - ASSERT((dst - rma) + image_len < eomem); - - printk("loading initrd: 0x%lx, 0x%lx\n", dst, initrd_len); - memcpy((void *)dst, (void *)initrd_start, initrd_len); - - mod_start = dst - rma; - mod_len = image_len; - - dst = ALIGN_UP(dst + initrd_len, PAGE_SIZE); - } else { - printk("no initrd\n"); - } - - if (elf_64bit(&elf)) { - v->arch.ctxt.msr = MSR_SF; - } else { - v->arch.ctxt.msr = 0; - } - v->arch.ctxt.gprs[2] = 0; - v->arch.ctxt.gprs[3] = mod_start; - v->arch.ctxt.gprs[4] = mod_len; + + /* fixup and add stuff for dom0 */ + sz = ofd_dom0_fixup(d, *ofh_tree + rma, cmdline, shared_info_addr); + printk("modified OFD size: 0x%lx\n", sz); + dst = ALIGN_UP(dst + sz + PAGE_SIZE, PAGE_SIZE); printk("dom0 initial register state:\n" " pc %016lx msr %016lx\n" @@ -268,11 +283,6 @@ int construct_dom0(struct domain *d, v->arch.ctxt.gprs[4], v->arch.ctxt.gprs[5]); - /* convert xen pointer shared_info into guest physical */ - shared_info_addr = (ulong)d->shared_info - page_to_maddr(d->arch.rma_page); - - ofd_dom0_fixup(d, *ofh_tree + rma, cmdline, shared_info_addr); - v->is_initialised = 1; clear_bit(_VPF_down, &v->pause_flags); diff -r d54d47fc8c6c -r 8a8e6dfa6dea xen/arch/powerpc/of_handler/Makefile --- a/xen/arch/powerpc/of_handler/Makefile Thu Jul 05 10:19:25 2007 +0100 +++ b/xen/arch/powerpc/of_handler/Makefile Fri Jul 06 16:01:04 2007 -0500 @@ -16,6 +16,7 @@ obj-y += memory.o obj-y += memory.o obj-y += ofh.o obj-y += papr.o +obj-y += rtas.o obj-y += services.o obj-y += vdevice.o obj-y += xencomm.o diff -r d54d47fc8c6c -r 8a8e6dfa6dea xen/arch/powerpc/of_handler/head.S --- a/xen/arch/powerpc/of_handler/head.S Thu Jul 05 10:19:25 2007 +0100 +++ b/xen/arch/powerpc/of_handler/head.S Fri Jul 06 16:01:04 2007 -0500 @@ -1,25 +1,28 @@ /* - * Copyright (C) 2005 Jimi Xenidis <jimix@xxxxxxxxxxxxxx>, IBM Corporation - * * 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright (C) IBM Corp. 2005, 2007 + * + * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx> */ + /* * Glue code for open-firmware client interface implementation. */ -#define OF_STACK_SIZE (32*1024) +#define OF_STACK_SIZE (64*1024) #include <asm/config.h> #include <asm/processor.h> @@ -62,11 +65,6 @@ _ofh_lastarg: .long 0x0 .long 0x0 - . = 0x30 -_ofh_cih_stack_end: - .space OF_STACK_SIZE -_ofh_cih_stack: - _ofh_cih_continue: mflr r12 # r12 = &_ofh_work_space mr r11, r1 # r11 = orig stk ptr @@ -150,3 +148,9 @@ 1: mflr r5 subf r3,r4,r5 mtlr r0 blr + + .data + .p2align 3 +_ofh_cih_stack_end: + .space OF_STACK_SIZE +_ofh_cih_stack: diff -r d54d47fc8c6c -r 8a8e6dfa6dea xen/arch/powerpc/of_handler/ofh.c --- a/xen/arch/powerpc/of_handler/ofh.c Thu Jul 05 10:19:25 2007 +0100 +++ b/xen/arch/powerpc/of_handler/ofh.c Fri Jul 06 16:01:04 2007 -0500 @@ -234,6 +234,7 @@ ofh_init(ulong b) ofh_service_init(b); ofh_chosen_init(b); + ofh_rtas_init(b); ofh_options_init(b); } diff -r d54d47fc8c6c -r 8a8e6dfa6dea xen/arch/powerpc/of_handler/rtas.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/powerpc/of_handler/rtas.c Fri Jul 06 16:01:04 2007 -0500 @@ -0,0 +1,82 @@ +/* + * 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. 2007 + * + * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx> + */ + +#include "ofh.h" +#include <stdarg.h> +#include <xen/lib.h> +extern char _rtas_image_start[]; +extern char _rtas_image_end[]; + +static int +rtas_instantiate_rtas(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b) +{ + if (nargs == 1) { + if (nrets == 1) { + void *rtas_base_address = (void *)(ulong)argp[0]; + u32 sz = (_rtas_image_end - _rtas_image_start); + + memcpy(rtas_base_address, + DRELA(&_rtas_image_start[0], b), sz); + retp[0] = (ulong)rtas_base_address; + + return OF_SUCCESS; + } + } + return OF_FAILURE; +} + + +static struct ofh_methods _rtas_methods[] = { + { "instantiate-rtas", rtas_instantiate_rtas }, + { NULL, NULL}, +}; + +static struct ofh_ihandle _ih_rtas = { + .ofi_methods = _rtas_methods, +}; + +static int rtas_open(u32 b) +{ + u32 ih = DRELA((u32)&_ih_rtas, b); + + return ih; +} + +void ofh_rtas_init(ulong b) +{ + static const char path[] = "/rtas"; + ofdn_t n; + void *m = ofd_mem(b); + u32 sz; + + n = ofd_node_find(m, DRELA(&path[0], b)); + if (n <= 0) + return; + + sz = (_rtas_image_end - _rtas_image_start); + /* Round size up to a multiple of 0x1000 */ + sz = ALIGN_UP(sz, PAGE_SIZE); + + ofd_prop_add(m, n, DRELA((const char *)"rtas-size", b), + &sz, sizeof(sz)); + + /* create an IO node */ + ofd_io_create(m, n, (ulong)rtas_open); +} diff -r d54d47fc8c6c -r 8a8e6dfa6dea xen/arch/powerpc/of_handler/vdevice.c --- a/xen/arch/powerpc/of_handler/vdevice.c Thu Jul 05 10:19:25 2007 +0100 +++ b/xen/arch/powerpc/of_handler/vdevice.c Fri Jul 06 16:01:04 2007 -0500 @@ -36,7 +36,7 @@ ofh_vty_init(ofdn_t chosen, ulong b) /* find the vty */ n = ofd_node_find(mem, - DRELA((const char *)"/vdevice/vty", b)); + DRELA((const char *)"/vdevice/vty", b)); if (n > 0) { /* PAPR VTERM */ ret = ofd_getprop(mem, n, DRELA((const char *)"reg", b), diff -r d54d47fc8c6c -r 8a8e6dfa6dea xen/arch/powerpc/of_handler/xen_hvcall.S --- a/xen/arch/powerpc/of_handler/xen_hvcall.S Thu Jul 05 10:19:25 2007 +0100 +++ b/xen/arch/powerpc/of_handler/xen_hvcall.S Fri Jul 06 16:01:04 2007 -0500 @@ -1,19 +1,21 @@ /* - * Copyright (C) 2005 Jimi Xenidis <jimix@xxxxxxxxxxxxxx>, IBM Corporation - * * 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright (C) IBM Corp. 2005, 2007 + * + * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx> */ #include <asm/config.h> @@ -26,3 +28,17 @@ _GLOBAL(xen_hvcall) _GLOBAL(xen_hvcall) HSC blr + +/* The following stub will get instantiated as RTAS in the guest */ +#define H_RTAS_PROXY 23 + .p2align 3 + .global _rtas_image_start + .global _rtas_image_end +_rtas_image_start: + mr r4,r3 + lis r3,0xffff + ori r3,r3,H_RTAS_PROXY + HSC + blr + nop +_rtas_image_end: diff -r d54d47fc8c6c -r 8a8e6dfa6dea xen/arch/powerpc/ofd_fixup.c --- a/xen/arch/powerpc/ofd_fixup.c Thu Jul 05 10:19:25 2007 +0100 +++ b/xen/arch/powerpc/ofd_fixup.c Fri Jul 06 16:01:04 2007 -0500 @@ -26,8 +26,6 @@ #include "of-devtree.h" #include "oftree.h" #include "rtas.h" - -#undef RTAS ofdn_t ofd_boot_cpu; @@ -307,26 +305,6 @@ static ofdn_t ofd_chosen_props(void *m, return n; } -#ifdef RTAS -static ofdn_t ofd_rtas_props(void *m) -{ - static const char path[] = "/rtas"; - static const char hypertas[] = "dummy"; - ofdn_t p; - ofdn_t n; - - /* just enough to make linux think its on LPAR */ - - p = ofd_node_find(m, "/"); - - n = ofd_node_add(m, p, path, sizeof(path)); - ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1); - ofd_prop_add(m, n, "ibm,hypertas-functions", hypertas, sizeof (hypertas)); - - return n; -} -#endif - static ofdn_t ofd_xen_props(void *m, struct domain *d, ulong shared_info) { ofdn_t n; @@ -382,8 +360,8 @@ static ofdn_t ofd_xen_props(void *m, str return n; } -int ofd_dom0_fixup(struct domain *d, ulong mem, const char *cmdline, - ulong shared_info) +ulong ofd_dom0_fixup(struct domain *d, ulong mem, const char *cmdline, + ulong shared_info) { void *m; const ofdn_t n = OFD_ROOT; @@ -423,11 +401,8 @@ int ofd_dom0_fixup(struct domain *d, ulo printk("Remove original /rtas\n"); ofd_prune_path(m, "/rtas"); -#ifdef RTAS - printk("Create a new RTAS with just enough stuff to convince " - "Linux that its on LPAR\n"); - ofd_rtas_props(m); -#endif + rtas_proxy_init(m); + #ifdef FIX_COMPAT const char compat[] = "Hypervisor,Maple"; r = ofd_prop_add(m, n, "compatible", compat, sizeof (compat)); @@ -446,5 +421,5 @@ int ofd_dom0_fixup(struct domain *d, ulo #ifdef DEBUG ofd_walk(m, __func__, OFD_ROOT, ofd_dump_props, OFD_DUMP_ALL); #endif - return 1; -} + return ofd_size(m); +} diff -r d54d47fc8c6c -r 8a8e6dfa6dea xen/arch/powerpc/oftree.h --- a/xen/arch/powerpc/oftree.h Thu Jul 05 10:19:25 2007 +0100 +++ b/xen/arch/powerpc/oftree.h Fri Jul 06 16:01:04 2007 -0500 @@ -28,8 +28,8 @@ extern ulong oftree_end; extern ulong oftree_end; extern ofdn_t ofd_boot_cpu; -extern int ofd_dom0_fixup(struct domain *d, ulong mem, const char *cmdline, - ulong shared_info); +extern ulong ofd_dom0_fixup(struct domain *d, ulong mem, const char *cmdline, + ulong shared_info); extern void ofd_memory_props(void *m, struct domain *d); extern int firmware_image_start[0]; diff -r d54d47fc8c6c -r 8a8e6dfa6dea xen/arch/powerpc/powerpc64/hypercall_table.S --- a/xen/arch/powerpc/powerpc64/hypercall_table.S Thu Jul 05 10:19:25 2007 +0100 +++ b/xen/arch/powerpc/powerpc64/hypercall_table.S Fri Jul 06 16:01:04 2007 -0500 @@ -27,7 +27,7 @@ __hypercall_table: .quad do_grant_table_op /* 20 */ .quad do_vm_assist .quad 0 /* do_update_va_mapping_otherdomain */ - .quad 0 /* do_switch_vm86 */ + .quad do_rtas_proxy /* do_switch_vm86 */ .quad do_vcpu_op .quad do_ni_hypercall /* 25 */ .quad 0 /* do_mmuext_op */ diff -r d54d47fc8c6c -r 8a8e6dfa6dea xen/arch/powerpc/rtas.c --- a/xen/arch/powerpc/rtas.c Thu Jul 05 10:19:25 2007 +0100 +++ b/xen/arch/powerpc/rtas.c Fri Jul 06 16:01:04 2007 -0500 @@ -13,7 +13,7 @@ * 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 + * Copyright (C) IBM Corp. 2006, 2007 * * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx> */ @@ -22,24 +22,16 @@ #include <xen/init.h> #include <xen/lib.h> #include <xen/errno.h> +#include <xen/sched.h> #include "of-devtree.h" #include "rtas.h" -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) +int rtas_call(void *r) { if (rtas_entry == 0) return -ENOSYS; @@ -47,11 +39,51 @@ static int rtas_call(struct rtas_args *r return prom_call(r, rtas_base, rtas_entry, rtas_msr); } +/* rtas always uses physical address */ +void *rtas_remote_addr(ulong addr, ulong length) +{ + struct vcpu *v = get_current(); + struct domain *d = v->domain; + ulong mfn; + ulong mfn_end; + + mfn = gmfn_to_mfn(d, addr >> PAGE_SHIFT); + if (mfn == INVALID_MFN) + return NULL; + + /* a little paranoid since almost everyone will pass us page + * bounded thingies, but just in case */ + mfn_end = gmfn_to_mfn(d, (addr + length) >> PAGE_SHIFT); + if (mfn_end == INVALID_MFN) + return NULL; + + return (void *)((mfn << PAGE_SHIFT) | (addr & (PAGE_SIZE - 1))); +} + +/* these do not proxy */ +#define RTAS_HALT 0 +#define RTAS_REBOOT 1 + +struct rtas_token rt_power_off = { .name = "power-off", .token = -1, }; +struct rtas_token rt_system_reboot = { .name = "system-reboot", .token = -1}; + +static struct rtas_token *tokens[] = { + /* these do not proxy */ + [RTAS_HALT] = &rt_power_off, + [RTAS_REBOOT] = &rt_system_reboot, + &rt_nvram_store, + &rt_nvram_fetch, + &rt_manage_flash, + &rt_validate_flash, + &rt_update_reboot_flash +}; + +static int rtas_proxy; + int __init rtas_init(void *m) { - static const char halt[] = "power-off"; - static const char reboot[] = "system-reboot"; ofdn_t n; + int i; if (rtas_entry == 0) return -ENOSYS; @@ -60,22 +92,87 @@ int __init rtas_init(void *m) 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)); + for (i = 0; i < ARRAY_SIZE(tokens); i++) { + ofd_getprop(m, n, tokens[i]->name, + &tokens[i]->token, sizeof (tokens[i]->token)); + if (!rtas_proxy && tokens[i]->proxy && tokens[i]->token != -1) + rtas_proxy = 1; + } return 1; +} + +int rtas_proxy_init(void *m) +{ + static const char path[] = "/rtas"; + ofdn_t p; + ofdn_t n; + int i; + + if (!rtas_proxy) + return -1; + + printk("Create a new /rtas with tokens Xen is willing to proxy\n"); + + p = ofd_node_find(m, "/"); + + n = ofd_node_add(m, p, path, sizeof(path)); + ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1); + + /* and the tokens for proxy */ + for (i = 0; i < ARRAY_SIZE(tokens); i++) { + if (tokens[i]->proxy && tokens[i]->token != -1) + ofd_prop_add(m, n, tokens[i]->name, &i, sizeof (i)); + } + return n; +} + +int do_rtas_proxy(ulong arg) +{ + struct rtas_args *r; + unsigned i; + int token; + ulong sz; + + if (!IS_PRIV(current->domain)) + return -EPERM; + if (!rtas_proxy) + return -ENOSYS; + + /* has to be at least 5 words */ + sz = (3 + 1 + 1) * sizeof (int); + r = rtas_remote_addr(arg, sz); + if (r == NULL) { + /* this is about all we can do at this point */ + return -1; + } + /* make sure we can deal with everything */ + sz = (3 + r->ra_nargs + r->ra_nrets) * sizeof (int); + if (rtas_remote_addr(arg, sz) == NULL) { + r->ra_args[r->ra_nargs] = RTAS_HW; + return -1; + } + + i = r->ra_token; + token = tokens[i]->token; + + if (i < ARRAY_SIZE(tokens) && + tokens[i]->proxy != NULL && + token != -1) + return tokens[i]->proxy(token, r); + + return -1; } int rtas_halt(void) { struct rtas_args r; - - if (rtas_halt_token == -1) - return -1; - - r.ra_token = rtas_halt_token; + int token = tokens[RTAS_HALT]->token; + + if (token == -1) + return -1; + + r.ra_token = token; r.ra_nargs = 2; r.ra_nrets = 1; r.ra_args[0] = 0; @@ -89,10 +186,12 @@ rtas_reboot(void) { struct rtas_args r; - if (rtas_reboot_token == -1) - return -ENOSYS; - - r.ra_token = rtas_reboot_token; + int token = tokens[RTAS_REBOOT]->token; + + if (token == -1) + return -1; + + r.ra_token = token; r.ra_nargs = 2; r.ra_nrets = 1; r.ra_args[0] = 0; diff -r d54d47fc8c6c -r 8a8e6dfa6dea xen/arch/powerpc/rtas.h --- a/xen/arch/powerpc/rtas.h Thu Jul 05 10:19:25 2007 +0100 +++ b/xen/arch/powerpc/rtas.h Fri Jul 06 16:01:04 2007 -0500 @@ -26,9 +26,40 @@ extern unsigned long rtas_base; extern unsigned long rtas_base; extern unsigned long rtas_end; +struct rtas_args { + int ra_token; + int ra_nargs; + int ra_nrets; + int ra_args[10]; +} __attribute__ ((aligned(8))); + +struct rtas_token { + char *name; + int (*proxy)(int token, struct rtas_args *r); + int token; +}; + +extern struct rtas_token rt_power_off; +extern struct rtas_token rt_system_reboot; +extern struct rtas_token rt_nvram_fetch; +extern struct rtas_token rt_nvram_store; +extern struct rtas_token rt_manage_flash; +extern struct rtas_token rt_validate_flash; +extern struct rtas_token rt_update_reboot_flash; + +/* RTAS errors */ +#define RTAS_HW -1 +#define RTAS_BUSY -2 +#define RTAS_PARAMETER -3 + + extern int prom_call(void *arg, unsigned base, unsigned long func, unsigned long msr); extern int rtas_init(void *); extern int rtas_halt(void); extern int rtas_reboot(void); +extern int rtas_proxy_init(void *m); +extern int do_rtas_proxy(ulong arg); +extern void *rtas_remote_addr(ulong addr, ulong length); +extern int rtas_call(void *r); #endif diff -r d54d47fc8c6c -r 8a8e6dfa6dea xen/arch/powerpc/rtas_flash.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/powerpc/rtas_flash.c Fri Jul 06 16:01:04 2007 -0500 @@ -0,0 +1,182 @@ +/* + * 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. 2007 + * + * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx> + */ + +#include <xen/config.h> +#include <xen/init.h> +#include <xen/lib.h> +#include <xen/sched.h> +#include "rtas.h" + +static int rtas_manage_flash(int token, struct rtas_args *ra) +{ + struct rtas_args r; + ulong sz = (3 + ra->ra_nargs + ra->ra_nrets) * sizeof (int); + int ret; + + if (ra->ra_nargs != 1 || ra->ra_nrets != 1) { + ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER; + return -1; + } + memcpy(&r, ra, sz); + r.ra_token = token; + + ret = rtas_call(&r); + ra->ra_args[ra->ra_nargs] = r.ra_args[r.ra_nargs]; + return ret; +} +struct rtas_token rt_manage_flash = { + .name = "ibm,manage-flash-image", + .proxy = rtas_manage_flash, + .token = -1 +}; + +static int rtas_validate_flash(int token, struct rtas_args *ra) +{ + ulong length = ra->ra_args[1]; + char *buffer; + char *local; + struct rtas_args r; + ulong sz = (3 + ra->ra_nargs + ra->ra_nrets) * sizeof (int); + int ret; + + if (ra->ra_nargs != 2 || ra->ra_nrets != 2) { + ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER; + return -1; + } + + /* the original pointer can be in memory that is too high so we + * need to do it locally */ + buffer = rtas_remote_addr(ra->ra_args[0], length); + if (buffer == NULL) { + ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER; + return -1; + } + + local = xmalloc_bytes(length); + if (local == NULL) { + printk("%s: could not allocate local buffer size: 0x%lx\n", + __func__, length); + ra->ra_args[ra->ra_nargs] = RTAS_HW; + return -1; + } + /* RTAS is 32bits so we need to make sure that that local + * buffer is in that range */ + BUG_ON(((ulong)local + length) & ~0xffffffffUL); + + /* copy the remote buffer to the local one */ + memcpy(local, buffer, length); + + memcpy(&r, ra, sz); + r.ra_token = token; + r.ra_args[0] = (unsigned)(ulong)local; + ret = rtas_call(&r); + ra->ra_args[ra->ra_nargs] = r.ra_args[r.ra_nargs]; + ra->ra_args[ra->ra_nargs + 1] = r.ra_args[r.ra_nargs + 1]; + xfree(local); + return ret; +} + +struct rtas_token rt_validate_flash = { + .name = "ibm,validate-flash-image", + .proxy = rtas_validate_flash, + .token = -1 +}; + +/* flash data structs */ +struct flash_block { + u64 addr; + u64 length; +}; +struct flash_block_list { + struct { + u64 ver:8; + u64 bytes:56; + } header; + u64 *next; + struct flash_block blocks[0]; +}; + +static int safe_to_flash; +static int rtas_update_reboot_flash(int token, struct rtas_args *ra) +{ + struct rtas_args r; + ulong sz = (3 + ra->ra_nargs + ra->ra_nrets) * sizeof (int); + int ret; + void *local; + struct flash_block_list *l; + ulong blocks; + + if (ra->ra_nargs != 1 || ra->ra_nrets != 1) { + ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER; + return -1; + } + + if (!safe_to_flash) { + printk("%s: this has not been fully tested yet\n", __func__); + ra->ra_args[ra->ra_nargs] = RTAS_HW; + return -1; + } + + /* we only need to relocate the first block address to 4G, for now + * lets just bug on that */ + local = rtas_remote_addr(ra->ra_args[0], 16); + BUG_ON((ulong)local & ~0xffffffffUL); + + /* now we run through the block list and translate base addresses */ + l = (struct flash_block_list *)local; + + /* header and next count as one block */ + blocks = (l->header.bytes / sizeof (struct flash_block)) - 1; + if (blocks == 0) { + ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER; + return -1; + } + + /* go thru the block lists */ + do { + int i = 0; + + /* go thru the block in the list */ + for (i = 0; i < blocks; i++) { + void *addr; + + addr = rtas_remote_addr(l->blocks[i].addr, l->blocks[i].length); + BUG_ON(addr == NULL); + l->blocks[i].addr = (u64)addr; + } + l = (struct flash_block_list *)l->next; + } while (l != NULL); + + memcpy(&r, ra, sz); + r.ra_token = token; + + /* this arguement is a pointer to a block list */ + r.ra_args[0] = (unsigned)(ulong)local; + + ret = rtas_call(&r); + ra->ra_args[ra->ra_nargs] = r.ra_args[r.ra_nargs]; + return ret; +} + +struct rtas_token rt_update_reboot_flash = { + .name = "ibm,update-flash-64-and-reboot", + .proxy = rtas_update_reboot_flash, + .token = -1 +}; diff -r d54d47fc8c6c -r 8a8e6dfa6dea xen/arch/powerpc/rtas_nvram.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/powerpc/rtas_nvram.c Fri Jul 06 16:01:04 2007 -0500 @@ -0,0 +1,129 @@ +/* + * 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. 2007 + * + * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx> + */ + +#include <xen/config.h> +#include <xen/init.h> +#include <xen/lib.h> +#include <xen/sched.h> +#include "rtas.h" + +static int rtas_nvram_store(int token, struct rtas_args *ra) +{ + ulong length = ra->ra_args[2]; + char *buffer; + char *local; + struct rtas_args r; + ulong sz = (3 + ra->ra_nargs + ra->ra_nrets) * sizeof (int); + int ret; + + if (ra->ra_nargs != 3 || ra->ra_nrets != 2) { + ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER; + return -1; + } + + /* the original pointer can be in memory that is too high so we + * need to do it locally */ + buffer = rtas_remote_addr(ra->ra_args[1], length); + if (buffer == NULL) { + ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER; + return -1; + } + + local = xmalloc_bytes(length); + if (local == NULL) { + printk("%s: could not allocate local buffer size: 0x%lx\n", + __func__, length); + ra->ra_args[ra->ra_nargs] = RTAS_HW; + return -1; + } + /* RTAS is 32bits so we need to make sure that that local + * buffer is in that range */ + BUG_ON(((ulong)local + length) & ~0xffffffffUL); + + /* copy the remote buffer to the local one */ + memcpy(local, buffer, length); + + memcpy(&r, ra, sz); + r.ra_token = token; + r.ra_args[1] = (unsigned)(ulong)local; + + ret = rtas_call(&r); + ra->ra_args[ra->ra_nargs] = r.ra_args[r.ra_nargs]; + ra->ra_args[ra->ra_nargs + 1] = r.ra_args[r.ra_nargs + 1]; + xfree(local); + return ret; +} + +struct rtas_token rt_nvram_store = { + .name = "nvram-store", + .proxy = rtas_nvram_store, + .token = -1 +}; + +static int rtas_nvram_fetch(int token, struct rtas_args *ra) +{ + ulong length = ra->ra_args[2]; + char *buffer; + char *local; + struct rtas_args r; + ulong sz = (3 + ra->ra_nargs + ra->ra_nrets) * sizeof (int); + int ret; + + if (ra->ra_nargs != 3 || ra->ra_nrets != 2) { + ra->ra_args[ra->ra_nargs] = RTAS_PARAMETER; + return -1; + } + /* the original pointer can be in ememory that is too high so + * we need to do it locally */ + buffer = rtas_remote_addr(ra->ra_args[1], length); + + local = xmalloc_bytes(length); + if (local == NULL) { + printk("%s: could not allocate local buffer size: 0x%lx\n", + __func__, length); + ra->ra_args[ra->ra_nargs] = RTAS_HW; + return -1; + } + /* RTAS is 32bits so we need to make sure that that local + * buffer is in that range */ + BUG_ON(((ulong)local + length) & ~0xffffffffUL); + + memcpy(&r, ra, sz); + r.ra_token = token; + r.ra_args[1] = (unsigned)(ulong)local; + + ret = rtas_call(&r); + ra->ra_args[ra->ra_nargs] = r.ra_args[r.ra_nargs]; + ra->ra_args[ra->ra_nargs + 1] = r.ra_args[r.ra_nargs + 1]; + if (r.ra_args[r.ra_nargs] >= 0) { + /* copy from local to remote */ + sz = r.ra_args[r.ra_nargs + 1]; + memcpy(buffer, local, sz); + } + xfree(local); + return ret; +} + +struct rtas_token rt_nvram_fetch = { + .name = "nvram-fetch", + .proxy = rtas_nvram_fetch, + .token = -1 +}; + _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |