[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.