WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] [XEN][POWERPC] Merge with xen-unstable.hg

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [XEN][POWERPC] Merge with xen-unstable.hg.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 09 Jul 2007 04:22:40 -0700
Delivery-date: Mon, 09 Jul 2007 04:20:56 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [XEN][POWERPC] Merge with xen-unstable.hg., Xen patchbot-unstable <=