# 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
|