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] [powerpc] Initial checkin of new powerpc

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [powerpc] Initial checkin of new powerpc files.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 14 Jul 2006 17:40:32 +0000
Delivery-date: Fri, 14 Jul 2006 10:43:39 -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 kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID 050de6b53961b91059449bad6059a76bdf508516
# Parent  69c4f7963a19c0e1243f25532a52592bc5b170cf
[powerpc] Initial checkin of new powerpc files.
From: Hollis Blanchard et al (IBM)
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 config/powerpc64.mk                                |    4 
 tools/libxc/xc_ppc_linux_build.c                   |  408 +++++++
 xen/arch/powerpc/0opt.c                            |   28 
 xen/arch/powerpc/Makefile                          |  117 ++
 xen/arch/powerpc/Rules.mk                          |   51 
 xen/arch/powerpc/audit.c                           |   45 
 xen/arch/powerpc/bitops.c                          |   94 +
 xen/arch/powerpc/boot/boot32.S                     |   75 +
 xen/arch/powerpc/boot/start.S                      |   51 
 xen/arch/powerpc/boot_of.c                         | 1016 +++++++++++++++++++
 xen/arch/powerpc/dart.c                            |  299 +++++
 xen/arch/powerpc/dart.h                            |   36 
 xen/arch/powerpc/dart_u3.c                         |  108 ++
 xen/arch/powerpc/dart_u4.c                         |  177 +++
 xen/arch/powerpc/delay.c                           |   37 
 xen/arch/powerpc/dom0_ops.c                        |   87 +
 xen/arch/powerpc/domain.c                          |  251 ++++
 xen/arch/powerpc/domain_build.c                    |  285 +++++
 xen/arch/powerpc/elf32.c                           |    5 
 xen/arch/powerpc/exceptions.c                      |   87 +
 xen/arch/powerpc/exceptions.h                      |   57 +
 xen/arch/powerpc/external.c                        |  247 ++++
 xen/arch/powerpc/float.S                           |  243 ++++
 xen/arch/powerpc/gdbstub.c                         |  207 +++
 xen/arch/powerpc/hcalls.c                          |  172 +++
 xen/arch/powerpc/htab.c                            |   69 +
 xen/arch/powerpc/iommu.c                           |   79 +
 xen/arch/powerpc/iommu.h                           |   28 
 xen/arch/powerpc/irq.c                             |   22 
 xen/arch/powerpc/mambo.S                           |   64 +
 xen/arch/powerpc/mm.c                              |  141 ++
 xen/arch/powerpc/mpic.c                            | 1109 +++++++++++++++++++++
 xen/arch/powerpc/mpic_init.c                       |  390 +++++++
 xen/arch/powerpc/mpic_init.h                       |   29 
 xen/arch/powerpc/of-devtree.c                      | 1088 ++++++++++++++++++++
 xen/arch/powerpc/of-devtree.h                      |  139 ++
 xen/arch/powerpc/of-devwalk.c                      |  135 ++
 xen/arch/powerpc/of_handler/Makefile               |   31 
 xen/arch/powerpc/of_handler/console.c              |  233 ++++
 xen/arch/powerpc/of_handler/control.c              |   90 +
 xen/arch/powerpc/of_handler/cpu.c                  |   82 +
 xen/arch/powerpc/of_handler/devtree.c              |  266 +++++
 xen/arch/powerpc/of_handler/head.S                 |  152 ++
 xen/arch/powerpc/of_handler/io.c                   |  160 +++
 xen/arch/powerpc/of_handler/leap.S                 |   38 
 xen/arch/powerpc/of_handler/memcmp.c               |   39 
 xen/arch/powerpc/of_handler/memory.c               |  129 ++
 xen/arch/powerpc/of_handler/memset.c               |   67 +
 xen/arch/powerpc/of_handler/ofh.c                  |  454 ++++++++
 xen/arch/powerpc/of_handler/ofh.h                  |  164 +++
 xen/arch/powerpc/of_handler/papr.S                 |   97 +
 xen/arch/powerpc/of_handler/papr.h                 |   69 +
 xen/arch/powerpc/of_handler/services.c             |   96 +
 xen/arch/powerpc/of_handler/snprintf.c             |  332 ++++++
 xen/arch/powerpc/of_handler/strcmp.c               |   36 
 xen/arch/powerpc/of_handler/strlen.c               |   30 
 xen/arch/powerpc/of_handler/strncmp.c              |   39 
 xen/arch/powerpc/of_handler/strncpy.c              |   54 +
 xen/arch/powerpc/of_handler/strnlen.c              |   30 
 xen/arch/powerpc/of_handler/vdevice.c              |   74 +
 xen/arch/powerpc/of_handler/xen_hvcall.S           |   28 
 xen/arch/powerpc/of_handler/xencomm.c              |   84 +
 xen/arch/powerpc/ofd_fixup.c                       |  509 +++++++++
 xen/arch/powerpc/oftree.h                          |   33 
 xen/arch/powerpc/papr/Makefile                     |   10 
 xen/arch/powerpc/papr/debug.c                      |   84 +
 xen/arch/powerpc/papr/tce.c                        |   84 +
 xen/arch/powerpc/papr/vtce.c                       |  158 ++
 xen/arch/powerpc/papr/vterm.c                      |   70 +
 xen/arch/powerpc/papr/xlate.c                      |  499 +++++++++
 xen/arch/powerpc/physdev.c                         |   24 
 xen/arch/powerpc/powerpc64/Makefile                |   11 
 xen/arch/powerpc/powerpc64/asm-offsets.c           |   65 +
 xen/arch/powerpc/powerpc64/domain.c                |  143 ++
 xen/arch/powerpc/powerpc64/exceptions.S            |  519 +++++++++
 xen/arch/powerpc/powerpc64/hypercall_table.S       |   83 +
 xen/arch/powerpc/powerpc64/io.S                    |  142 ++
 xen/arch/powerpc/powerpc64/memcpy.S                |  171 +++
 xen/arch/powerpc/powerpc64/ppc970.c                |  164 +++
 xen/arch/powerpc/powerpc64/prom_call.S             |  116 ++
 xen/arch/powerpc/powerpc64/string.S                |  286 +++++
 xen/arch/powerpc/powerpc64/traps.c                 |   50 
 xen/arch/powerpc/ppc32/prom_call.c                 |   41 
 xen/arch/powerpc/rtas.c                            |   24 
 xen/arch/powerpc/setup.c                           |  370 +++++++
 xen/arch/powerpc/smp.c                             |   60 +
 xen/arch/powerpc/tce.h                             |   71 +
 xen/arch/powerpc/time.c                            |  131 ++
 xen/arch/powerpc/usercopy.c                        |  232 ++++
 xen/arch/powerpc/xen.lds                           |  226 ++++
 xen/include/asm-powerpc/asm_defns.h                |   28 
 xen/include/asm-powerpc/atomic.h                   |  211 +++
 xen/include/asm-powerpc/bitops.h                   |  309 +++++
 xen/include/asm-powerpc/cache.h                    |   60 +
 xen/include/asm-powerpc/config.h                   |   77 +
 xen/include/asm-powerpc/current.h                  |   79 +
 xen/include/asm-powerpc/debugger.h                 |   44 
 xen/include/asm-powerpc/delay.h                    |   28 
 xen/include/asm-powerpc/desc.h                     |   25 
 xen/include/asm-powerpc/div64.h                    |   33 
 xen/include/asm-powerpc/domain.h                   |  114 ++
 xen/include/asm-powerpc/event.h                    |   99 +
 xen/include/asm-powerpc/flushtlb.h                 |  108 ++
 xen/include/asm-powerpc/grant_table.h              |   64 +
 xen/include/asm-powerpc/guest_access.h             |   99 +
 xen/include/asm-powerpc/hardirq.h                  |   21 
 xen/include/asm-powerpc/hcalls.h                   |   34 
 xen/include/asm-powerpc/htab.h                     |  142 ++
 xen/include/asm-powerpc/hypercall.h                |   26 
 xen/include/asm-powerpc/init.h                     |   59 +
 xen/include/asm-powerpc/io.h                       |   67 +
 xen/include/asm-powerpc/iocap.h                    |   26 
 xen/include/asm-powerpc/irq.h                      |   31 
 xen/include/asm-powerpc/mach-default/irq_vectors.h |  105 +
 xen/include/asm-powerpc/memory.h                   |   39 
 xen/include/asm-powerpc/misc.h                     |   33 
 xen/include/asm-powerpc/mm.h                       |  224 ++++
 xen/include/asm-powerpc/mpic.h                     |  294 +++++
 xen/include/asm-powerpc/msr.h                      |   66 +
 xen/include/asm-powerpc/multicall.h                |   27 
 xen/include/asm-powerpc/page.h                     |  116 ++
 xen/include/asm-powerpc/papr.h                     |  218 ++++
 xen/include/asm-powerpc/pci.h                      |   35 
 xen/include/asm-powerpc/powerpc64/config.h         |   45 
 xen/include/asm-powerpc/powerpc64/ppc970-hid.h     |  107 ++
 xen/include/asm-powerpc/powerpc64/ppc970.h         |   31 
 xen/include/asm-powerpc/powerpc64/procarea.h       |   36 
 xen/include/asm-powerpc/powerpc64/processor.h      |  193 +++
 xen/include/asm-powerpc/powerpc64/string.h         |   40 
 xen/include/asm-powerpc/processor.h                |  202 +++
 xen/include/asm-powerpc/reg_defs.h                 |  180 +++
 xen/include/asm-powerpc/regs.h                     |   25 
 xen/include/asm-powerpc/shadow.h                   |   45 
 xen/include/asm-powerpc/smp.h                      |   36 
 xen/include/asm-powerpc/smpboot.h                  |   21 
 xen/include/asm-powerpc/spinlock.h                 |  221 ++++
 xen/include/asm-powerpc/string.h                   |   26 
 xen/include/asm-powerpc/system.h                   |  243 ++++
 xen/include/asm-powerpc/time.h                     |   42 
 xen/include/asm-powerpc/types.h                    |   69 +
 xen/include/asm-powerpc/uaccess.h                  |   38 
 xen/include/public/arch-powerpc.h                  |  119 ++
 xen/include/public/xencomm.h                       |   37 
 143 files changed, 19427 insertions(+)

diff -r 69c4f7963a19 -r 050de6b53961 config/powerpc64.mk
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/config/powerpc64.mk       Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,4 @@
+CONFIG_POWERPC := y
+
+CFLAGS += -DELFSIZE=64
+LIBDIR := lib
diff -r 69c4f7963a19 -r 050de6b53961 tools/libxc/xc_ppc_linux_build.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxc/xc_ppc_linux_build.c  Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,408 @@
+/*
+ * 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.
+ *
+ * Copyright (C) IBM Corporation 2006
+ *
+ * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <inttypes.h>
+
+#include <xen/dom0_ops.h>
+#include <xen/memory.h>
+#include <xc_private.h>
+#include <xg_private.h>
+#include <xenctrl.h>
+
+/* XXX 64M hack */
+#define MEMSIZE (64UL << 20)
+#define INITRD_ADDR (24UL << 20)
+
+int verbose;
+#define VERBOSE(stuff, ...) \
+    if (verbose) \
+        stuff __VA_ARGS__;
+
+#define ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1)))
+
+#define max(x,y) ({ \
+        const typeof(x) _x = (x);       \
+        const typeof(y) _y = (y);       \
+        (void) (&_x == &_y);            \
+        _x > _y ? _x : _y; })
+
+static void *load_file(const char *path, unsigned long *filesize)
+{
+    void *img;
+    ssize_t size;
+    int fd;
+
+    VERBOSE(printf("load_file(%s)\n", path));
+
+    fd = open(path, O_RDONLY);
+    if (fd < 0) {
+        perror(path);
+        return NULL;
+    }
+
+    size = lseek(fd, 0, SEEK_END);
+    if (size < 0) {
+        perror(path);
+        close(fd);
+        return NULL;
+    }
+    lseek(fd, 0, SEEK_SET);
+
+    img = malloc(size);
+    if (img == NULL) {
+        perror(path);
+        close(fd);
+        return NULL;
+    }
+
+    size = read(fd, img, size);
+    if (size <= 0) {
+        perror(path);
+        close(fd);
+        free(img);
+        return NULL;
+    }
+
+    if (filesize)
+        *filesize = size;
+    close(fd);
+    return img;
+}
+
+static int init_boot_vcpu(
+    int xc_handle,
+    int domid,
+    struct domain_setup_info *dsi,
+    unsigned long dtb,
+    unsigned long kaddr)
+{
+    vcpu_guest_context_t ctxt;
+    int rc;
+
+    memset(&ctxt.user_regs, 0x55, sizeof(ctxt.user_regs));
+    ctxt.user_regs.pc = dsi->v_kernentry;
+    ctxt.user_regs.msr = 0;
+    ctxt.user_regs.gprs[1] = 32<<20; /* XXX arbitrary stack address */
+    ctxt.user_regs.gprs[3] = dtb;
+    ctxt.user_regs.gprs[4] = kaddr;
+    ctxt.user_regs.gprs[5] = 0;
+
+    VERBOSE(printf("xc_vcpu_setvcpucontext:\n"
+                 "  pc 0x%"PRIx64", msr 0x016%"PRIx64"\n"
+                 "  r1-5 %016"PRIx64" %016"PRIx64" %016"PRIx64" %016"PRIx64
+                 " %016"PRIx64"\n",
+                 ctxt.user_regs.pc, ctxt.user_regs.msr,
+                 ctxt.user_regs.gprs[1],
+                 ctxt.user_regs.gprs[2],
+                 ctxt.user_regs.gprs[3],
+                 ctxt.user_regs.gprs[4],
+                 ctxt.user_regs.gprs[5]));
+    rc = xc_vcpu_setcontext(xc_handle, domid, 0, &ctxt);
+    if (rc < 0)
+        perror("setdomaininfo");
+
+    return rc;
+}
+
+static int install_image(
+        int xc_handle,
+        int domid,
+        xen_pfn_t *page_array,
+        void *image,
+        unsigned long paddr,
+        unsigned long size)
+{
+    uint8_t *img = image;
+    int i;
+    int rc = 0;
+
+    if (paddr & ~PAGE_MASK) {
+        printf("*** unaligned address\n");
+        return -1;
+    }
+
+    for (i = 0; i < size; i += PAGE_SIZE) {
+        void *page = img + i;
+        xen_pfn_t pfn = (paddr + i) >> PAGE_SHIFT;
+        xen_pfn_t mfn = page_array[pfn];
+
+        rc = xc_copy_to_domain_page(xc_handle, domid, mfn, page);
+        if (rc < 0) {
+            perror("xc_copy_to_domain_page");
+            break;
+        }
+    }
+    return rc;
+}
+
+/* XXX be more flexible about placement in memory */
+static int load_dtb(
+    int xc_handle,
+    int domid,
+    const char *dtb_path,
+    unsigned long dtb_addr,
+    struct domain_setup_info *dsi,
+    xen_pfn_t *page_array)
+{
+    uint8_t *img;
+    unsigned long dtb_size;
+    int rc = 0;
+
+    img = load_file(dtb_path, &dtb_size);
+    if (img == NULL) {
+        rc = -1;
+        goto out;
+    }
+
+    VERBOSE(printf("copying device tree to 0x%lx[0x%lx]\n",
+            dtb_addr, dtb_size));
+    rc = install_image(xc_handle, domid, page_array, img, dtb_addr, dtb_size);
+
+out:
+    free(img);
+    return rc;
+}
+
+unsigned long spin_list[] = {
+#if 0
+    0x100,
+    0x200,
+    0x300,
+    0x380,
+    0x400,
+    0x480,
+    0x500,
+    0x700,
+    0x900,
+    0xc00,
+#endif
+    0
+};
+
+/* XXX yes, this is a hack */
+static void hack_kernel_img(char *img)
+{
+    const off_t file_offset = 0x10000;
+    unsigned long *addr = spin_list;
+
+    while (*addr) {
+        uint32_t *instruction = (uint32_t *)(img + *addr + file_offset);
+        printf("installing spin loop at %lx (%x)\n", *addr, *instruction);
+        *instruction = 0x48000000;
+        addr++;
+    }
+}
+
+static int load_kernel(
+    int xc_handle,
+    int domid,
+    const char *kernel_path,
+    struct domain_setup_info *dsi,
+    xen_pfn_t *page_array)
+{
+    struct load_funcs load_funcs;
+    char *kernel_img;
+    unsigned long kernel_size;
+    int rc;
+
+    /* load the kernel ELF file */
+    kernel_img = load_file(kernel_path, &kernel_size);
+    if (kernel_img == NULL) {
+        rc = -1;
+        goto out;
+    }
+
+    hack_kernel_img(kernel_img);
+
+    VERBOSE(printf("probe_elf\n"));
+    rc = probe_elf(kernel_img, kernel_size, &load_funcs);
+    if (rc < 0) {
+        rc = -1;
+        printf("%s is not an ELF file\n", kernel_path);
+        goto out;
+    }
+
+    VERBOSE(printf("parseimage\n"));
+    rc = (load_funcs.parseimage)(kernel_img, kernel_size, dsi);
+    if (rc < 0) {
+        rc = -1;
+        goto out;
+    }
+
+    VERBOSE(printf("loadimage\n"));
+    (load_funcs.loadimage)(kernel_img, kernel_size, xc_handle, domid,
+            page_array, dsi);
+
+    VERBOSE(printf("  v_start     %016"PRIx64"\n", dsi->v_start));
+    VERBOSE(printf("  v_end       %016"PRIx64"\n", dsi->v_end));
+    VERBOSE(printf("  v_kernstart %016"PRIx64"\n", dsi->v_kernstart));
+    VERBOSE(printf("  v_kernend   %016"PRIx64"\n", dsi->v_kernend));
+    VERBOSE(printf("  v_kernentry %016"PRIx64"\n", dsi->v_kernentry));
+
+out:
+    free(kernel_img);
+    return rc;
+}
+
+static int load_initrd(
+    int xc_handle,
+    int domid,
+    xen_pfn_t *page_array,
+    const char *initrd_path,
+    unsigned long *base,
+    unsigned long *len)
+{
+    uint8_t *initrd_img;
+    int rc = -1;
+
+    /* load the initrd file */
+    initrd_img = load_file(initrd_path, len);
+    if (initrd_img == NULL)
+        return -1;
+
+    VERBOSE(printf("copying initrd to 0x%lx[0x%lx]\n", INITRD_ADDR, *len));
+    if (install_image(xc_handle, domid, page_array, initrd_img, INITRD_ADDR,
+                *len))
+        goto out;
+
+    *base = INITRD_ADDR;
+    rc = 0;
+
+out:
+    free(initrd_img);
+    return rc;
+}
+
+static unsigned long create_start_info(start_info_t *si,
+        unsigned int console_evtchn, unsigned int store_evtchn)
+{
+    unsigned long eomem;
+    unsigned long si_addr;
+
+    memset(si, 0, sizeof(*si));
+    snprintf(si->magic, sizeof(si->magic), "xen-%d.%d-powerpc64HV", 3, 0);
+
+    eomem = MEMSIZE;
+    si->nr_pages = eomem >> PAGE_SHIFT;
+    si->shared_info = eomem - (PAGE_SIZE * 1);
+    si->store_mfn = si->nr_pages - 2;
+    si->store_evtchn = store_evtchn;
+    si->console_mfn = si->nr_pages - 3;
+    si->console_evtchn = console_evtchn;
+    si_addr = eomem - (PAGE_SIZE * 4);
+
+    return si_addr;
+}
+
+static int get_page_array(int xc_handle, int domid, xen_pfn_t **page_array)
+{
+    int nr_pages;
+    int rc;
+
+    VERBOSE(printf("xc_get_tot_pages\n"));
+    nr_pages = xc_get_tot_pages(xc_handle, domid);
+    VERBOSE(printf("  0x%x\n", nr_pages));
+
+    *page_array = malloc(nr_pages * sizeof(xen_pfn_t));
+    if (*page_array == NULL) {
+        perror("malloc");
+        return -1;
+    }
+
+    VERBOSE(printf("xc_get_pfn_list\n"));
+    rc = xc_get_pfn_list(xc_handle, domid, *page_array, nr_pages);
+    if (rc != nr_pages) {
+        perror("Could not get the page frame list");
+        return -1;
+    }
+
+    return 0;
+}
+
+int xc_linux_build(int xc_handle,
+                   uint32_t domid,
+                   const char *image_name,
+                   const char *initrd_name,
+                   const char *cmdline,
+                   const char *features,
+                   unsigned long flags,
+                   unsigned int store_evtchn,
+                   unsigned long *store_mfn,
+                   unsigned int console_evtchn,
+                   unsigned long *console_mfn)
+{
+    struct domain_setup_info dsi;
+    xen_pfn_t *page_array = NULL;
+    unsigned long kern_addr;
+    unsigned long dtb_addr;
+    unsigned long si_addr;
+    unsigned long initrd_base = 0;
+    unsigned long initrd_len = 0;
+    start_info_t si;
+    int rc = 0;
+
+    if (get_page_array(xc_handle, domid, &page_array)) {
+        rc = -1;
+        goto out;
+    }
+
+    if (load_kernel(xc_handle, domid, image_name, &dsi, page_array)) {
+        rc = -1;
+        goto out;
+    }
+    kern_addr = 0;
+
+    if (initrd_name && initrd_name[0] != '\0' &&
+        load_initrd(xc_handle, domid, page_array, initrd_name, &initrd_base,
+                &initrd_len)) {
+        rc = -1;
+        goto out;
+    }
+    /* XXX install initrd addr/len into device tree */
+
+    dtb_addr = (16 << 20);
+    if (load_dtb(xc_handle, domid, "DomU.dtb", dtb_addr, &dsi, page_array)) {
+        dtb_addr = 0;
+    }
+
+    si_addr = create_start_info(&si, store_evtchn, console_evtchn);
+    *console_mfn = si.console_mfn;
+    *store_mfn = si.store_mfn;
+    if (install_image(xc_handle, domid, page_array, &si, si_addr,
+                sizeof(start_info_t))) {
+        rc = -1;
+        goto out;
+    }
+
+    if (init_boot_vcpu(xc_handle, domid, &dsi, dtb_addr, kern_addr)) {
+        rc = -1;
+        goto out;
+    }
+
+out:
+    return rc;
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/0opt.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/0opt.c   Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,28 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <xen/config.h>
+#include <asm/misc.h>
+
+extern void __cmpxchg_called_with_bad_pointer(void);
+void __cmpxchg_called_with_bad_pointer(void)
+{
+    trap();
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/Makefile Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,117 @@
+ifneq ($(DOM0_IMAGE),)
+builtin_dom0 := y
+endif
+
+subdir-$(HAS_PPC64) += powerpc64
+subdir-y += papr
+
+obj-y += audit.o
+obj-y += bitops.o
+obj-y += boot_of.o
+obj-y += dart.o
+obj-y += dart_u3.o
+obj-y += dart_u4.o
+obj-y += delay.o
+obj-y += dom0_ops.o
+obj-y += domain_build.o
+obj-y += domain.o
+obj-y += exceptions.o
+obj-y += external.o
+obj-y += float.o
+obj-y += hcalls.o
+obj-y += htab.o
+obj-y += iommu.o
+obj-y += irq.o
+obj-y += mambo.o
+obj-y += mm.o
+obj-y += mpic.o
+obj-y += mpic_init.o
+obj-y += of-devtree.o
+obj-y += of-devwalk.o
+obj-y += ofd_fixup.o
+obj-y += physdev.o
+obj-y += rtas.o
+obj-y += setup.o
+obj-y += smp.o
+obj-y += time.o
+obj-y += usercopy.o
+
+obj-$(debug) += 0opt.o
+obj-$(crash_debug) += gdbstub.o
+obj-$(builtin_dom0) += dom0.o
+
+obj-y += firmware_image.o
+
+obj-y += elf32.o
+
+# These are extra warnings like for the arch/ppc directory but may not
+# allow the rest of the tree to build.
+PPC_C_WARNINGS += -Wundef -Wmissing-prototypes -Wmissing-declarations
+CFLAGS += $(PPC_C_WARNINGS)
+
+LINK=0x3000000
+boot32_link_base = $(LINK)
+xen_link_offset  = 100
+xen_link_base    = $(patsubst %000,%$(xen_link_offset),$(LINK))
+
+#
+# The following flags are fed to gcc in order to link several
+# objects into a single ELF segment and to not link in any additional
+# objects that gcc would normally like to
+#
+OMAGIC = -N -nodefaultlibs -nostartfiles
+
+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: firmware
+       $(CROSS_COMPILE)objcopy --output-target=binary $< $@
+
+firmware_image.o: firmware_image
+       $(CROSS_COMPILE)objcopy --input-target=binary \
+               --output-target=elf64-powerpc \
+               --binary-architecture=powerpc \
+               --redefine-sym _binary_$<_start=$(@:%.o=%)_start \
+               --redefine-sym _binary_$<_end=$(@:%.o=%)_end \
+               --redefine-sym _binary_$<_size=$(@:%.o=%)_size  $< $@
+
+#
+# Hacks for included C files
+#
+irq.o: ../x86/irq.c
+physdev.o: ../x86/physdev.c
+
+HDRS += $(wildcard *.h)
+
+start.o: boot/start.S
+       $(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $@
+
+$(TARGET)-syms: start.o $(ALL_OBJS) xen.lds
+       $(CC) $(CFLAGS) $(OMAGIC) -Wl,-Ttext,$(xen_link_base),-T,xen.lds 
start.o $(ALL_OBJS) -o $@
+
+$(TARGET).bin: $(TARGET)-syms
+       $(CROSS_COMPILE)objcopy --output-target=binary $< $@
+
+$(TARGET).bin.o: $(TARGET).bin
+       $(CROSS_COMPILE)objcopy --input-target=binary \
+               --output-target=elf32-powerpc \
+               --binary-architecture=powerpc  $< $@
+
+boot32.o: boot/boot32.S
+       $(CC) -m32 -Wa,-a32,-mppc64bridge \
+               -D__ASSEMBLY__ -D__BRIDGE64__ $(CFLAGS) -c $< -o $@
+
+$(TARGET): boot32.o $(TARGET).bin.o
+       $(CC) -m32 -N -Wl,-melf32ppclinux -static -nostdlib \
+               -Wl,-Ttext,$(boot32_link_base)  -Wl,-Tdata,$(xen_link_base) \
+               $(CFLAGS) $^ -o $@
+
+asm-offsets.s: $(TARGET_SUBARCH)/asm-offsets.c $(HDRS)
+       $(CC) $(CFLAGS) -S -o $@ $<
+
+dom0.bin: $(DOM0_IMAGE)
+       cp $< $@
+
+clean::
+       $(MAKE) -f $(BASEDIR)/Rules.mk -C of_handler clean
+       rm -f firmware firmware_image dom0.bin
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/Rules.mk
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/Rules.mk Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,51 @@
+HAS_PPC64 := y
+
+CC := $(CROSS_COMPILE)gcc
+LD := $(CROSS_COMPILE)ld
+
+# These are goodess that applies to all source.
+C_WARNINGS := -Wpointer-arith -Wredundant-decls
+
+# _no_ common code can have packed data structures or we are in touble.
+C_WARNINGS += -Wpacked
+
+CFLAGS := -m64 -ffreestanding -fno-builtin -fno-common -fno-strict-aliasing
+CFLAGS += -iwithprefix include -Wall -Werror -pipe
+CFLAGS += -I$(BASEDIR)/include
+CFLAGS += -I$(BASEDIR)/include/asm-powerpc/mach-generic
+CFLAGS += -I$(BASEDIR)/include/asm-powerpc/mach-default
+CFLAGS += $(C_WARNINGS)
+CFLAGS += -msoft-float -O2
+CFLAGS-$(debug) += -O0 # last one wins
+CFLAGS-$(papr_vterm) += -DPAPR_VDEVICE -DPAPR_VTERM
+
+LDFLAGS += -m elf64ppc
+
+#
+# command to embed a binary inside a .o
+#
+%.o: %.bin
+       $(CROSS_COMPILE)objcopy --input-target=binary \
+               --output-target=elf64-powerpc \
+               --binary-architecture=powerpc \
+               --redefine-sym _binary_$*_bin_start=$*_start \
+               --redefine-sym _binary_$*_bin_end=$*_end \
+               --redefine-sym _binary_$*_bin_size=$*_size \
+               $< $@
+
+# Test for at least GCC v3.2.x.
+gcc-ver = $(shell $(CC) -dumpversion | sed -e 's/^\(.\)\.\(.\)\.\(.\)/\$(1)/')
+ifeq ($(call gcc-ver,1),1)
+$(error gcc-1.x.x unsupported - upgrade to at least gcc-3.2.x)
+endif
+ifeq ($(call gcc-ver,1),2)
+$(error gcc-2.x.x unsupported - upgrade to at least gcc-3.2.x)
+endif
+ifeq ($(call gcc-ver,1),3)
+ifeq ($(call gcc-ver,2),0)
+$(error gcc-3.0.x unsupported - upgrade to at least gcc-3.2.x)
+endif
+ifeq ($(call gcc-ver,2),1)
+$(error gcc-3.1.x unsupported - upgrade to at least gcc-3.2.x)
+endif
+endif
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/audit.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/audit.c  Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,45 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
+ */
+
+#ifndef NDEBUG
+#include <xen/lib.h>
+#include <xen/sched.h>
+
+extern void audit_domain(struct domain *d);
+extern void audit_domains(void);
+extern void audit_domains_key(unsigned char key);
+
+void audit_domain(struct domain *d)
+{
+    panic("%s unimplemented\n", __func__);
+}
+
+void audit_domains(void)
+{
+    struct domain *d;
+    for_each_domain ( d )
+        audit_domain(d);
+}
+
+void audit_domains_key(unsigned char key)
+{
+    audit_domains();
+}
+#endif
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/bitops.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/bitops.c Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,94 @@
+/* from linux/arch/powerpc/lib/bitops.c */
+
+#include <asm/types.h>
+#include <asm/bitops.h>
+
+#define BITOP_WORD(nr)      ((nr) / BITS_PER_LONG)
+
+/**
+ * find_next_bit - find the next set bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The maximum size to search
+ */
+unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
+                           unsigned long offset)
+{
+       const unsigned long *p = addr + BITOP_WORD(offset);
+       unsigned long result = offset & ~(BITS_PER_LONG-1);
+       unsigned long tmp;
+
+       if (offset >= size)
+               return size;
+       size -= result;
+       offset %= BITS_PER_LONG;
+       if (offset) {
+               tmp = *(p++);
+               tmp &= (~0UL << offset);
+               if (size < BITS_PER_LONG)
+                       goto found_first;
+               if (tmp)
+                       goto found_middle;
+               size -= BITS_PER_LONG;
+               result += BITS_PER_LONG;
+       }
+       while (size & ~(BITS_PER_LONG-1)) {
+               if ((tmp = *(p++)))
+                       goto found_middle;
+               result += BITS_PER_LONG;
+               size -= BITS_PER_LONG;
+       }
+       if (!size)
+               return result;
+       tmp = *p;
+
+found_first:
+       tmp &= (~0UL >> (BITS_PER_LONG - size));
+       if (tmp == 0UL)         /* Are any bits set? */
+               return result + size;   /* Nope. */
+found_middle:
+       return result + __ffs(tmp);
+}
+
+/*
+ * This implementation of find_{first,next}_zero_bit was stolen from
+ * Linus' asm-alpha/bitops.h.
+ */
+unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
+                                unsigned long offset)
+{
+       const unsigned long *p = addr + BITOP_WORD(offset);
+       unsigned long result = offset & ~(BITS_PER_LONG-1);
+       unsigned long tmp;
+
+       if (offset >= size)
+               return size;
+       size -= result;
+       offset %= BITS_PER_LONG;
+       if (offset) {
+               tmp = *(p++);
+               tmp |= ~0UL >> (BITS_PER_LONG - offset);
+               if (size < BITS_PER_LONG)
+                       goto found_first;
+               if (~tmp)
+                       goto found_middle;
+               size -= BITS_PER_LONG;
+               result += BITS_PER_LONG;
+       }
+       while (size & ~(BITS_PER_LONG-1)) {
+               if (~(tmp = *(p++)))
+                       goto found_middle;
+               result += BITS_PER_LONG;
+               size -= BITS_PER_LONG;
+       }
+       if (!size)
+               return result;
+       tmp = *p;
+
+found_first:
+       tmp |= ~0UL << size;
+       if (tmp == ~0UL)        /* Are any bits zero? */
+               return result + size;   /* Nope. */
+found_middle:
+       return result + ffz(tmp);
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/boot/boot32.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/boot/boot32.S    Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,75 @@
+/*
+ * 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
+ *
+ */
+       
+### 32 bit strapping code so Of will like us
+       .section        ".text"
+       .align 3
+       .globl _start
+               
+_start:
+       ## Double word align the MSR value below
+       nop
+       bl _real_start
+       ## static value for MSR
+       .llong 0x9000000000001000
+
+       ## see also docs/reference/ppc/msr.txt
+##bit C  Hex               Name Desc
+##  0 63 80000000 00000000 SF   64-bit Mode
+##  3 60 10000000 00000000 HV   Hypervisor State iff PR = 0 in hypervisor 
state.
+## 51 12 00000000 00001000 ME   Machine Check Enable
+
+_real_start:           
+       # pass the original msr as argument to hype_init
+       mfmsr   8
+
+       ## Set PC
+       li      21, 0
+       oris    21, 21, _hype64@h
+       ori     21, 21, _hype64@l
+#ifdef __BRIDGE64__
+       ## In 64bit we use rfid to switch from 32bit to 64 bit
+       mtsrr0  21
+
+       ## Set MSR
+       mflr    21
+       ld      22, 0(21)
+       mtsrr1  22
+       bl __leap
+       /* should never return */
+       trap
+__leap:                
+       rfid
+#else
+       mtctr 21
+       bctrl
+       /* should never return */
+       trap
+#endif
+
+       
+_real_end:
+       .data
+       .align 3
+       ## Hypervisor starts here, at the first data address
+       ## linker magic positions _hype64 0x100 after _start
+       ## hype/ppc64/Makefile.isa 
+_hype64:               
+
+
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/boot/start.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/boot/start.S     Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,51 @@
+/*
+ * 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
+ *
+ */
+
+#include <asm/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+
+    .globl _start
+_start:
+    /* load up the stack */
+    SET_REG_TO_LABEL(r1, cpu0_stack)
+
+    /* call the init function */
+    LOADADDR(r21,__start_xen_ppc)
+
+#ifdef __PPC64__
+    ld r2, 8(r21)
+    ld r21, 0(r21)
+#endif
+    mtctr r21
+    bctrl
+    /* should never return */
+    trap
+
+    /* Note! GDB 6.3 makes the very stupid assumption that PC > SP means we are
+     * in a Linux signal trampoline, and it begins groping for a struct
+     * rt_sigframe on the stack. Naturally, this fails miserably for our
+     * backtrace. To work around this behavior, we must make certain that our
+     * stack is always above our text, e.g. in the data section. */
+    .data /* DO NOT REMOVE; see GDB note above */
+    .align 4
+cpu0_stack_bottom:
+    .space STACK_SIZE
+cpu0_stack:
+    .space STACK_FRAME_OVERHEAD
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/boot_of.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/boot_of.c        Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,1016 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/multiboot.h>
+#include <xen/compile.h>
+#include <xen/spinlock.h>
+#include <xen/serial.h>
+#include <xen/time.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include "exceptions.h"
+#include "of-devtree.h"
+
+static ulong of_vec;
+static ulong of_msr;
+static int of_out;
+static ofdn_t boot_cpu;
+static char bootargs[256];
+
+extern struct ns16550_defaults ns16550;
+
+#undef OF_DEBUG
+
+#ifdef OF_DEBUG
+#define DBG(args...) of_printf(args)
+#else
+#define DBG(args...)
+#endif
+
+#define of_panic(MSG...) \
+    do { of_printf(MSG); of_printf("\nHANG\n"); for (;;); } while (0)
+
+struct of_service {
+    u32 ofs_service;
+    u32 ofs_nargs;
+    u32 ofs_nrets;
+    u32 ofs_args[10];
+};
+
+static int bof_chosen;
+
+static struct of_service s;
+extern s32 prom_call(void *arg, ulong rtas_base, ulong func, ulong msr);
+
+static int __init of_call(
+    const char *service, u32 nargs, u32 nrets, s32 rets[], ...)
+{
+    int rc;
+
+    if (of_vec != 0) {
+        va_list args;
+        int i;
+
+        memset(&s, 0, sizeof (s));
+        s.ofs_service = (ulong)service;
+        s.ofs_nargs = nargs;
+        s.ofs_nrets = nrets;
+        s.ofs_nargs = nargs;
+
+        /* copy all the params into the args array */
+        va_start(args, rets);
+
+        for (i = 0; i < nargs; i++) {
+            s.ofs_args[i] = va_arg(args, u32);
+        }
+
+        va_end(args);
+
+        rc = prom_call(&s, 0, of_vec, of_msr);
+
+        /* yes always to the copy, just in case */
+        for (i = 0; i < nrets; i++) {
+            rets[i] = s.ofs_args[i + nargs];
+        }
+    } else {
+        rc = OF_FAILURE;
+    }
+    return rc;
+}
+
+/* popular OF methods */
+static int __init _of_write(int ih, const char *addr, u32 len)
+{
+    int rets[1] = { OF_FAILURE };
+    if (of_call("write", 3, 1, rets, ih, addr, len) == OF_FAILURE) {
+        return OF_FAILURE;
+    }
+    return rets[0];
+}
+
+/* popular OF methods */
+static int __init of_write(int ih, const char *addr, u32 len)
+{
+    int rc;
+    int i = 0;
+    int sum = 0;
+
+    while (i < len) {
+        if (addr[i] == '\n') {
+            if (i > 0) {
+                rc = _of_write(ih, addr, i);
+                if (rc == OF_FAILURE)
+                    return rc;
+                sum += rc;
+            }
+            rc = _of_write(ih, "\r\n", 2);
+            if (rc == OF_FAILURE)
+                return rc;
+            sum += rc;
+            i++;
+            addr += i;
+            len -= i;
+            i = 0;
+            continue;
+        }
+        i++;
+    }
+    if (len > 0) {
+        rc = _of_write(ih, addr, len);
+        if (rc == OF_FAILURE)
+            return rc;
+        sum += rc;
+    }
+            
+    return sum;
+}
+
+static int of_printf(const char *fmt, ...)
+    __attribute__ ((format (printf, 1, 2)));
+static int __init of_printf(const char *fmt, ...)
+{
+    static char buf[1024];
+    va_list args;
+    int sz;
+
+    if (of_out == 0) {
+        return OF_FAILURE;
+    }
+
+    va_start(args, fmt);
+
+    sz = vsnprintf(buf, sizeof (buf), fmt, args);
+    if (sz <= sizeof (buf)) {
+        of_write(of_out, buf, sz);
+    } else {
+        static const char trunc[] = "\n(TRUNCATED)\n";
+
+        sz = sizeof (buf);
+        of_write(of_out, buf, sz);
+        of_write(of_out, trunc, sizeof (trunc));
+    }
+    return sz;
+}
+
+static int __init of_finddevice(const char *devspec)
+{
+    int rets[1] = { OF_FAILURE };
+
+    of_call("finddevice", 1, 1, rets, devspec);
+    if (rets[0] == OF_FAILURE) {
+        DBG("finddevice %s -> FAILURE %d\n",devspec,rets[0]);
+        return OF_FAILURE;
+    }
+    DBG("finddevice %s -> %d\n",devspec, rets[0]);
+    return rets[0];
+}
+
+static int __init of_getprop(int ph, const char *name, void *buf, u32 buflen)
+{
+    int rets[1] = { OF_FAILURE };
+
+    of_call("getprop", 4, 1, rets, ph, name, buf, buflen);
+
+    if (rets[0] == OF_FAILURE) {
+        DBG("getprop 0x%x %s -> FAILURE\n", ph, name);
+        return OF_FAILURE;
+    }
+
+    DBG("getprop 0x%x %s -> 0x%x (%s)\n", ph, name, rets[0], (char *)buf);
+    return rets[0];
+}
+
+static int __init of_setprop(
+    int ph, const char *name, const void *buf, u32 buflen)
+{
+    int rets[1] = { OF_FAILURE };
+
+    of_call("setprop", 4, 1, rets, ph, name, buf, buflen);
+
+    if (rets[0] == OF_FAILURE) {
+        DBG("setprop 0x%x %s -> FAILURE\n", ph, name);
+        return OF_FAILURE;
+    }
+
+    DBG("setprop 0x%x %s -> %s\n", ph, name, (char *)buf);
+    return rets[0];
+}
+
+/*
+ * returns 0 if there are no children (of spec)
+ */
+static int __init of_getchild(int ph)
+{
+    int rets[1] = { OF_FAILURE };
+
+    of_call("child", 1, 1, rets, ph);
+    DBG("getchild 0x%x -> 0x%x\n", ph, rets[0]);
+
+    return rets[0];
+}
+
+/*
+ * returns 0 is there are no peers
+ */
+static int __init of_getpeer(int ph)
+{
+    int rets[1] = { OF_FAILURE };
+
+    of_call("peer", 1, 1, rets, ph);
+    DBG("getpeer 0x%x -> 0x%x\n", ph, rets[0]);
+
+    return rets[0];
+}
+
+static int __init of_getproplen(int ph, const char *name)
+{
+    int rets[1] = { OF_FAILURE };
+
+    of_call("getproplen", 2, 1, rets, ph, name);
+    if (rets[0] == OF_FAILURE) {
+        DBG("getproplen 0x%x %s -> FAILURE\n", ph, name);
+        return OF_FAILURE;
+    }
+    DBG("getproplen 0x%x %s -> 0x%x\n", ph, name, rets[0]);
+    return rets[0];
+}
+
+static int __init of_package_to_path(int ph, char *buffer, u32 buflen)
+{
+    int rets[1] = { OF_FAILURE };
+
+    of_call("package-to-path", 3, 1, rets, ph, buffer, buflen);
+    if (rets[0] == OF_FAILURE) {
+        DBG("%s 0x%x -> FAILURE\n", __func__, ph);
+        return OF_FAILURE;
+    }
+    DBG("%s 0x%x %s -> 0x%x\n", __func__, ph, buffer, rets[0]);
+    if (rets[0] <= buflen)
+        buffer[rets[0]] = '\0';
+    return rets[0];
+}
+
+static int __init of_nextprop(int ph, const char *name, void *buf)
+{
+    int rets[1] = { OF_FAILURE };
+
+    of_call("nextprop", 3, 1, rets, ph, name, buf);
+
+    if (rets[0] == OF_FAILURE) {
+        DBG("nextprop 0x%x %s -> FAILURE\n", ph, name);
+        return OF_FAILURE;
+    }
+
+    DBG("nextprop 0x%x %s -> %s\n", ph, name, (char *)buf);
+    return rets[0];
+}
+
+static int __init of_instance_to_path(int ih, char *buffer, u32 buflen)
+{
+    int rets[1] = { OF_FAILURE };
+
+    if (of_call("instance-to-path", 3, 1, rets, ih, buffer, buflen)
+         == OF_FAILURE)
+        return OF_FAILURE;
+
+    if (rets[0] <= buflen)
+        buffer[rets[0]] = '\0';
+    return rets[0];
+}
+
+static int __init of_start_cpu(int cpu, u32 pc, u32 reg)
+{
+    int rets[1] = { OF_FAILURE };
+
+    if ( of_call("start-cpu", 3, 0, rets, cpu, pc, reg) == OF_FAILURE )
+        return OF_FAILURE;
+
+    return rets[0];
+}
+
+static void __init of_test(const char *of_method_name)
+{
+    int rets[1] = { OF_FAILURE };
+    
+    of_call("test", 1, 1, rets, of_method_name);
+    if (rets[0] == OF_FAILURE ) {
+        of_printf("Warning: possibly no OF method %s.\n"
+                  "(Ignore this warning on PIBS.)\n", of_method_name);
+    }
+}
+
+static int __init of_claim(void * virt, u32 size)
+{
+    int rets[1] = { OF_FAILURE };
+    
+    of_call("claim", 3, 1, rets, virt, size, 0/*align*/);
+    if (rets[0] == OF_FAILURE) {
+        DBG("%s 0x%p 0x%08x -> FAIL\n", __func__, virt, size);
+        return OF_FAILURE;
+    }
+
+    DBG("%s 0x%p 0x%08x -> 0x%x\n", __func__, virt, size, rets[0]);
+    return rets[0];
+}
+
+static int __init of_instance_to_package(int ih)
+{
+    int rets[1] = { OF_FAILURE };
+
+    of_call("instance-to-package", 1, 1, rets, ih);
+    if (rets[0] == OF_FAILURE)
+        return OF_FAILURE;
+
+    return rets[0];
+}
+
+static int __init of_getparent(int ph)
+{
+    int rets[1] = { OF_FAILURE };
+
+    of_call("parent", 1, 1, rets, ph);
+
+    DBG("getparent 0x%x -> 0x%x\n", ph, rets[0]);
+    return rets[0];
+}
+
+static void boot_of_probemem(multiboot_info_t *mbi)
+{
+    int root;
+    int p;
+    u32 addr_cells = 1;
+    u32 size_cells = 1;
+    int rc;
+    int mcount = 0;
+    static memory_map_t mmap[16];
+
+    root = of_finddevice("/");
+    p = of_getchild(root);
+
+    /* code is writen to assume sizes of 1 */
+    of_getprop(root, "#address-cells", &addr_cells, sizeof (addr_cells));
+    of_getprop(root, "#size-cells", &size_cells, sizeof (size_cells));
+    DBG("%s: address_cells=%d  size_cells=%d\n",
+                    __func__, addr_cells, size_cells);
+    
+    do {
+        const char memory[] = "memory";
+        char type[32];
+
+        type[0] = '\0';
+
+        of_getprop(p, "device_type", type, sizeof (type));
+        if (strncmp(type, memory, sizeof (memory)) == 0) {
+            u32 reg[48];  
+            u32 al, ah, ll, lh;
+            int r;
+
+            rc = of_getprop(p, "reg", reg, sizeof (reg));
+            if (rc == OF_FAILURE) {
+                of_panic("no reg property for memory node: 0x%x.\n", p);
+            }
+            int l = rc/sizeof(u32); /* number reg element */
+            DBG("%s: number of bytes in property 'reg' %d\n",
+                            __func__, rc);
+            
+            r = 0;
+            while (r < l) {
+                al = ah = ll = lh = 0;
+                if (addr_cells == 2) {
+                    ah = reg[r++];
+                    if (r >= l)
+                        break;  /* partial line.  Skip  */
+                    al = reg[r++];
+                    if (r >= l)
+                        break;  /* partial line.  Skip */
+                } else {
+                    al = reg[r++];
+                    if (r >= l)
+                        break;  /* partial line.  Skip */
+                }
+                if (size_cells == 2) {
+                    lh = reg[r++];
+                    if (r >= l)
+                        break;  /* partial line.  Skip */
+                    ll = reg[r++];
+                } else {
+                    ll = reg[r++];
+                }
+
+                if ((ll != 0) || (lh != 0)) {
+                    mmap[mcount].size = 20; /* - size field */
+                    mmap[mcount].type = 1; /* Regular ram */
+                    mmap[mcount].length_high = lh;
+                    mmap[mcount].length_low = ll;
+                    mmap[mcount].base_addr_high = ah;
+                    mmap[mcount].base_addr_low = al;
+                    of_printf("%s: memory 0x%016lx[0x%08lx]\n",
+                      __func__,
+                      (u64)(((u64)mmap[mcount].base_addr_high << 32)
+                            | mmap[mcount].base_addr_low),
+                      (u64)(((u64)mmap[mcount].length_high << 32)
+                            | mmap[mcount].length_low));
+                    ++mcount;
+                }
+            }
+        }
+        p = of_getpeer(p);
+    } while (p != OF_FAILURE && p != 0);
+
+    if (mcount > 0) {
+        mbi->flags |= MBI_MEMMAP;
+        mbi->mmap_length = sizeof (mmap[0]) * mcount;
+        mbi->mmap_addr = (ulong)mmap;
+    }
+}
+
+static void boot_of_bootargs(multiboot_info_t *mbi)
+{
+    int rc;
+
+    rc = of_getprop(bof_chosen, "bootargs", &bootargs, sizeof (bootargs));
+    if (rc == OF_FAILURE) {
+        strcpy(bootargs, "xen");
+    }
+
+    mbi->flags |= MBI_CMDLINE;
+    mbi->cmdline = (u32)bootargs;
+
+    of_printf("bootargs = %s\n", bootargs);
+}
+
+static int save_props(void *m, ofdn_t n, int pkg)
+{
+    int ret;
+    char name[128];
+    int result = 1;
+    int found_name = 0;
+    int found_device_type = 0;
+    const char name_str[] = "name";
+    const char devtype_str[] = "device_type";
+
+    /* get first */
+    result = of_nextprop(pkg, 0, name);
+
+    while (result > 0) {
+        int sz;
+        u64 obj[1024];
+
+        sz = of_getproplen(pkg, name);
+        if (sz >= 0) {
+            ret = OF_SUCCESS;
+        } else {
+            ret = OF_FAILURE;
+        }
+
+        if (ret == OF_SUCCESS) {
+            int actual = 0;
+            ofdn_t pos;
+
+            if (sz > 0) {
+                if (sz > sizeof (obj)) {
+                    of_panic("obj array not big enough for 0x%x\n", sz);
+                }
+                actual = of_getprop(pkg, name, obj, sz);
+                if (actual > sz) of_panic("obj too small");
+            }
+
+            if (strncmp(name, name_str, sizeof(name_str)) == 0) {
+                found_name = 1;
+            }
+
+            if (strncmp(name, devtype_str, sizeof(devtype_str)) == 0) {
+                found_device_type = 1;
+            }
+
+            pos = ofd_prop_add(m, n, name, obj, actual);
+            if (pos == 0) of_panic("prop_create");
+        }
+
+        result = of_nextprop(pkg, name, name);
+    }
+
+    return 1;
+}
+
+
+static void do_pkg(void *m, ofdn_t n, int p, char *path, size_t psz)
+{
+    int pnext;
+    ofdn_t nnext;
+    int sz;
+
+retry:
+    save_props(m, n, p);
+
+    /* do children first */
+    pnext = of_getchild(p);
+
+    if (pnext != 0) {
+        sz = of_package_to_path(pnext, path, psz);
+        if (sz == OF_FAILURE) of_panic("bad path\n");
+
+        nnext = ofd_node_child_create(m, n, path, sz);
+        if (nnext == 0) of_panic("out of mem\n");
+
+        do_pkg(m, nnext, pnext, path, psz);
+    }
+
+    /* do peer */
+    pnext = of_getpeer(p);
+
+    if (pnext != 0) {
+        sz = of_package_to_path(pnext, path, psz);
+
+        nnext = ofd_node_peer_create(m, n, path, sz);
+        if (nnext <= 0) of_panic("out of space in OFD tree.\n");
+
+        n = nnext;
+        p = pnext;
+        goto retry;
+    }
+}
+
+static int pkg_save(void *mem)
+{
+    int root;
+    char path[256];
+    int r;
+
+    path[0]='/';
+    path[1]='\0';
+
+    /* get root */
+    root = of_getpeer(0);
+    if (root == OF_FAILURE) of_panic("no root package\n");
+
+    do_pkg(mem, OFD_ROOT, root, path, sizeof(path));
+
+    r = (((ofdn_t *)mem)[1] + 1) * sizeof (u64);
+
+    of_printf("%s: saved device tree in 0x%x bytes\n", __func__, r);
+
+    return r;
+}
+
+static int boot_of_fixup_refs(void *mem)
+{
+    static const char *fixup_props[] = {
+        "interrupt-parent",
+    };
+    int i;
+    int count = 0;
+
+    for (i = 0; i < ARRAY_SIZE(fixup_props); i++) {
+        ofdn_t c;
+        const char *name = fixup_props[i];
+
+        c = ofd_node_find_by_prop(mem, OFD_ROOT, name, NULL, 0);
+        while (c > 0) {
+            const char *path;
+            int rp;
+            int ref;
+            ofdn_t dp;
+            int rc;
+            ofdn_t upd;
+            char ofpath[256];
+
+            path = ofd_node_path(mem, c);
+            if (path == NULL) of_panic("no path to found prop: %s\n", name);
+
+            rp = of_finddevice(path);
+            if (rp == OF_FAILURE)
+                of_panic("no real device for: name %s, path %s\n",
+                          name, path);
+            /* Note: In theory 0 is a valid node handle but it is highly
+             * unlikely.
+             */
+            if (rp == 0) {
+                of_panic("%s: of_finddevice returns 0 for path %s\n",
+                                    __func__, path);
+            } 
+
+            rc = of_getprop(rp, name, &ref, sizeof(ref));
+            if ((rc == OF_FAILURE) || (rc == 0))
+                of_panic("no prop: name %s, path %s, device 0x%x\n",
+                         name, path, rp);
+
+            rc = of_package_to_path(ref, ofpath, sizeof (ofpath));
+            if (rc == OF_FAILURE)
+                of_panic("no package: name %s, path %s, device 0x%x,\n"
+                         "ref 0x%x\n", name, path, rp, ref);
+
+            dp = ofd_node_find(mem, ofpath);
+            if (dp <= 0) of_panic("no ofd node for OF node[0x%x]: %s\n",
+                                  ref, ofpath);
+
+            ref = dp;
+
+            upd = ofd_prop_add(mem, c, name, &ref, sizeof(ref));
+            if (upd <= 0) of_panic("update failed: %s\n", name);
+
+#ifdef DEBUG
+            of_printf("%s: %s/%s -> %s\n", __func__,
+                    path, name, ofpath);
+#endif
+            ++count;
+            c = ofd_node_find_next(mem, c);
+        }
+    }
+    return count;
+}
+
+static int boot_of_fixup_chosen(void *mem)
+{
+    int ch;
+    ofdn_t dn;
+    ofdn_t dc;
+    int val;
+    int rc;
+    char ofpath[256];
+
+    ch = of_finddevice("/chosen");
+    if (ch == OF_FAILURE) of_panic("/chosen not found\n");
+
+    rc = of_getprop(ch, "cpu", &val, sizeof (val));
+
+    if (rc != OF_FAILURE) {
+        rc = of_instance_to_path(val, ofpath, sizeof (ofpath));
+
+        if (rc > 0) {
+            dn = ofd_node_find(mem, ofpath);
+            if (dn <= 0) of_panic("no node for: %s\n", ofpath);
+
+            boot_cpu = dn;
+            val = dn;
+
+            dn = ofd_node_find(mem, "/chosen");
+            if (dn <= 0) of_panic("no /chosen node\n");
+
+            dc = ofd_prop_add(mem, dn, "cpu", &val, sizeof (val));
+            if (dc <= 0) of_panic("could not fix /chosen/cpu\n");
+            rc = 1;
+        } else {
+            of_printf("*** can't find path to booting cpu, "
+                    "SMP is disabled\n");
+            boot_cpu = -1;
+        }
+    }
+    return rc;
+}
+
+static ulong space_base;
+static ulong find_space(u32 size, ulong align, multiboot_info_t *mbi)
+{
+    memory_map_t *map = (memory_map_t *)((ulong)mbi->mmap_addr);
+    ulong eomem = ((u64)map->length_high << 32) | (u64)map->length_low;
+    ulong base;
+
+    of_printf("%s base=0x%016lx  eomem=0x%016lx  size=0x%08x  align=0x%lx\n",
+                    __func__, space_base, eomem, size, align);
+    base = ALIGN_UP(space_base, PAGE_SIZE);
+    if ((base + size) >= 0x4000000) return 0;
+    if (base + size > eomem) of_panic("not enough RAM\n");
+
+    if (size == 0) return base;
+    if (of_claim((void*)base, size) != OF_FAILURE) {
+        space_base = base + size;
+        return base;
+    } else {
+        for(base += 0x100000; (base+size) < 0x4000000; base += 0x100000) {
+            of_printf("Trying 0x%016lx\n", base);
+            if (of_claim((void*)base, size) != OF_FAILURE) {
+                space_base = base + size;
+                return base;
+            }
+        }
+        return 0;
+    }
+}
+
+/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges
+ * property.  The values are bad, and it doesn't even have the
+ * right number of cells. */
+
+static void __init boot_of_fix_maple(void)
+{
+    int isa;
+    const char *ranges = "ranges";
+    u32 isa_ranges[3];
+    const u32 isa_test[] = { 0x00000001, 0xf4000000, 0x00010000 };
+    const u32 isa_fixed[] = {
+        0x00000001,
+        0x00000000,
+        0x00000000, /* 0xf4000000, matt says this */
+        0x00000000,
+        0x00000000,
+        0x00010000
+    };
+
+    isa = of_finddevice("/ht@0/isa@4");
+    if (isa != OF_FAILURE) {
+        if (of_getproplen(isa, ranges) == sizeof (isa_test)) {
+            of_getprop(isa, ranges, isa_ranges, sizeof (isa_ranges));
+            if (memcmp(isa_ranges, isa_test, sizeof (isa_test)) == 0) {
+                int rc;
+
+                of_printf("OF: fixing bogus ISA range on maple\n");
+                rc = of_setprop(isa, ranges, isa_fixed, sizeof (isa_fixed));
+                if (rc == OF_FAILURE) {
+                    of_panic("of_setprop() failed\n");
+                }
+            }
+        }
+    }
+}
+    
+static int __init boot_of_serial(void *oftree)
+{
+    int n;
+    int p;
+    int rc;
+    u32 val[3];
+    char buf[128];
+
+    n = of_instance_to_package(of_out);
+    if (n == OF_FAILURE) {
+        of_panic("instance-to-package of /chosen/stdout: failed\n");
+    }
+
+    /* prune this from the oftree */
+    rc = of_package_to_path(n, buf, sizeof(buf));
+    if (rc == OF_FAILURE) {
+        of_panic("package-to-path of /chosen/stdout: failed\n");
+    }
+    of_printf("Pruning from devtree: %s\n"
+              "  since Xen will be using it for console\n", buf);
+    rc = ofd_prune_path(oftree, buf);
+    if (rc < 0) {
+        of_panic("prune path \"%s\" failed\n", buf);
+    }
+    
+
+    p = of_getparent(n);
+    if (p == OF_FAILURE) {
+        of_panic("no parent for: 0x%x\n", n);
+    }
+
+    buf[0] = '\0';
+    of_getprop(p, "device_type", buf, sizeof (buf));
+    if (strstr(buf, "isa") == NULL) {
+        of_panic("only ISA UARTS supported\n");
+    }
+
+    /* should get this from devtree */
+    isa_io_base = 0xf4000000;
+    of_printf("%s: ISA base: 0x%lx\n", __func__, isa_io_base);
+
+    buf[0] = '\0';
+    of_getprop(n, "device_type", buf, sizeof (buf));
+    if (strstr(buf, "serial") == NULL) {
+        of_panic("only UARTS supported\n");
+    }
+
+    rc = of_getprop(n, "reg", val, sizeof (val));
+    if (rc == OF_FAILURE) {
+        of_panic("%s: no location for serial port\n", __func__);
+    }
+    ns16550.io_base = val[1];
+
+    ns16550.baud = BAUD_AUTO;
+    ns16550.data_bits = 8;
+    ns16550.parity = 'n';
+    ns16550.stop_bits = 1;
+
+    rc = of_getprop(n, "interrupts", val, sizeof (val));
+    if (rc == OF_FAILURE) {
+        of_printf("%s: no ISRC, forcing poll mode\n", __func__);
+        ns16550.irq = 0;
+    } else {
+        ns16550.irq = val[0];
+        of_printf("%s: ISRC=0x%x, but forcing poll mode\n",
+                  __func__, ns16550.irq);
+        ns16550.irq = 0;
+    }
+
+    return 1;
+}
+
+static void boot_of_module(ulong r3, ulong r4, multiboot_info_t *mbi)
+{
+    static module_t mods[3];
+    void *oftree;
+    ulong oftree_sz = 48 * PAGE_SIZE;
+    char *mod0_start;
+    ulong mod0_size;
+    ulong mod0;
+    static const char sepr[] = " -- ";
+    extern char dom0_start[] __attribute__ ((weak));
+    extern char dom0_size[] __attribute__ ((weak));
+    const char *p;
+
+    if ((r3 > 0) && (r4 > 0)) {
+        /* was it handed to us in registers ? */
+        mod0_start = (void *)r3;
+        mod0_size = r4;
+    } else {
+        /* see if it is in the boot params */
+        p = strstr((char *)((ulong)mbi->cmdline), "dom0_start=");
+        if ( p != NULL) {
+            p += 11;
+            mod0_start = (char *)simple_strtoul(p, NULL, 0);
+
+            p = strstr((char *)((ulong)mbi->cmdline), "dom0_size=");
+            p += 10;
+            mod0_size = simple_strtoul(p, NULL, 0);
+
+            of_printf("mod0: %o %c %c %c\n",
+                      mod0_start[0],
+                      mod0_start[1],
+                      mod0_start[2],
+                      mod0_start[3]);
+
+        } else if ( ((ulong)dom0_start != 0) && ((ulong)dom0_size != 0) ) {
+            /* was it linked in ? */
+        
+            mod0_start = dom0_start;
+            mod0_size = (ulong)dom0_size;
+            of_printf("%s: linked in module copied after _end "
+                      "(start 0x%p size 0x%lx)\n",
+                      __func__, mod0_start, mod0_size);
+        } else {
+            mod0_start = _end;
+            mod0_size = 0;
+        }
+    }
+
+    space_base = (ulong)_end;
+    mod0 = find_space(mod0_size, PAGE_SIZE, mbi);
+
+    /* three cases
+     * 1) mod0_size is not 0 and the image can be copied
+     * 2) mod0_size is not 0 and the image cannot be copied
+     * 3) mod0_size is 0
+     */
+    if (mod0_size > 0) {
+        if (mod0 != 0) {
+            memcpy((void *)mod0, mod0_start, mod0_size);
+            mods[0].mod_start = mod0;
+            mods[0].mod_end = mod0 + mod0_size;
+        } else {
+            of_panic("No space to copy mod0\n");
+        }
+    } else {
+        mods[0].mod_start = mod0;
+        mods[0].mod_end = mod0;
+    }
+
+    of_printf("%s: mod[0] @ 0x%016x[0x%x]\n", __func__,
+              mods[0].mod_start, mods[0].mod_end);
+    p = strstr((char *)(ulong)mbi->cmdline, sepr);
+    if (p != NULL) {
+        p += sizeof (sepr) - 1;
+        mods[0].string = (u32)(ulong)p;
+        of_printf("%s: mod[0].string: %s\n", __func__, p);
+    }
+
+    /* snapshot the tree */
+    oftree = (void*)find_space(oftree_sz, PAGE_SIZE, mbi);
+    if (oftree == 0) of_panic("Could not allocate OFD tree\n");
+
+    of_printf("creating oftree\n");
+    of_test("package-to-path");
+    ofd_create(oftree, oftree_sz);
+    pkg_save(oftree);
+
+    boot_of_fixup_refs(oftree);
+    boot_of_fixup_chosen(oftree);
+
+    ofd_walk(oftree, OFD_ROOT, /* add_hype_props */ NULL, 2);
+
+    mods[1].mod_start = (ulong)oftree;
+    mods[1].mod_end = mods[1].mod_start + oftree_sz;
+    of_printf("%s: mod[1] @ 0x%016x[0x%x]\n", __func__,
+              mods[1].mod_start, mods[1].mod_end);
+
+
+    mbi->flags |= MBI_MODULES;
+    mbi->mods_count = 2;
+    mbi->mods_addr = (u32)mods;
+
+    boot_of_serial(oftree);
+}
+
+static int __init boot_of_cpus(void)
+{
+    int cpus;
+    int cpu;
+    int result;
+    u32 cpu_clock[2];
+
+    cpus = of_finddevice("/cpus");
+    cpu = of_getchild(cpus);
+    result = of_getprop(cpu, "timebase-frequency", &timebase_freq,
+            sizeof(timebase_freq));
+    if (result == OF_FAILURE) {
+        of_panic("Couldn't get timebase frequency!\n");
+    }
+    of_printf("OF: timebase-frequency = %d Hz\n", timebase_freq);
+
+    result = of_getprop(cpu, "clock-frequency", &cpu_clock, sizeof(cpu_clock));
+    if (result == OF_FAILURE || (result !=4 && result != 8)) {
+        of_panic("Couldn't get clock frequency!\n");
+    }
+    cpu_khz = cpu_clock[0];
+    if (result == 8) {
+        cpu_khz <<= 32;
+        cpu_khz |= cpu_clock[1];
+    }
+    cpu_khz /= 1000;
+    of_printf("OF: clock-frequency = %ld KHz\n", cpu_khz);
+
+    /* FIXME: should not depend on the boot CPU bring the first child */
+    cpu = of_getpeer(cpu);
+    while (cpu > 0) {
+        of_start_cpu(cpu, (ulong)spin_start, 0);
+        cpu = of_getpeer(cpu);
+    }
+    return 1;
+}
+
+static int __init boot_of_rtas(void)
+{
+    return 1;
+}
+
+multiboot_info_t __init *boot_of_init(
+        ulong r3, ulong r4, ulong vec, ulong r6, ulong r7, ulong orig_msr)
+{
+    static multiboot_info_t mbi;
+
+    of_vec = vec;
+    of_msr = orig_msr;
+
+    bof_chosen = of_finddevice("/chosen");
+    of_getprop(bof_chosen, "stdout", &of_out, sizeof (of_out));
+
+    of_printf("%s\n", "---------------------------------------------------");
+    of_printf("OF: Xen/PPC version %d.%d%s (%s@%s) (%s) %s\n",
+              XEN_VERSION, XEN_SUBVERSION, XEN_EXTRAVERSION,
+              XEN_COMPILE_BY, XEN_COMPILE_DOMAIN,
+              XEN_COMPILER, XEN_COMPILE_DATE);
+
+    of_printf("%s args: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n"
+            "boot msr: 0x%lx\n",
+            __func__,
+            r3, r4, vec, r6, r7, orig_msr);
+
+    if ((vec >= (ulong)_start) && (vec <= (ulong)_end)) {
+        of_printf("Hmm.. OF[0x%lx] seems to have stepped on our image "
+                "that ranges: %p .. %p.\n HANG!\n",
+                vec, _start, _end);
+    }
+    of_printf("%s: _start %p _end %p 0x%lx\n", __func__, _start, _end, r6);
+
+    boot_of_fix_maple();
+    boot_of_probemem(&mbi);
+    boot_of_bootargs(&mbi);
+    boot_of_module(r3, r4, &mbi);
+    boot_of_cpus();
+    boot_of_rtas();
+
+    /* end of OF */
+    of_call("quiesce", 0, 0, NULL);
+
+    return &mbi;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/dart.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/dart.c   Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,299 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/mm.h>
+#include <asm/cache.h>
+#include <xen/init.h>
+#include "tce.h"
+#include "iommu.h"
+#include "dart.h"
+#include "oftree.h"
+#include "of-devtree.h"
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(fmt...) printk(fmt)
+static int dbg_after;
+#define DBG_SET_AFTER dbg_after = 1;
+#define DBG_AFTER(fmt...) if (dbg_after) DBG(fmt)
+#else
+#define DBG(fmt...)
+#define DBG_SET_AFTER
+#define DBG_AFTER(fmt...)
+#endif
+
+/* Max size of 512 pages */
+#define U3_LOG_MAX_PAGES 9
+
+#define DART_DEF_BASE   0xf8033000UL
+#define DART_NONE 0
+#define DART_U3 3
+#define DART_U4 4
+#define DART_WRITE 0x1
+#define DART_READ 0x2
+
+static ulong dummy_page;
+static ulong dart_entries;
+static struct dart_ops *dops;
+static u32 *dart_table;
+
+union dart_entry {
+    u32 de_word;
+    struct {
+        u32 de_v:1;             /* valid */
+        u32 de_rp:1;             /* read protected*/
+        u32 de_wp:1;             /* write protected*/
+        u32 _de_res:5;
+        u32 de_ppn:24;         /* 24 bit Physical Page Number
+                                 * representing address [28:51] */
+    } de_bits;
+};
+
+struct dma_window {
+    u32 dw_liobn;
+    u32 dw_base_hi;
+    u64 dw_base;
+    u64 dw_size;
+};
+
+struct dart_info {
+    struct dma_window di_window;
+    ulong di_base;
+    int di_model;
+};
+
+static u32 dart_encode(int perm, ulong rpn)
+{
+    union dart_entry e;
+
+    e.de_word = 0;
+    e.de_bits.de_v = 1;
+    e.de_bits.de_ppn = rpn;
+
+    /* protect the page */
+    e.de_bits.de_rp = 1;
+    e.de_bits.de_wp = 1;
+    if (perm & DART_READ) {
+        e.de_bits.de_rp = 0;
+    }
+    if (perm & DART_WRITE) {
+        e.de_bits.de_wp = 0;
+    }
+
+    return e.de_word;
+}
+
+static void dart_fill(ulong index, int perm, ulong rpg, ulong num_pg)
+{
+    u32 volatile *entry = dart_table + index;
+    ulong i = 0;
+    ulong last_flush = 0;
+
+    while (1) {
+        entry[i] = dart_encode(perm, rpg);
+        ++i;
+        ++rpg;
+        if (i == num_pg) break;
+
+        if (((ulong)&entry[i]) % CACHE_LINE_SIZE == 0) {
+            last_flush = (ulong)&entry[i - 1];
+            dcbst(last_flush);
+        }
+    }
+    dcbst((ulong) &entry[i - 1]);
+}
+
+static void dart_clear(ulong index, ulong num_pg)
+{
+    u32 *entry = dart_table + index;
+    ulong i = 0;
+    ulong rpg = dummy_page;
+    ulong last_flush = 0;
+
+    while (1) {
+        entry[i] = dart_encode(DART_READ | DART_WRITE, rpg);
+        ++i;
+        if (i == num_pg) break;
+
+        if (((ulong)&entry[i]) % CACHE_LINE_SIZE == 0) {
+            last_flush = (ulong)&entry[i - 1];
+            dcbst(last_flush);
+        }
+    }
+    dcbst((ulong)&entry[i - 1]);
+}
+
+static int dart_put(ulong ioba, union tce tce)
+{
+    ulong index = ioba >> PAGE_SHIFT;
+
+    if (index > dart_entries) {
+        return -1;
+    }
+
+    if (tce.tce_bits.tce_vlps  != 0 || tce.tce_bits.tce_lpx != 0) {
+        panic("no support for large TCEs\n");
+    }
+
+    if (tce.tce_bits.tce_read == 0 &&
+        tce.tce_bits.tce_write == 0) {
+        /* the TCE table is inited by the domain by a bunch of 0
+         * perminssion puts.  We are only interesting in debugging the
+         * ones after the first put */
+        DBG_AFTER(">DART[0x%lx] clear\n", index);
+        dart_clear(index, 1);
+    } else {
+        unsigned perm = 0;
+
+        if (tce.tce_bits.tce_read)
+            perm |= DART_READ;
+        if (tce.tce_bits.tce_write)
+            perm |= DART_WRITE;
+
+        DBG("<DART[0x%lx]: ioba: 0x%lx perm:%x[%c%c] rpn:0x%lx\n",
+            index, ioba, perm,
+            (perm & DART_READ) ? 'R' : '-',
+            (perm & DART_WRITE) ? 'W' : '-',
+            (ulong)tce.tce_bits.tce_rpn);
+        DBG_SET_AFTER;
+
+        dart_fill(index, perm, tce.tce_bits.tce_rpn, 1);
+    }
+    dops->do_inv_entry(tce.tce_bits.tce_rpn);
+    
+    return 0;
+}
+
+static int find_dart(struct dart_info *di)
+{
+    int rc;
+    void *ofd_p;
+    ofdn_t n;
+    char compat[128];
+
+
+    if (on_mambo()) {
+        /* mambo has no dart */
+        DBG("%s: Mambo does not support a dart\n", __func__);
+        return -1;
+    }
+
+    ofd_p = (void *)oftree;
+    n = ofd_node_find(ofd_p, "/ht");
+    if (n <= 0)
+        return -1;
+
+    /* get the defaults from the HT node model */
+    rc = ofd_getprop(ofd_p, n, "compatible", compat, sizeof (compat));
+    if (rc <= 0)
+        return -1;
+
+    di->di_base = DART_DEF_BASE;
+
+    if (strstr(compat, "u3")) {
+        di->di_model = DART_U3;
+    } else if (strstr(compat, "u4")) {
+        di->di_model = DART_U4;
+    } else {
+        DBG("%s: not a U3 or U4\n", __func__);
+        return -1;
+    }
+    /* FIXME: this should actually be the HT reg value */
+    di->di_window.dw_liobn = 0;
+    di->di_window.dw_base_hi = 0;
+    di->di_window.dw_base = 0;
+
+    /* lets see if the devtree has more info */
+    n = ofd_node_find(ofd_p, "/dart");
+    if (n > 0) {
+        ulong base;
+
+        rc = ofd_getprop(ofd_p, n, "compatible", compat, sizeof (compat));
+        if (rc > 0) {
+            if (strstr(compat, "u4")) {
+                di->di_model = DART_U4;
+            }
+        }
+
+        rc = ofd_getprop(ofd_p, n, "reg", &base, sizeof (base));
+        if (rc > 0) {
+            di->di_base = base;
+        }
+    }
+    return 0;
+}
+
+static int init_dart(void)
+{
+    ulong log_pgs;
+    void *ofd_p;
+    ofdn_t n;
+    struct dart_info di;
+
+    if (find_dart(&di))
+        return 0;
+
+    /* Max size of 512 pages == 2MB == 1<<21. That siz is good enough for U4 */
+    log_pgs = U3_LOG_MAX_PAGES;
+    dart_table = alloc_xenheap_pages(log_pgs);
+    BUG_ON(dart_table == NULL);
+
+    dart_entries = (1UL << (log_pgs + PAGE_SHIFT)) / sizeof (union dart_entry);
+    di.di_window.dw_size = dart_entries << PAGE_SHIFT;
+
+    /* Linux uses a dummy page, filling "empty" DART entries with a
+       reference to this page to capture stray DMA's */
+    dummy_page = (ulong)alloc_xenheap_pages(1);
+    memset((void *)dummy_page, 0, PAGE_SIZE);
+    dummy_page >>= PAGE_SHIFT;
+
+    printk("Initializing DART 0x%lx: tbl: %p[0x%lx] entries: 0x%lx\n",
+           di.di_base, dart_table, 1UL << log_pgs, dart_entries);
+           
+    /* register this iommu */
+    iommu_register(di.di_window.dw_liobn, dart_put);
+
+    switch (di.di_model) {
+    case DART_U3:
+        dops = u3_init(di.di_base, (ulong)dart_table, 1UL << log_pgs);
+        break;
+    case DART_U4:
+        dops = u4_init(di.di_base, (ulong)dart_table, 1UL << log_pgs);
+        break;
+    }
+
+    dart_clear(0, dart_entries);
+    dops->do_inv_all();
+
+    /* fix up the devtree */
+    ofd_p = (void *)oftree;
+    n = ofd_node_find(ofd_p, "/ht");
+    if (n > 0) {
+        di.di_window.dw_size = dart_entries << PAGE_SHIFT;
+        ofd_prop_add(ofd_p, n, "ibm,dma-window", &di.di_window,
+                     sizeof (di.di_window));
+    } else {
+        panic("%s: no /ht node\n", __func__);
+    }
+    return 0;
+}
+__initcall(init_dart);
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/dart.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/dart.h   Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,36 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#ifndef _DART_H
+#define _DART_H
+
+#include <xen/config.h>
+#include <xen/types.h>
+
+struct dart_ops {
+    void (*do_inv_all)(void);
+    void (*do_inv_entry)(ulong pg);
+};
+
+extern struct dart_ops *u3_init(ulong base, ulong table, ulong dart_pages);
+extern struct dart_ops *u4_init(ulong base, ulong table, ulong dart_pages);
+
+#endif /* _DART_H */
+
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/dart_u3.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/dart_u3.c        Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,108 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#undef DEBUG
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/sched.h>
+#include <xen/mm.h>
+#include <public/xen.h>
+#include <asm/io.h>
+#include <asm/current.h>
+#include "tce.h"
+#include "iommu.h"
+#include "dart.h"
+
+union dart_ctl {
+    u32 dc_word;
+    struct {
+        u32 dc_base:20;
+        u32 dc_stop_access:1;
+        u32 dc_invtlb:1;
+        u32 dc_enable:1;
+        u32 dc_size:9;
+    } reg;
+};
+
+static u32 volatile *dart_ctl_reg;
+
+static void u3_inv_all(void)
+{
+    union dart_ctl dc;
+    ulong r = 0;
+    int l = 0;
+
+    for (;;) {
+        dc.dc_word = in_32(dart_ctl_reg);
+        dc.reg.dc_invtlb = 1;
+        out_32(dart_ctl_reg, dc.dc_word);
+
+    do {
+        dc.dc_word = in_32(dart_ctl_reg);
+        r++;
+    } while ((dc.reg.dc_invtlb == 1) && (r < (1 << l)));
+
+        if (r == (1 << l)) {
+            if (l < 4) {
+                l++;
+                dc.dc_word = in_32(dart_ctl_reg);
+                dc.reg.dc_invtlb = 0;
+                out_32(dart_ctl_reg, dc.dc_word);
+                continue;
+            } else {
+                panic(" broken U3???\n");
+            }
+        }
+        return;
+    }
+}
+
+static void u3_inv_entry(ulong pg)
+{
+    /* sadly single entry invalidation has been reported not to work */
+    u3_inv_all();
+}
+
+static struct dart_ops u3_ops = {
+    .do_inv_all = u3_inv_all,
+    .do_inv_entry = u3_inv_entry,
+};
+
+struct dart_ops *u3_init(ulong base, ulong table, ulong dart_pages)
+{
+    union dart_ctl dc;
+
+    dart_ctl_reg = (u32 *)base;
+
+    dc.dc_word = 0;
+
+    dc.reg.dc_base = table >> PAGE_SHIFT;
+    dc.reg.dc_size = dart_pages;
+    dc.reg.dc_enable = 1;
+
+
+    printk("Initializing DART Model U3: reg: %p word: %x\n",
+           dart_ctl_reg, dc.dc_word);
+
+    out_32(dart_ctl_reg, dc.dc_word);
+
+    return &u3_ops;
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/dart_u4.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/dart_u4.c        Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,177 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#undef DEBUG
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/sched.h>
+#include <xen/init.h>
+#include <xen/mm.h>
+#include <public/xen.h>
+#include <asm/io.h>
+#include <asm/current.h>
+#include "tce.h"
+#include "iommu.h"
+#include "dart.h"
+
+#define TOO_MANY_RETRIES ~0
+
+union dart_ctl {
+    u32 dc_word;
+    struct {
+        u32 dc_darten:1;      /* DART Enable (0:disabled) */
+        u32 dc_ione:1;        /* Invalidate one DART TLB entry (using ILPN) */
+        u32 dc_iall:1;        /* Invalidate all DART TLB entries */
+        u32 dc_idle:1;        /* DART is idle */
+        u32 dc_peen:1;        /* Parity Checking is enabled */
+        u32 dc_ilpn:27;       /* 27-bit Logical Page Address for 
+                               * invalidating one TLB entry */
+    } dc_bits;
+};
+
+union dart_base {
+    u32 db_word;
+    struct {
+        u32 _db_resv:8;
+        u32 db_dartbase:24;     /* Base Address of DART (4K byte Alignment) */
+    } db_bits;
+};
+
+union dart_size {
+    u32 ds_word;
+    struct {
+        u32 _ds_resv:15;
+        u32 ds_dartsize:17;     /* Size of Dart in 4K-Byte Pages */
+    } ds_bits;
+};
+
+union dart_excp {
+    u32 de_word;
+    struct {
+        u32 de_rqsrc:1;    /* Request Source.  [0:PCIE, 1:HT] */
+        u32 de_lpn:27;     /* 27Ðbit Logical Address of Exception [25:51] */
+        u32 de_rqop:1;     /* Request operation.  [0:Read, 1:Write] */
+        u32 de_xcd:3;      /* Exception code */
+    } de_bits;
+};
+
+struct dart {
+    /* 0x00 */
+    union dart_ctl d_dartcntl;
+    u32 _pad0x04_0x10[3];
+    /* 0x10 */
+    union dart_base d_dartbase;
+    u32 _pad0x14_0x20[3];
+    /* 0x20 */
+    union dart_size d_dartsize;
+    u32 _pad0x24_0x30[3];
+    /* 0x30 */
+    union dart_excp d_dartexcp;
+    u32 _pad0x34_0x40[3];
+};
+
+static volatile struct dart *dart;
+
+static void u4_inv_all(void)
+{
+    union dart_ctl dc;
+    ulong r = 0;
+    int l = 0;
+
+    for (;;) {
+        dc.dc_word = in_32(&dart->d_dartcntl.dc_word);
+        dc.dc_bits.dc_iall = 1;
+        out_32(&dart->d_dartcntl.dc_word, dc.dc_word);
+
+        do {
+            dc.dc_word = in_32(&dart->d_dartcntl.dc_word);
+            r++;
+        } while ((dc.dc_bits.dc_iall == 1) && (r < (1 << l)));
+
+        if (r == (1 << l)) {
+            if (l < 4) {
+                l++;
+                dc.dc_word = in_32(&dart->d_dartcntl.dc_word);
+                dc.dc_bits.dc_iall = 0;
+                out_32(&dart->d_dartcntl.dc_word, dc.dc_word);
+                continue;
+            } else {
+                panic(" broken U4???\n");
+            }
+        }
+        return;
+    }
+}
+
+static void u4_inv_entry(ulong pgn)
+{
+    union dart_ctl dc;
+    ulong retries = 0;
+
+    dc.dc_word = in_32(&dart->d_dartcntl.dc_word);
+    dc.dc_bits.dc_ilpn = pgn;
+    dc.dc_bits.dc_ione = 1;
+    out_32(&dart->d_dartcntl.dc_word, dc.dc_word);
+
+    /* wait for completion */
+    /* FIXME: since we do this from the HV do we need to wait?! */
+    do {
+        dc.dc_word = in_32(&dart->d_dartcntl.dc_word);
+        retries++;
+        if (retries > 1000000)
+            panic("WAY! too long\n");
+    } while (dc.dc_bits.dc_ione != 0);
+}
+
+static struct dart_ops u4_ops = {
+    .do_inv_all = u4_inv_all,
+    .do_inv_entry = u4_inv_entry,
+};
+
+struct dart_ops *u4_init(ulong base, ulong table, ulong dart_pages)
+{
+    union dart_base db;
+    union dart_size ds;
+    union dart_ctl dc;
+
+    dart = (struct dart *)base;
+
+    db.db_word = 0;
+    db.db_bits.db_dartbase = table >> PAGE_SHIFT;
+
+    ds.ds_word = 0;
+    ds.ds_bits.ds_dartsize = dart_pages;
+
+    dc.dc_word = in_32(&dart->d_dartcntl.dc_word);
+    if (dc.dc_bits.dc_darten == 1) {
+        panic("%s: dart is already enabled: 0x%x\n", __func__, dc.dc_word);
+    }
+    dc.dc_bits.dc_darten = 1;   /* enable it */
+
+    printk("Initializing DART Model U4: ctl: 0x%x base: 0x%x size: 0x%x\n",
+           dc.dc_word, db.db_word, ds.ds_word);
+
+    out_32(&dart->d_dartbase.db_word, db.db_word);
+    out_32(&dart->d_dartsize.ds_word, ds.ds_word);
+    out_32(&dart->d_dartcntl.dc_word, dc.dc_word);
+
+    return &u4_ops;
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/delay.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/delay.c  Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,37 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <xen/config.h>
+#include <xen/delay.h>
+#include <xen/time.h>
+#include <asm/processor.h>
+
+void udelay(unsigned long usecs)
+{
+    ulong ticks = usecs * ticks_per_usec;
+    ulong s;
+    ulong e;
+
+    s = get_timebase();
+    do {
+        asm volatile("or 1,1,1"); /* also puts the thread to low priority */
+        e = get_timebase();
+    } while ((e-s) < ticks);
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/dom0_ops.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/dom0_ops.c       Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,87 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/lib.h>
+#include <xen/sched.h>
+#include <xen/guest_access.h>
+#include <public/xen.h>
+#include <public/dom0_ops.h>
+
+extern void arch_getdomaininfo_ctxt(struct vcpu *v, vcpu_guest_context_t *c);
+extern long arch_do_dom0_op(struct dom0_op *op, XEN_GUEST_HANDLE(dom0_op_t) 
u_dom0_op);
+
+void arch_getdomaininfo_ctxt(struct vcpu *v, vcpu_guest_context_t *c)
+{ 
+    memcpy(&c->user_regs, &v->arch.ctxt, sizeof(struct cpu_user_regs));
+    /* XXX fill in rest of vcpu_guest_context_t */
+}
+
+long arch_do_dom0_op(struct dom0_op *op, XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op)
+{
+    long ret = 0;
+
+    switch (op->cmd) {
+    case DOM0_GETMEMLIST: {
+        /* XXX 64M hackage */
+        const int memsize = (64UL<<20);
+        int domain_pfns = memsize>>12;
+        int max_pfns = op->u.getmemlist.max_pfns;
+        int domid = op->u.getmemlist.domain;
+        int i;
+
+        for (i = 0; (i < max_pfns) && (i < domain_pfns); i++) {
+            xen_pfn_t mfn = (((domid + 1) * memsize) >> 12) + i;
+            if (copy_to_guest_offset(op->u.getmemlist.buffer, i, &mfn, 1)) {
+                ret = -EFAULT;
+                break;
+            }
+        }
+        op->u.getmemlist.num_pfns = i;
+        copy_to_guest(u_dom0_op, op, 1);
+    }
+    break;
+
+    case DOM0_PHYSINFO:
+    {
+        dom0_physinfo_t *pi = &op->u.physinfo;
+
+        pi->threads_per_core = 1;
+        pi->cores_per_socket = 1;
+        pi->sockets_per_node = 1;
+        pi->nr_nodes         = 1;
+        pi->total_pages      = total_pages;
+        pi->free_pages       = avail_domheap_pages();
+        pi->cpu_khz          = cpu_khz;
+        memset(pi->hw_cap, 0, sizeof(pi->hw_cap));
+        ret = 0;
+        if ( copy_to_guest(u_dom0_op, op, 1) )
+            ret = -EFAULT;
+    }
+    break;
+
+    default:
+        ret = -ENOSYS;
+        break;
+    }
+
+    return ret;
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/domain.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/domain.c Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,251 @@
+/*
+ * 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. 2005, 2006
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <stdarg.h>
+#include <xen/config.h>
+#include <xen/lib.h>
+#include <xen/sched.h>
+#include <xen/mm.h>
+#include <xen/serial.h>
+#include <xen/domain.h>
+#include <xen/console.h>
+#include <xen/reboot.h>
+#include <asm/htab.h>
+#include <asm/current.h>
+#include <asm/hcalls.h>
+
+extern void idle_loop(void);
+
+#define next_arg(fmt, args) ({                                              \
+    unsigned long __arg;                                                    \
+    switch ( *(fmt)++ )                                                     \
+    {                                                                       \
+    case 'i': __arg = (unsigned long)va_arg(args, unsigned int);  break;    \
+    case 'l': __arg = (unsigned long)va_arg(args, unsigned long); break;    \
+    case 'p': __arg = (unsigned long)va_arg(args, void *);        break;    \
+    case 'h': __arg = (unsigned long)va_arg(args, void *);        break;    \
+    default:  __arg = 0; BUG();                                             \
+    }                                                                       \
+    __arg;                                                                  \
+})
+
+unsigned long hypercall_create_continuation(unsigned int op,
+        const char *format, ...)
+{
+    struct cpu_user_regs *regs = guest_cpu_user_regs();
+    const char *p = format;
+    va_list args;
+    int gprnum = 4;
+    int i;
+
+    va_start(args, format);
+
+    regs->pc -= 4; /* re-execute 'sc' */
+
+    for (i = 0; *p != '\0'; i++) {
+        regs->gprs[gprnum++] = next_arg(p, args);
+    }
+
+    va_end(args);
+
+    /* As luck would have it, we use the same register for hcall opcodes and
+     * for hcall return values. The return value from this function is placed
+     * in r3 on return, so modifying regs->gprs[3] would have no effect. */
+    return XEN_MARK(op);
+}
+
+int arch_domain_create(struct domain *d)
+{
+
+    if (d->domain_id == IDLE_DOMAIN_ID) {
+        d->shared_info = (void *)alloc_xenheap_page();
+        clear_page(d->shared_info);
+
+        return 0;
+    }
+
+    /* XXX the hackage... hardcode 64M domains */
+    d->arch.rma_base = (64<<20) * (d->domain_id + 1);
+    d->arch.rma_size = (64<<20);
+
+    printk("clearing RMO: 0x%lx[0x%lx]\n", d->arch.rma_base, d->arch.rma_size);
+    memset((void*)d->arch.rma_base, 0, d->arch.rma_size);
+
+    htab_alloc(d, LOG_DEFAULT_HTAB_BYTES);
+
+    d->shared_info = (shared_info_t *)
+        (rma_addr(&d->arch, RMA_SHARED_INFO) + d->arch.rma_base);
+
+    d->arch.large_page_sizes = 1;
+    d->arch.large_page_shift[0] = 24; /* 16 M for 970s */
+
+    return 0;
+}
+
+void arch_domain_destroy(struct domain *d)
+{
+    unimplemented();
+}
+
+void machine_halt(void)
+{
+    printf("machine_halt called: spinning....\n");
+    console_start_sync();
+    while(1);
+}
+
+void machine_restart(char * __unused)
+{
+    printf("machine_restart called: spinning....\n");
+    console_start_sync();
+    while(1);
+}
+
+struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id)
+{
+    struct vcpu *v;
+
+    if ( (v = xmalloc(struct vcpu)) == NULL )
+        return NULL;
+
+    memset(v, 0, sizeof(*v));
+    v->vcpu_id = vcpu_id;
+
+    return v;
+}
+
+void free_vcpu_struct(struct vcpu *v)
+{
+    BUG_ON(v->next_in_list != NULL);
+    if ( v->vcpu_id != 0 )
+        v->domain->vcpu[v->vcpu_id - 1]->next_in_list = NULL;
+    xfree(v);
+}
+
+int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_t *c)
+{ 
+    memcpy(&v->arch.ctxt, &c->user_regs, sizeof(c->user_regs));
+
+    set_bit(_VCPUF_initialised, &v->vcpu_flags);
+
+    cpu_init_vcpu(v);
+
+    return 0;
+}
+
+void dump_pageframe_info(struct domain *d)
+{
+    struct page_info *page;
+
+    printk("Memory pages belonging to domain %u:\n", d->domain_id);
+
+    if ( d->tot_pages >= 10 )
+    {
+        printk("    DomPage list too long to display\n");
+    }
+    else
+    {
+        list_for_each_entry ( page, &d->page_list, list )
+        {
+            printk("    DomPage %p: mfn=%p, caf=%016lx, taf=%" PRtype_info 
"\n",
+                   _p(page_to_maddr(page)), _p(page_to_mfn(page)),
+                   page->count_info, page->u.inuse.type_info);
+        }
+    }
+
+    list_for_each_entry ( page, &d->xenpage_list, list )
+    {
+        printk("    XenPage %p: mfn=%p, caf=%016lx, taf=%" PRtype_info "\n",
+               _p(page_to_maddr(page)), _p(page_to_mfn(page)),
+               page->count_info, page->u.inuse.type_info);
+    }
+}
+
+
+void context_switch(struct vcpu *prev, struct vcpu *next)
+{
+    struct cpu_user_regs *stack_regs = guest_cpu_user_regs();
+    cpumask_t dirty_mask = next->vcpu_dirty_cpumask;
+    unsigned int cpu = smp_processor_id();
+
+#if 0
+    printf("%s: dom %x to dom %x\n", __func__, prev->domain->domain_id,
+            next->domain->domain_id);
+#endif
+
+    /* Allow at most one CPU at a time to be dirty. */
+    ASSERT(cpus_weight(dirty_mask) <= 1);
+    if (unlikely(!cpu_isset(cpu, dirty_mask) && !cpus_empty(dirty_mask)))
+    {
+        /* Other cpus call __sync_lazy_execstate from flush ipi handler. */
+        if (!cpus_empty(next->vcpu_dirty_cpumask))
+            flush_tlb_mask(next->vcpu_dirty_cpumask);
+    }
+
+    /* copy prev guest state off the stack into its vcpu */
+    memcpy(&prev->arch.ctxt, stack_regs, sizeof(struct cpu_user_regs));
+
+    set_current(next);
+
+    /* copy next guest state onto the stack */
+    memcpy(stack_regs, &next->arch.ctxt, sizeof(struct cpu_user_regs));
+
+    /* save old domain state */
+    save_sprs(prev);
+    save_float(prev);
+    save_segments(prev);
+
+    context_saved(prev);
+
+    /* load up new domain */
+    load_sprs(next);
+    load_float(next);
+    load_segments(next);
+
+    mtsdr1(next->domain->arch.htab.sdr1);
+    local_flush_tlb(); /* XXX maybe flush_tlb_mask? */
+
+    if (is_idle_vcpu(next)) {
+        reset_stack_and_jump(idle_loop);
+    }
+
+    reset_stack_and_jump(full_resume);
+    /* not reached */
+}
+
+void continue_running(struct vcpu *same)
+{
+    /* nothing to do */
+}
+
+void sync_vcpu_execstate(struct vcpu *v)
+{
+    /* XXX for now, for domain destruction, make this non-fatal */
+    printf("%s: called\n", __func__);
+}
+
+void domain_relinquish_resources(struct domain *d)
+{
+    /* nothing to do? */
+}
+
+void arch_dump_domain_info(struct domain *d)
+{
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/domain_build.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/domain_build.c   Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,285 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <xen/config.h>
+#include <xen/lib.h>
+#include <xen/elf.h>
+#include <xen/sched.h>
+#include <xen/init.h>
+#include <xen/ctype.h>
+#include <xen/iocap.h>
+#include <xen/compile.h>
+#include <asm/processor.h>
+#include <asm/papr.h>
+#include "oftree.h"
+
+extern int parseelfimage_32(struct domain_setup_info *dsi);
+extern int loadelfimage_32(struct domain_setup_info *dsi);
+
+/* opt_dom0_mem: memory allocated to domain 0. */
+static unsigned int opt_dom0_mem;
+static void parse_dom0_mem(char *s)
+{
+    unsigned long long bytes = parse_size_and_unit(s);
+    /* If no unit is specified we default to kB units, not bytes. */
+    if (isdigit(s[strlen(s)-1]))
+        opt_dom0_mem = (unsigned int)bytes;
+    else
+        opt_dom0_mem = (unsigned int)(bytes >> 10);
+}
+custom_param("dom0_mem", parse_dom0_mem);
+
+int elf_sanity_check(Elf_Ehdr *ehdr)
+{
+    if (IS_ELF(*ehdr))
+        /* we are happy with either */
+        if ((ehdr->e_ident[EI_CLASS] == ELFCLASS32
+             && ehdr->e_machine == EM_PPC)
+            || (ehdr->e_ident[EI_CLASS] == ELFCLASS64
+                && ehdr->e_machine == EM_PPC64)) {
+            if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB
+                && ehdr->e_type == ET_EXEC)
+                return 1;
+        }
+    printk("DOM0 image is not a Xen-compatible Elf image.\n");
+    return 0;
+}
+
+/* adapted from common/elf.c */
+#define RM_MASK(a,l) ((a) & ((1UL << (l)) - 1))
+
+static int rm_loadelfimage_64(struct domain_setup_info *dsi, ulong rma)
+{
+    char *elfbase = (char *)dsi->image_addr;
+    Elf64_Ehdr *ehdr = (Elf64_Ehdr *)dsi->image_addr;
+    Elf64_Phdr *phdr;
+    int h;
+  
+    for (h = 0; h < ehdr->e_phnum; h++ ) 
+    {
+        phdr = (Elf64_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
+        if (!((phdr->p_type == PT_LOAD) &&
+             ((phdr->p_flags & (PF_W|PF_X)) != 0)))
+            continue;
+
+        if (phdr->p_filesz != 0)
+            memcpy((char *)(rma + RM_MASK(phdr->p_paddr, 42)),
+                   elfbase + phdr->p_offset, 
+                   phdr->p_filesz);
+        if (phdr->p_memsz > phdr->p_filesz)
+            memset((char *)(rma + RM_MASK(phdr->p_paddr, 42) + phdr->p_filesz),
+                   0, phdr->p_memsz - phdr->p_filesz);
+    }
+
+#ifdef NOT_YET
+    loadelfsymtab(dsi, 1);
+#endif
+
+    return 0;
+}
+
+int construct_dom0(struct domain *d,
+                   unsigned long image_start, unsigned long image_len, 
+                   unsigned long initrd_start, unsigned long initrd_len,
+                   char *cmdline)
+{
+    int rc;
+    struct vcpu *v = d->vcpu[0];
+    struct domain_setup_info dsi;
+    ulong dst;
+    u64 *ofh_tree;
+    ulong rma_sz = d->arch.rma_size;
+    ulong rma = d->arch.rma_base;
+    start_info_t *si;
+    ulong eomem;
+    int am64 = 1;
+    ulong msr;
+    ulong pc;
+    ulong r2;
+
+    /* Sanity! */
+    BUG_ON(d->domain_id != 0);
+    BUG_ON(d->vcpu[0] == NULL);
+
+    cpu_init_vcpu(v);
+
+    memset(&dsi, 0, sizeof(struct domain_setup_info));
+    dsi.image_addr = image_start;
+    dsi.image_len  = image_len;
+
+    if ((rc = parseelfimage(&dsi)) != 0) {
+        if ((rc = parseelfimage_32(&dsi)) != 0)
+            return rc;
+        am64 = 0;
+    }
+
+    /* 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 */
+    dsi.v_kernstart = RM_MASK(dsi.v_kernstart, 42);
+    dsi.v_kernend = RM_MASK(dsi.v_kernend, 42);
+    dsi.v_kernentry = RM_MASK(dsi.v_kernentry, 42);
+
+    if (dsi.xen_section_string == NULL) {
+        printk("Not a Xen-ELF image: '__xen_guest' section not found.\n");
+        return -EINVAL;
+    }
+    printk("*** LOADING DOMAIN 0 ***\n");
+
+    /* By default DOM0 is allocated all available memory. */
+    d->max_pages = ~0U;
+    d->tot_pages = (d->arch.rma_size >> PAGE_SHIFT);
+
+    ASSERT( image_len < rma_sz );
+
+    si = (start_info_t *)(rma_addr(&d->arch, RMA_START_INFO) + rma);
+    printk("xen_start_info: %p\n", si);
+
+    sprintf(si->magic, "xen-%i.%i-powerpc%d%s",
+            XEN_VERSION, XEN_SUBVERSION, BITS_PER_LONG, "HV");
+    si->flags = SIF_PRIVILEGED | SIF_INITDOMAIN;
+
+    si->shared_info = ((ulong)d->shared_info) - rma;
+    printk("shared_info: 0x%lx,%p\n", si->shared_info, d->shared_info);
+
+    eomem = si->shared_info;
+
+    /* allow dom0 to access all of system RAM */
+    d->arch.logical_base_pfn = 128 << (20 - PAGE_SHIFT); /* 128 MB */
+    d->arch.logical_end_pfn = max_page;
+
+    /* number of pages accessible */
+    si->nr_pages = rma_sz >> PAGE_SHIFT;
+
+    si->pt_base = 0;
+    si->nr_pt_frames = 0;
+    si->mfn_list = 0;
+
+    /* 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;
+
+    ASSERT((dst - rma) + (ulong)firmware_image_size < eomem);
+    printk("loading OFH: 0x%lx, RMA: 0x%lx\n", dst, dst - rma);
+    memcpy((void *)dst, firmware_image_start, (ulong)firmware_image_size);
+
+    v->arch.ctxt.gprs[5] = (dst - rma);
+    ofh_tree = (u64 *)(dst + 0x10);
+    ASSERT(*ofh_tree == 0xdeadbeef00000000);
+
+    /* 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);
+
+    if (am64) {
+        ulong kbase;
+        ulong *fdesc;
+
+        printk("loading 64-bit Dom0: 0x%lx, in RMA:0x%lx\n", dst, dst - rma);
+        rm_loadelfimage_64(&dsi, dst);
+
+        kbase = dst;
+        /* move dst to end of bss */
+        dst = ALIGN_UP(dsi.v_kernend + dst, PAGE_SIZE);
+
+        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);
+
+            si->mod_start = dst - rma;
+            si->mod_len = image_len;
+
+            dst = ALIGN_UP(dst + initrd_len, PAGE_SIZE);
+        } else {
+            printk("no initrd\n");
+            si->mod_start = 0;
+            si->mod_len = 0;
+        }
+        /* it may be a function descriptor */
+        fdesc = (ulong *)(dsi.v_kernstart + dsi.v_kernentry + kbase);
+
+        if (fdesc[2] == 0
+            && ((fdesc[0] >= dsi.v_kernstart)
+                && (fdesc[0] < dsi.v_kernend)) /* text entry is in range */
+            && ((fdesc[1] >= dsi.v_kernstart)  /* toc can be > image */
+                && (fdesc[1] < (dsi.v_kernend + (0x7fff * sizeof (ulong)))))) {
+            /* it is almost certainly a function descriptor */
+            pc = RM_MASK(fdesc[0], 42) + kbase - rma;
+            r2 = RM_MASK(fdesc[1], 42) + kbase - rma;
+        } else {
+            pc = ((ulong)fdesc) - rma;
+            r2 = 0;
+        }
+        msr = MSR_SF;
+    } else {
+        printk("loading 32-bit Dom0: 0x%lx, in RMA:0x%lx\n",
+               dsi.v_kernstart + rma, dsi.v_kernstart);
+        dsi.v_start = rma;
+        loadelfimage_32(&dsi);
+
+        pc = dsi.v_kernentry;
+        r2 = 0;
+        msr = 0;
+    }
+
+    v->arch.ctxt.gprs[3] = si->mod_start;
+    v->arch.ctxt.gprs[4] = si->mod_len;
+
+    memset(si->cmd_line, 0, sizeof(si->cmd_line));
+    if ( cmdline != NULL )
+        strncpy((char *)si->cmd_line, cmdline, sizeof(si->cmd_line)-1);
+
+    v->arch.ctxt.msr = msr;
+    v->arch.ctxt.pc = pc;
+    v->arch.ctxt.gprs[2] = r2;
+
+    printk("DOM: pc = 0x%lx, r2 = 0x%lx\n", pc, r2);
+
+    ofd_dom0_fixup(d, *ofh_tree + rma, si, dst - rma);
+
+    set_bit(_VCPUF_initialised, &v->vcpu_flags);
+
+    rc = 0;
+
+    /* DOM0 is permitted full I/O capabilities. */
+    rc |= iomem_permit_access(dom0, 0UL, ~0UL);
+    rc |= irqs_permit_access(dom0, 0, NR_IRQS-1);
+
+    BUG_ON(rc != 0);
+
+    return 0;
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/elf32.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/elf32.c  Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,5 @@
+#define parseelfimage parseelfimage_32
+#define loadelfimage loadelfimage_32
+#define ELFSIZE 32
+#include "../../common/elf.c"
+
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/exceptions.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/exceptions.c     Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,87 @@
+/*
+ * 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. 2005, 2006
+ *
+ * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
+ */
+
+#include <xen/config.h>
+#include <xen/softirq.h>
+#include <xen/sched.h>
+#include <xen/serial.h>
+#include <xen/gdbstub.h>
+#include <public/xen.h>
+#include <asm/time.h>
+
+#undef DEBUG
+#define HDEC_PREEMPT
+
+extern ulong ppc_do_softirq(ulong orig_msr);
+extern void do_timer(struct cpu_user_regs *regs);
+extern void do_dec(struct cpu_user_regs *regs);
+extern void program_exception(struct cpu_user_regs *regs, unsigned long 
cookie);
+
+int hdec_sample = 0;
+
+void do_timer(struct cpu_user_regs *regs)
+{
+    /* XXX this is just here to keep HDEC from firing until
+     * reprogram_ac_timer() sets the proper next-tick time */
+    mthdec(timebase_freq);
+
+#ifdef HDEC_PREEMPT
+    raise_softirq(TIMER_SOFTIRQ);
+#endif
+#ifdef DEBUG
+    {
+        int d;
+        if (regs->msr & MSR_HV) {
+            d = -1;
+        } else {
+            d = get_current()->domain->domain_id;
+        }
+        extern char serial_getc_nb(int handle);
+        if (0 && serial_getc_nb(0) > 0) {
+            printk("H: pc: 0x%lx lr: 0x%lx \n", regs->pc, regs->lr);
+        }
+        if (hdec_sample)  {
+            printk("H: pc: 0x%lx lr: 0x%lx \n", regs->pc, regs->lr);
+            hdec_sample = 0;
+        }
+    }
+#endif
+}
+
+void do_dec(struct cpu_user_regs *regs)
+{
+    if (!(regs->msr & MSR_HV)) {
+        panic("HV dec from domain\n");
+    }
+    printk("DEC_HV: pc: 0x%lx lr: 0x%lx \n", regs->pc, regs->lr);
+    mtdec(INT_MAX);
+}
+
+void program_exception(struct cpu_user_regs *regs, unsigned long cookie)
+{
+#ifdef CRASH_DEBUG
+    __trap_to_gdb(regs, cookie);
+#else /* CRASH_DEBUG */
+    show_registers(regs);
+    printk("dar 0x%016lx, dsisr 0x%08x\n", mfdar(), mfdsisr());
+    printk("hid4 0x%016lx\n", regs->hid4);
+    panic("%s: 0x%lx\n", __func__, cookie);
+#endif /* CRASH_DEBUG */
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/exceptions.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/exceptions.h     Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,57 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
+ */
+
+#ifndef _ARCH_PPC_EXCEPTIONS_H_
+#define _ARCH_PPC_EXCEPTIONS_H_
+
+#include <xen/types.h>
+#include <public/xen.h>
+#include <xen/multiboot.h>
+
+extern void do_hcall(struct cpu_user_regs *regs);
+extern void do_IRQ(struct cpu_user_regs *regs);
+extern void deliver_ee(struct cpu_user_regs *regs);
+extern void do_external(struct cpu_user_regs *regs);
+extern void init_IRQ(void);
+extern void ack_APIC_irq(void);
+extern int ioapic_guest_read(unsigned long physbase, unsigned int reg, u32 
*pval);
+extern int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 
val);
+extern void __start_xen_ppc(
+    ulong r3, ulong r4, ulong r5, ulong r6, ulong r7, ulong orig_msr);
+extern  multiboot_info_t *boot_of_init(ulong r3, ulong r4, ulong vec, ulong 
r6, ulong r7, ulong orig_msr);
+
+extern void do_timer(struct cpu_user_regs *regs);
+extern void do_dec(struct cpu_user_regs *regs);
+extern void program_exception(
+    struct cpu_user_regs *regs, unsigned long cookie);
+
+extern long xen_hvcall_jump(struct cpu_user_regs *regs, ulong address);
+extern void *mambo_memset(void *, int, ulong);
+extern void *mambo_memcpy(void *, const void *, ulong);
+
+extern ulong *__hypercall_table[];
+
+extern char exception_vectors[];
+extern char exception_vectors_end[];
+extern int spin_start[];
+extern int firmware_image_start[0];
+extern int firmware_image_size[0];
+
+#endif
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/external.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/external.c       Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,247 @@
+/*
+ * 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. 2005, 2006
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/sched.h>
+#include <xen/lib.h>
+#include <xen/event.h>
+#include <xen/irq.h>
+#include <public/xen.h>
+#include <asm/current.h>
+#include <asm/hardirq.h>
+#include <asm/mpic.h>
+#include "mpic_init.h"
+#include "exceptions.h"
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(fmt...) printk(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
+
+unsigned long io_apic_irqs;
+int ioapic_ack_new = 1;
+
+static struct hw_interrupt_type *hc_irq;
+
+/* deliver_ee: called with interrupts off when resuming every vcpu */
+void deliver_ee(struct cpu_user_regs *regs)
+{
+    const ulong srr_mask = ~(MSR_IR | MSR_DR | MSR_FE0 | MSR_FE1 | MSR_EE |
+                             MSR_RI |
+                             MSR_BE | MSR_FP | MSR_PMM | MSR_PR | MSR_SE);
+
+    BUG_ON(mfmsr() & MSR_EE);
+    BUG_ON(regs->msr & MSR_HV);
+
+    if (!local_events_need_delivery())
+        return;
+
+    /* XXX OS error: EE was set but RI was not. We could trigger a machine
+     * check, or kill the domain... for now just crash Xen so we notice. */
+    BUG_ON(!(regs->msr & MSR_RI));
+
+    regs->srr0 = regs->pc;
+    /* zero SRR1[33:36] and SRR1[42:47] */
+    regs->srr1 = regs->msr & ~0x00000000783f0000;
+    regs->pc = 0x500;
+    regs->msr &= srr_mask;
+    regs->msr |= MSR_SF | MSR_ME;
+
+    DBG("<HV: pc=0x%lx, msr=0x%lx\n", regs->pc, regs->msr);
+}
+
+void do_external(struct cpu_user_regs *regs)
+{
+    int vec;
+
+    BUG_ON(!(regs->msr & MSR_EE));
+    BUG_ON(mfmsr() & MSR_EE);
+
+    vec = xen_mpic_get_irq(regs);
+
+    if (vec != -1) {
+        DBG("EE:0x%lx isrc: %d\n", regs->msr, vec);
+        regs->entry_vector = vec;
+        do_IRQ(regs);
+
+        BUG_ON(mfmsr() & MSR_EE);
+    }
+}
+
+static int xen_local_irq(unsigned int irq)
+{
+    irq_desc_t *desc;
+    unsigned int vector;
+
+    vector = irq_to_vector(irq);
+    desc = &irq_desc[vector];
+
+    return !(desc->status & IRQ_GUEST);
+}
+
+static unsigned int xen_startup_irq(unsigned int irq)
+{
+    DBG("%s(%d)\n", __func__, irq);
+    if (xen_local_irq(irq)) {
+        return hc_irq->startup(irq);
+    }
+    return 0;
+}
+
+static void xen_shutdown_irq(unsigned int irq)
+{
+    DBG("%s(%d)\n", __func__, irq);
+    if (xen_local_irq(irq)) {
+        hc_irq->shutdown(irq);
+    }
+}
+
+static void xen_enable_irq(unsigned int irq)
+{
+    DBG("%s(%d)\n", __func__, irq);
+    if (xen_local_irq(irq)) {
+        hc_irq->enable(irq);
+    }
+}
+
+static void xen_disable_irq(unsigned int irq)
+{
+    DBG("%s(%d)\n", __func__, irq);
+    if (xen_local_irq(irq)) {
+        hc_irq->disable(irq);
+    }
+}
+    
+static void xen_ack_irq(unsigned int irq)
+{
+    DBG("%s(%d)\n", __func__, irq);
+    if (xen_local_irq(irq)) {
+        if (hc_irq->ack) hc_irq->ack(irq);
+    }
+}
+
+static void xen_end_irq(unsigned int irq)
+{
+    DBG("%s(%d)\n", __func__, irq);
+    if (xen_local_irq(irq)) {
+        hc_irq->end(irq);
+    }
+}
+
+static void xen_set_affinity(unsigned int irq, cpumask_t mask)
+{
+    DBG("%s(%d)\n", __func__, irq);
+    if (xen_local_irq(irq)) {
+        if (hc_irq->set_affinity) hc_irq->set_affinity(irq, mask);
+    }
+}
+
+static struct hw_interrupt_type xen_irq = {
+    .startup = xen_startup_irq,
+    .enable = xen_enable_irq,
+    .disable = xen_disable_irq,
+    .shutdown = xen_shutdown_irq,
+    .ack = xen_ack_irq,
+    .end = xen_end_irq,
+    .set_affinity = xen_set_affinity,
+};
+
+void init_IRQ(void)
+{
+    hc_irq = xen_mpic_init(&xen_irq);
+}
+
+void ack_APIC_irq(void)
+{
+    printk("%s: EOI the whole MPIC?\n", __func__);
+    for (;;);
+}
+
+void ack_bad_irq(unsigned int irq)
+{
+    printk("unexpected IRQ trap at vector %02x\n", irq);
+    /*
+     * Currently unexpected vectors happen only on SMP and APIC.
+     * We _must_ ack these because every local APIC has only N
+     * irq slots per priority level, and a 'hanging, unacked' IRQ
+     * holds up an irq slot - in excessive cases (when multiple
+     * unexpected vectors occur) that might lock up the APIC
+     * completely.
+     */
+    ack_APIC_irq();
+}
+
+extern void dump_ioapic_irq_info(void);
+void dump_ioapic_irq_info(void)
+{
+    printk("%s: can't dump yet\n", __func__);
+}
+
+/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
+u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };
+int assign_irq_vector(int irq)
+{
+    static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
+
+    BUG_ON(irq >= NR_IRQ_VECTORS);
+    if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0)
+        return IO_APIC_VECTOR(irq);
+next:
+    current_vector += 8;
+
+    /* Skip the hypercall vector. */
+    if (current_vector == HYPERCALL_VECTOR)
+        goto next;
+
+    /* Skip the Linux/BSD fast-trap vector. */
+    if (current_vector == FAST_TRAP)
+        goto next;
+
+    if (current_vector >= FIRST_SYSTEM_VECTOR) {
+        offset++;
+        if (!(offset%8))
+            return -ENOSPC;
+        current_vector = FIRST_DEVICE_VECTOR + offset;
+    }
+
+    vector_irq[current_vector] = irq;
+    if (irq != AUTO_ASSIGN)
+        IO_APIC_VECTOR(irq) = current_vector;
+
+    return current_vector;
+}
+
+int ioapic_guest_read(unsigned long physbase, unsigned int reg, u32 *pval)
+{
+    BUG_ON(pval != pval);
+
+    return 0;
+}
+
+int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
+{
+    BUG_ON(val != val);
+    return 0;
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/float.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/float.S  Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,243 @@
+/*
+ * 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
+ */
+
+#include <asm/config.h>
+#include <asm/asm-offsets.h>
+#include <asm/reg_defs.h>
+#include <asm/msr.h>
+#include <asm/processor.h>
+
+#ifdef HAS_FLOAT
+save_fp:
+       addi    r4, r3, VCPU_fprs - FPR_WIDTH
+       stfdu   fr0,FPR_WIDTH(r4)
+       stfdu   fr1,FPR_WIDTH(r4)
+       stfdu   fr2,FPR_WIDTH(r4)
+       stfdu   fr3,FPR_WIDTH(r4)
+       stfdu   fr4,FPR_WIDTH(r4)
+       stfdu   fr5,FPR_WIDTH(r4)
+       stfdu   fr6,FPR_WIDTH(r4)
+       stfdu   fr7,FPR_WIDTH(r4)
+       stfdu   fr8,FPR_WIDTH(r4)
+       stfdu   fr9,FPR_WIDTH(r4)
+       stfdu   fr10,FPR_WIDTH(r4)
+       stfdu   fr11,FPR_WIDTH(r4)
+       stfdu   fr12,FPR_WIDTH(r4)
+       stfdu   fr13,FPR_WIDTH(r4)
+       stfdu   fr14,FPR_WIDTH(r4)
+       stfdu   fr15,FPR_WIDTH(r4)
+       stfdu   fr16,FPR_WIDTH(r4)
+       stfdu   fr17,FPR_WIDTH(r4)
+       stfdu   fr18,FPR_WIDTH(r4)
+       stfdu   fr19,FPR_WIDTH(r4)
+       stfdu   fr20,FPR_WIDTH(r4)
+       stfdu   fr21,FPR_WIDTH(r4)
+       stfdu   fr22,FPR_WIDTH(r4)
+       stfdu   fr23,FPR_WIDTH(r4)
+       stfdu   fr24,FPR_WIDTH(r4)
+       stfdu   fr25,FPR_WIDTH(r4)
+       stfdu   fr26,FPR_WIDTH(r4)
+       stfdu   fr27,FPR_WIDTH(r4)
+       stfdu   fr28,FPR_WIDTH(r4)
+       stfdu   fr29,FPR_WIDTH(r4)
+       stfdu   fr30,FPR_WIDTH(r4)
+       stfdu   fr31,FPR_WIDTH(r4)
+       mffs    fr0
+       stfd    fr0,VCPU_fpscr(r3)
+       blr
+
+load_fp:
+       lfd     fr0,VCPU_fpscr(r3)
+       mtfsf   0xff,fr0
+
+       addi    r4, r3, VCPU_fprs - FPR_WIDTH
+       lfdu    fr0,FPR_WIDTH(r4)
+       lfdu    fr1,FPR_WIDTH(r4)
+       lfdu    fr2,FPR_WIDTH(r4)
+       lfdu    fr3,FPR_WIDTH(r4)
+       lfdu    fr4,FPR_WIDTH(r4)
+       lfdu    fr5,FPR_WIDTH(r4)
+       lfdu    fr6,FPR_WIDTH(r4)
+       lfdu    fr7,FPR_WIDTH(r4)
+       lfdu    fr8,FPR_WIDTH(r4)
+       lfdu    fr9,FPR_WIDTH(r4)
+       lfdu    fr10,FPR_WIDTH(r4)
+       lfdu    fr11,FPR_WIDTH(r4)
+       lfdu    fr12,FPR_WIDTH(r4)
+       lfdu    fr13,FPR_WIDTH(r4)
+       lfdu    fr14,FPR_WIDTH(r4)
+       lfdu    fr15,FPR_WIDTH(r4)
+       lfdu    fr16,FPR_WIDTH(r4)
+       lfdu    fr17,FPR_WIDTH(r4)
+       lfdu    fr18,FPR_WIDTH(r4)
+       lfdu    fr19,FPR_WIDTH(r4)
+       lfdu    fr20,FPR_WIDTH(r4)
+       lfdu    fr21,FPR_WIDTH(r4)
+       lfdu    fr22,FPR_WIDTH(r4)
+       lfdu    fr23,FPR_WIDTH(r4)
+       lfdu    fr24,FPR_WIDTH(r4)
+       lfdu    fr25,FPR_WIDTH(r4)
+       lfdu    fr26,FPR_WIDTH(r4)
+       lfdu    fr27,FPR_WIDTH(r4)
+       lfdu    fr28,FPR_WIDTH(r4)
+       lfdu    fr29,FPR_WIDTH(r4)
+       lfdu    fr30,FPR_WIDTH(r4)
+       lfdu    fr31,FPR_WIDTH(r4)
+       blr
+#endif /* HAS_FLOAT */
+
+#ifdef HAS_VMX
+
+#define VCPU_vr(n) (VCPU_vrs + ((n) * 16))
+
+/*
+ * We cannot rely on the domain to correctly use VRSAVE
+ * so it is required that all VMX registers are saved and restored.
+ */
+save_vmx:
+       mfspr   r0,SPRN_VRSAVE
+       stw     r0,VCPU_vrsave(r3)
+
+       addi r0,r3,VCPU_vr(0);  stvxl   vr0,0,r0
+       addi r0,r3,VCPU_vr(1);  stvxl   vr1,0,r0
+       addi r0,r3,VCPU_vr(2);  stvxl   vr2,0,r0
+       addi r0,r3,VCPU_vr(3);  stvxl   vr3,0,r0
+       addi r0,r3,VCPU_vr(4);  stvxl   vr4,0,r0
+       addi r0,r3,VCPU_vr(5);  stvxl   vr5,0,r0
+       addi r0,r3,VCPU_vr(6);  stvxl   vr6,0,r0
+       addi r0,r3,VCPU_vr(7);  stvxl   vr7,0,r0
+       addi r0,r3,VCPU_vr(8);  stvxl   vr8,0,r0
+
+       /*
+        * By now vr0 should be pushed out so now is a good time to
+        * get the VRSCR which can take a long time and has no dependcies
+        * on the following operations.
+        */
+       mfvscr  vr0
+       addi r0,r3,VCPU_vscr ;  stvxl   vr0,0,r0
+
+       addi r0,r3,VCPU_vr(9);  stvxl   vr9,0,r0
+       addi r0,r3,VCPU_vr(10); stvxl   vr10,0,r0
+       addi r0,r3,VCPU_vr(11); stvxl   vr11,0,r0
+       addi r0,r3,VCPU_vr(12); stvxl   vr12,0,r0
+       addi r0,r3,VCPU_vr(13); stvxl   vr13,0,r0
+       addi r0,r3,VCPU_vr(14); stvxl   vr14,0,r0
+       addi r0,r3,VCPU_vr(15); stvxl   vr15,0,r0
+       addi r0,r3,VCPU_vr(16); stvxl   vr16,0,r0
+       addi r0,r3,VCPU_vr(17); stvxl   vr17,0,r0
+       addi r0,r3,VCPU_vr(18); stvxl   vr18,0,r0
+       addi r0,r3,VCPU_vr(19); stvxl   vr19,0,r0
+       addi r0,r3,VCPU_vr(20); stvxl   vr20,0,r0
+       addi r0,r3,VCPU_vr(21); stvxl   vr21,0,r0
+       addi r0,r3,VCPU_vr(22); stvxl   vr22,0,r0
+       addi r0,r3,VCPU_vr(23); stvxl   vr23,0,r0
+       addi r0,r3,VCPU_vr(24); stvxl   vr24,0,r0
+       addi r0,r3,VCPU_vr(25); stvxl   vr25,0,r0
+       addi r0,r3,VCPU_vr(26); stvxl   vr26,0,r0
+       addi r0,r3,VCPU_vr(27); stvxl   vr27,0,r0
+       addi r0,r3,VCPU_vr(28); stvxl   vr28,0,r0
+       addi r0,r3,VCPU_vr(29); stvxl   vr29,0,r0
+       addi r0,r3,VCPU_vr(30); stvxl   vr30,0,r0
+       addi r0,r3,VCPU_vr(31); stvxl   vr31,0,r0
+       blr
+
+load_vmx:
+       lwz     r0,VCPU_vrsave(r3)
+       mtspr   SPRN_VRSAVE,r0
+
+       /*
+        * This operation can take a long time so we use vr31 to
+        * eliminate the depency on r0 for the next load
+        */
+       addi r0,r3,VCPU_vscr ;  lvxl    vr31,0,r0
+       mtvscr  vr31
+
+       addi r0,r3,VCPU_vr(0);  lvxl    vr0,0,r0
+       addi r0,r3,VCPU_vr(1);  lvxl    vr1,0,r0
+       addi r0,r3,VCPU_vr(2);  lvxl    vr2,0,r0
+       addi r0,r3,VCPU_vr(3);  lvxl    vr3,0,r0
+       addi r0,r3,VCPU_vr(4);  lvxl    vr4,0,r0
+       addi r0,r3,VCPU_vr(5);  lvxl    vr5,0,r0
+       addi r0,r3,VCPU_vr(6);  lvxl    vr6,0,r0
+       addi r0,r3,VCPU_vr(7);  lvxl    vr7,0,r0
+       addi r0,r3,VCPU_vr(8);  lvxl    vr8,0,r0
+       addi r0,r3,VCPU_vr(9);  lvxl    vr9,0,r0
+       addi r0,r3,VCPU_vr(10); lvxl    vr10,0,r0
+       addi r0,r3,VCPU_vr(11); lvxl    vr11,0,r0
+       addi r0,r3,VCPU_vr(12); lvxl    vr12,0,r0
+       addi r0,r3,VCPU_vr(13); lvxl    vr13,0,r0
+       addi r0,r3,VCPU_vr(14); lvxl    vr14,0,r0
+       addi r0,r3,VCPU_vr(15); lvxl    vr15,0,r0
+       addi r0,r3,VCPU_vr(16); lvxl    vr16,0,r0
+       addi r0,r3,VCPU_vr(17); lvxl    vr17,0,r0
+       addi r0,r3,VCPU_vr(18); lvxl    vr18,0,r0
+       addi r0,r3,VCPU_vr(19); lvxl    vr19,0,r0
+       addi r0,r3,VCPU_vr(20); lvxl    vr20,0,r0
+       addi r0,r3,VCPU_vr(21); lvxl    vr21,0,r0
+       addi r0,r3,VCPU_vr(22); lvxl    vr22,0,r0
+       addi r0,r3,VCPU_vr(23); lvxl    vr23,0,r0
+       addi r0,r3,VCPU_vr(24); lvxl    vr24,0,r0
+       addi r0,r3,VCPU_vr(25); lvxl    vr25,0,r0
+       addi r0,r3,VCPU_vr(26); lvxl    vr26,0,r0
+       addi r0,r3,VCPU_vr(27); lvxl    vr27,0,r0
+       addi r0,r3,VCPU_vr(28); lvxl    vr28,0,r0
+       addi r0,r3,VCPU_vr(29); lvxl    vr29,0,r0
+       addi r0,r3,VCPU_vr(30); lvxl    vr30,0,r0
+       addi r0,r3,VCPU_vr(31); lvxl    vr31,0,r0
+       blr
+#endif /* HAS_VMX */
+
+/* void save_float(struct exec_domain *ed) */
+_GLOBAL(save_float)
+       mflr    r8
+#ifdef HAS_FLOAT
+       mfmsr   r9              # save msr
+       ori     r0,r9,MSR_FP    # turn on FPU
+       mtmsr   r0
+       bl      save_fp         # uses r3, r4
+       mtmsr   r9              # restore msr
+#endif /* HAS_FLOAT */
+#ifdef HAS_VMX
+       mfmsr   r9              # save msr
+       oris    r0,r9,MSR_VMX@h # turn on VMX
+       mtmsr   r0
+       bl      save_vmx        # uses r3
+       mtmsr   r9              # restore msr
+#endif /* HAS_VMX */
+       mtlr    r8
+       blr
+
+/* void load_float(struct exec_domain *ed) */
+_GLOBAL(load_float)
+       mflr    r8
+#ifdef HAS_FLOAT
+       mfmsr   r9              # save msr
+       ori     r0,r9,MSR_FP    # turn on FPU
+       mtmsr   r0
+       bl      load_fp # uses r3, r4
+       mtmsr   r9              # restore msr
+#endif /* HAS_FLOAT */
+#ifdef HAS_VMX
+       mfmsr   r9              # save msr
+       oris    r0,r9,MSR_VMX@h # turn on VMX
+       mtmsr   r0
+       bl      load_vmx        # uses r3
+       mtmsr   r9              # restore msr
+#endif /* HAS_VMX */
+       mtlr    r8
+       blr
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/gdbstub.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/gdbstub.c        Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,207 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
+ */
+
+#include <xen/types.h>
+#include <xen/lib.h>
+#include <xen/gdbstub.h>
+#include <public/xen.h>
+#include <asm/msr.h>
+#include <asm/bitops.h>
+#include <asm/cache.h>
+#include <asm/processor.h>
+
+asm(".globl trap_instruction\n"
+        "trap_instruction:\n"
+        "trap\n");
+extern u32 trap_instruction[];
+
+static unsigned int dec_entry;
+static unsigned int hdec_entry;
+
+static inline ulong
+gdb_ppc_0x700(struct cpu_user_regs *state)
+{
+    ulong instr;
+
+    switch (state->msr & MSR_TRAP_BITS) {
+        case MSR_TRAP_FE:
+            return SIGFPE;
+        case MSR_TRAP_IOP:
+        case MSR_TRAP_PRIV:
+            return SIGILL;
+        case MSR_TRAP:
+            instr = *((u32 *)state->pc);
+
+            /* if this was a hardcoded trap in the source, step past it */
+            if (instr == *trap_instruction) {
+                state->pc += sizeof (u32);
+            }
+            return SIGTRAP;
+    }
+    return SIGBUS;
+}
+
+u16 gdb_arch_signal_num(struct cpu_user_regs *regs, unsigned long cookie)
+{
+    /* exception type identifies, trap or bad address */
+    switch (cookie) {
+        case 0x200: /* Machine Check */
+            return SIGTERM;
+        case 0x300: /* DSI */
+        case 0x380: /* Data SLB */
+        case 0x400: /* ISI */
+        case 0x480: /* Instruction SLB */
+            return SIGSEGV;
+        case 0x600: /* Alignment SLB */
+            return SIGBUS;
+        case 0x700: /* Program */
+            return gdb_ppc_0x700(regs);
+        case 0x800: /* Float */
+            return SIGFPE;
+        case 0x900: /* Decrementer */
+            return SIGALRM; /* is this right? */
+        case 0xd00: /* TRAP */
+            return SIGTRAP;
+        case 0xe00: /* FP */
+            return SIGFPE;
+    }
+    return SIGBUS;
+}
+
+void
+gdb_arch_resume(struct cpu_user_regs *regs,
+                unsigned long addr, unsigned long type,
+                struct gdb_context *ctx)
+{
+    if (addr != ~((ulong)0)) {
+        regs->pc = addr;
+    }
+
+    if (type == GDB_CONTINUE) {
+        regs->msr &= ~MSR_SE;
+    } else {
+        regs->msr |= MSR_SE;
+    }
+}
+
+void 
+gdb_arch_read_reg(unsigned long regnum, struct cpu_user_regs *regs,
+                  struct gdb_context *ctx)
+{
+    unimplemented();
+    gdb_send_reply("", ctx);
+}
+
+void
+gdb_arch_read_reg_array(struct cpu_user_regs *state, struct gdb_context *ctx)
+{
+    ulong i = 0;
+
+    for (i = 0; i < 32; ++i) {
+        gdb_write_to_packet_hex(state->gprs[i], sizeof(state->gprs[i]), ctx);
+    }
+    /* Avoid floating point for now */
+    for (i = 0; i < 32; ++i) {
+        gdb_write_to_packet_hex(0, sizeof(u64), ctx);
+    }
+    gdb_write_to_packet_hex(state->pc, sizeof (state->pc), ctx);
+    gdb_write_to_packet_hex(state->msr, sizeof (state->msr), ctx);
+    gdb_write_to_packet_hex(state->cr, sizeof (state->cr), ctx);
+    gdb_write_to_packet_hex(state->lr, sizeof (state->lr), ctx);
+    gdb_write_to_packet_hex(state->ctr, sizeof (state->ctr), ctx);
+    gdb_write_to_packet_hex(state->xer, sizeof (u32), ctx);
+    gdb_write_to_packet_hex(0, sizeof(u32), ctx); /* fpscr */
+    gdb_send_packet(ctx);
+}
+
+void
+gdb_arch_write_reg_array(struct cpu_user_regs *regs, const char *buf,
+                         struct gdb_context *ctx)
+{
+    ulong i;
+
+    for (i = 0; i < 32; ++i) {
+        regs->gprs[i] = str2ulong(buf, sizeof (ulong));
+        buf += sizeof (regs->gprs[0]) * 2;
+    }
+    /* Avoid floating point for now */
+    for (i = 0; i < 32; ++i) {
+        buf += sizeof (u64) * 2;
+    }
+
+    regs->pc = str2ulong(buf, sizeof (regs->pc));
+    buf += sizeof (regs->pc) * 2;
+    regs->msr = str2ulong(buf, sizeof (regs->msr));
+    buf += sizeof (regs->msr) * 2;
+    regs->cr = str2ulong(buf, sizeof (regs->cr));
+    buf += sizeof (regs->cr) * 2;
+    regs->lr = str2ulong(buf, sizeof (regs->lr));
+    buf += sizeof (regs->lr) * 2;
+    regs->ctr = str2ulong(buf, sizeof (regs->ctr));
+    buf += sizeof (regs->ctr) * 2;
+    regs->xer = str2ulong(buf, sizeof (u32));
+    buf += sizeof (u32) * 2;
+}
+
+unsigned int
+gdb_arch_copy_from_user(void *dest, const void *src, unsigned len)
+{
+    memcpy(dest, src, len);
+    return 0;
+}
+
+unsigned int
+gdb_arch_copy_to_user(void *dest, const void *src, unsigned len)
+{
+    memcpy(dest, src, len);
+    synchronize_caches((ulong)dest, len);
+    return 0;
+}
+
+void
+gdb_arch_print_state(struct cpu_user_regs *state)
+{
+    int i = 0;
+    printk("PC: 0x%016lx MSR: 0x%016lx\n", state->pc, state->msr);
+    printk("LR: 0x%016lx CTR: 0x%016lx\n", state->lr, state->ctr);
+    /* XXX
+       printk("DAR: 0x%016lx DSISR: 0x%016lx\n", state->dar, state->dsisr);
+       */
+    printk("CR: 0x%08x XER: 0x%016lx\n", state->cr, state->xer);
+    for (; i < 32; i+=4) {
+        printk("%02d: 0x%016lx 0x%016lx 0x%016lx 0x%016lx\n",
+                i, state->gprs[i], state->gprs[i+1],
+                state->gprs[i+2], state->gprs[i+3]);
+    }
+}
+
+void
+gdb_arch_enter(struct cpu_user_regs *state)
+{
+    dec_entry = mfdec();
+    hdec_entry = mfhdec();
+}
+
+void
+gdb_arch_exit(struct cpu_user_regs *state)
+{
+    mtdec(dec_entry);
+    mthdec(hdec_entry);
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/hcalls.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/hcalls.c Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,172 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/sched.h>
+#include <xen/lib.h>
+#include <xen/init.h>
+#include <xen/multicall.h>
+#include <public/xen.h>
+#include <asm/current.h>
+#include <asm/papr.h>
+#include <asm/hcalls.h>
+#include <asm/debugger.h>
+#include <asm/msr.h>
+#include "exceptions.h"
+
+u32 *papr_hcalls;               /* PAPR Hypervisor Calls */
+u32 *hypercall_table;           /* Xen Hypervisor Calls */
+
+static void hcall_papr(ulong num, struct cpu_user_regs *regs)
+{
+    u32 address;
+
+    if (regs->msr & MSR_PR) {
+        regs->gprs[3] = H_Privilege;
+        return;
+    }
+
+    if ((num & 0x3) || (num > RPA_HCALL_END)) {
+        regs->gprs[3] = H_Parameter;
+        return;
+    }
+
+    address = papr_hcalls[num/4];
+    papr_hcall_jump(regs, address);
+}
+
+static void hcall_xen(ulong num, struct cpu_user_regs *regs)
+{
+    u32 address;
+
+    if (regs->msr & MSR_PR) {
+        regs->gprs[3] = -EPERM;
+        return;
+    }
+
+    if ((num >= NR_hypercalls)) {
+        regs->gprs[3] = -ENOSYS;
+        return;
+    }
+    address = hypercall_table[num];
+    if (address == 0) {
+        printk("unsupported Xen hypercall: 0x%lx\n", num);
+        regs->gprs[3] = -ENOSYS;
+        return;
+    }
+
+    regs->gprs[3] = xen_hvcall_jump(regs, address);
+}
+
+void do_multicall_call(multicall_entry_t *call)
+{
+    struct cpu_user_regs regs;
+
+    regs.gprs[3] = call->args[0];
+    regs.gprs[4] = call->args[1];
+    regs.gprs[5] = call->args[2];
+    regs.gprs[6] = call->args[3];
+    regs.gprs[7] = call->args[4];
+    regs.gprs[8] = call->args[5];
+
+    hcall_xen(call->op, &regs);
+
+    call->result = regs.gprs[3];
+}
+
+void do_hcall(struct cpu_user_regs *regs)
+{
+    ulong num = regs->gprs[3];
+
+    local_irq_enable();
+
+    if ((num & XEN_MARK(0)) == XEN_MARK(0)) {
+        /* it's a Xen call */
+        num &= ~XEN_MARK(0);
+        hcall_xen(num, regs);
+    } else {
+        /* it's a PAPR call */
+        hcall_papr(num, regs);
+    }
+}
+
+static void do_ni_papr_hypercall(struct cpu_user_regs *regs)
+{
+    struct vcpu *v = get_current();
+
+    printk("unsupported hcall 0x%lx was called by dom0x%x\n",
+            regs->gprs[3], v->domain->domain_id);
+    debugger_trap_immediate();
+
+    regs->gprs[3] = H_Parameter;
+}
+
+/* store low 32 bits of 64-bit address in hcall table (this is safe because we
+ * know we will not link above 4GB). We don't need to preserve the TOC
+ * because that only changes when calling dynamically linked objects. */
+static void register_papr_hcall(ulong num, hcall_handler_t handler)
+{
+    int index = num/4;
+
+    papr_hcalls[index] = (u32)(*(u64 *)handler);
+}
+
+static void init_papr_hcalls(void)
+{
+    inithcall_t *hcall;
+    int i;
+
+    /* initialize PAPR hcall table */
+    papr_hcalls = xmalloc_array(u32, RPA_HCALL_END/4);
+    ASSERT(papr_hcalls != NULL);
+    for (i = 0; i <= RPA_HCALL_END; i += 4)
+        register_papr_hcall(i, do_ni_papr_hypercall);
+
+    /* register the PAPR hcalls */
+    for (hcall = &__inithcall_start; hcall < &__inithcall_end; hcall++) {
+        register_papr_hcall(hcall->number, hcall->handler);
+    }
+}
+
+static void init_hypercall_table(void)
+{
+    int i;
+
+    hypercall_table = xmalloc_array(u32, NR_hypercalls);
+    ASSERT(hypercall_table != NULL);
+
+    for (i = 0; i < NR_hypercalls; i++) {
+        if (__hypercall_table[i] == NULL ) {
+            hypercall_table[i] = 0;
+        } else {
+            hypercall_table[i] = (u32)(*__hypercall_table[i]);
+        }
+    }
+}
+
+static int init_hcalls(void)
+{
+    init_papr_hcalls();
+    init_hypercall_table();
+
+    return 0;
+}
+__initcall(init_hcalls);
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/htab.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/htab.c   Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,69 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
+ */
+
+#include <xen/config.h>
+#include <xen/sched.h>
+
+static ulong htab_calc_sdr1(ulong htab_addr, ulong log_htab_size)
+{
+    ulong sdr1_htabsize;
+
+    ASSERT((htab_addr & ((1UL << log_htab_size) - 1)) == 0);
+    ASSERT(log_htab_size <= SDR1_HTABSIZE_MAX);
+    ASSERT(log_htab_size >= HTAB_MIN_LOG_SIZE);
+
+    sdr1_htabsize = log_htab_size - LOG_PTEG_SIZE - SDR1_HTABSIZE_BASEBITS;
+
+    return (htab_addr | (sdr1_htabsize & SDR1_HTABSIZE_MASK));
+}
+
+void htab_alloc(struct domain *d, int log_htab_bytes)
+{
+    ulong htab_raddr;
+    ulong htab_bytes = 1UL << log_htab_bytes;
+
+    /* XXX use alloc_domheap_pages instead? */
+    htab_raddr = (ulong)alloc_xenheap_pages(log_htab_bytes - PAGE_SHIFT);
+    ASSERT(htab_raddr != 0);
+    /* XXX check alignment guarantees */
+    ASSERT((htab_raddr & (htab_bytes-1)) == 0);
+
+    /* XXX slow. move memset out to service partition? */
+    memset((void *)htab_raddr, 0, htab_bytes);
+
+    d->arch.htab.log_num_ptes = log_htab_bytes - LOG_PTE_SIZE;
+    d->arch.htab.sdr1 = htab_calc_sdr1(htab_raddr, log_htab_bytes);
+    d->arch.htab.map = (union pte *)htab_raddr;
+    d->arch.htab.shadow = xmalloc_array(ulong,
+                                        1UL << d->arch.htab.log_num_ptes);
+    ASSERT(d->arch.htab.shadow != NULL);
+
+    printf("%s: dom%x sdr1: %lx\n", __func__, d->domain_id, d->arch.htab.sdr1);
+}
+
+void htab_free(struct domain *d)
+{
+    ulong htab_raddr = GET_HTAB(d);
+
+    free_xenheap_pages((void *)htab_raddr,
+                       (1UL << d->arch.htab.log_num_ptes) << LOG_PTE_SIZE);
+    xfree(d->arch.htab.shadow);
+}
+
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/iommu.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/iommu.c  Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,79 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#undef DEBUG
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/sched.h>
+#include <xen/init.h>
+#include <xen/mm.h>
+#include <asm/current.h>
+#include <asm/papr.h>
+#include <asm/hcalls.h>
+#include <public/xen.h>
+#include "tce.h"
+#include "iommu.h"
+
+struct iommu_funcs {
+    int (*iommu_put)(ulong, union tce);
+};
+
+/* individual host bridges */
+static struct iommu_funcs iommu_phbs[16];
+static u32 iommu_phbs_num = ARRAY_SIZE(iommu_phbs);
+
+int iommu_put(u32 buid, ulong ioba, union tce tce)
+{
+    struct vcpu *v = get_current();
+    struct domain *d = v->domain;
+
+    if (buid < iommu_phbs_num && iommu_phbs[buid].iommu_put != NULL) {
+        ulong pfn;
+        ulong mfn;
+        int mtype;
+
+        pfn = tce.tce_bits.tce_rpn;
+        mfn = pfn2mfn(d, pfn, &mtype);
+        if (mtype != 0) {
+            panic("we don't do non-RMO memory yet\n");
+        }
+
+#ifdef DEBUG
+        printk("%s: ioba=0x%lx pfn=0x%lx mfn=0x%lx\n", __func__,
+               ioba, pfn, mfn);
+#endif
+        tce.tce_bits.tce_rpn = mfn;
+
+        return iommu_phbs[buid].iommu_put(ioba, tce);
+    }
+    return -1;
+}
+
+int iommu_register(u32 buid, int (*put)(ulong ioba, union tce ltce))
+{
+
+    if (buid < iommu_phbs_num && iommu_phbs[buid].iommu_put == NULL) {
+        iommu_phbs[0].iommu_put = put;
+        return 0;
+    }
+    panic("bad IOMMU registration\n");
+    return -1;
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/iommu.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/iommu.h  Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,28 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#ifndef _IOMMU_H
+#define _IOMMU_H
+
+extern int iommu_put(u32 buid, ulong ioba, union tce tce);
+extern int iommu_register(u32 buid, int (*put)(ulong, union tce));
+
+#endif /* _IOMMU_H */
+
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/irq.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/irq.c    Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,22 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include "exceptions.h"
+#include "../x86/irq.c"
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/mambo.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/mambo.S  Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,64 @@
+/*
+ * 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
+ *
+ */
+
+#include <asm/config.h>
+#include <asm/processor.h>
+
+_GLOBAL(mambo_callthru)
+       .long 0x000eaeb0
+       blr
+
+_GLOBAL(mambo_write)
+       mr      r5, r4
+       mr      r4, r3
+       li      r3, 0           # Write console code
+       
+       li      r6, 0
+       /* need to fix return value */
+       mflr    r7
+       bl      _ENTRY(mambo_callthru)
+       mtlr    r7
+       mr      r3, r5
+       blr
+
+_GLOBAL(mambo_memset)
+       mr      r6, r5
+       mr      r5, r4
+       mr      r4, r3
+       li      r3, 0x47        # memset
+       /* need to fix return value */
+       mflr    r7
+       bl      _ENTRY(mambo_callthru)
+       mtlr    r7
+       mr      r3, r4
+       blr
+
+_GLOBAL(mambo_memcpy)
+       mr      r6, r5
+       mr      r5, r4
+       mr      r4, r3
+       li      r3, 0x45 # memcpy
+       /* need to fix return value */
+       mflr    r7
+       bl      _ENTRY(mambo_callthru)
+       mtlr    r7
+       mr      r3, r4
+       blr
+
+       
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/mm.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/mm.c     Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,141 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
+ */
+
+#include <xen/config.h>
+#include <xen/mm.h>
+#include <xen/kernel.h>
+#include <xen/sched.h>
+#include <asm/misc.h>
+#include <asm/init.h>
+#include <asm/page.h>
+
+/* Frame table and its size in pages. */
+struct page_info *frame_table;
+unsigned long frame_table_size;
+unsigned long max_page;
+unsigned long total_pages;
+
+int create_grant_host_mapping(
+    unsigned long addr, unsigned long frame, unsigned int flags)
+{
+    panic("%s called\n", __func__);
+    return 1;
+}
+
+int destroy_grant_host_mapping(
+    unsigned long addr, unsigned long frame, unsigned int flags)
+{
+    panic("%s called\n", __func__);
+    return 1;
+}
+
+int steal_page(struct domain *d, struct page_info *page, unsigned int memflags)
+{
+    panic("%s called\n", __func__);
+    return 1;
+}
+
+
+int get_page_type(struct page_info *page, u32 type)
+{
+    panic("%s called\n", __func__);
+    return 1;
+}
+
+void put_page_type(struct page_info *page)
+{
+    panic("%s called\n", __func__);
+}
+
+void __init init_frametable(void)
+{
+    unsigned long p;
+
+    frame_table_size = PFN_UP(max_page * sizeof(struct page_info));
+
+    p = alloc_boot_pages(min(frame_table_size, 4UL << 20), 1);
+    if (p == 0)
+        panic("Not enough memory for frame table\n");
+
+    frame_table = (struct page_info *)(p << PAGE_SHIFT);
+    frame_table_size = (frame_table_size + PAGE_SIZE - 1) & PAGE_MASK;
+
+    memset(frame_table, 0, frame_table_size);
+}
+
+long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
+{
+    printk("%s: no PPC specific memory ops\n", __func__);
+    return -ENOSYS;
+}
+
+void clear_page(void *page)
+{
+    if (on_mambo()) {
+        extern void *mambo_memset(void *,int ,__kernel_size_t);
+        mambo_memset(page, 0, PAGE_SIZE);
+    } else {
+        memset(page, 0, PAGE_SIZE);
+    }
+}
+
+extern void copy_page(void *dp, void *sp)
+{
+    if (on_mambo()) {
+        extern void *mambo_memcpy(void *,const void *,__kernel_size_t);
+        mambo_memcpy(dp, sp, PAGE_SIZE);
+    } else {
+        memcpy(dp, sp, PAGE_SIZE);
+    }
+}
+
+ulong pfn2mfn(struct domain *d, long pfn, int *type)
+{
+    ulong rma_base_mfn = d->arch.rma_base >> PAGE_SHIFT;
+    ulong rma_size_mfn = d->arch.rma_size >> PAGE_SHIFT;
+    ulong mfn;
+    int t;
+
+    if (pfn < rma_size_mfn) {
+        mfn = pfn + rma_base_mfn;
+        t = PFN_TYPE_RMA;
+    } else if (pfn >= d->arch.logical_base_pfn &&
+               pfn < d->arch.logical_end_pfn) {
+        if (test_bit(_DOMF_privileged, &d->domain_flags)) {
+            /* This hack allows dom0 to map all memory, necessary to
+             * initialize domU state. */
+            mfn = pfn;
+        } else {
+            panic("we do not handle the logical area yet\n");
+            mfn = 0;
+        }
+
+        t = PFN_TYPE_LOGICAL;
+    } else {
+        /* don't know */
+        mfn = pfn;
+        t = PFN_TYPE_IO;
+    }
+
+    if (type != NULL)
+        *type = t;
+
+    return mfn;
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/mpic.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/mpic.c   Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,1109 @@
+/*
+ *  arch/powerpc/kernel/mpic.c
+ *
+ *  Driver for interrupt controllers following the OpenPIC standard, the
+ *  common implementation beeing IBM's MPIC. This driver also can deal
+ *  with various broken implementations of this HW.
+ *
+ *  Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp.
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+/* XXX Xen hacks ... */
+/* make this generic */
+
+#define le32_to_cpu(x) \
+({ \
+       __u32 __x = (x); \
+       ((__u32)( \
+               (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | \
+               (((__u32)(__x) & (__u32)0x0000ff00UL) <<  8) | \
+               (((__u32)(__x) & (__u32)0x00ff0000UL) >>  8) | \
+               (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); \
+})
+
+
+#define alloc_bootmem(x) xmalloc_bytes(x)
+#define request_irq(irq, handler, f, devname, dev_id) \
+    panic("IPI requested: %d: %p: %s: %p\n", irq, handler, devname, dev_id)
+
+typedef int irqreturn_t;
+
+#define IRQ_NONE       (0)
+#define IRQ_HANDLED    (1)
+#define IRQ_RETVAL(x)  ((x) != 0)
+
+#define IRQ_SENSE_MASK         0x1
+#define IRQ_SENSE_LEVEL                0x1     /* interrupt on active level */
+#define IRQ_SENSE_EDGE         0x0     /* interrupt triggered by edge */
+
+#define IRQ_POLARITY_MASK      0x2
+#define IRQ_POLARITY_POSITIVE  0x2     /* high level or low->high edge */
+#define IRQ_POLARITY_NEGATIVE  0x0     /* low level or high->low edge */
+
+#define CONFIG_IRQ_ALL_CPUS 0
+#define distribute_irqs        CONFIG_IRQ_ALL_CPUS
+#define CONFIG_MPIC_BROKEN_U3
+
+#define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
+#define PCI_FUNC(devfn) ((devfn) & 0x07)
+#define PCI_HEADER_TYPE                0x0e    /* 8 bits */
+#define PCI_VENDOR_ID          0x00    /* 16 bits */
+#define PCI_VENDOR_ID_AMD 0x1022
+#define PCI_CAPABILITY_LIST    0x34    /* Offset of first capability list 
entry */
+#define PCI_CAP_LIST_NEXT      1       /* Next capability in the list */
+#define PCI_CAP_LIST_ID                0       /* Capability ID */
+#define  PCI_CAP_ID_HT_IRQCONF 0x08    /* HyperTransport IRQ Configuration */
+#define PCI_STATUS             0x06    /* 16 bits */
+#define  PCI_STATUS_CAP_LIST   0x10    /* Support Capability List */
+#define MSG_ALL 0x8001
+#define MSG_ALL_BUT_SELF 0x8000
+
+/* keeps file even closer to the original */
+#define pt_regs cpu_user_regs
+/* XXX ... Xen hacks */
+
+#undef DEBUG
+#undef DEBUG_IPI
+#undef DEBUG_IRQ
+#undef DEBUG_LOW
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/kernel.h>
+#include <xen/init.h>
+#include <xen/irq.h>
+#include <xen/smp.h>
+#ifndef __XEN__ 
+#include <linux/interrupt.h>
+#include <linux/bootmem.h>
+#endif
+#include <xen/spinlock.h>
+#ifndef __XEN__
+#include <asm/pci.h>
+
+#include <asm/ptrace.h>
+#include <asm/signal.h>
+#endif
+#include <asm/io.h>
+#ifndef __XEN__
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+#endif
+#include <asm/mpic.h>
+#include <asm/smp.h>
+
+static inline void smp_message_recv(int msg, struct pt_regs *regs)
+{
+    return;
+}
+
+#ifdef DEBUG
+#define DBG(fmt...) printk(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+static struct mpic *mpics;
+static struct mpic *mpic_primary;
+static DEFINE_SPINLOCK(mpic_lock);
+
+#ifdef CONFIG_PPC32    /* XXX for now */
+#ifdef CONFIG_IRQ_ALL_CPUS
+#define distribute_irqs        (1)
+#else
+#define distribute_irqs        (0)
+#endif
+#endif
+
+/*
+ * Register accessor functions
+ */
+
+
+static inline u32 _mpic_read(unsigned int be, volatile u32 __iomem *base,
+                           unsigned int reg)
+{
+       if (be)
+               return in_be32(base + (reg >> 2));
+       else
+               return in_le32(base + (reg >> 2));
+}
+
+static inline void _mpic_write(unsigned int be, volatile u32 __iomem *base,
+                             unsigned int reg, u32 value)
+{
+       if (be)
+               out_be32(base + (reg >> 2), value);
+       else
+               out_le32(base + (reg >> 2), value);
+}
+
+static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)
+{
+       unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0;
+       unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
+
+       if (mpic->flags & MPIC_BROKEN_IPI)
+               be = !be;
+       return _mpic_read(be, mpic->gregs, offset);
+}
+
+static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 
value)
+{
+       unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
+
+       _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value);
+}
+
+static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)
+{
+       unsigned int cpu = 0;
+
+       if (mpic->flags & MPIC_PRIMARY)
+               cpu = hard_smp_processor_id();
+
+       return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], 
reg);
+}
+
+static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 
value)
+{
+       unsigned int cpu = 0;
+
+       if (mpic->flags & MPIC_PRIMARY)
+               cpu = hard_smp_processor_id();
+
+       _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg, 
value);
+}
+
+static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, 
unsigned int reg)
+{
+       unsigned int    isu = src_no >> mpic->isu_shift;
+       unsigned int    idx = src_no & mpic->isu_mask;
+
+       return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
+                         reg + (idx * MPIC_IRQ_STRIDE));
+}
+
+static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
+                                  unsigned int reg, u32 value)
+{
+       unsigned int    isu = src_no >> mpic->isu_shift;
+       unsigned int    idx = src_no & mpic->isu_mask;
+
+       _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
+                   reg + (idx * MPIC_IRQ_STRIDE), value);
+}
+
+#define mpic_read(b,r)         _mpic_read(mpic->flags & 
MPIC_BIG_ENDIAN,(b),(r))
+#define mpic_write(b,r,v)      _mpic_write(mpic->flags & 
MPIC_BIG_ENDIAN,(b),(r),(v))
+#define mpic_ipi_read(i)       _mpic_ipi_read(mpic,(i))
+#define mpic_ipi_write(i,v)    _mpic_ipi_write(mpic,(i),(v))
+#define mpic_cpu_read(i)       _mpic_cpu_read(mpic,(i))
+#define mpic_cpu_write(i,v)    _mpic_cpu_write(mpic,(i),(v))
+#define mpic_irq_read(s,r)     _mpic_irq_read(mpic,(s),(r))
+#define mpic_irq_write(s,r,v)  _mpic_irq_write(mpic,(s),(r),(v))
+
+
+/*
+ * Low level utility functions
+ */
+
+
+
+/* Check if we have one of those nice broken MPICs with a flipped endian on
+ * reads from IPI registers
+ */
+static void __init mpic_test_broken_ipi(struct mpic *mpic)
+{
+       u32 r;
+
+       mpic_write(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0, MPIC_VECPRI_MASK);
+       r = mpic_read(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0);
+
+       if (r == le32_to_cpu(MPIC_VECPRI_MASK)) {
+               printk(KERN_INFO "mpic: Detected reversed IPI registers\n");
+               mpic->flags |= MPIC_BROKEN_IPI;
+       }
+}
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+
+/* Test if an interrupt is sourced from HyperTransport (used on broken U3s)
+ * to force the edge setting on the MPIC and do the ack workaround.
+ */
+static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source)
+{
+       if (source >= 128 || !mpic->fixups)
+               return 0;
+       return mpic->fixups[source].base != NULL;
+}
+
+
+static inline void mpic_ht_end_irq(struct mpic *mpic, unsigned int source)
+{
+       struct mpic_irq_fixup *fixup = &mpic->fixups[source];
+
+       if (fixup->applebase) {
+               unsigned int soff = (fixup->index >> 3) & ~3;
+               unsigned int mask = 1U << (fixup->index & 0x1f);
+               writel(mask, fixup->applebase + soff);
+       } else {
+               spin_lock(&mpic->fixup_lock);
+               writeb(0x11 + 2 * fixup->index, fixup->base + 2);
+               writel(fixup->data, fixup->base + 4);
+               spin_unlock(&mpic->fixup_lock);
+       }
+}
+
+static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source,
+                                     unsigned int irqflags)
+{
+       struct mpic_irq_fixup *fixup = &mpic->fixups[source];
+       unsigned long flags;
+       u32 tmp;
+
+       if (fixup->base == NULL)
+               return;
+
+       DBG("startup_ht_interrupt(%u, %u) index: %d\n",
+           source, irqflags, fixup->index);
+       spin_lock_irqsave(&mpic->fixup_lock, flags);
+       /* Enable and configure */
+       writeb(0x10 + 2 * fixup->index, fixup->base + 2);
+       tmp = readl(fixup->base + 4);
+       tmp &= ~(0x23U);
+       if (irqflags & IRQ_LEVEL)
+               tmp |= 0x22;
+       writel(tmp, fixup->base + 4);
+       spin_unlock_irqrestore(&mpic->fixup_lock, flags);
+}
+
+static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
+                                      unsigned int irqflags)
+{
+       struct mpic_irq_fixup *fixup = &mpic->fixups[source];
+       unsigned long flags;
+       u32 tmp;
+
+       if (fixup->base == NULL)
+               return;
+
+       DBG("shutdown_ht_interrupt(%u, %u)\n", source, irqflags);
+
+       /* Disable */
+       spin_lock_irqsave(&mpic->fixup_lock, flags);
+       writeb(0x10 + 2 * fixup->index, fixup->base + 2);
+       tmp = readl(fixup->base + 4);
+       tmp |= 1;
+       writel(tmp, fixup->base + 4);
+       spin_unlock_irqrestore(&mpic->fixup_lock, flags);
+}
+
+static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
+                                   unsigned int devfn, u32 vdid)
+{
+       int i, irq, n;
+       u8 __iomem *base;
+       u32 tmp;
+       u8 pos;
+
+       for (pos = readb(devbase + PCI_CAPABILITY_LIST); pos != 0;
+            pos = readb(devbase + pos + PCI_CAP_LIST_NEXT)) {
+               u8 id = readb(devbase + pos + PCI_CAP_LIST_ID);
+               if (id == PCI_CAP_ID_HT_IRQCONF) {
+                       id = readb(devbase + pos + 3);
+                       if (id == 0x80)
+                               break;
+               }
+       }
+       if (pos == 0)
+               return;
+
+       base = devbase + pos;
+       writeb(0x01, base + 2);
+       n = (readl(base + 4) >> 16) & 0xff;
+
+       printk(KERN_INFO "mpic:   - HT:%02x.%x [0x%02x] vendor %04x device %04x"
+              " has %d irqs\n",
+              devfn >> 3, devfn & 0x7, pos, vdid & 0xffff, vdid >> 16, n + 1);
+
+       for (i = 0; i <= n; i++) {
+               writeb(0x10 + 2 * i, base + 2);
+               tmp = readl(base + 4);
+               irq = (tmp >> 16) & 0xff;
+               DBG("HT PIC index 0x%x, irq 0x%x, tmp: %08x\n", i, irq, tmp);
+               /* mask it , will be unmasked later */
+               tmp |= 0x1;
+               writel(tmp, base + 4);
+               mpic->fixups[irq].index = i;
+               mpic->fixups[irq].base = base;
+               /* Apple HT PIC has a non-standard way of doing EOIs */
+               if ((vdid & 0xffff) == 0x106b)
+                       mpic->fixups[irq].applebase = devbase + 0x60;
+               else
+                       mpic->fixups[irq].applebase = NULL;
+               writeb(0x11 + 2 * i, base + 2);
+               mpic->fixups[irq].data = readl(base + 4) | 0x80000000;
+       }
+}
+ 
+
+static void __init mpic_scan_ht_pics(struct mpic *mpic)
+{
+       unsigned int devfn;
+       u8 __iomem *cfgspace;
+
+       printk(KERN_INFO "mpic: Setting up HT PICs workarounds for U3/U4\n");
+
+       /* Allocate fixups array */
+       mpic->fixups = alloc_bootmem(128 * sizeof(struct mpic_irq_fixup));
+       BUG_ON(mpic->fixups == NULL);
+       memset(mpic->fixups, 0, 128 * sizeof(struct mpic_irq_fixup));
+
+       /* Init spinlock */
+       spin_lock_init(&mpic->fixup_lock);
+
+       /* Map U3 config space. We assume all IO-APICs are on the primary bus
+        * so we only need to map 64kB.
+        */
+       cfgspace = ioremap(0xf2000000, 0x10000);
+       BUG_ON(cfgspace == NULL);
+
+       /* Now we scan all slots. We do a very quick scan, we read the header
+        * type, vendor ID and device ID only, that's plenty enough
+        */
+       for (devfn = 0; devfn < 0x100; devfn++) {
+               u8 __iomem *devbase = cfgspace + (devfn << 8);
+               u8 hdr_type = readb(devbase + PCI_HEADER_TYPE);
+               u32 l = readl(devbase + PCI_VENDOR_ID);
+               u16 s;
+
+               DBG("devfn %x, l: %x\n", devfn, l);
+
+               /* If no device, skip */
+               if (l == 0xffffffff || l == 0x00000000 ||
+                   l == 0x0000ffff || l == 0xffff0000)
+                       goto next;
+               /* Check if is supports capability lists */
+               s = readw(devbase + PCI_STATUS);
+               if (!(s & PCI_STATUS_CAP_LIST))
+                       goto next;
+
+               mpic_scan_ht_pic(mpic, devbase, devfn, l);
+
+       next:
+               /* next device, if function 0 */
+               if (PCI_FUNC(devfn) == 0 && (hdr_type & 0x80) == 0)
+                       devfn += 7;
+       }
+}
+
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+
+/* Find an mpic associated with a given linux interrupt */
+static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi)
+{
+       struct mpic *mpic = mpics;
+
+       while(mpic) {
+               /* search IPIs first since they may override the main 
interrupts */
+               if (irq >= mpic->ipi_offset && irq < (mpic->ipi_offset + 4)) {
+                       if (is_ipi)
+                               *is_ipi = 1;
+                       return mpic;
+               }
+               if (irq >= mpic->irq_offset &&
+                   irq < (mpic->irq_offset + mpic->irq_count)) {
+                       if (is_ipi)
+                               *is_ipi = 0;
+                       return mpic;
+               }
+               mpic = mpic -> next;
+       }
+       return NULL;
+}
+
+/* Convert a cpu mask from logical to physical cpu numbers. */
+static inline u32 mpic_physmask(u32 cpumask)
+{
+       int i;
+       u32 mask = 0;
+
+       for (i = 0; i < NR_CPUS; ++i, cpumask >>= 1)
+               mask |= (cpumask & 1) << get_hard_smp_processor_id(i);
+       return mask;
+}
+
+#ifdef CONFIG_SMP
+/* Get the mpic structure from the IPI number */
+static inline struct mpic * mpic_from_ipi(unsigned int ipi)
+{
+       return container_of(irq_desc[ipi].handler, struct mpic, hc_ipi);
+}
+#endif
+
+/* Get the mpic structure from the irq number */
+static inline struct mpic * mpic_from_irq(unsigned int irq)
+{
+       return container_of(irq_desc[irq].handler, struct mpic, hc_irq);
+}
+
+/* Send an EOI */
+static inline void mpic_eoi(struct mpic *mpic)
+{
+       mpic_cpu_write(MPIC_CPU_EOI, 0);
+       (void)mpic_cpu_read(MPIC_CPU_WHOAMI);
+}
+
+#ifdef CONFIG_SMP
+static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct mpic *mpic = dev_id;
+
+       smp_message_recv(irq - mpic->ipi_offset, regs);
+       return IRQ_HANDLED;
+}
+#endif /* CONFIG_SMP */
+
+/*
+ * Linux descriptor level callbacks
+ */
+
+
+static void mpic_enable_irq(unsigned int irq)
+{
+       unsigned int loops = 100000;
+       struct mpic *mpic = mpic_from_irq(irq);
+       unsigned int src = irq - mpic->irq_offset;
+
+       DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
+
+       mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
+                      mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) &
+                      ~MPIC_VECPRI_MASK);
+
+       /* make sure mask gets to controller before we return to user */
+       do {
+               if (!loops--) {
+                       printk(KERN_ERR "mpic_enable_irq timeout\n");
+                       break;
+               }
+       } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);    
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+       if (mpic->flags & MPIC_BROKEN_U3) {
+               unsigned int src = irq - mpic->irq_offset;
+               if (mpic_is_ht_interrupt(mpic, src) &&
+                   (irq_desc[irq].status & IRQ_LEVEL))
+                       mpic_ht_end_irq(mpic, src);
+       }
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+}
+
+static unsigned int mpic_startup_irq(unsigned int irq)
+{
+#ifdef CONFIG_MPIC_BROKEN_U3
+       struct mpic *mpic = mpic_from_irq(irq);
+       unsigned int src = irq - mpic->irq_offset;
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+       mpic_enable_irq(irq);
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+       if (mpic_is_ht_interrupt(mpic, src))
+               mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status);
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+       return 0;
+}
+
+static void mpic_disable_irq(unsigned int irq)
+{
+       unsigned int loops = 100000;
+       struct mpic *mpic = mpic_from_irq(irq);
+       unsigned int src = irq - mpic->irq_offset;
+
+       DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
+
+       mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
+                      mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) |
+                      MPIC_VECPRI_MASK);
+
+       /* make sure mask gets to controller before we return to user */
+       do {
+               if (!loops--) {
+                       printk(KERN_ERR "mpic_enable_irq timeout\n");
+                       break;
+               }
+       } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
+}
+
+static void mpic_shutdown_irq(unsigned int irq)
+{
+#ifdef CONFIG_MPIC_BROKEN_U3
+       struct mpic *mpic = mpic_from_irq(irq);
+       unsigned int src = irq - mpic->irq_offset;
+
+       if (mpic_is_ht_interrupt(mpic, src))
+               mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status);
+
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+       mpic_disable_irq(irq);
+}
+
+static void mpic_end_irq(unsigned int irq)
+{
+       struct mpic *mpic = mpic_from_irq(irq);
+
+#ifdef DEBUG_IRQ
+       DBG("%s: end_irq: %d\n", mpic->name, irq);
+#endif
+       /* We always EOI on end_irq() even for edge interrupts since that
+        * should only lower the priority, the MPIC should have properly
+        * latched another edge interrupt coming in anyway
+        */
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+       if (mpic->flags & MPIC_BROKEN_U3) {
+               unsigned int src = irq - mpic->irq_offset;
+               if (mpic_is_ht_interrupt(mpic, src) &&
+                   (irq_desc[irq].status & IRQ_LEVEL))
+                       mpic_ht_end_irq(mpic, src);
+       }
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+       mpic_eoi(mpic);
+}
+
+#ifdef CONFIG_SMP
+
+static void mpic_enable_ipi(unsigned int irq)
+{
+       struct mpic *mpic = mpic_from_ipi(irq);
+       unsigned int src = irq - mpic->ipi_offset;
+
+       DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src);
+       mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
+}
+
+static void mpic_disable_ipi(unsigned int irq)
+{
+       /* NEVER disable an IPI... that's just plain wrong! */
+}
+
+static void mpic_end_ipi(unsigned int irq)
+{
+       struct mpic *mpic = mpic_from_ipi(irq);
+
+       /*
+        * IPIs are marked IRQ_PER_CPU. This has the side effect of
+        * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from
+        * applying to them. We EOI them late to avoid re-entering.
+        * We mark IPI's with SA_INTERRUPT as they must run with
+        * irqs disabled.
+        */
+       mpic_eoi(mpic);
+}
+
+#endif /* CONFIG_SMP */
+
+static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
+{
+       struct mpic *mpic = mpic_from_irq(irq);
+
+       cpumask_t tmp;
+
+       cpus_and(tmp, cpumask, cpu_online_map);
+
+       mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_DESTINATION,
+                      mpic_physmask(cpus_addr(tmp)[0]));       
+}
+
+
+/*
+ * Exported functions
+ */
+
+
+struct mpic * __init mpic_alloc(unsigned long phys_addr,
+                               unsigned int flags,
+                               unsigned int isu_size,
+                               unsigned int irq_offset,
+                               unsigned int irq_count,
+                               unsigned int ipi_offset,
+                               unsigned char *senses,
+                               unsigned int senses_count,
+                               const char *name)
+{
+       struct mpic     *mpic;
+       u32             reg;
+       const char      *vers;
+       int             i;
+
+       mpic = alloc_bootmem(sizeof(struct mpic));
+       if (mpic == NULL)
+               return NULL;
+       
+
+       memset(mpic, 0, sizeof(struct mpic));
+       mpic->name = name;
+
+       mpic->hc_irq.typename = name;
+       mpic->hc_irq.startup = mpic_startup_irq;
+       mpic->hc_irq.shutdown = mpic_shutdown_irq;
+       mpic->hc_irq.enable = mpic_enable_irq;
+       mpic->hc_irq.disable = mpic_disable_irq;
+       mpic->hc_irq.end = mpic_end_irq;
+       if (flags & MPIC_PRIMARY)
+               mpic->hc_irq.set_affinity = mpic_set_affinity;
+#ifdef CONFIG_SMP
+       mpic->hc_ipi.typename = name;
+       mpic->hc_ipi.enable = mpic_enable_ipi;
+       mpic->hc_ipi.disable = mpic_disable_ipi;
+       mpic->hc_ipi.end = mpic_end_ipi;
+#endif /* CONFIG_SMP */
+
+       mpic->flags = flags;
+       mpic->isu_size = isu_size;
+       mpic->irq_offset = irq_offset;
+       mpic->irq_count = irq_count;
+       mpic->ipi_offset = ipi_offset;
+       mpic->num_sources = 0; /* so far */
+       mpic->senses = senses;
+       mpic->senses_count = senses_count;
+
+       /* Map the global registers */
+       mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000);
+       mpic->tmregs = mpic->gregs + ((MPIC_TIMER_BASE - MPIC_GREG_BASE) >> 2);
+       BUG_ON(mpic->gregs == NULL);
+
+       /* Reset */
+       if (flags & MPIC_WANTS_RESET) {
+               mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
+                          mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+                          | MPIC_GREG_GCONF_RESET);
+               while( mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+                      & MPIC_GREG_GCONF_RESET)
+                       mb();
+       }
+
+       /* Read feature register, calculate num CPUs and, for non-ISU
+        * MPICs, num sources as well. On ISU MPICs, sources are counted
+        * as ISUs are added
+        */
+       reg = mpic_read(mpic->gregs, MPIC_GREG_FEATURE_0);
+       mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK)
+                         >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
+       if (isu_size == 0)
+               mpic->num_sources = ((reg & MPIC_GREG_FEATURE_LAST_SRC_MASK)
+                                    >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
+
+       /* Map the per-CPU registers */
+       for (i = 0; i < mpic->num_cpus; i++) {
+               mpic->cpuregs[i] = ioremap(phys_addr + MPIC_CPU_BASE +
+                                          i * MPIC_CPU_STRIDE, 0x1000);
+               BUG_ON(mpic->cpuregs[i] == NULL);
+       }
+
+       /* Initialize main ISU if none provided */
+       if (mpic->isu_size == 0) {
+               mpic->isu_size = mpic->num_sources;
+               mpic->isus[0] = ioremap(phys_addr + MPIC_IRQ_BASE,
+                                       MPIC_IRQ_STRIDE * mpic->isu_size);
+               BUG_ON(mpic->isus[0] == NULL);
+       }
+       mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
+       mpic->isu_mask = (1 << mpic->isu_shift) - 1;
+
+       /* Display version */
+       switch (reg & MPIC_GREG_FEATURE_VERSION_MASK) {
+       case 1:
+               vers = "1.0";
+               break;
+       case 2:
+               vers = "1.2";
+               break;
+       case 3:
+               vers = "1.3";
+               break;
+       default:
+               vers = "<unknown>";
+               break;
+       }
+       printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %lx, max 
%d CPUs\n",
+              name, vers, phys_addr, mpic->num_cpus);
+       printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n", 
mpic->isu_size,
+              mpic->isu_shift, mpic->isu_mask);
+
+       mpic->next = mpics;
+       mpics = mpic;
+
+       if (flags & MPIC_PRIMARY)
+               mpic_primary = mpic;
+
+       return mpic;
+}
+
+void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
+                           unsigned long phys_addr)
+{
+       unsigned int isu_first = isu_num * mpic->isu_size;
+
+       BUG_ON(isu_num >= MPIC_MAX_ISU);
+
+       mpic->isus[isu_num] = ioremap(phys_addr, MPIC_IRQ_STRIDE * 
mpic->isu_size);
+       if ((isu_first + mpic->isu_size) > mpic->num_sources)
+               mpic->num_sources = isu_first + mpic->isu_size;
+}
+
+void __init mpic_setup_cascade(unsigned int irq, mpic_cascade_t handler,
+                              void *data)
+{
+       struct mpic *mpic = mpic_find(irq, NULL);
+       unsigned long flags;
+
+       /* Synchronization here is a bit dodgy, so don't try to replace cascade
+        * interrupts on the fly too often ... but normally it's set up at boot.
+        */
+       spin_lock_irqsave(&mpic_lock, flags);
+       if (mpic->cascade)             
+               mpic_disable_irq(mpic->cascade_vec + mpic->irq_offset);
+       mpic->cascade = NULL;
+       wmb();
+       mpic->cascade_vec = irq - mpic->irq_offset;
+       mpic->cascade_data = data;
+       wmb();
+       mpic->cascade = handler;
+       mpic_enable_irq(irq);
+       spin_unlock_irqrestore(&mpic_lock, flags);
+}
+
+void __init mpic_init(struct mpic *mpic)
+{
+       int i;
+
+       BUG_ON(mpic->num_sources == 0);
+
+       printk(KERN_INFO "mpic: Initializing for %d sources\n", 
mpic->num_sources);
+
+       /* Set current processor priority to max */
+       mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
+
+       /* Initialize timers: just disable them all */
+       for (i = 0; i < 4; i++) {
+               mpic_write(mpic->tmregs,
+                          i * MPIC_TIMER_STRIDE + MPIC_TIMER_DESTINATION, 0);
+               mpic_write(mpic->tmregs,
+                          i * MPIC_TIMER_STRIDE + MPIC_TIMER_VECTOR_PRI,
+                          MPIC_VECPRI_MASK |
+                          (MPIC_VEC_TIMER_0 + i));
+       }
+
+       /* Initialize IPIs to our reserved vectors and mark them disabled for 
now */
+       mpic_test_broken_ipi(mpic);
+       for (i = 0; i < 4; i++) {
+               mpic_ipi_write(i,
+                              MPIC_VECPRI_MASK |
+                              (10 << MPIC_VECPRI_PRIORITY_SHIFT) |
+                              (MPIC_VEC_IPI_0 + i));
+#ifdef CONFIG_SMP
+               if (!(mpic->flags & MPIC_PRIMARY))
+                       continue;
+               irq_desc[mpic->ipi_offset+i].status |= IRQ_PER_CPU;
+               irq_desc[mpic->ipi_offset+i].handler = &mpic->hc_ipi;
+#endif /* CONFIG_SMP */
+       }
+
+       /* Initialize interrupt sources */
+       if (mpic->irq_count == 0)
+               mpic->irq_count = mpic->num_sources;
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+       /* Do the HT PIC fixups on U3 broken mpic */
+       DBG("MPIC flags: %x\n", mpic->flags);
+       if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY))
+               mpic_scan_ht_pics(mpic);
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+       for (i = 0; i < mpic->num_sources; i++) {
+               /* start with vector = source number, and masked */
+               u32 vecpri = MPIC_VECPRI_MASK | i | (8 << 
MPIC_VECPRI_PRIORITY_SHIFT);
+               int level = 0;
+               
+               /* if it's an IPI, we skip it */
+               if ((mpic->irq_offset + i) >= (mpic->ipi_offset + i) &&
+                   (mpic->irq_offset + i) <  (mpic->ipi_offset + i + 4))
+                       continue;
+
+               /* do senses munging */
+               if (mpic->senses && i < mpic->senses_count) {
+                       if (mpic->senses[i] & IRQ_SENSE_LEVEL)
+                               vecpri |= MPIC_VECPRI_SENSE_LEVEL;
+                       if (mpic->senses[i] & IRQ_POLARITY_POSITIVE)
+                               vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
+               } else
+                       vecpri |= MPIC_VECPRI_SENSE_LEVEL;
+
+               /* remember if it was a level interrupts */
+               level = (vecpri & MPIC_VECPRI_SENSE_LEVEL);
+
+               /* deal with broken U3 */
+               if (mpic->flags & MPIC_BROKEN_U3) {
+#ifdef CONFIG_MPIC_BROKEN_U3
+                       if (mpic_is_ht_interrupt(mpic, i)) {
+                               vecpri &= ~(MPIC_VECPRI_SENSE_MASK |
+                                           MPIC_VECPRI_POLARITY_MASK);
+                               vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
+                       }
+#else
+                       printk(KERN_ERR "mpic: BROKEN_U3 set, but CONFIG 
doesn't match\n");
+#endif
+               }
+
+               DBG("setup source %d, vecpri: %08x, level: %d\n", i, vecpri,
+                   (level != 0));
+
+               /* init hw */
+               mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri);
+               mpic_irq_write(i, MPIC_IRQ_DESTINATION,
+                              1 << hard_smp_processor_id());
+
+               /* init linux descriptors */
+               if (i < mpic->irq_count) {
+                       irq_desc[mpic->irq_offset+i].status = level ? IRQ_LEVEL 
: 0;
+                       irq_desc[mpic->irq_offset+i].handler = &mpic->hc_irq;
+               }
+       }
+       
+       /* Init spurrious vector */
+       mpic_write(mpic->gregs, MPIC_GREG_SPURIOUS, MPIC_VEC_SPURRIOUS);
+
+       /* Disable 8259 passthrough */
+       mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
+                  mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+                  | MPIC_GREG_GCONF_8259_PTHROU_DIS);
+
+       /* Set current processor priority to 0 */
+       mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
+}
+
+
+
+void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
+{
+       unsigned is_ipi;
+       struct mpic *mpic = mpic_find(irq, &is_ipi);
+       unsigned long flags;
+       u32 reg;
+
+       spin_lock_irqsave(&mpic_lock, flags);
+       if (is_ipi) {
+               reg = mpic_ipi_read(irq - mpic->ipi_offset) &
+                       ~MPIC_VECPRI_PRIORITY_MASK;
+               mpic_ipi_write(irq - mpic->ipi_offset,
+                              reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
+       } else {
+               reg = mpic_irq_read(irq - mpic->irq_offset,MPIC_IRQ_VECTOR_PRI)
+                       & ~MPIC_VECPRI_PRIORITY_MASK;
+               mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI,
+                              reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
+       }
+       spin_unlock_irqrestore(&mpic_lock, flags);
+}
+
+unsigned int mpic_irq_get_priority(unsigned int irq)
+{
+       unsigned is_ipi;
+       struct mpic *mpic = mpic_find(irq, &is_ipi);
+       unsigned long flags;
+       u32 reg;
+
+       spin_lock_irqsave(&mpic_lock, flags);
+       if (is_ipi)
+               reg = mpic_ipi_read(irq - mpic->ipi_offset);
+       else
+               reg = mpic_irq_read(irq - mpic->irq_offset, 
MPIC_IRQ_VECTOR_PRI);
+       spin_unlock_irqrestore(&mpic_lock, flags);
+       return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT;
+}
+
+void mpic_setup_this_cpu(void)
+{
+#ifdef CONFIG_SMP
+       struct mpic *mpic = mpic_primary;
+       unsigned long flags;
+       u32 msk = 1 << hard_smp_processor_id();
+       unsigned int i;
+
+       BUG_ON(mpic == NULL);
+
+       DBG("%s: setup_this_cpu(%d)\n", mpic->name, hard_smp_processor_id());
+
+       spin_lock_irqsave(&mpic_lock, flags);
+
+       /* let the mpic know we want intrs. default affinity is 0xffffffff
+        * until changed via /proc. That's how it's done on x86. If we want
+        * it differently, then we should make sure we also change the default
+        * values of irq_affinity in irq.c.
+        */
+       if (distribute_irqs) {
+               for (i = 0; i < mpic->num_sources ; i++)
+                       mpic_irq_write(i, MPIC_IRQ_DESTINATION,
+                               mpic_irq_read(i, MPIC_IRQ_DESTINATION) | msk);
+       }
+
+       /* Set current processor priority to 0 */
+       mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
+
+       spin_unlock_irqrestore(&mpic_lock, flags);
+#endif /* CONFIG_SMP */
+}
+
+int mpic_cpu_get_priority(void)
+{
+       struct mpic *mpic = mpic_primary;
+
+       return mpic_cpu_read(MPIC_CPU_CURRENT_TASK_PRI);
+}
+
+void mpic_cpu_set_priority(int prio)
+{
+       struct mpic *mpic = mpic_primary;
+
+       prio &= MPIC_CPU_TASKPRI_MASK;
+       mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, prio);
+}
+
+/*
+ * XXX: someone who knows mpic should check this.
+ * do we need to eoi the ipi including for kexec cpu here (see xics comments)?
+ * or can we reset the mpic in the new kernel?
+ */
+void mpic_teardown_this_cpu(int secondary)
+{
+       struct mpic *mpic = mpic_primary;
+       unsigned long flags;
+       u32 msk = 1 << hard_smp_processor_id();
+       unsigned int i;
+
+       BUG_ON(mpic == NULL);
+
+       DBG("%s: teardown_this_cpu(%d)\n", mpic->name, hard_smp_processor_id());
+       spin_lock_irqsave(&mpic_lock, flags);
+
+       /* let the mpic know we don't want intrs.  */
+       for (i = 0; i < mpic->num_sources ; i++)
+               mpic_irq_write(i, MPIC_IRQ_DESTINATION,
+                       mpic_irq_read(i, MPIC_IRQ_DESTINATION) & ~msk);
+
+       /* Set current processor priority to max */
+       mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
+
+       spin_unlock_irqrestore(&mpic_lock, flags);
+}
+
+
+void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)
+{
+       struct mpic *mpic = mpic_primary;
+
+       BUG_ON(mpic == NULL);
+
+#ifdef DEBUG_IPI
+       DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);
+#endif
+
+       mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10,
+                      mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
+}
+
+int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs)
+{
+       u32 irq;
+
+       irq = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;
+#ifdef DEBUG_LOW
+       DBG("%s: get_one_irq(): %d\n", mpic->name, irq);
+#endif
+       if (mpic->cascade && irq == mpic->cascade_vec) {
+#ifdef DEBUG_LOW
+               DBG("%s: cascading ...\n", mpic->name);
+#endif
+               irq = mpic->cascade(regs, mpic->cascade_data);
+               mpic_eoi(mpic);
+               return irq;
+       }
+       if (unlikely(irq == MPIC_VEC_SPURRIOUS))
+               return -1;
+       if (irq < MPIC_VEC_IPI_0) {
+#ifdef DEBUG_IRQ
+               DBG("%s: irq %d\n", mpic->name, irq + mpic->irq_offset);
+#endif
+               return irq + mpic->irq_offset;
+       }
+#ifdef DEBUG_IPI
+               DBG("%s: ipi %d !\n", mpic->name, irq - MPIC_VEC_IPI_0);
+#endif
+       return irq - MPIC_VEC_IPI_0 + mpic->ipi_offset;
+}
+
+int mpic_get_irq(struct pt_regs *regs)
+{
+       struct mpic *mpic = mpic_primary;
+
+       BUG_ON(mpic == NULL);
+
+       return mpic_get_one_irq(mpic, regs);
+}
+
+
+#ifdef CONFIG_SMP
+void mpic_request_ipis(void)
+{
+       struct mpic *mpic = mpic_primary;
+
+       BUG_ON(mpic == NULL);
+       
+       printk("requesting IPIs ... \n");
+
+       /* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */
+       request_irq(mpic->ipi_offset+0, mpic_ipi_action, SA_INTERRUPT,
+                   "IPI0 (call function)", mpic);
+       request_irq(mpic->ipi_offset+1, mpic_ipi_action, SA_INTERRUPT,
+                  "IPI1 (reschedule)", mpic);
+       request_irq(mpic->ipi_offset+2, mpic_ipi_action, SA_INTERRUPT,
+                  "IPI2 (unused)", mpic);
+       request_irq(mpic->ipi_offset+3, mpic_ipi_action, SA_INTERRUPT,
+                  "IPI3 (debugger break)", mpic);
+
+       printk("IPIs requested... \n");
+}
+
+void smp_mpic_message_pass(int target, int msg)
+{
+       /* make sure we're sending something that translates to an IPI */
+       if ((unsigned int)msg > 3) {
+               printk("SMP %d: smp_message_pass: unknown msg %d\n",
+                      smp_processor_id(), msg);
+               return;
+       }
+       switch (target) {
+       case MSG_ALL:
+               mpic_send_ipi(msg, 0xffffffff);
+               break;
+       case MSG_ALL_BUT_SELF:
+               mpic_send_ipi(msg, 0xffffffff & ~(1 << smp_processor_id()));
+               break;
+       default:
+               mpic_send_ipi(msg, 1 << target);
+               break;
+       }
+}
+#endif /* CONFIG_SMP */
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/mpic_init.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/mpic_init.c      Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,390 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/compile.h>
+#include <asm/mpic.h>
+#include "mpic_init.h"
+#include "oftree.h"
+#include "of-devtree.h"
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(fmt...) printk(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+#define PANIC(fmt...) DBG(fmt)
+
+static struct mpic *mpic;
+static unsigned long opic_addr;
+static unsigned int opic_flags;
+
+/*
+ * from OF_IEEE_1275
+ *
+ * pg 175, property "ranges"
+ *
+ * The number of integers in each size entry is determined by the
+ * value of the #size-cells property of this node (the node in which
+ * the ranges property appears) or 1 if the #size-cells property is
+ * absent.
+ *
+ *
+ * pg 177, property "reg"
+ *
+ * The number of integers in each size entry is determined by the
+ * value of the "#size-cells" property in the parent node.  If the
+ * parent node has no such property, the value is one.
+ */
+static unsigned long reg2(void *oft_p, ofdn_t c)
+{
+    int rc;
+    /* the struct isa_reg_property is for a value of 2 for
+     * #address-cells and a value of 1 for #size-cells (of the
+     * parent).
+     */
+    struct isa_reg_property {
+        u32 space;
+        u32 address;
+        u32 size;
+    } isa_reg;
+
+    rc = ofd_getprop(oft_p, c, "reg", &isa_reg, sizeof(isa_reg));
+
+    DBG("%s: reg property address=0x%08x  size=0x%08x\n", __func__,
+                    isa_reg.address, isa_reg.size);
+    return isa_reg.address;
+}
+
+static unsigned long reg1(void *oft_p, ofdn_t c)
+{
+    int rc;
+    /* the struct reg_property32 is for a value of 1 for
+     * #address-cells and a value of 1 for #size-cells.
+     */
+    struct reg_property32 {
+        u32 address;
+        u32 size;
+    } reg;
+
+    rc = ofd_getprop(oft_p, c, "reg", &reg, sizeof(reg));
+
+    DBG("%s: reg property address=0x%08x  size=0x%08x\n", __func__,
+                        reg.address, reg.size);
+    return reg.address;
+}
+
+static unsigned long find_reg_addr_from_node(void *oft_p, ofdn_t c)
+{
+    int p_len;
+    unsigned long reg_addr = 0;
+    u32 size_c = 1;
+    u32 addr_c = 2;
+    ofdn_t parent;
+
+    if (c == OFD_ROOT) {
+        parent = c;
+    } else {
+        parent = ofd_node_parent(oft_p, c);
+    }
+
+    p_len = ofd_getprop(oft_p, parent, "#size-cells", &size_c, sizeof(size_c));
+    DBG("%s size is %d\n", __func__, size_c);
+
+    p_len = ofd_getprop(oft_p, parent, "#address-cells", &addr_c,
+                        sizeof(addr_c));
+    DBG("%s address is %d\n", __func__, addr_c);
+
+    if ( 1 != size_c ) {
+        PANIC("Unsupported size for reg property\n");
+    }
+    
+    if ( 1 == addr_c) {
+        reg_addr = reg1(oft_p, c);
+    } else if ( 2 == addr_c ) {
+        reg_addr = reg2(oft_p, c);
+    } else {
+        PANIC("Unsupported address size for reg property\n");
+    }
+    DBG("%s: address 0x%lx\n", __func__, reg_addr);
+    return reg_addr;
+}
+
+/*
+ * from OF_IEEE_1275
+ *
+ * pg 175, property "ranges"
+ * 
+ * The ranges property value is a sequence of child-phys parent-phys
+ * size specifications. Child-phys is an address, encoded as with
+ * encode-phys, in the child address space. Parent-phys is an address
+ * (likewise encoded as with encode-phys) in the parent address
+ * space. Size is a list of integers, each encoded as with encode-int,
+ * denoting the length of the child's address range.
+ */
+static unsigned long find_ranges_addr_from_node(void *oft_p, ofdn_t c)
+{
+    unsigned long ranges_addr = 0;
+    int ranges_i;
+    ofdn_t parent;
+    u32 addr_c = 2;
+    u32 ranges[64];
+    int p_len;
+
+    parent = ofd_node_parent(oft_p, c);
+    parent = ofd_node_parent(oft_p, parent);
+
+    p_len = ofd_getprop(oft_p, parent, "ranges", &ranges, sizeof(ranges));
+    DBG("%s: ranges\n", __func__);
+    int i; for (i=0; i<p_len; i++) {DBG("%08x ", ranges[i]);}
+    DBG("\n");
+
+    p_len = ofd_getprop(oft_p, parent, "#address-cells",
+                        &addr_c, sizeof(addr_c));
+    DBG("%s address is %d\n", __func__, addr_c);
+    ranges_i = addr_c;  /* skip over the child address */
+    
+    DBG("%s address is %d\n", __func__, addr_c);
+    switch (addr_c) {
+    case 1: 
+        ranges_addr = ranges[ranges_i];
+        break;
+    case 2:
+        ranges_addr = (((u64)ranges[ranges_i]) << 32) |
+                      ranges[ranges_i + 1];
+        break;
+    case 3:  /* the G5 case, how to squeeze 96 bits into 64 */
+        ranges_addr = (((u64)ranges[ranges_i+1]) << 32) |
+                      ranges[ranges_i + 2];
+        break;
+    case 4:
+        ranges_addr = (((u64)ranges[ranges_i+2]) << 32) |
+                      ranges[ranges_i + 4];
+        break;
+    default:
+        PANIC("#address-cells out of range\n");
+        break;
+    }
+    
+    DBG("%s: address 0x%lx\n", __func__, ranges_addr);
+    return ranges_addr;
+}
+
+static unsigned long find_pic_address_from_node(void *oft_p, ofdn_t c)
+{
+    unsigned long reg_addr, range_addr, addr;
+
+    /*
+     * The address is the sum of the address in the reg property of this node
+     * and the ranges property of the granparent node.
+     */
+    reg_addr = find_reg_addr_from_node(oft_p, c);
+    range_addr = find_ranges_addr_from_node(oft_p, c);
+    addr = reg_addr + range_addr;
+    DBG("%s: address 0x%lx\n", __func__, addr);
+    return addr;
+}
+
+static unsigned int find_pic_flags_from_node(void *oft_p, ofdn_t c)
+{
+    int be_len;
+    unsigned int flags = 0;
+
+    /* does it have the property big endian? */
+    be_len = ofd_getprop(oft_p, c, "big_endian", NULL, 0);
+    if (be_len >= 0) {
+        DBG("%s: Big Endian found\n", __func__);
+        flags |= MPIC_BIG_ENDIAN;
+    }
+    DBG("%s: flags 0x%x\n", __func__, flags);
+    return flags;
+}
+
+static int find_mpic_simple_probe(void *oft_p)
+{
+    u32 addr_cells;
+    int rc;
+    u32 addr[2];
+
+    rc = ofd_getprop(oft_p, OFD_ROOT, "#address-cells",
+                     &addr_cells, sizeof(addr_cells));
+    if ( rc < 0 ) {
+        /* if the property does not exist use its default value, 2 */
+        addr_cells = 2;
+    }
+
+    rc = ofd_getprop(oft_p, OFD_ROOT, "platform-open-pic", addr, sizeof(addr));
+    if (rc < 0) {
+        return rc;
+    }
+
+    opic_addr = addr[0];
+    if (addr_cells == 2) {
+        opic_addr <<= 32;
+        opic_addr |= addr[1];
+    }
+    DBG("%s: found OpenPIC at: 0x%lx\n", __func__, opic_addr);
+    /* we did not really find the pic device, only its address. 
+     * We use big endian and broken u3 by default.
+     */
+    opic_flags |= MPIC_BIG_ENDIAN | MPIC_BROKEN_U3;
+    return 0;
+}
+
+static int find_mpic_canonical_probe(void *oft_p)
+{
+    ofdn_t c;
+    const char mpic_type[] = "open-pic";
+    /* some paths are special and we cannot find the address
+     * by the usual method */
+    const char *excluded_paths[] = { "/interrupt-controller" };
+
+    /*
+     * Search through the OFD tree for all devices of type 'open_pic'.
+     * We select the one without an 'interrupt' property.
+     */
+    c = ofd_node_find_by_prop(oft_p, OFD_ROOT, "device_type", mpic_type,
+                                        sizeof(mpic_type));
+    while (c > 0) {
+        int int_len;
+        int good_mpic;
+        const char * path = ofd_node_path(oft_p, c);
+
+        good_mpic = 0;
+        int_len = ofd_getprop(oft_p, c, "interrupts", NULL, 0);
+        if (int_len < 0) {
+            int i;
+
+            /* there is no property interrupt.  This could be the pic */
+            DBG("%s: potential OpenPIC in: %s\n", __func__, path);
+            good_mpic = 1;
+
+            for (i = 0; i < ARRAY_SIZE(excluded_paths) && good_mpic; i++) {
+                const char *excluded_path = excluded_paths[i];
+                if (!strncmp(path, excluded_path, strlen(excluded_path)))
+                    good_mpic = 0;
+            }
+        }
+
+        if (good_mpic) {
+            DBG("%s: found OpenPIC in: %s\n", __func__, path);
+            opic_addr = find_pic_address_from_node(oft_p, c);
+            opic_flags = find_pic_flags_from_node(oft_p, c);
+            return 0;
+        }
+
+        c = ofd_node_find_next(oft_p, c);
+    }
+
+    DBG("%s: Could not find a pic\n", __func__);
+    return -1;
+}
+
+static int find_mpic(void)
+{
+    void *oft_p;
+    int rc;
+
+    opic_addr = (unsigned long)-1;
+    opic_flags = 0;
+
+    oft_p = (void *)oftree;
+    rc = find_mpic_simple_probe(oft_p);
+
+    if (rc < 0) {
+        DBG("%s: Searching for pic ...\n", __func__);
+        rc = find_mpic_canonical_probe(oft_p);
+    }
+
+    return rc;
+}
+
+static struct hw_interrupt_type hc_irq;
+
+struct hw_interrupt_type *xen_mpic_init(struct hw_interrupt_type *xen_irq)
+{
+    unsigned int isu_size;
+    unsigned int irq_offset;
+    unsigned int irq_count;
+    unsigned int ipi_offset;
+    unsigned char *senses;
+    unsigned int senses_count;
+
+    printk("%s: start\n", __func__);
+
+    io_apic_irqs = ~0;  /* all IRQs go through IOAPIC */
+       irq_vector[0] = FIRST_DEVICE_VECTOR;
+       vector_irq[FIRST_DEVICE_VECTOR] = 0;
+
+    isu_size = 0;
+    irq_offset = 0;
+    irq_count = 128;
+    ipi_offset = 128;
+    senses = NULL;
+    senses_count = 0;
+
+    if (find_mpic()) {
+        printk("%s: ERROR: Could not find open pic.\n", __func__);
+        return NULL;
+    }
+
+    mpic = mpic_alloc(opic_addr,
+                      opic_flags | MPIC_PRIMARY | MPIC_WANTS_RESET,
+                      isu_size, irq_offset, irq_count,
+                      ipi_offset, senses, senses_count, "Xen-U3-MPIC");
+
+    BUG_ON(mpic == NULL);
+    mpic_init(mpic);
+
+    hc_irq.startup = mpic->hc_irq.startup;
+    mpic->hc_irq.startup = xen_irq->startup;
+
+    hc_irq.enable = mpic->hc_irq.enable;
+    mpic->hc_irq.enable = xen_irq->enable;
+
+    hc_irq.disable = mpic->hc_irq.disable;
+    mpic->hc_irq.disable = xen_irq->disable;
+
+    hc_irq.shutdown = mpic->hc_irq.shutdown;
+    mpic->hc_irq.shutdown = xen_irq->shutdown;
+
+    hc_irq.ack = mpic->hc_irq.ack;
+    mpic->hc_irq.ack = xen_irq->ack;
+
+    hc_irq.end = mpic->hc_irq.end;
+    mpic->hc_irq.end = xen_irq->end;
+
+    hc_irq.set_affinity = mpic->hc_irq.set_affinity;
+    mpic->hc_irq.set_affinity = xen_irq->set_affinity;
+
+    printk("%s: success\n", __func__);
+    return &hc_irq;
+}
+
+int xen_mpic_get_irq(struct cpu_user_regs *regs)
+{
+    BUG_ON(mpic == NULL);
+
+       return mpic_get_one_irq(mpic, regs);
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/mpic_init.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/mpic_init.h      Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,29 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#ifndef _MPIC_INIT_H
+#define _MPIC_INIT_H
+
+extern struct hw_interrupt_type *xen_mpic_init(
+    struct hw_interrupt_type *xen_irq);
+
+extern int xen_mpic_get_irq(struct cpu_user_regs *regs);
+
+#endif  /* #ifndef _MPIC_INIT_H */
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/of-devtree.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/of-devtree.c     Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,1088 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ * This code is intended to be used but relocatable routines So PLEASE
+ * do not place any global data here including const integrals or
+ * literals.
+ * The local assert() is ok for string literal usage.. but thats it.
+ */
+
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include "of-devtree.h"
+
+static int (*ofd_write)(const char *, size_t len) = NULL;
+
+void ofd_init(int (*write)(const char *, size_t len))
+{
+    ofd_write = write;
+}
+                  
+
+static void ofd_stop(void)
+{
+    for ( ; ; ) ;
+}
+
+/* this is so it can be called from anywhere */
+static void ofd_assprint(int line)
+{
+    char a[13];
+    char num[20];
+    int i;
+
+    a[0]  = '\n';
+    a[1]  = '\n';
+    a[2]  = 'O';
+    a[3]  = 'F';
+    a[4]  = 'D';
+    a[5]  = ':';
+    a[6]  = 'A';
+    a[7]  = 'S';
+    a[8]  = 'S';
+    a[9]  = 'E';
+    a[10] = 'R';
+    a[11] = 'T';
+    a[12] = ':';
+
+
+    ofd_write(a, sizeof (a) - 1);
+    
+    /* put the number in backwards */
+    i = 0;
+    while ( line > 0 ) {
+        num[i++] = '0' + (line % 10);
+        line /= 10;
+    }
+    /* print it */
+    /* number */
+    while (i-- > 0) {
+        ofd_write(&num[i], 1);
+    }
+    ofd_write("\n", 1);
+
+    ofd_stop();
+}
+
+#ifdef assert
+#undef assert
+#endif
+
+#define assert(EX)                                              \
+    do {                                                        \
+        if ( !(EX) ) {                                          \
+            ofd_assprint(__LINE__);                             \
+        }                                                       \
+    } while (0)
+
+/*
+ * We treat memory like an array of u64.  For the sake of
+ * compactness we assume that a short is big enough as an index.
+ */
+struct ofd_node {
+    ofdn_t on_ima;
+    ofdn_t on_parent;
+    ofdn_t on_child;
+    ofdn_t on_peer;
+    ofdn_t on_io;
+    ofdn_t on_next;     /* for search lists */
+    ofdn_t on_prev;
+    ofdn_t on_prop;
+    u32 on_pathlen;
+    u32 on_last;
+    char on_path[0];
+};
+
+struct ofd_prop {
+    ofdn_t op_ima;
+    ofdn_t op_next;
+    u32 op_objsz;
+    u32 op_namesz;
+    /* must have 64bit alignment */
+    char op_data[0]  __attribute__ ((aligned(8)));
+};
+
+struct ofd_io {
+    ofdn_t oi_ima;
+    ofdn_t oi_node;
+    u64 oi_open   __attribute__ ((aligned(8)));
+};
+
+struct ofd_free {
+    ofdn_t of_cells;
+    ofdn_t of_next;
+};
+
+struct ofd_mem {
+    ofdn_t om_num;
+    ofdn_t om_next;
+    ofdn_t om_free;     /* Future site of a free list */
+    ofdn_t _om_pad;
+    u64 om_mem[0] __attribute__((aligned(8)));
+};
+
+#define NODE_PAT    0x0f01
+#define PROP_PAT    0x0f03
+#define IO_PAT      0x0f05
+
+
+size_t ofd_size(void *mem)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    size_t sz;
+
+    sz = m->om_next * sizeof (u64) + sizeof(*m);
+    return sz;
+}
+
+size_t ofd_space(void *mem)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    size_t sz;
+
+    sz = m->om_num * sizeof (u64);
+    return sz;
+}
+
+
+static int ofd_pathsplit_right(const char *s, int c, size_t max)
+{
+    int i = 0;
+
+    if ( max == 0 ) {
+        --max;
+    }
+    
+    while ( *s != '\0' && *s != c && max != 0 ) {
+        ++i;
+        ++s;
+        --max;
+    }
+    return i;
+}
+
+static int ofd_pathsplit_left(const char *p, int c, size_t len)
+{
+    const char *s;
+
+    if ( len > 0 ) {
+        /* move s to the end */
+        s = p + len - 1;
+
+        /* len could include a null */
+        if ( *s == '\0' ) {
+            --s;
+        }
+        while ( s >= p ) {
+            if ( *s == c ) {
+                ++s;
+                break;
+            }
+            --s;
+        }
+        if ( s < p ) {
+            return 0;
+        }
+        return (s - p);
+    }
+    return 0;
+}
+
+void *ofd_create(void *mem, size_t sz)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    struct ofd_node *n;
+    size_t sum;
+    ofdn_t cells;
+
+    if ( sz < (sizeof (*n) * 4) ) {
+        return NULL;
+    }
+
+    memset(mem, 0, sz);
+
+    m->om_num = (sz - sizeof(*m)) / sizeof (u64);
+
+    /* skip the first cell */
+    m->om_next = OFD_ROOT;
+    n = (struct ofd_node *)&m->om_mem[m->om_next];
+    n->on_ima = NODE_PAT;
+    n->on_pathlen = 2;
+    n->on_last = 1;
+    n->on_path[0] = '/';
+    n->on_path[1] = '\0';
+
+    sum = sizeof (*n) + 2; /* Don't forget the path */
+    cells = (sum + sizeof (m->om_mem[0]) - 1) / sizeof (m->om_mem[0]);
+    m->om_next += cells;
+
+    return m;
+}
+
+static struct ofd_node *ofd_node_get(struct ofd_mem *m, ofdn_t n)
+{
+    if ( n < m->om_next ) {
+        struct ofd_node *r;
+
+        r = (struct ofd_node *)&m->om_mem[n];
+        if ( r->on_ima == NODE_PAT ) {
+            return r;
+        }
+    }
+    return NULL;
+}
+
+ofdn_t ofd_node_parent(void *mem, ofdn_t n)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    struct ofd_node *r = ofd_node_get(m, n);
+
+    if ( r == NULL) return 0;
+    return r->on_parent;
+}
+
+ofdn_t ofd_node_peer(void *mem, ofdn_t n)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    struct ofd_node *r;
+
+    if ( n == 0 ) {
+        return OFD_ROOT;
+    }
+
+    r = ofd_node_get(m, n);
+    if ( r == NULL) return 0;
+    return r->on_peer;
+}
+
+const char *ofd_node_path(void *mem, ofdn_t n)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    struct ofd_node *r = ofd_node_get(m, n);
+
+    if ( r == NULL) return NULL;
+    return r->on_path;
+}
+
+static ofdn_t ofd_node_prop(void *mem, ofdn_t n)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    struct ofd_node *r = ofd_node_get(m, n);
+
+    if ( r == NULL) return 0;
+    return r->on_prop;
+}
+
+ofdn_t ofd_node_child(void *mem, ofdn_t p)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    struct ofd_node *r = ofd_node_get(m, p);
+
+    if ( r == NULL) return 0;
+    return r->on_child;
+}
+
+int ofd_node_to_path(void *mem, ofdn_t p, void *buf, size_t sz)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    struct ofd_node *r = ofd_node_get(m, p);
+
+    if ( sz > r->on_pathlen ) {
+        sz = r->on_pathlen;
+    }
+
+    memcpy(buf, r->on_path, sz);
+
+    if ( r == NULL) return -1;
+    return r->on_pathlen;
+}
+
+static int ofd_check(void *p, size_t l)
+{
+    int i;
+    u64 *v = (u64 *)p;
+
+    for ( i = 0; i < l; i++ ) {
+        if ( v[i] != 0ULL ) {
+            return 0;
+        }
+    }
+    return 1;
+}
+
+
+
+static ofdn_t ofd_node_create(
+    struct ofd_mem *m, const char *path, size_t pathlen)
+{
+    struct ofd_node *n;
+    ofdn_t pos;
+    size_t sum = pathlen + 1 + sizeof (*n); /* add trailing zero to path */
+    ofdn_t cells = (sum + sizeof(m->om_mem[0]) - 1) / sizeof(m->om_mem[0]);
+
+    if ( m->om_next + cells >= m->om_num ) {
+        return 0;
+    }
+
+    pos = m->om_next;
+        
+    assert(ofd_check(&m->om_mem[pos], cells)); /* non-zero */
+    m->om_next += cells;
+
+    n = (struct ofd_node *)&m->om_mem[pos];
+    assert(n->on_ima == 0); /* new node not empty */
+
+    n->on_ima = NODE_PAT;
+    n->on_peer = 0;
+    n->on_child = 0;
+    n->on_io = 0;
+    n->on_pathlen = pathlen;
+    n->on_last = ofd_pathsplit_left(path, '/', pathlen);
+    strncpy(n->on_path, path, pathlen);
+    n->on_path[n->on_pathlen] = 0;
+
+    return pos;
+}
+
+/* prunes a node and all its children simply by wasting memory and
+ * unlinking it from the tree */
+int ofd_node_prune(void *mem, ofdn_t node)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    struct ofd_node *n;
+    struct ofd_node *p;
+
+    n = ofd_node_get(m, node);
+    if (n == NULL) return -1;
+
+    p = ofd_node_get(m, n->on_parent);
+    assert(p != NULL);
+
+    if ( p->on_child == node ) {
+        /* easy case */
+        p->on_child = n->on_peer;
+    } else {
+        struct ofd_node *s;
+
+        s = ofd_node_get(m, p->on_child);
+        assert(s != NULL);
+        while ( s->on_peer != node ) {
+            s = ofd_node_get(m, s->on_peer);
+            assert(s != NULL);
+        }
+        s->on_peer = n->on_peer;
+    }
+    return 1;
+}
+
+ofdn_t ofd_prune_path(void *m, const char *path)
+{
+    ofdn_t n;
+    int rc = -1;
+    while ((n = ofd_node_find(m, path)) > 0) {
+        rc = ofd_node_prune(m, n);
+    }
+
+    return rc;
+}
+
+ofdn_t ofd_node_child_create(
+    void *mem, ofdn_t parent, const char *path, size_t pathlen)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    struct ofd_node *p;
+    struct ofd_node *n;
+    ofdn_t pos;
+
+    p = ofd_node_get(m, parent);
+    if (p == NULL) return  0;
+
+    pos = ofd_node_create(m, path, pathlen);
+    n = ofd_node_get(m, pos);
+    assert(n != NULL);
+
+    assert(p->on_child == 0); /* child exists */
+    if ( p->on_child == 0 ) {
+        p->on_child = pos;
+        n->on_parent = parent;
+    } else {
+        pos = 0;
+    }
+
+    return pos;
+}
+
+ofdn_t ofd_node_peer_create(
+    void *mem, ofdn_t sibling, const char *path, size_t pathlen)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    struct ofd_node *s;
+    struct ofd_node *n;
+    ofdn_t pos;
+
+    s = ofd_node_get(m, sibling);
+    if (s == NULL) return 0;
+
+    pos = ofd_node_create(m, path, pathlen);
+    n = ofd_node_get(m, pos);
+    assert(n != NULL);
+
+    if ( s->on_peer == 0 ) {
+        s->on_peer = pos;
+        n->on_parent = s->on_parent;
+    } else {
+        assert(0); /* peer exists */
+        pos = 0;
+    }
+    return pos;
+}
+
+static ofdn_t ofd_node_peer_last(void *mem, ofdn_t c)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    struct ofd_node *n;
+
+    n = ofd_node_get(m, c);
+    if (n == NULL) return 0;
+
+    while ( n->on_peer > 0 ) {
+        c = n->on_peer;
+        n = ofd_node_get(m, c);
+        assert(n != NULL);
+    }
+
+    return c;
+}
+
+static ofdn_t ofd_node_walk(struct ofd_mem *m, ofdn_t p, const char *s)
+{
+    struct ofd_node *np;
+    ofdn_t n;
+    ofdn_t r;
+
+    if ( *s == '/' ) {
+        ++s;
+        if ( *s == '\0' ) {
+            assert(0); /* ends in / */
+            return 0;
+        }
+    }
+
+    np = ofd_node_get(m, p);
+    if (np == NULL) return 0;
+
+    r = p;
+    do {
+        int last = np->on_last;
+        size_t lsz = np->on_pathlen - last;
+        size_t sz;
+
+        sz = ofd_pathsplit_right(s, '/', 0);
+        
+        if ( lsz > 0 && strncmp(s, &np->on_path[last], sz) == 0 ) {
+            if ( s[sz] == '\0' ) {
+                return r;
+            }
+            /* there is more to the path */
+            n = ofd_node_child(m, p);
+            if ( n != 0 ) {
+                r = ofd_node_walk(m, n, &s[sz]);
+                return r;
+            }
+            /* there are no children */
+            return 0;
+        }
+    } while ( 0 );
+
+    /*
+     * we know that usually we are only serching for top level peers
+     * so we do peers first peer
+     */
+    n = ofd_node_peer(m, p);
+    if ( n > 0 ) {
+        r = ofd_node_walk(m, n, s);
+    } else {
+        r = 0;
+    }
+
+    return r;
+}
+
+
+ofdn_t ofd_node_find(void *mem, const char *devspec)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    ofdn_t n = OFD_ROOT;
+    const char *s = devspec;
+    size_t sz;
+
+    if ( s == NULL || s[0] == '\0' ) {
+        return OFD_ROOT;
+    }
+
+    if ( s[0] != '/' ) {
+        size_t asz;
+
+        /* get the component length */
+        sz = ofd_pathsplit_right(s, '/', 0);
+
+        /* check for an alias */
+        asz = ofd_pathsplit_right(s, ':', sz);
+
+        if ( s[asz] == ':' ) {
+            /*
+             * s points to an alias and &s[sz] points to the alias
+             * args.
+             */
+            assert(0); /* aliases no supported */
+            return 0;
+        }
+    } else if ( s[1] == '\0' ) {
+        return n;
+    }
+
+    n = ofd_node_child(m, n);
+    if ( n == 0 ) {
+        return 0;
+    }
+
+    return ofd_node_walk(m, n, s);
+}
+
+
+static struct ofd_prop *ofd_prop_get(struct ofd_mem *m, ofdn_t p)
+{
+    if ( p < m->om_next ) {
+        struct ofd_prop *r;
+
+        r = (struct ofd_prop *)&m->om_mem[p];
+        if ( r->op_ima == PROP_PAT ) {
+            return r;
+        }
+        assert(r->op_ima == PROP_PAT); /* bad object */
+    }
+    return NULL;
+}
+
+static ofdn_t ofd_prop_create(
+    struct ofd_mem *m,
+    ofdn_t node,
+    const char *name,
+    const void *src,
+    size_t sz)
+{
+    struct ofd_node *n;
+    struct ofd_prop *p;
+    size_t len = strlen(name) + 1;
+    size_t sum = sizeof (*p) + sz + len;
+    ofdn_t cells;
+    char *dst;
+    ofdn_t pos;
+
+    cells = (sum + sizeof (m->om_mem[0]) - 1) / sizeof (m->om_mem[0]);
+
+    if ( m->om_next + cells >= m->om_num ) {
+        return 0;
+    }
+
+    /* actual data structure */
+    pos = m->om_next;
+    assert(ofd_check(&m->om_mem[pos], cells)); /* non-zero */
+
+    p = (struct ofd_prop *)&m->om_mem[pos];
+    m->om_next += cells;
+
+    assert(p->op_ima == 0); /* new node not empty */
+    p->op_ima = PROP_PAT;
+    p->op_next = 0;
+    p->op_objsz = sz;
+    p->op_namesz = len;
+
+    /* the rest of the data */
+    dst = p->op_data;
+
+    /* zero what will be the pad, cheap and cannot hurt */
+    m->om_mem[m->om_next - 1] = 0;
+
+    if ( sz > 0 ) {
+        /* some props have no data, just a name */
+        memcpy(dst, src, sz);
+        dst += sz;
+    }
+
+    memcpy(dst, name, len);
+
+    /* now place it in the tree */
+    n = ofd_node_get(m, node);
+    assert(n != NULL);
+
+    if ( n->on_prop == 0 ) {
+        n->on_prop = pos;
+    } else {
+        ofdn_t pn = n->on_prop;
+        struct ofd_prop *nxt;
+
+        for (;;) {
+            nxt = ofd_prop_get(m, pn);
+            if (nxt->op_next == 0) {
+                nxt->op_next = pos;
+                break;
+            }
+            pn = nxt->op_next;
+        }
+    }
+
+    return pos;
+}
+
+void ofd_prop_remove(void *mem, ofdn_t node, ofdn_t prop)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    struct ofd_node *n = ofd_node_get(m, node);
+    struct ofd_prop *p = ofd_prop_get(m, prop);
+
+    if (n == NULL) return;
+    if (p == NULL) return;
+
+    if ( n->on_prop == prop ) {
+        n->on_prop = p->op_next;
+    } else {
+        ofdn_t pn = n->on_prop;
+        struct ofd_prop *nxt;
+
+        for ( ; ; ) {
+            nxt = ofd_prop_get(m, pn);
+            if ( nxt->op_next == prop ) {
+                nxt->op_next = p->op_next;
+                break;
+            }
+            pn = nxt->op_next;
+        }
+    }
+    return;
+}
+
+ofdn_t ofd_prop_find(void *mem, ofdn_t n, const char *name)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    ofdn_t p = ofd_node_prop(m, n);
+    struct ofd_prop *r;
+    char *s;
+    size_t len;
+
+    if ( name == NULL || *name == '\0' ) {
+        return OFD_ROOT;
+    }
+
+    len = strlen(name) + 1;
+    
+    while ( p != 0 ) {
+        r = ofd_prop_get(m, p);
+        s = &r->op_data[r->op_objsz];
+        if ( len == r->op_namesz ) {
+            if ( strncmp(name, s, r->op_namesz) == 0 ) {
+                break;
+            }
+        }
+        p = r->op_next;
+    }
+    return p;
+}
+
+static ofdn_t ofd_prop_next(struct ofd_mem *m, ofdn_t n, const char *prev)
+{
+    ofdn_t p;
+
+    if ( prev == NULL || *prev == '\0' ) {
+        /* give the first */
+        p = ofd_node_prop(m, n);
+    } else {
+        struct ofd_prop *r;
+
+        /* look for the name */
+        p = ofd_prop_find(m, n, prev);
+        if ( p != 0 ) {
+            /* get the data for prev */
+            r = ofd_prop_get(m, p);
+
+            /* now get next */
+            p = r->op_next;
+        } else {
+            p = -1;
+        }
+    }
+
+    return p;
+}
+
+ofdn_t ofd_nextprop(void *mem, ofdn_t n, const char *prev, char *name)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    ofdn_t p = ofd_prop_next(m, n, prev);
+    struct ofd_prop *r;
+    char *s;
+
+    if ( p > 0 ) {
+        r = ofd_prop_get(m, p);
+        s = &r->op_data[r->op_objsz];
+        memcpy(name, s, r->op_namesz);
+    }
+
+    return p;
+}
+
+/*
+ * It is valid to call with NULL pointers, in case you want only one
+ * cell size.
+ */
+int ofd_getcells(void* mem, ofdn_t n, u32* addr_cells, u32* size_cells)
+{
+    if ( addr_cells != NULL ) *addr_cells = 0;
+    if ( size_cells != NULL ) *size_cells = 0;
+
+retry:
+    if ( addr_cells  != NULL && *addr_cells == 0 ) {
+        ofd_getprop(mem, n, "#address-cells",
+                addr_cells, sizeof(u32));
+    }
+
+    if ( size_cells != NULL && *size_cells == 0 ) {
+        ofd_getprop(mem, n, "#size-cells", size_cells, sizeof(u32));
+    }
+
+    if ( ( size_cells != NULL && *size_cells == 0 )
+            || ( addr_cells != NULL && *addr_cells == 0 ) ) {
+        if ( n != OFD_ROOT ) {
+            n = ofd_node_parent(mem, n);
+            goto retry;
+        }
+        return -1;
+    }
+
+    return 1;
+}
+
+int ofd_getprop(void *mem, ofdn_t n, const char *name, void *buf, size_t sz)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    ofdn_t p = ofd_prop_find(m, n, name);
+    struct ofd_prop *r;
+
+    if ( p == 0 ) {
+        return -1;
+    }
+
+    r = ofd_prop_get(m, p);
+
+    if ( sz > r->op_objsz ) {
+        sz = r->op_objsz;
+    }
+    memcpy(buf, r->op_data, sz);
+
+    return r->op_objsz;
+}
+
+int ofd_getproplen(void *mem, ofdn_t n, const char *name)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    ofdn_t p = ofd_prop_find(m, n, name);
+    struct ofd_prop *r;
+
+    if ( p == 0 ) {
+        return -1;
+    }
+
+    r = ofd_prop_get(m, p);
+
+    return r->op_objsz;
+}
+
+static ofdn_t ofd_prop_set(
+    void *mem, ofdn_t n, const char *name, const void *src, size_t sz)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    ofdn_t p = ofd_prop_find(m, n, name);
+    struct ofd_prop *r;
+    char *dst;
+
+    r = ofd_prop_get(m, p);
+
+    if ( sz <= r->op_objsz ) {
+        /* we can reuse */
+        memcpy(r->op_data, src, sz);
+        if ( sz < r->op_objsz ) {
+            /* need to move name */
+            dst = r->op_data + sz;
+            /*
+             * use the name arg size we may have overlap with the
+             * original
+             */
+            memcpy(dst, name, r->op_namesz);
+            r->op_objsz = sz;
+        }
+    } else {
+        /*
+         * Sadly, we remove from the list, wasting the space and then
+         * we can creat a new one
+         */
+        ofd_prop_remove(m, n, p);
+        p = ofd_prop_create(mem, n, name, src, sz);
+    }
+
+    return p;
+}
+
+int ofd_setprop(
+    void *mem, ofdn_t n, const char *name, const void *buf, size_t sz)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    ofdn_t r;
+
+    r = ofd_prop_find(m, n, name);
+    if ( r == 0 ) {
+        r = ofd_prop_create(mem, n, name, buf, sz);
+    } else {
+        r = ofd_prop_set(mem, n, name, buf, sz);
+    }
+
+    if ( r > 0 ) {
+        struct ofd_prop *pp = ofd_prop_get(m, r);
+        return pp->op_objsz;
+    }
+
+    return OF_FAILURE;
+}
+
+
+static ofdn_t ofd_find_by_prop(
+    struct ofd_mem *m,
+    ofdn_t head,
+    ofdn_t *prev_p,
+    ofdn_t n,
+    const char *name,
+    const void *val,
+    size_t sz)
+{
+    struct ofd_node *np;
+    struct ofd_prop *pp;
+    ofdn_t p;
+
+retry:
+    p = ofd_prop_find(m, n, name);
+
+    if ( p > 0 ) {
+        int match = 0;
+
+        /* a property exists by that name */
+        if ( val == NULL ) {
+            match = 1;
+        } else {
+            /* need to compare values */
+            pp = ofd_prop_get(m, p);
+            if ( sz == pp->op_objsz
+                 && memcmp(pp->op_data, val, sz) == 0 ) {
+                match = 1;
+            }
+        }
+        if ( match == 1 ) {
+            if ( *prev_p >= 0 ) {
+                np = ofd_node_get(m, *prev_p);
+                np->on_next = n;
+            } else {
+                head = n;
+            }
+            np = ofd_node_get(m, n);
+            np->on_prev = *prev_p;
+            np->on_next = -1;
+            *prev_p = n;
+        }
+    }
+
+    p = ofd_node_child(m, n);
+    if ( p > 0 ) {
+        head = ofd_find_by_prop(m, head, prev_p, p, name, val, sz);
+    }
+
+    p = ofd_node_peer(m, n);
+    if ( p > 0 ) {
+        n = p;
+        goto retry;
+    }
+
+    return head;
+}
+
+ofdn_t ofd_node_find_by_prop(
+    void *mem,
+    ofdn_t n,
+    const char *name,
+    const void *val,
+    size_t sz)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+
+    if ( n <= 0 ) {
+        n = OFD_ROOT;
+    }
+
+    ofdn_t prev = -1;
+    return ofd_find_by_prop(m, -1, &prev, n, name, val, sz);
+}
+
+ofdn_t ofd_node_find_next(void *mem, ofdn_t n)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    struct ofd_node *np;
+
+    np = ofd_node_get(m, n);
+
+    if (np == NULL) return 0;
+    return np->on_next;
+}
+
+ofdn_t ofd_node_find_prev(void *mem, ofdn_t n)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    struct ofd_node *np;
+
+    np = ofd_node_get(m, n);
+    if (np == NULL) return 0;
+
+    return np->on_prev;
+}
+
+ofdn_t ofd_io_create(void *mem, ofdn_t node, u64 open)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    struct ofd_node *n;
+    struct ofd_io *i;
+    ofdn_t pos;
+    ofdn_t cells;
+
+    cells = (sizeof (*i) + sizeof (m->om_mem[0]) - 1) / sizeof(m->om_mem[0]);
+
+    n = ofd_node_get(m, node);
+    if ( n == NULL ) return 0;
+
+    if ( m->om_next + cells >= m->om_num ) {
+        return 0;
+    }
+
+    pos = m->om_next;
+    assert(ofd_check(&m->om_mem[pos], cells)); /* non-zero */
+
+    m->om_next += cells;
+    
+    i = (struct ofd_io *)&m->om_mem[pos];
+    assert(i->oi_ima == 0); /* new node not empty */
+
+    i->oi_ima = IO_PAT;
+    i->oi_node = node;
+    i->oi_open = open;
+
+    n->on_io = pos;
+
+    return pos;
+}
+
+static struct ofd_io *ofd_io_get(struct ofd_mem *m, ofdn_t i)
+{
+    if ( i < m->om_next ) {
+        struct ofd_io *r;
+
+        r = (struct ofd_io *)&m->om_mem[i];
+        if ( r->oi_ima == IO_PAT ) {
+            return r;
+        }
+        assert(r->oi_ima == IO_PAT); /* bad object */
+    }
+
+    return NULL;
+}
+
+ofdn_t ofd_node_io(void *mem, ofdn_t n)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    struct ofd_node *r = ofd_node_get(m, n);
+
+    if (r == NULL) return 0;
+    return r->on_io;
+}
+
+uint ofd_io_open(void *mem, ofdn_t n)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    struct ofd_io *r = ofd_io_get(m, n);
+
+    if (r == NULL) return 0;
+    return r->oi_open;
+}
+
+void ofd_io_close(void *mem, ofdn_t n)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    struct ofd_io *o = ofd_io_get(m, n);
+    struct ofd_node *r = ofd_node_get(m, o->oi_node);
+
+    assert(o != NULL);
+    assert(r != NULL);
+    o->oi_open = 0;
+    r->on_io = 0;
+}
+
+ofdn_t ofd_node_add(void *m, ofdn_t p, const char *path, size_t sz)
+{
+    ofdn_t n;
+
+    n = ofd_node_child(m, p);
+    if ( n > 0 ) {
+        n = ofd_node_peer_last(m, n);
+        if ( n > 0 ) {
+            n = ofd_node_peer_create(m, n, path, sz);
+        }
+    } else {
+        n = ofd_node_child_create(m, p, path, sz);
+    }
+
+    return n;
+}
+
+ofdn_t ofd_prop_add(
+    void *mem,
+    ofdn_t n,
+    const char *name,
+    const void *buf,
+    size_t sz)
+{
+    struct ofd_mem *m = (struct ofd_mem *)mem;
+    ofdn_t r;
+
+    r = ofd_prop_find(m, n, name);
+    if ( r == 0 ) {
+        r = ofd_prop_create(mem, n, name, buf, sz);
+    } else {
+        r = ofd_prop_set(mem, n, name, buf, sz);
+    }
+
+    return r;
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/of-devtree.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/of-devtree.h     Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,139 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#ifndef _OF_DEVTREE_H
+#define _OF_DEVTREE_H
+
+#include <xen/types.h>
+#include <public/xen.h>
+
+enum {
+    OF_FAILURE = -1,
+    OF_SUCCESS = 0,
+};
+
+union of_pci_hi {
+    u32 word;
+    struct {
+        u32    opa_n: 1; /* relocatable */
+        u32    opa_p: 1; /* prefetchable */
+        u32    opa_t: 1; /* aliased */
+        u32 _opa_res: 3;
+        u32    opa: 2; /* space code */
+        u32  opa_b: 8; /* bus number */
+        u32    opa_d: 5; /* device number */
+        u32    opa_f: 3; /* function number */
+        u32    opa_r: 8; /* register number */
+    } bits;
+};
+
+struct of_pci_addr {
+    union of_pci_hi opa_hi;
+    u32 opa_mid;
+    u32 opa_lo;
+};
+
+struct of_pci_range32 {
+    struct of_pci_addr opr_addr;
+    u32 opr_phys;
+    u32 opr_size;
+};
+
+struct of_pci_range64 {
+    struct of_pci_addr opr_addr;
+    u32 opr_phys_hi;
+    u32 opr_phys_lo;
+    u32 opr_size_hi;
+    u32 opr_size_lo;
+};
+
+struct of_pci_addr_range64 {
+    struct of_pci_addr opr_addr;
+    u32 opr_size_hi;
+    u32 opr_size_lo;
+};
+
+struct reg_property32 {
+    u32 address;
+    u32 size;
+};
+
+typedef s32 ofdn_t;
+
+#define OFD_ROOT 1
+#define OFD_DUMP_NAMES 0x1
+#define OFD_DUMP_VALUES        0x2
+#define OFD_DUMP_ALL   (OFD_DUMP_VALUES|OFD_DUMP_NAMES)
+
+extern void *ofd_create(void *mem, size_t sz);
+extern ofdn_t ofd_node_parent(void *mem, ofdn_t n);
+extern ofdn_t ofd_node_peer(void *mem, ofdn_t n);
+extern ofdn_t ofd_node_child(void *mem, ofdn_t p);
+extern const char *ofd_node_path(void *mem, ofdn_t p);
+extern int ofd_node_to_path(void *mem, ofdn_t p, void *buf, size_t sz);
+extern ofdn_t ofd_node_child_create(void *mem, ofdn_t parent,
+                                   const char *path, size_t pathlen);
+extern ofdn_t ofd_node_peer_create(void *mem, ofdn_t sibling,
+                                  const char *path, size_t pathlen);
+extern ofdn_t ofd_node_find(void *mem, const char *devspec);
+extern ofdn_t ofd_node_add(void *m, ofdn_t n, const char *path, size_t sz);
+extern int ofd_node_prune(void *m, ofdn_t n);
+extern int ofd_prune_path(void *m, const char *path);
+extern ofdn_t ofd_node_io(void *mem, ofdn_t n);
+
+extern ofdn_t ofd_nextprop(void *mem, ofdn_t n, const char *prev, char *name);
+extern ofdn_t ofd_prop_find(void *mem, ofdn_t n, const char *name);
+extern int ofd_getprop(void *mem, ofdn_t n, const char *name,
+                       void *buf, size_t sz);
+extern int ofd_getproplen(void *mem, ofdn_t n, const char *name);
+
+extern int ofd_setprop(void *mem, ofdn_t n, const char *name,
+                       const void *buf, size_t sz);
+extern void ofd_prop_remove(void *mem, ofdn_t node, ofdn_t prop);
+extern ofdn_t ofd_prop_add(void *mem, ofdn_t n, const char *name,
+                          const void *buf, size_t sz);
+extern ofdn_t ofd_io_create(void *m, ofdn_t node, u64 open);
+extern u32 ofd_io_open(void *mem, ofdn_t n);
+extern void ofd_io_close(void *mem, ofdn_t n);
+
+
+typedef void (*walk_fn)(void *m, ofdn_t p, int arg);
+extern void ofd_dump_props(void *m, ofdn_t p, int dump);
+
+extern void ofd_walk(void *m, ofdn_t p, walk_fn fn, int arg);
+
+
+/* Recursively look up #address_cells and #size_cells properties */
+extern int ofd_getcells(void *mem, ofdn_t n,
+                        u32 *addr_cells, u32 *size_cells);
+
+extern size_t ofd_size(void *mem);
+extern size_t ofd_space(void *mem);
+
+extern void ofd_prop_print(const char *head, const char *path,
+                          const char *name, const char *prop, size_t sz);
+
+extern ofdn_t ofd_node_find_by_prop(void *mem, ofdn_t n, const char *name,
+                                   const void *val, size_t sz);
+extern ofdn_t ofd_node_find_next(void *mem, ofdn_t n);
+extern ofdn_t ofd_node_find_prev(void *mem, ofdn_t n);
+extern void ofd_init(int (*write)(const char *, size_t len));
+
+#endif /* _OF_DEVTREE_H */
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/of-devwalk.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/of-devwalk.c     Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,135 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/ctype.h>
+#include <xen/kernel.h>
+#include "of-devtree.h"
+
+void ofd_prop_print(
+    const char *head,
+    const char *path,
+    const char *name,
+    const char *prop,
+    size_t sz)
+{
+    if ( path[0] == '/' && path[1] == '\0' ) {
+        path = "";
+    }
+    printf("%s: %s/%s: 0x%lx\n", head, path,  name, sz);
+
+#define DEBUG_PROP
+#ifdef DEBUG_PROP
+    int i;
+    int isstr = sz;
+    const char *b = prop;
+
+    for ( i = 0; i < sz; i++ ) {
+        /* see if there is any non printable characters */
+        if ( !isprint(b[i]) ) {
+            /* not printable */
+            if (b[i] != '\0' || (i + 1) != sz) {
+                /* not the end of string */
+                isstr = 0;
+                break;
+            }
+        }
+    }
+
+    if ( isstr > 0 ) {
+        printf("%s: \t%s\n", head, b);
+    } else if ( sz != 0 ) {
+        printf("%s: \t0x", head);
+
+        for ( i = 0; i < sz; i++ ) {
+            if ( (i % 4) == 0 && i != 0 ) {
+                if ( (i % 16) == 0 && i != 0 ) {
+                    printf("\n%s: \t0x", head);
+                } else {
+                    printf(" 0x");
+                }
+            }
+            if (b[i] < 0x10) {
+                printf("0");
+            }
+            printf("%x", b[i]);
+        }
+        printf("\n");
+    }
+#else
+    (void)prop;
+#endif
+}
+
+void ofd_dump_props(void *mem, ofdn_t n, int dump)
+{
+    ofdn_t p;
+    char name[128];
+    char prop[256] __attribute__ ((aligned (__alignof__ (u64))));
+    int sz;
+    const char *path;
+
+    if ( n == OFD_ROOT ) {
+        path = "";
+    } else {
+        path = ofd_node_path(mem, n);
+    }
+
+    if (dump & OFD_DUMP_NAMES) {
+        printf("of_walk: %s: phandle 0x%x\n", path, n);
+    }
+
+    p = ofd_nextprop(mem, n, NULL, name);
+    while ( p > 0 ) {
+        sz = ofd_getprop(mem, n, name, prop, sizeof (prop));
+        if ( sz > 0 && sz > sizeof (prop) ) {
+            sz = sizeof (prop);
+        }
+
+        if ( dump & OFD_DUMP_VALUES ) {
+            ofd_prop_print("of_walk", path, name, prop, sz);
+        }
+
+        p = ofd_nextprop(mem, n, name, name);
+    }
+}
+
+void ofd_walk(void *m, ofdn_t p, walk_fn fn, int arg)
+{
+    ofdn_t n;
+
+    if ( fn != NULL ) {
+        (*fn)(m, p, arg);
+    }
+
+    /* child */
+    n = ofd_node_child(m, p);
+    if ( n != 0 ) {
+        ofd_walk(m, n, fn, arg);
+    }
+
+    /* peer */
+    n = ofd_node_peer(m, p);
+    if ( n != 0 ) {
+        ofd_walk(m, n, fn, arg);
+    }
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/of_handler/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/of_handler/Makefile      Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,31 @@
+#
+# Build the Open Firmware handler
+#
+
+CFLAGS += -I..
+
+# head.o must be first
+obj-y = head.o
+obj-y += console.o
+obj-y += control.o
+obj-y += cpu.o
+obj-y += devtree.o
+obj-y += head.o
+obj-y += io.o
+obj-y += leap.o
+obj-y += memory.o
+obj-y += ofh.o
+obj-y += papr.o
+obj-y += services.o
+obj-y += vdevice.o
+obj-y += xencomm.o
+obj-y += xen_hvcall.o
+
+obj-y += memcmp.o
+obj-y += memset.o
+obj-y += snprintf.o
+obj-y += strcmp.o
+obj-y += strlen.o
+obj-y += strncmp.o
+obj-y += strncpy.o
+obj-y += strnlen.o
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/of_handler/console.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/of_handler/console.c     Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,233 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include "ofh.h"
+#include "papr.h"
+#include <xen/string.h>
+#include <asm/system.h>
+
+union chpack {
+    u64 oct[2];
+    u32 quad[4];
+    char c[16];
+};
+
+/* used for internal printing */
+static struct ofh_ihandle *ofh_ihp;
+
+static s32 ofh_papr_read(s32 chan, void *buf, u32 count, s32 *actual, ulong b)
+{
+    s32 rc;
+    ulong ret[5];
+    ulong sz = 0;
+
+    rc = papr_get_term_char(ret, chan);
+    if (rc == H_Success && ret[0] > 0) {
+        sz = MIN(count, ret[0]);
+        memcpy(buf, &ret[1], sz);
+    }
+    *actual = sz;
+    return OF_SUCCESS;
+}
+
+static s32 ofh_papr_write(s32 chan, const void *buf, u32 count, s32 *actual,
+                          ulong b)
+{
+    const char *str = (const char *)buf;
+    u32 i;
+    union chpack ch;
+    s32 ret;
+
+    for (i = 0; i < count; i++) {
+        int m = i % sizeof(ch);
+        ch.c[m] = str[i];
+        if (m == sizeof(ch) - 1 || i == count - 1) {
+            for (;;) {
+                if (sizeof (ulong) == sizeof (u64)) {
+                    ret = papr_put_term_char(NULL,
+                                             chan,
+                                             m + 1,
+                                             ch.oct[0],
+                                             ch.oct[1]);
+                } else {
+                    ret = papr_put_term_char(NULL,
+                                             chan,
+                                             m + 1,
+                                             ch.quad[0],
+                                             ch.quad[1],
+                                             ch.quad[2],
+                                             ch.quad[3]);
+                }
+                if (ret != H_Busy) {
+                    break;
+                }
+                /* yielding here would be nice */
+            }
+            if (ret != H_Success) {
+                return -1;
+            }
+        }
+    }
+    *actual = count;
+    if (*actual == -1) {
+        return OF_FAILURE;
+    }
+    return OF_SUCCESS;
+}
+
+#define __HYPERVISOR_console_io 18
+#define CONSOLEIO_write         0
+#define CONSOLEIO_read          1
+#define XEN_MARK(a) ((a) | (~0UL << 16))
+extern long xen_hvcall(ulong code, ...);
+
+#define XENCOMM_MINI_AREA (sizeof(struct xencomm_mini) * 2)
+static s32 ofh_xen_dom0_read(s32 chan, void *buf, u32 count, s32 *actual,
+                             ulong b)
+{
+    char __storage[XENCOMM_MINI_AREA];
+    struct xencomm_desc *desc;
+    s32 rc;
+    char *s = buf;
+    s32 ret = 0;
+
+    while (count > 0) {
+        if (xencomm_create_mini(__storage, XENCOMM_MINI_AREA, s, count, &desc))
+            return ret;
+
+        rc = xen_hvcall(XEN_MARK(__HYPERVISOR_console_io), CONSOLEIO_read,
+                count, desc);
+        if (rc <= 0) {
+            return ret;
+        }
+        count -= rc;
+        s += rc;
+        ret += rc;
+    }
+    *actual = ret;
+    return OF_SUCCESS;
+}
+
+static s32 ofh_xen_dom0_write(s32 chan, const void *buf, u32 count,
+                              s32 *actual, ulong b)
+{
+    char __storage[XENCOMM_MINI_AREA];
+    struct xencomm_desc *desc;
+    s32 rc;
+    char *s = (char *)buf;
+    s32 ret = 0;
+
+    while (count > 0) {
+        if (xencomm_create_mini(__storage, XENCOMM_MINI_AREA, s, count, &desc))
+            return ret;
+
+        rc = xen_hvcall(XEN_MARK(__HYPERVISOR_console_io), CONSOLEIO_write,
+                count, desc);
+        if (rc <= 0) {
+            return ret;
+        }
+        count -= rc;
+        s += rc;
+        ret += rc;
+    }
+    *actual = ret;
+    if (*actual == -1) {
+        return OF_FAILURE;
+    }
+    return OF_SUCCESS;
+}
+
+static s32 ofh_xen_domu_read(s32 chan, void *buf, u32 count, s32 *actual,
+                             ulong b)
+{
+       struct xencons_interface *intf;
+       XENCONS_RING_IDX cons, prod;
+    s32 ret;
+
+    intf = DRELA(ofh_ihp, b)->ofi_intf;
+    cons = intf->in_cons;
+    prod = intf->in_prod;
+    mb();
+
+    ret = prod - cons;
+
+    if (ret > 0) {
+        ret = (ret < count) ? ret : count;
+        memcpy(buf, intf->in+MASK_XENCONS_IDX(cons,intf->in), ret);
+    }
+
+    *actual = (ret < 0) ? 0 : ret;
+    return OF_SUCCESS;
+}
+
+static s32 ofh_xen_domu_write(s32 chan, const void *buf, u32 count,
+                              s32 *actual, ulong b)
+{
+       struct xencons_interface *intf;
+       XENCONS_RING_IDX cons, prod;
+    s32 ret;
+
+    intf = DRELA(ofh_ihp, b)->ofi_intf;
+    cons = intf->in_cons;
+    prod = intf->in_prod;
+    mb();
+
+    ret = prod - cons;
+    /* FIXME: Do we have to write the whole thing or are partial writes ok? */
+    if (ret > 0) {
+        ret = (ret < count) ? ret : count;
+        memcpy(intf->in+MASK_XENCONS_IDX(cons,intf->in), buf, ret);
+    }
+
+    *actual = (ret < 0) ? 0 : ret;
+    return OF_SUCCESS;
+}
+
+/* for emergency printing in the OFH */
+s32 ofh_cons_write(const void *buf, u32 count, s32 *actual)
+{
+    ulong b = get_base();
+    struct ofh_ihandle *ihp = DRELA(ofh_ihp, b);
+
+    return ihp->ofi_write(ihp->ofi_chan, buf, count, actual, b);
+}
+
+s32 ofh_cons_close(void)
+{
+    return OF_SUCCESS;
+}
+
+void
+ofh_cons_init(struct ofh_ihandle *ihp, ulong b)
+{
+    if (ihp->ofi_chan == OFH_CONS_XEN) {
+        if (ihp->ofi_intf == NULL) {
+            ihp->ofi_write = ofh_xen_dom0_write;
+            ihp->ofi_read = ofh_xen_dom0_read;
+        } else {
+            ihp->ofi_write = ofh_xen_domu_write;
+            ihp->ofi_read = ofh_xen_domu_read;
+        }
+    } else {
+        ihp->ofi_write = ofh_papr_write;
+        ihp->ofi_read = ofh_papr_read;
+    }
+    *DRELA(&ofh_ihp, b) = ihp;
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/of_handler/control.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/of_handler/control.c     Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,90 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include "ofh.h"
+
+s32
+ofh_boot(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    b=b;
+    nargs = nargs;
+    nrets = nrets;
+    argp = argp;
+    retp = retp;
+    return OF_FAILURE;
+}
+
+s32
+ofh_enter(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    b=b;
+    nargs = nargs;
+    nrets = nrets;
+    argp = argp;
+    retp = retp;
+    return OF_FAILURE;
+}
+
+s32
+ofh_exit(u32 nargs __attribute__ ((unused)),
+        u32 nrets  __attribute__ ((unused)),
+        s32 argp[]  __attribute__ ((unused)),
+        s32 retp[] __attribute__ ((unused)),
+        ulong b)
+{
+    static const char msg[] = "OFH: exit method called\n";
+    s32 dummy;
+
+    ofh_cons_write(DRELA(&msg[0], b), sizeof (msg), &dummy);
+
+    for (;;) {
+        /* kill domain here */
+    }
+    return OF_FAILURE;
+}
+
+s32
+ofh_chain(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    b=b;
+    nargs = nargs;
+    nrets = nrets;
+    argp = argp;
+    retp = retp;
+    return OF_FAILURE;
+}
+
+s32
+ofh_quiesce(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    if (nargs == 0) {
+        if (nrets == 0) {
+            void *mem = ofd_mem(b);
+            (void)nargs;
+            (void)nrets;
+            (void)argp;
+            (void)retp;
+            (void)mem;
+
+            return OF_SUCCESS;
+        }
+    }
+    return OF_FAILURE;
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/of_handler/cpu.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/of_handler/cpu.c Fri Jul 14 10:47:50 2006 +0100
@@ -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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include "ofh.h"
+
+s32
+ofh_start_cpu(u32 nargs, u32 nrets, s32 argp[],
+        s32 retp[] __attribute__ ((unused)),
+        ulong b __attribute__ ((unused)))
+{
+    if (nargs == 3) {
+        if (nrets == 0) {
+            ofdn_t ph = argp[0];
+            u32 pc = argp[1];
+            u32 arg = argp[2];
+
+            (void)ph; (void)pc; (void)arg;
+            return OF_FAILURE;
+        }
+    }
+    return OF_FAILURE;
+}
+
+s32
+ofh_stop_self(u32 nargs, u32 nrets,
+        s32 argp[] __attribute__ ((unused)),
+        s32 retp[] __attribute__ ((unused)),
+        ulong b __attribute__ ((unused)))
+{
+    if (nargs == 0) {
+        if (nrets == 0) {
+            return OF_FAILURE;
+        }
+    }
+    return OF_FAILURE;
+}
+
+s32
+ofh_idle_self(u32 nargs, u32 nrets,
+        s32 argp[] __attribute__ ((unused)),
+        s32 retp[] __attribute__ ((unused)),
+        ulong b __attribute__ ((unused)))
+{
+    if (nargs == 0) {
+        if (nrets == 0) {
+            return OF_FAILURE;
+        }
+    }
+    return OF_FAILURE;
+}
+s32
+ofh_resume_cpu(u32 nargs, u32 nrets, s32 argp[],
+        s32 retp[] __attribute__ ((unused)),
+        ulong b __attribute__ ((unused)))
+{
+    if (nargs == 1) {
+        if (nrets == 0) {
+            ofdn_t ph = argp[0];
+
+            (void)ph;
+            return OF_FAILURE;
+        }
+    }
+    return OF_FAILURE;
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/of_handler/devtree.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/of_handler/devtree.c     Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,266 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include "ofh.h"
+#include <of-devtree.h> 
+
+s32
+ofh_peer(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    if (nargs == 1) {
+        if (nrets == 1) {
+            ofdn_t ph = argp[0];
+            s32 *sib_ph = &retp[0];
+            void *mem = ofd_mem(b);
+
+            *sib_ph = ofd_node_peer(mem, ph);
+            return OF_SUCCESS;
+        }
+    }
+    return OF_FAILURE;
+}
+
+s32
+ofh_child(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    if (nargs == 1) {
+        if (nrets == 1) {
+            ofdn_t ph = argp[0];
+            s32 *ch_ph = &retp[0];
+            void *mem = ofd_mem(b);
+
+            *ch_ph = ofd_node_child(mem, ph);
+            return OF_SUCCESS;
+        }
+    }
+    return OF_FAILURE;
+}
+
+s32
+ofh_parent(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    if (nargs == 1) {
+        if (nrets == 1) {
+            ofdn_t ph = argp[0];
+            s32 *parent_ph = &retp[0];
+            void *mem = ofd_mem(b);
+
+            *parent_ph = ofd_node_parent(mem, ph);
+            return OF_SUCCESS;
+        }
+    }
+    return OF_FAILURE;
+}
+
+s32
+ofh_instance_to_package(u32 nargs, u32 nrets, s32 argp[], s32 retp[],
+        ulong b __attribute__ ((unused)))
+{
+    if (nargs == 1) {
+        if (nrets == 1) {
+            struct ofh_ihandle *ih =
+                (struct ofh_ihandle *)(ulong)argp[0];
+            s32 *p = &retp[0];
+
+            *p = (s32)ih->ofi_node;
+            return OF_SUCCESS;
+        }
+    }
+    return OF_FAILURE;
+}
+
+s32
+ofh_getproplen(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    if (nargs == 2) {
+        if (nrets == 1) {
+            ofdn_t ph = argp[0];
+            const char *name = (const char *)(ulong)argp[1];
+            s32 *size = &retp[0];
+            void *mem = ofd_mem(b);
+
+            *size = ofd_getproplen(mem, ph, name);
+            if (*size >= 0) {
+                return OF_SUCCESS;
+            }
+        }
+    }
+    return OF_FAILURE;
+}
+
+s32
+ofh_getprop(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    if (nargs == 4) {
+        if (nrets == 1) {
+            ofdn_t ph = argp[0];
+            const char *name = (const char *)(ulong)argp[1];
+            void *buf = (void *)(ulong)argp[2];
+            ulong buflen = argp[3];
+            s32 *size = &retp[0];
+            void *mem = ofd_mem(b);
+
+            *size = ofd_getprop(mem, ph, name, buf, buflen);
+            if (*size > 0) {
+                return OF_SUCCESS;
+            }
+        }
+    }
+    return OF_FAILURE;
+}
+
+s32
+ofh_nextprop(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    if (nargs == 3) {
+        if (nrets == 1) {
+            ofdn_t ph = argp[0];
+            const char *prev = (const char *)(ulong)argp[1];
+            char *name = (char *)(ulong)argp[2];
+            s32 *flag = &retp[0];
+            void *mem = ofd_mem(b);
+
+            *flag = ofd_nextprop(mem, ph, prev, name);
+            if (*flag > 0) {
+                *flag = 1;
+            }
+            return OF_SUCCESS;
+        }
+    }
+    return OF_FAILURE;
+}
+
+s32
+ofh_setprop(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    if (nargs == 4) {
+        if (nrets == 1) {
+            ofdn_t ph = argp[0];
+            const char *name = (const char *)(ulong)argp[1];
+            const void *buf = (void *)(ulong)argp[2];
+            ulong buflen = argp[3];
+            s32 *size = &retp[0];
+            void *mem = ofd_mem(b);
+
+            *size = ofd_setprop(mem, ph, name, buf, buflen);
+            return OF_SUCCESS;
+        }
+    }
+    return OF_FAILURE;
+}
+
+s32
+ofh_canon(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    if (nargs == 3) {
+        if (nrets == 1) {
+            const char *dev_spec = (const char *)(ulong)argp[0];
+            char *buf = (char *)(ulong)argp[1];
+            u32 sz = argp[2];
+            s32 *len = &retp[0];
+            void *mem = ofd_mem(b);
+            ofdn_t ph;
+
+            ph = ofd_node_find(mem, dev_spec);
+            if (ph > 0) {
+                *len = ofd_node_to_path(mem, ph, buf, sz);
+                return OF_SUCCESS;
+            }
+        }
+    }
+    return OF_FAILURE;
+}
+
+s32 ofh_active_package = -1;
+
+s32
+ofh_finddevice(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    if (nargs == 1) {
+        if (nrets == 1) {
+            s32 *ap = DRELA(&ofh_active_package, b);
+            const char *devspec = (const char *)(ulong)argp[0];
+            s32 *ph = &retp[0];
+            void *mem = ofd_mem(b);
+
+            /* good enuff */
+            if (devspec[0] == '\0') {
+                if (*ap == -1) {
+                    return OF_FAILURE;
+                }
+                *ph = *ap;
+            } else {
+                *ph = ofd_node_find(mem, devspec);
+                if (*ph <= 0) {
+                    return OF_FAILURE;
+                }
+            }
+            *ap = *ph;
+            return OF_SUCCESS;
+        }
+    }
+    return OF_FAILURE;
+}
+
+s32
+ofh_instance_to_path(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    if (nargs == 3) {
+        if (nrets == 1) {
+            struct ofh_ihandle *ih =
+                (struct ofh_ihandle *)((ulong)argp[0]);
+            char *buf = (char *)(ulong)argp[1];
+            u32 sz = argp[2];
+            s32 *len = &retp[0];
+            ofdn_t ph;
+            void *mem = ofd_mem(b);
+
+            ph = ih->ofi_node;
+            if (ph > 0) {
+                *len = ofd_node_to_path(mem, ph, buf, sz);
+                return OF_SUCCESS;
+            }
+        }
+    }
+    return OF_FAILURE;
+}
+
+s32
+ofh_package_to_path(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    if (nargs == 3) {
+        if (nrets == 1) {
+            ofdn_t ph = argp[0];
+            char *buf = (char *)(ulong)argp[1];
+            u32 sz = argp[2];
+            s32 *len = &retp[0];
+            void *mem = ofd_mem(b);
+
+            if (ph > 0) {
+                *len = ofd_node_to_path(mem, ph, buf, sz);
+                return OF_SUCCESS;
+            }
+        }
+    }
+    return OF_FAILURE;
+}
+
+
+
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/of_handler/head.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/of_handler/head.S        Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,152 @@
+/*
+ * 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
+ */
+/*
+ * Glue code for open-firmware client interface implementation.
+ */
+
+#define OF_STACK_SIZE (32*1024)
+
+#include <asm/config.h>
+#include <asm/processor.h>
+
+#define SAVE_STACK     0
+#define SAVE_SRR0      1
+#define SAVE_SRR1      2
+#define SAVE_MSR       3
+#define SAVE_LR                4
+#define SAVE_TOC       5
+#define SAVE_BASE      6
+#define SAVE_BCHAIN    7  /* MUST be last */
+
+/* This code is NOT MP safe and does not need to be */
+       .p2align 3
+       . = 0x0
+_GLOBAL(ofh_start)             # make the linker happy
+_ofh_cih:
+       ## r3 holds the parameter.  All other volatiles are available.
+       mflr    r0
+       # Obtain address of _ofh_work_space via a branch-and-link
+       bl      _ofh_cih_continue
+_ofh_work_space:
+       nop
+
+       . = 0x10
+       .global _ofh_tree
+_ofh_tree:
+       .long 0xdeadbeef
+       .long 0x0
+
+       . = 0x18
+       .global _ofh_inited
+_ofh_inited:
+       .long 0x0       
+
+       . = 0x20
+       .global _ofh_lastarg
+_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
+
+       /* load base address in r4 */
+       LOADADDR(r4, _ofh_work_space)
+       sub     r4, r12, r4
+       
+
+       # save srr0/1
+       mfsrr0  r9
+       mfsrr1  r8
+       mfmsr   r7
+       LOADADDR(r5, _ofh_cih_64bit)
+       add     r5, r5, r4      # offset base
+       mtsrr0  r5
+       # r5 = MSR_SF
+       li      r5,-1
+       rldicr  r5,r5,0,0
+       or      r5,r5,r7
+       mtsrr1  r5
+       rfid
+       trap
+
+_ofh_cih_64bit:                
+       # move to local stack
+       lis     r1, (_ofh_cih_stack - _ofh_cih_stack_end) >> 16
+       ori     r1, r1, (_ofh_cih_stack - _ofh_cih_stack_end) & 0xffff
+       add     r1, r12, r1
+       # create an initial chain
+       li      r10, 0
+       # frame with 3 slots
+       stdu    r10, -(STACK_FRAME_OVERHEAD + (SAVE_BCHAIN * 8))(r1)
+       # preserve base
+       std     r4, (STACK_FRAME_OVERHEAD + (SAVE_BASE * 8))(r1)
+       # preserve orig stk ptr
+       std     r11, (STACK_FRAME_OVERHEAD + (SAVE_STACK * 8))(r1)
+       # preserve orig srr0
+       std     r9, (STACK_FRAME_OVERHEAD + (SAVE_SRR0 * 8))(r1)
+       # preserve orig srr1
+       std     r8, (STACK_FRAME_OVERHEAD + (SAVE_SRR1 * 8))(r1)
+       # preserve orig msr
+       std     r7, (STACK_FRAME_OVERHEAD + (SAVE_MSR * 8))(r1)
+       # preserve orig lr
+       std     r0,  (STACK_FRAME_OVERHEAD + (SAVE_LR * 8))(r1)
+       # preserve orig toc
+       std     r2,  (STACK_FRAME_OVERHEAD + (SAVE_TOC * 8))(r1)
+
+       LOADADDR(r2, ofh_start) # get the address of any function
+       add     r2, r2, r4      # add the base
+       ld      r2, 8(r2)       # get the TOC for that funtion
+       add     r2, r2, r4      # add the base
+
+       bl      _ENTRY(ofh_handler)                     # call handler
+
+       ld      r4, (STACK_FRAME_OVERHEAD + (SAVE_BASE * 8))(r1)
+       ld      r9, (STACK_FRAME_OVERHEAD + (SAVE_SRR0 * 8))(r1)
+       ld      r8, (STACK_FRAME_OVERHEAD + (SAVE_SRR1 * 8))(r1)
+       ld      r7, (STACK_FRAME_OVERHEAD + (SAVE_MSR * 8))(r1)
+       ld      r2, (STACK_FRAME_OVERHEAD + (SAVE_TOC * 8))(r1)
+       ld      r0, (STACK_FRAME_OVERHEAD + (SAVE_LR * 8))(r1)
+       ld      r1, (STACK_FRAME_OVERHEAD + (SAVE_STACK * 8))(r1)
+
+       LOADADDR(r5, _ofh_cih_orig_msr)
+       add     r5, r5, r4
+       mtsrr0 r5
+       mtsrr1 r7
+       rfid
+       
+_ofh_cih_orig_msr:
+       mtsrr0  r9
+       mtsrr1  r8
+       mtlr    r0
+       blr
+
+_GLOBAL(get_base)
+       mflr    r0
+       bl      1f
+1:     mflr    r5
+       LOADADDR(r4,1b)
+       subf    r3,r4,r5
+       mtlr    r0
+       blr
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/of_handler/io.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/of_handler/io.c  Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,160 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include "ofh.h"
+#include "xen/lib.h"
+
+s32
+ofh_open(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    if (nargs == 1) {
+        if (nrets == 1) {
+            const char *devspec = (const char *)(ulong)argp[0];
+            s32 *ih = &retp[0];
+            ofdn_t p;
+            void *mem = ofd_mem(b);
+
+            p = ofd_node_find(mem, devspec);
+            if (p > 0) {
+                ofdn_t io;
+                io = ofd_node_io(mem, p);
+                if (io > 0) {
+                    void *f = (void *)(ulong)ofd_io_open(mem, io);
+                    if (f != 0) {
+                        *ih = leap(b, 0, NULL, NULL,
+                                   b, f);
+                        return OF_SUCCESS;
+                    }
+                }
+            }
+            *ih = 0;
+        }
+    }
+    return OF_FAILURE;
+}
+
+s32
+ofh_close(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    if (nargs == 1) {
+        if (nrets == 0) {
+            argp = argp;
+            retp = retp;
+            b = b;
+            return  OF_FAILURE;
+        }
+    }
+    return OF_FAILURE;
+}
+s32
+ofh_read(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    if (nargs == 3) {
+        if (nrets == 1) {
+            struct ofh_ihandle *ih =
+                (struct ofh_ihandle *)(ulong)argp[0];
+
+            if (ih->ofi_read != NULL) {
+                void *addr = (void *)(ulong)argp[1];
+                u32 sz = argp[2];
+                s32 *actual = &retp[0];
+                void *f = ih->ofi_read;
+
+                if (f != 0) {
+                    return io_leap(ih->ofi_chan, addr, sz, actual,
+                                b, f);
+                }
+            }
+        }
+    }
+    return OF_FAILURE;
+}
+
+s32
+ofh_write(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    if (nargs == 3) {
+        if (nrets == 1) {
+            struct ofh_ihandle *ih =
+                (struct ofh_ihandle *)(ulong)argp[0];
+
+            if (ih->ofi_write != NULL) {
+                void *addr = (void *)(ulong)argp[1];
+                u32 sz = argp[2];
+                s32 *actual = &retp[0];
+                void *f = ih->ofi_write;
+
+                if (f != 0) {
+                    return io_leap(ih->ofi_chan, addr, sz, actual,
+                                b, f);
+                }
+            }
+        }
+    }
+    return OF_FAILURE;
+}
+
+s32
+ofh_seek(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    b=b;
+    nargs = nargs;
+    nrets = nrets;
+    argp = argp;
+    retp = retp;
+    return OF_FAILURE;
+}
+
+static ofh_func_t *
+method_lookup(struct ofh_ihandle *ih, const char *name, ulong b)
+{
+    struct ofh_methods *m = DRELA(ih->ofi_methods, b);
+
+    while (m != NULL && m->ofm_name != NULL ) {
+        if (strcmp(name, DRELA(m->ofm_name, b)) == 0) {
+            return m->ofm_method;
+        }
+    }
+    return NULL;
+}
+
+
+s32
+ofh_call_method(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    if (nargs > 2) {
+        if (nrets > 1) {
+            const char *method = (const char *)(ulong)argp[0];
+            struct ofh_ihandle *ih =
+                (struct ofh_ihandle *)(ulong)argp[1];
+            ofh_func_t *f;
+
+            f = method_lookup(ih, method, b);
+            if (f != NULL) {
+                /* set catch methods return 0 on success */
+                retp[0] = leap(nargs - 2, nrets - 1,
+                               &argp[2], &retp[1], b, f);
+                return OF_SUCCESS;
+            }
+        }
+    }
+    return OF_FAILURE;
+}
+
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/of_handler/leap.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/of_handler/leap.S        Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,38 @@
+/*
+ * 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
+ */
+#include <asm/config.h>
+#include <asm/processor.h>
+
+/* 
+ * sval
+ * rh_leap(uval nargs, uval nrets, uval args[], uval rets[], uval ba,
+ *              rh_func_t f)
+ *    We need to deal with f actually bein a function descriptor, we can
+ *    assume that TOC is correct.
+ */    
+
+       
+_GLOBAL(io_leap)       
+_GLOBAL(leap)
+       ## r8 contains the base address for everyone
+       add     r8,r8,r7        # add
+       ld      r8, 0(r8)       # get the entry point
+       add     r8,r8,r7        # add
+       mtctr   r8              #     and
+       bctr                    #         leap
+       /* never get here */
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/of_handler/memcmp.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/of_handler/memcmp.c      Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,39 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <xen/string.h>
+
+int
+memcmp(const void *v1, const void *v2, size_t n)
+{
+    const char *s1 = (const char *)v1;
+    const char *s2 = (const char *)v2;
+
+    while (n > 0) {
+        if (*s1 != *s2) {
+            return (*s1 - *s2);
+        }
+        /* advance pointers to next character */
+        ++s1;
+        ++s2;
+        --n;
+    }
+    return 0;
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/of_handler/memory.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/of_handler/memory.c      Fri Jul 14 10:47:50 2006 +0100
@@ -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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include "ofh.h"
+
+struct of_malloc_s {
+    u32 ofm_start;
+    u32 ofm_end;
+};
+static struct of_malloc_s claimed[64];
+
+static s32
+claim(ulong b, u32 virt, u32 size, u32 align, s32 *baseaddr)
+{
+    struct of_malloc_s *cp;
+    u32 i;
+    s32 e;
+    u32 end;
+
+    if (align != 0) {
+        /* we don't do this now */
+        return OF_FAILURE;
+    }
+
+    end = virt + size;
+
+    /* you cannot claim OF's own space */
+    if (virt >= (u32)ofh_start && end < (u32)_end) {
+        return OF_FAILURE;
+    }
+
+    cp = DRELA(&claimed[0], b);
+    /* don't care about speed at the moment */
+    e = -1;
+    for (i = 0; i < sizeof (claimed)/sizeof (claimed[0]); i++) {
+        if (cp[i].ofm_end == 0) {
+            if (e == -1) {
+                e = i;
+            }
+            continue;
+        }
+        if (virt >= cp[i].ofm_start && virt < cp[i].ofm_end) {
+            return OF_FAILURE;
+        }
+        if (end >= cp[i].ofm_start && end < cp[i].ofm_end) {
+            return OF_FAILURE;
+        }
+    }
+    /* e points to the first empty */
+    cp[e].ofm_start = virt;
+    cp[e].ofm_end = end;
+    *baseaddr = virt;
+    return OF_SUCCESS;
+}
+
+s32
+ofh_claim(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    if (nargs == 3) {
+        if (nrets == 1) {
+            u32 virt = argp[0];
+            u32 size = argp[1];
+            u32 align = argp[2];
+            s32 *baseaddr = &retp[0];
+
+            return claim(b, virt, size, align, baseaddr);
+        }
+    }
+    return OF_FAILURE;
+}
+
+static s32
+release(ulong b, u32 virt, u32 size)
+{
+    struct of_malloc_s *cp;
+    u32 i;
+    u32 end;
+
+    end = virt + size;
+
+    /* you cannot release OF's own space */
+    if (virt >= (u32)ofh_start && end < (u32)_end) {
+        return OF_FAILURE;
+    }
+
+    cp = DRELA(&claimed[0], b);
+    /* don't care about speed at the moment */
+    for (i = 0; i < sizeof (claimed)/sizeof (claimed[0]); i++) {
+        if (virt == cp[i].ofm_start && end == cp[i].ofm_end) {
+            cp[i].ofm_start = 0;
+            cp[i].ofm_end = 0;
+            return OF_SUCCESS;
+        }
+    }
+    return OF_FAILURE;
+}
+
+s32
+ofh_release(u32 nargs, u32 nrets, s32 argp[],
+        s32 retp[] __attribute__ ((unused)),
+        ulong b)
+{
+    if (nargs == 2) {
+        if (nrets == 0) {
+            u32 virt = argp[0];
+            u32 size = argp[1];
+
+            return release(b, virt, size);
+        }
+    }
+    return OF_FAILURE;
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/of_handler/memset.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/of_handler/memset.c      Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,67 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <xen/string.h>
+
+void *
+memset(void *s, int c, size_t n)
+{
+    uint8_t *ss = (uint8_t *)s;
+
+    if (n == 0) {
+        return s;
+    }
+
+    /* yes, I pulled the 2 out of this air */
+    if (n >= (2 * sizeof (ulong))) {
+        ulong val = 0;
+        ulong i;
+
+        /* construct val assignment from c */
+        if (c != 0) {
+            for (i = 0; i < sizeof (ulong); i++) {
+                val = (val << 8) | c;
+            }
+        }
+
+        /* do by character until aligned */
+        while (((ulong)ss & (sizeof (ulong) - 1)) > 0) {
+            *ss = c;
+            ++ss;
+            --n;
+        }
+
+        /* now do the aligned stores */
+        while (n >= sizeof (ulong)) {
+            *(ulong *)ss = val;
+            ss += sizeof (ulong);
+            n -= sizeof (ulong);
+        }
+    }
+    /* do that last unaligned bit */
+    while (n > 0) {
+        *ss = c;
+        ++ss;
+        --n;
+
+    }          
+
+    return s;
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/of_handler/ofh.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/of_handler/ofh.c Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,454 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include "ofh.h"
+#include <stdarg.h>
+#include <xen/lib.h>
+
+/*
+ * 6.3.1 Access to the client interface functions
+ * This is the spec'd maximum
+ */
+#define PFW_MAXSRVCLEN 31
+
+static u32 ofh_maxsrvclen;
+
+extern s32 debug(const char *fmt, ...);
+
+s32 debug(const char *fmt, ...)
+{
+    s32 sz;
+    va_list ap;
+    char buf[512];
+    va_start(ap, fmt);
+    sz = vsnprintf(buf, 512, fmt, ap);
+    va_end(ap);
+    ofh_cons_write(buf, sz, &sz);
+
+    return sz;
+}
+
+
+
+void
+assprint(const char *expr, const char *file, int line, const char *fmt, ...)
+{
+    char a[15];
+
+    a[0]  = '\n';
+    a[1]  = '\n';
+    a[2]  = 'O';
+    a[3]  = 'F';
+    a[4]  = 'H';
+    a[5]  = ':';
+    a[6]  = 'A';
+    a[7]  = 'S';
+    a[8]  = 'S';
+    a[9]  = 'E';
+    a[10] = 'R';
+    a[11] = 'T';
+    a[12] = '!';
+    a[13] = '\n';
+    a[14] = '\n';
+
+    s32 actual;
+    u32 t = 1;
+    volatile u32 *tp = &t;
+
+    (void)expr; (void)file; (void)line; (void)fmt;
+
+    ofh_cons_write(a, sizeof (a), &actual);
+
+    /* maybe I can break out of this loop manually (like with a
+     * debugger) */
+    while (*tp) {
+        continue;
+    }
+}
+
+/*
+ * we use elf hash since it is pretty standard
+ */
+static u32
+of_hash(const char *s)
+{
+    u32 hash = 0;
+    u32 hnib;
+
+    if (s != NULL) {
+        while (*s != '\0') {
+            hash = (hash << 4) + *s++;
+            hnib = hash & 0xf0000000UL;
+            if (hnib != 0) {
+                hash ^= hnib >> 24;
+            }
+            hash &= ~hnib;
+        }
+    }
+    return hash;
+}
+
+static void
+ofh_service_init(ulong b)
+{
+    ulong sz;
+    int i;
+    int j = 0;
+    struct ofh_srvc *o;
+    struct ofh_srvc *ofs[] = {
+        DRELA(&ofh_srvc[0], b),
+        DRELA(&ofh_isa_srvc[0], b),
+        NULL
+    };
+
+    j = 0;
+    while (ofs[j] != NULL) {
+        /* find the maximum string length for services */
+        o = &ofs[j][0];
+        while (o->ofs_name != NULL) {
+            const char *n;
+
+            n = DRELA(&o->ofs_name[0], b);
+            /* fix it up so we don't have to fix it anymore */
+            o->ofs_name = n;
+
+            sz = strlen(n);
+            if (sz > *DRELA(&ofh_maxsrvclen, b)) {
+                *DRELA(&ofh_maxsrvclen, b) = sz;
+            }
+            o->ofs_hash =
+                of_hash(n);
+            ++i;
+            ++o;
+        }
+        ++j;
+    }
+}
+
+
+static void
+ofh_cpu_init(ofdn_t chosen, ulong b)
+{
+    static struct ofh_ihandle _ih_cpu_0;
+    void *mem = ofd_mem(b);
+    u32 ih = DRELA((ulong)&_ih_cpu_0, b);
+    struct ofh_ihandle *ihp = (struct ofh_ihandle *)((ulong)ih);
+    const char *cpu_type = DRELA((const char*)"cpu",b);
+
+    ofdn_t cpu = ofd_node_find_by_prop(mem, OFD_ROOT,
+                                       DRELA((const char*)"device_type",b),
+                                       cpu_type, 4);
+    ihp->ofi_node = cpu;
+    ofd_prop_add(mem, chosen, DRELA((const char *)"cpu", b),
+                 &ih, sizeof (ih));
+}
+static s32
+mmu_translate(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    /* FIXME: need a little more here */
+    nargs = nargs;
+    nrets = nrets;
+    argp = argp;
+    retp = retp;
+    b = b;
+    return OF_SUCCESS;
+}
+
+static void
+ofh_mmu_init(ofdn_t chosen, ulong b)
+{
+    static struct ofh_methods _mmu_methods[] = {
+        { "translate", mmu_translate },
+        { NULL, NULL},
+    };
+    static struct ofh_ihandle _ih_mmu = {
+        .ofi_methods = _mmu_methods,
+    };
+    void *mem = ofd_mem(b);
+    u32 ih = DRELA((ulong)&_ih_mmu, b);
+
+    ofd_prop_add(mem, chosen, DRELA((const char *)"mmu", b),
+                 &ih, sizeof (ih));
+}
+
+static void
+ofh_chosen_init(ulong b)
+{
+    ofdn_t ph;
+    void *mem = ofd_mem(b);
+
+    ph = ofd_node_find(mem, DRELA((const char *)"/chosen", b));
+
+    ofh_vty_init(ph, b);
+    ofh_cpu_init(ph, b);
+    ofh_mmu_init(ph, b);
+}
+
+static void
+ofh_options_init(ulong b)
+{
+    void *mem = ofd_mem(b);
+    ofdn_t options;
+    u32 size = 1 << 20;
+    u32 base = b;
+    char buf[20];
+    int i;
+
+
+    /* fixup the ihandle */
+    options = ofd_node_find(mem,
+                            DRELA((const char *)"options", b));
+
+    i = snprintf(buf, sizeof (buf), "0x%x", base);
+    ofd_prop_add(mem, options, DRELA((const char *)"real-base", b),
+                 buf, i);
+
+    i = snprintf(buf,sizeof (buf), "0x%x", size);
+    ofd_prop_add(mem, options, DRELA((const char *)"real-size", b),
+                 buf, i);
+}
+
+static void
+ofh_init(ulong b)
+{
+    ulong sz = (ulong)_end - (ulong)__bss_start;
+    /* clear bss */
+    memset(__bss_start + b, 0, sz);
+
+    ofh_service_init(b);
+    ofh_chosen_init(b);
+    ofh_options_init(b);
+}
+
+static ofh_func_t *
+ofh_lookup(const char *service, ulong b)
+{
+    int j;
+    u32 hash;
+    struct ofh_srvc *o;
+    struct ofh_srvc *ofs[] = {
+        DRELA(&ofh_srvc[0], b),
+        DRELA(&ofh_isa_srvc[0], b),
+        NULL
+    };
+    u32 sz;
+
+    sz = *DRELA(&ofh_maxsrvclen, b);
+
+    if (strnlen(service, sz + 1) > sz) {
+        return NULL;
+    }
+
+    hash = of_hash(service);
+
+    j = 0;
+    while (ofs[j] != NULL) {
+        /* yes this could be quicker */
+        o = &ofs[j][0];
+        while (o->ofs_name != NULL) {
+            if (o->ofs_hash == hash) {
+                const char *n = o->ofs_name;
+                if (strcmp(service, n) == 0) {
+                    return o->ofs_func;
+                }
+            }
+            ++o;
+        }
+        ++j;
+    }
+    return NULL;
+}
+
+s32
+ofh_nosup(u32 nargs __attribute__ ((unused)),
+        u32 nrets __attribute__ ((unused)),
+        s32 argp[] __attribute__ ((unused)),
+        s32 retp[] __attribute__ ((unused)),
+        ulong b __attribute__ ((unused)))
+{
+    return OF_FAILURE;
+}
+
+s32
+ofh_test_method(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
+{
+    if (nargs == 2) {
+        if (nrets == 1) {
+            s32 *ap = DRELA(&ofh_active_package, b);
+            u32 service = (s32)argp[0];
+            const char *method = (const char *)(ulong)argp[1];
+            s32 *stat = &retp[0];
+
+            (void)ap; (void)service; (void)method;
+
+            *stat = 0;
+            /* we do not do this yet */
+            return OF_FAILURE;
+        }
+    }
+    return OF_FAILURE;
+}
+extern u32 _ofh_inited[0];
+extern u32 _ofh_lastarg[0];
+
+s32
+ofh_handler(struct ofh_args *args, ulong b)
+{
+    u32 *inited = (u32 *)DRELA(&_ofh_inited[0],b);
+    u32 *lastarg = (u32 *)DRELA(&_ofh_lastarg[0],b);
+    ofh_func_t *f;
+
+    if (*inited == 0) {
+        ofh_init(b);
+
+        if ((ulong)ofd_mem(b) < (ulong)_end + b) {
+            static const char msg[] = "PANIC: OFD and BSS collide\n";
+            s32 dummy;
+
+            ofh_cons_write(DRELA(&msg[0], b), sizeof (msg), &dummy);
+            for (;;);
+        }
+
+        *inited = 1;
+    }
+
+    *lastarg = (ulong)args;
+
+    f = ofh_lookup((char *)((ulong)args->ofa_service), b);
+
+    if (f == ((ofh_func_t *)~0UL)) {
+        /* do test */
+        if (args->ofa_nargs == 1) {
+            if (args->ofa_nreturns == 1) {
+                char *name = (char *)(ulong)args->ofa_args[0];
+                if (ofh_lookup(name, b) != NULL) {
+                    args->ofa_args[args->ofa_nargs] =
+                        OF_SUCCESS;
+                    return OF_SUCCESS;
+                }
+            }
+        }
+        return OF_FAILURE;
+
+    } else if (f != NULL) {
+        return leap(args->ofa_nargs,
+                    args->ofa_nreturns,
+                    args->ofa_args,
+                    &args->ofa_args[args->ofa_nargs],
+                    b, f);
+    }
+    return OF_FAILURE;
+}
+
+/*
+ * The following code exists solely to run the handler code standalone
+ */
+void
+__ofh_start(void)
+{
+    s32 ret;
+    u32 of_stdout;
+    u32 ihandle;
+    char buf[1024];
+    u32 args_buf[sizeof (struct ofh_args) + (sizeof (u32) * 10)];
+    struct ofh_args *args;
+
+    args = (struct ofh_args *)args_buf;
+
+    args->ofa_service = (u32)"finddevice";
+    args->ofa_nargs     = 1;
+    args->ofa_nreturns  = 1;
+    args->ofa_args[0]   = (u32)"/";
+    args->ofa_args[1]   = -1;
+    ret = ofh_start(args);
+
+    if (ret == OF_SUCCESS) {
+        args->ofa_service   = (u32)"finddevice";
+        args->ofa_nargs     = 1;
+        args->ofa_nreturns  = 1;
+        args->ofa_args[0]   = (u32)"/chosen";
+        args->ofa_args[1]   = -1;
+        ret = ofh_start(args);
+    }
+
+    if (ret == OF_SUCCESS) {
+        u32 phandle = args->ofa_args[1];
+
+        args->ofa_service   = (u32)"getprop";
+        args->ofa_nargs     = 4;
+        args->ofa_nreturns  = 1;
+        args->ofa_args[0]   = phandle;
+        args->ofa_args[1]   = (ulong)"stdout";
+        args->ofa_args[2]   = (ulong)&of_stdout;
+        args->ofa_args[3]   = sizeof(of_stdout);
+        args->ofa_args[4]   = -1;
+        ret = ofh_start(args);
+    }
+
+    ihandle = *(u32 *)((ulong)args->ofa_args[2]);
+
+    if (ret == OF_SUCCESS) {
+        /* instance to path */
+        args->ofa_service   = (u32)"instance-to-path";
+        args->ofa_nargs     = 3;
+        args->ofa_nreturns  = 1;
+        args->ofa_args[0]   = ihandle;
+        args->ofa_args[1]   = (ulong)buf;
+        args->ofa_args[2]   = sizeof (buf);
+        args->ofa_args[3]   = -1;
+        ret = ofh_start(args);
+
+    }
+
+    if (ret == OF_SUCCESS) {
+        /* open rtas */
+        args->ofa_service   = (u32)"open";
+        args->ofa_nargs     = 1;
+        args->ofa_nreturns  = 1;
+        args->ofa_args[0]   = (u32)"/rtas";
+        ret = ofh_start(args);
+        if (ret == OF_SUCCESS) {
+            u32 ir = args->ofa_args[1];
+            args->ofa_service   = (u32)"call-method";
+            args->ofa_nargs     = 3;
+            args->ofa_nreturns  = 2;
+            args->ofa_args[0]   = (ulong)"instantiate-rtas";
+            args->ofa_args[1]   = ir;
+            args->ofa_args[2]   = (ulong)buf;
+
+            ret = ofh_start(args);
+        }
+    }
+
+    if (ret == OF_SUCCESS) {
+        const char msg[] = "This is a test";
+        u32 msgsz = sizeof(msg) - 1; /* Includes \0 */
+
+        args->ofa_service   = (u32)"write";
+        args->ofa_nargs     = 3;
+        args->ofa_nreturns  = 1;
+        args->ofa_args[0]   = ihandle;
+        args->ofa_args[1]   = (ulong)msg;
+        args->ofa_args[2]   = msgsz;
+        args->ofa_args[3]   = -1;
+        ret = ofh_start(args);
+    }
+
+}
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/of_handler/ofh.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/of_handler/ofh.h Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,164 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#ifndef _PFW_H
+#define _PFW_H
+
+#include <xen/types.h>
+#include <public/xencomm.h>
+#include <public/io/console.h>
+#include <of-devtree.h>
+
+#define MIN(x,y) (((x)<(y))?(x):(y))
+
+#define PAGE_SHIFT 12
+#define PAGE_SIZE (1UL<<PAGE_SHIFT)
+
+struct ofh_args {
+    u32 ofa_service;
+    u32 ofa_nargs;
+    u32 ofa_nreturns;
+    s32 ofa_args[0];
+};
+
+typedef s32 (ofh_func_t)(u32, u32, s32 [], s32 [], ulong b);
+
+struct ofh_srvc {
+    const char *ofs_name;
+    ofh_func_t *ofs_func;
+    u32 ofs_hash;
+};
+
+extern ofh_func_t ofh_test_method;
+extern ofh_func_t ofh_nosup;
+
+/* device tree */
+extern ofh_func_t ofh_peer;
+extern ofh_func_t ofh_child;
+extern ofh_func_t ofh_parent;
+extern ofh_func_t ofh_instance_to_package;
+extern ofh_func_t ofh_getproplen;
+extern ofh_func_t ofh_getprop;
+extern ofh_func_t ofh_nextprop;
+extern ofh_func_t ofh_setprop;
+extern ofh_func_t ofh_canon;
+extern ofh_func_t ofh_finddevice;
+extern ofh_func_t ofh_instance_to_path;
+extern ofh_func_t ofh_package_to_path;
+extern ofh_func_t ofh_call_method;
+
+/* IO */
+extern ofh_func_t ofh_open;
+extern ofh_func_t ofh_close;
+extern ofh_func_t ofh_read;
+extern ofh_func_t ofh_write;
+extern ofh_func_t ofh_seek;
+
+/* memory */
+extern ofh_func_t ofh_claim;
+extern ofh_func_t ofh_release;
+
+/* control */
+extern ofh_func_t ofh_boot;
+extern ofh_func_t ofh_enter;
+extern ofh_func_t ofh_exit; /* __attribute__ ((noreturn)); */
+extern ofh_func_t ofh_chain;
+extern ofh_func_t ofh_quiesce;
+
+extern struct ofh_srvc ofh_srvc[];
+extern struct ofh_srvc ofh_isa_srvc[];
+extern s32 ofh_active_package;
+
+struct ofh_methods {
+    const char *ofm_name;
+    ofh_func_t *ofm_method;
+};
+
+struct ofh_ihandle {
+    s32 (*ofi_close)(void);
+    s32 (*ofi_read)(s32 chan, void *buf, u32 count, s32 *actual, ulong b);
+    s32 (*ofi_write)(s32 chan, const void *buf, u32 count, s32 *actual,
+                     ulong b);
+    s32 (*ofi_seek)(u32 pos_hi, u32 pos_lo, u32 *status);
+    struct ofh_methods *ofi_methods;
+    struct xencons_interface *ofi_intf;
+    s32 ofi_node;
+    s32 ofi_chan;
+};
+
+struct ofh_imem {
+    s32 (*ofi_xlate)(void *addr, u32 ret[4]);
+};
+
+
+enum prop_type {
+    pt_byte_array,
+    pt_value,
+    pt_string,
+    pt_composite,
+    /* these are for our own use */
+    pt_func,
+};
+
+extern s32 ofh_start(struct ofh_args *);
+
+#define OFH_CONS_XEN -1
+extern void ofh_cons_init(struct ofh_ihandle *ihp, ulong b);
+extern s32 ofh_cons_read(s32 chan, void *buf, u32 count, s32 *actual);
+extern s32 ofh_cons_write(const void *buf, u32 count, s32 *actual);
+extern s32 ofh_cons_close(void);
+extern s32 ofh_handler(struct ofh_args *args, ulong ifh_base);
+extern s32 leap(u32 nargs, u32 nrets, s32 args[], s32 rets[],
+                ulong ba, void *f);
+
+extern s32 io_leap(s32 chan, void *buf, u32 sz, s32 *actual,
+                ulong ba, void *f);
+
+extern void ofh_vty_init(ofdn_t chosen, ulong b);
+extern void ofh_rtas_init(ulong b);
+
+extern void *_ofh_tree;
+
+#if 1
+#define DRELA(p,b) ((__typeof__ (p))((((ulong)(p)) + (b))))
+#else
+#define DRELA(p,b) (b == b ? p : 0)
+#endif
+extern ulong get_base(void);
+
+static inline void *ofd_mem(ulong base) { return *DRELA(&_ofh_tree, base); }
+
+extern ofh_func_t ofh_start_cpu;
+extern ofh_func_t ofh_stop_self;
+extern ofh_func_t ofh_idle_self;
+extern ofh_func_t ofh_resume_cpu;
+
+/* In Open Firmware, we only use xencomm for reading/writing console data.
+ * Since that's always small, we can use this fixed-size structure. */
+#define XENCOMM_MINI_ADDRS 3
+struct xencomm_mini {
+    struct xencomm_desc _desc;
+    u64 address[XENCOMM_MINI_ADDRS];
+};
+
+extern int xencomm_create_mini(void *area, int arealen, void *buffer,
+            unsigned long bytes, struct xencomm_desc **ret);
+
+#endif
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/of_handler/papr.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/of_handler/papr.S        Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,97 @@
+/*
+ * 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
+ */
+
+#include <asm/config.h>
+#include <asm/processor.h>
+#include <asm/papr.h>
+#include <asm/asm-offsets.h>
+
+#define HSC    .long 0x44000022
+
+       
+/* in is unsused */
+#define PAPR(in, out, name, func_code) \
+       _GLOBAL(name);                  \
+       std r3,-GPR_WIDTH(r1);          \
+       li r3,func_code;                \
+       HSC;                            \
+       ld r12,-GPR_WIDTH(r1);          \
+       cmpi 0,r12,0;                   \
+        bne ret        ## out; /* only store regs if r12 != NULL */ \
+       b ret0
+
+ret8:  std r11, 7 * GPR_WIDTH(r12)
+ret7:  std r10, 6 * GPR_WIDTH(r12)
+ret6:  std r9, 5 * GPR_WIDTH(r12)
+ret5:  std r8, 4 * GPR_WIDTH(r12)
+ret4:  std r7, 3 * GPR_WIDTH(r12)
+ret3:  std r6, 2 * GPR_WIDTH(r12)
+ret2:  std r5, 1 * GPR_WIDTH(r12)
+ret1:  std r4, 0 * GPR_WIDTH(r12)
+       nop
+ret0:  blr
+       
+PAPR(5, 2,papr_remove, H_REMOVE)
+PAPR(5, 1,papr_clear_mod, H_CLEAR_MOD)
+PAPR(5, 1,papr_clear_ref, H_CLEAR_REF)
+PAPR(5, 0,papr_protect, H_PROTECT)
+PAPR(1, 0,papr_eoi, H_EOI)
+PAPR(5, 1,papr_cppr, H_CPPR)
+PAPR(5, 2,papr_ipi, H_IPI)
+PAPR(5, 1,papr_ipoll, H_IPOLL)
+PAPR(5, 1,papr_xirr, H_XIRR)
+PAPR(2, 0,papr_interrupt, H_INTERRUPT)
+PAPR(5, 1,papr_logical_ci_load_64, H_LOGICAL_CI_LOAD)
+PAPR(5, 0,papr_logical_ci_store_64, H_LOGICAL_CI_STORE)
+PAPR(5, 1,papr_logical_cache_load_64, H_LOGICAL_CACHE_LOAD)
+PAPR(5, 0,papr_logical_cache_store_64, H_LOGICAL_CACHE_STORE)
+PAPR(5, 0,papr_logical_icbi, H_LOGICAL_ICBI)
+PAPR(5, 0,papr_logical_dcbf, H_LOGICAL_DCBF)
+PAPR(5, 1,papr_set_dabr, H_SET_DABR)
+PAPR(5, 1,papr_real_to_logical, H_REAL_TO_LOGICAL)
+PAPR(5, 1,papr_pci_config_read, H_PCI_CONFIG_READ)
+PAPR(5, 0,papr_pci_config_write, H_PCI_CONFIG_WRITE)
+
+       PAPR(5, 1,papr_grant_logical, H_GRANT_LOGICAL)
+PAPR(1, 1,papr_accept_logical, H_ACCEPT_LOGICAL)
+PAPR(0, 2,papr_rescind_logical, H_RESCIND_LOGICAL)
+PAPR(3, 0,papr_register_vterm, H_REGISTER_VTERM)
+PAPR(4, 0,papr_vterm_partner_info, H_VTERM_PARTNER_INFO)
+PAPR(1, 0,papr_free_vterm, H_FREE_VTERM)
+
+/* Definitions for hypervisor functions. Note that we do not use the
+ * first macro arg */
+
+PAPR(x, 1,papr_enter, H_ENTER)
+PAPR(x, 8,papr_read, H_READ)
+PAPR(x, 1,papr_thread_control, H_THREAD_CONTROL)
+PAPR(x, 0,papr_cede, H_CEDE)
+
+PAPR(x, 0,papr_page_init, H_PAGE_INIT)
+PAPR(x, 1,papr_set_asr, H_SET_ASR)  /* ISTAR only. */
+PAPR(x, 0,papr_asr_on, H_ASR_ON)  /* ISTAR only. */
+PAPR(x, 0,papr_asr_off, H_ASR_OFF)  /* ISTAR only. */
+
+PAPR(x, 8,papr_hypervisor_data, H_HYPERVISOR_DATA)
+
+PAPR(x, 2,papr_get_xive, H_GET_XIVE)
+PAPR(x, 0,papr_set_xive, H_SET_XIVE)
+
+
+PAPR(x, 0,papr_put_term_char, H_PUT_TERM_CHAR)
+PAPR(x, 3,papr_get_term_char, H_GET_TERM_CHAR)
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/of_handler/papr.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/of_handler/papr.h        Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,69 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#ifndef _OFH_PAPR_H
+#define _OFH_PAPR_H
+
+#include <asm/papr.h>
+
+#ifndef __ASSEMBLY__
+
+extern long papr_enter(ulong *retvals, ulong flags, ulong idx, ...);
+extern long papr_read(ulong *retvals, ulong flags, ulong idx);
+extern long papr_remove(ulong *retvals, ulong flags, ulong pte_index,
+        ulong avpn);
+extern long papr_clear_mod(ulong *retvals, ulong flags, ulong pte_index);
+extern long papr_clear_ref(ulong *retvals, ulong flags, ulong pte_index);
+extern long papr_protect(ulong *retvals, ulong flags, ulong pte_index,
+        ulong avpn);
+extern long papr_get_term_char(ulong *retvals, ulong idx);
+extern long papr_put_term_char(ulong *retvals, ulong idx, ulong count, ...);
+extern long papr_register_vterm(ulong *retvals, ulong ua, ulong plpid, ulong 
pua);
+extern long papr_vterm_partner_info(ulong *retvals, ulong ua, ulong plpid,
+        ulong pua, ulong lpage);
+extern long papr_free_vterm(ulong *retvals, ulong uaddr);
+
+extern long papr_cede(ulong *retvals);
+extern long papr_page_init(ulong *retvals, ulong flags,
+        ulong destination, ulong source);
+extern long papr_set_asr(ulong *retvals, ulong value); /* ISTAR only. */
+extern long papr_asr_on(ulong *retvals); /* ISTAR only. */
+extern long papr_asr_off(ulong *retvals); /* ISTAR only. */
+extern long papr_eoi(ulong *retvals, ulong xirr);
+extern long papr_cppr(ulong *retvals, ulong cppr);
+extern long papr_ipi(ulong *retvals, ulong sn, ulong mfrr);
+extern long papr_ipoll(ulong *retvals, ulong sn);
+extern long papr_xirr(ulong *retvals);
+extern long papr_logical_ci_load_64(ulong *retvals, ulong size,
+        ulong addrAndVal);
+extern long papr_logical_ci_store_64(ulong *retvals, ulong size,
+        ulong addr, ulong value);
+extern long papr_logical_cache_load_64(ulong *retvals, ulong size,
+        ulong addrAndVal);
+extern long papr_logical_cache_store_64(ulong *retvals, ulong size,
+        ulong addr, ulong value);
+extern long papr_logical_icbi(ulong *retvals, ulong addr);
+extern long papr_logical_dcbf(ulong *retvals, ulong addr);
+extern long papr_set_dabr(ulong *retvals, ulong dabr);
+extern long papr_hypervisor_data(ulong *retvals, u64 control);
+extern long papr_real_to_logical(ulong *retvals, ulong raddr);
+
+#endif /* ! __ASSEMBLY__ */
+#endif /* ! _OFH_PAPR_H */
diff -r 69c4f7963a19 -r 050de6b53961 xen/arch/powerpc/of_handler/services.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/of_handler/services.c    Fri Jul 14 10:47:50 2006 +0100
@@ -0,0 +1,96 @@
+/*
+ * 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. 2005
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include "ofh.h"
+
+/*
+ * These are ISA independent OF services
+ */
+
+struct ofh_srvc ofh_srvc[] = {
+    /* Document Section 6.3.2.1 Client Interface */
+    { .ofs_name = "test", .ofs_func = ((ofh_func_t *)~0UL) },
+    { .ofs_name = "test-method", .ofs_func = ofh_test_method },
+
+    /* Document Section 6.3.2.2 Device Tree */
+    { .ofs_name = "peer", .ofs_func = ofh_peer },
+    { .ofs_name = "child", .ofs_func = ofh_child },
+    { .ofs_name = "parent", .ofs_func = ofh_parent },
+    { .ofs_name = "instance-to-package",
+      .ofs_func = ofh_instance_to_package },
+    { .ofs_name = "getproplen", .ofs_func = ofh_getproplen },
+    { .ofs_name = "getprop", .ofs_func = ofh_getprop },
+    { .ofs_name = "nextprop", .ofs_func = ofh_nextprop },
+    { .ofs_name = "setprop", .ofs_func = ofh_setprop },
+    { .ofs_name = "canon", .ofs_func = ofh_canon },
+    { .ofs_name = "finddevice", .ofs_func = ofh_finddevice },
+    { .ofs_name = "instance-to-path", .ofs_func = ofh_instance_to_path },
+    { .ofs_name = "package-to-path", .ofs_func = ofh_package_to_path },
+    { .ofs_name = "call-method", .ofs_func = ofh_call_method },
+
+    /* Document Section 6.3.2.3 Device I/O */
+    { .ofs_name = "open", .ofs_func = ofh_open },
+    { .ofs_name = "close", .ofs_func = ofh_close },
+    { .ofs_name = "read", .ofs_func = ofh_read },
+    { .ofs_name = "write", .ofs_func = ofh_write },
+    { .ofs_name = "seek", .ofs_func = ofh_seek },
+
+    /* Document Section 6.3.2.4 Memory */
+    { .ofs_name = "claim", .ofs_func = ofh_claim },
+    { .ofs_name = "release", .ofs_func = ofh_release },
+
+    /* Document Section 6.3.2.5 Control Transfer */
+    { .ofs_name = "boot", .ofs_func = ofh_boot },
+    { .ofs_name = "enter", .ofs_func = ofh_enter },
+    { .ofs_name = "exit", .ofs_func = ofh_exit },
+    { .ofs_name = "chain", .ofs_func = ofh_chain },
+    { .ofs_name = "quiesce", .ofs_func = ofh_quiesce },
+
+    /* Document Section 6.3.2.6 User Interface */
+    { .ofs_name = "interpret", .ofs_func = ofh_nosup },
+    { .ofs_name = "set-callback", .ofs_func = ofh_nosup },
+    { .ofs_name = "set-symbol-lookup", .ofs_func = ofh_nosup },
+
+    /* Document Section 6.3.2.7 Time */
+    { .ofs_name = "milliseconds", .ofs_func = ofh_nosup },
+    { .ofs_name = NULL, .ofs_func = NULL}
+};
+
+/*
+ * These are services particular to poweprc 32/64
+ */

_______________________________________________
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] [powerpc] Initial checkin of new powerpc files., Xen patchbot-unstable <=