ia64/xen-unstable

changeset 10748:050de6b53961

[powerpc] Initial checkin of new powerpc files.
From: Hollis Blanchard et al (IBM)
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Fri Jul 14 10:47:50 2006 +0100 (2006-07-14)
parents 69c4f7963a19
children 77fe42f6442b
files config/powerpc64.mk tools/libxc/xc_ppc_linux_build.c xen/arch/powerpc/0opt.c xen/arch/powerpc/Makefile xen/arch/powerpc/Rules.mk xen/arch/powerpc/audit.c xen/arch/powerpc/bitops.c xen/arch/powerpc/boot/boot32.S xen/arch/powerpc/boot/start.S xen/arch/powerpc/boot_of.c xen/arch/powerpc/dart.c xen/arch/powerpc/dart.h xen/arch/powerpc/dart_u3.c xen/arch/powerpc/dart_u4.c xen/arch/powerpc/delay.c xen/arch/powerpc/dom0_ops.c xen/arch/powerpc/domain.c xen/arch/powerpc/domain_build.c xen/arch/powerpc/elf32.c xen/arch/powerpc/exceptions.c xen/arch/powerpc/exceptions.h xen/arch/powerpc/external.c xen/arch/powerpc/float.S xen/arch/powerpc/gdbstub.c xen/arch/powerpc/hcalls.c xen/arch/powerpc/htab.c xen/arch/powerpc/iommu.c xen/arch/powerpc/iommu.h xen/arch/powerpc/irq.c xen/arch/powerpc/mambo.S xen/arch/powerpc/mm.c xen/arch/powerpc/mpic.c xen/arch/powerpc/mpic_init.c xen/arch/powerpc/mpic_init.h xen/arch/powerpc/of-devtree.c xen/arch/powerpc/of-devtree.h xen/arch/powerpc/of-devwalk.c xen/arch/powerpc/of_handler/Makefile xen/arch/powerpc/of_handler/console.c xen/arch/powerpc/of_handler/control.c xen/arch/powerpc/of_handler/cpu.c xen/arch/powerpc/of_handler/devtree.c xen/arch/powerpc/of_handler/head.S xen/arch/powerpc/of_handler/io.c xen/arch/powerpc/of_handler/leap.S xen/arch/powerpc/of_handler/memcmp.c xen/arch/powerpc/of_handler/memory.c xen/arch/powerpc/of_handler/memset.c xen/arch/powerpc/of_handler/ofh.c xen/arch/powerpc/of_handler/ofh.h xen/arch/powerpc/of_handler/papr.S xen/arch/powerpc/of_handler/papr.h xen/arch/powerpc/of_handler/services.c xen/arch/powerpc/of_handler/snprintf.c xen/arch/powerpc/of_handler/strcmp.c xen/arch/powerpc/of_handler/strlen.c xen/arch/powerpc/of_handler/strncmp.c xen/arch/powerpc/of_handler/strncpy.c xen/arch/powerpc/of_handler/strnlen.c xen/arch/powerpc/of_handler/vdevice.c xen/arch/powerpc/of_handler/xen_hvcall.S xen/arch/powerpc/of_handler/xencomm.c xen/arch/powerpc/ofd_fixup.c xen/arch/powerpc/oftree.h xen/arch/powerpc/papr/Makefile xen/arch/powerpc/papr/debug.c xen/arch/powerpc/papr/tce.c xen/arch/powerpc/papr/vtce.c xen/arch/powerpc/papr/vterm.c xen/arch/powerpc/papr/xlate.c xen/arch/powerpc/physdev.c xen/arch/powerpc/powerpc64/Makefile xen/arch/powerpc/powerpc64/asm-offsets.c xen/arch/powerpc/powerpc64/domain.c xen/arch/powerpc/powerpc64/exceptions.S xen/arch/powerpc/powerpc64/hypercall_table.S xen/arch/powerpc/powerpc64/io.S xen/arch/powerpc/powerpc64/memcpy.S xen/arch/powerpc/powerpc64/ppc970.c xen/arch/powerpc/powerpc64/prom_call.S xen/arch/powerpc/powerpc64/string.S xen/arch/powerpc/powerpc64/traps.c xen/arch/powerpc/ppc32/prom_call.c xen/arch/powerpc/rtas.c xen/arch/powerpc/setup.c xen/arch/powerpc/smp.c xen/arch/powerpc/tce.h xen/arch/powerpc/time.c xen/arch/powerpc/usercopy.c xen/arch/powerpc/xen.lds xen/include/asm-powerpc/asm_defns.h xen/include/asm-powerpc/atomic.h xen/include/asm-powerpc/bitops.h xen/include/asm-powerpc/cache.h xen/include/asm-powerpc/config.h xen/include/asm-powerpc/current.h xen/include/asm-powerpc/debugger.h xen/include/asm-powerpc/delay.h xen/include/asm-powerpc/desc.h xen/include/asm-powerpc/div64.h xen/include/asm-powerpc/domain.h xen/include/asm-powerpc/event.h xen/include/asm-powerpc/flushtlb.h xen/include/asm-powerpc/grant_table.h xen/include/asm-powerpc/guest_access.h xen/include/asm-powerpc/hardirq.h xen/include/asm-powerpc/hcalls.h xen/include/asm-powerpc/htab.h xen/include/asm-powerpc/hypercall.h xen/include/asm-powerpc/init.h xen/include/asm-powerpc/io.h xen/include/asm-powerpc/iocap.h xen/include/asm-powerpc/irq.h xen/include/asm-powerpc/mach-default/irq_vectors.h xen/include/asm-powerpc/memory.h xen/include/asm-powerpc/misc.h xen/include/asm-powerpc/mm.h xen/include/asm-powerpc/mpic.h xen/include/asm-powerpc/msr.h xen/include/asm-powerpc/multicall.h xen/include/asm-powerpc/page.h xen/include/asm-powerpc/papr.h xen/include/asm-powerpc/pci.h xen/include/asm-powerpc/powerpc64/config.h xen/include/asm-powerpc/powerpc64/ppc970-hid.h xen/include/asm-powerpc/powerpc64/ppc970.h xen/include/asm-powerpc/powerpc64/procarea.h xen/include/asm-powerpc/powerpc64/processor.h xen/include/asm-powerpc/powerpc64/string.h xen/include/asm-powerpc/processor.h xen/include/asm-powerpc/reg_defs.h xen/include/asm-powerpc/regs.h xen/include/asm-powerpc/shadow.h xen/include/asm-powerpc/smp.h xen/include/asm-powerpc/smpboot.h xen/include/asm-powerpc/spinlock.h xen/include/asm-powerpc/string.h xen/include/asm-powerpc/system.h xen/include/asm-powerpc/time.h xen/include/asm-powerpc/types.h xen/include/asm-powerpc/uaccess.h xen/include/public/arch-powerpc.h xen/include/public/xencomm.h
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/config/powerpc64.mk	Fri Jul 14 10:47:50 2006 +0100
     1.3 @@ -0,0 +1,4 @@
     1.4 +CONFIG_POWERPC := y
     1.5 +
     1.6 +CFLAGS += -DELFSIZE=64
     1.7 +LIBDIR := lib
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/libxc/xc_ppc_linux_build.c	Fri Jul 14 10:47:50 2006 +0100
     2.3 @@ -0,0 +1,408 @@
     2.4 +/*
     2.5 + * This program is free software; you can redistribute it and/or modify
     2.6 + * it under the terms of the GNU General Public License as published by
     2.7 + * the Free Software Foundation; either version 2 of the License, or
     2.8 + * (at your option) any later version.
     2.9 + *
    2.10 + * This program is distributed in the hope that it will be useful,
    2.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.13 + * GNU General Public License for more details.
    2.14 + *
    2.15 + * You should have received a copy of the GNU General Public License
    2.16 + * along with this program; if not, write to the Free Software
    2.17 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    2.18 + *
    2.19 + * Copyright (C) IBM Corporation 2006
    2.20 + *
    2.21 + * Authors: Hollis Blanchard <hollisb@us.ibm.com>
    2.22 + */
    2.23 +
    2.24 +#include <stdio.h>
    2.25 +#include <stdint.h>
    2.26 +#include <stdlib.h>
    2.27 +#include <string.h>
    2.28 +#include <unistd.h>
    2.29 +#include <fcntl.h>
    2.30 +#include <sys/types.h>
    2.31 +#include <inttypes.h>
    2.32 +
    2.33 +#include <xen/dom0_ops.h>
    2.34 +#include <xen/memory.h>
    2.35 +#include <xc_private.h>
    2.36 +#include <xg_private.h>
    2.37 +#include <xenctrl.h>
    2.38 +
    2.39 +/* XXX 64M hack */
    2.40 +#define MEMSIZE (64UL << 20)
    2.41 +#define INITRD_ADDR (24UL << 20)
    2.42 +
    2.43 +int verbose;
    2.44 +#define VERBOSE(stuff, ...) \
    2.45 +    if (verbose) \
    2.46 +        stuff __VA_ARGS__;
    2.47 +
    2.48 +#define ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1)))
    2.49 +
    2.50 +#define max(x,y) ({ \
    2.51 +        const typeof(x) _x = (x);       \
    2.52 +        const typeof(y) _y = (y);       \
    2.53 +        (void) (&_x == &_y);            \
    2.54 +        _x > _y ? _x : _y; })
    2.55 +
    2.56 +static void *load_file(const char *path, unsigned long *filesize)
    2.57 +{
    2.58 +    void *img;
    2.59 +    ssize_t size;
    2.60 +    int fd;
    2.61 +
    2.62 +    VERBOSE(printf("load_file(%s)\n", path));
    2.63 +
    2.64 +    fd = open(path, O_RDONLY);
    2.65 +    if (fd < 0) {
    2.66 +        perror(path);
    2.67 +        return NULL;
    2.68 +    }
    2.69 +
    2.70 +    size = lseek(fd, 0, SEEK_END);
    2.71 +    if (size < 0) {
    2.72 +        perror(path);
    2.73 +        close(fd);
    2.74 +        return NULL;
    2.75 +    }
    2.76 +    lseek(fd, 0, SEEK_SET);
    2.77 +
    2.78 +    img = malloc(size);
    2.79 +    if (img == NULL) {
    2.80 +        perror(path);
    2.81 +        close(fd);
    2.82 +        return NULL;
    2.83 +    }
    2.84 +
    2.85 +    size = read(fd, img, size);
    2.86 +    if (size <= 0) {
    2.87 +        perror(path);
    2.88 +        close(fd);
    2.89 +        free(img);
    2.90 +        return NULL;
    2.91 +    }
    2.92 +
    2.93 +    if (filesize)
    2.94 +        *filesize = size;
    2.95 +    close(fd);
    2.96 +    return img;
    2.97 +}
    2.98 +
    2.99 +static int init_boot_vcpu(
   2.100 +    int xc_handle,
   2.101 +    int domid,
   2.102 +    struct domain_setup_info *dsi,
   2.103 +    unsigned long dtb,
   2.104 +    unsigned long kaddr)
   2.105 +{
   2.106 +    vcpu_guest_context_t ctxt;
   2.107 +    int rc;
   2.108 +
   2.109 +    memset(&ctxt.user_regs, 0x55, sizeof(ctxt.user_regs));
   2.110 +    ctxt.user_regs.pc = dsi->v_kernentry;
   2.111 +    ctxt.user_regs.msr = 0;
   2.112 +    ctxt.user_regs.gprs[1] = 32<<20; /* XXX arbitrary stack address */
   2.113 +    ctxt.user_regs.gprs[3] = dtb;
   2.114 +    ctxt.user_regs.gprs[4] = kaddr;
   2.115 +    ctxt.user_regs.gprs[5] = 0;
   2.116 +
   2.117 +    VERBOSE(printf("xc_vcpu_setvcpucontext:\n"
   2.118 +                 "  pc 0x%"PRIx64", msr 0x016%"PRIx64"\n"
   2.119 +                 "  r1-5 %016"PRIx64" %016"PRIx64" %016"PRIx64" %016"PRIx64
   2.120 +                 " %016"PRIx64"\n",
   2.121 +                 ctxt.user_regs.pc, ctxt.user_regs.msr,
   2.122 +                 ctxt.user_regs.gprs[1],
   2.123 +                 ctxt.user_regs.gprs[2],
   2.124 +                 ctxt.user_regs.gprs[3],
   2.125 +                 ctxt.user_regs.gprs[4],
   2.126 +                 ctxt.user_regs.gprs[5]));
   2.127 +    rc = xc_vcpu_setcontext(xc_handle, domid, 0, &ctxt);
   2.128 +    if (rc < 0)
   2.129 +        perror("setdomaininfo");
   2.130 +
   2.131 +    return rc;
   2.132 +}
   2.133 +
   2.134 +static int install_image(
   2.135 +        int xc_handle,
   2.136 +        int domid,
   2.137 +        xen_pfn_t *page_array,
   2.138 +        void *image,
   2.139 +        unsigned long paddr,
   2.140 +        unsigned long size)
   2.141 +{
   2.142 +    uint8_t *img = image;
   2.143 +    int i;
   2.144 +    int rc = 0;
   2.145 +
   2.146 +    if (paddr & ~PAGE_MASK) {
   2.147 +        printf("*** unaligned address\n");
   2.148 +        return -1;
   2.149 +    }
   2.150 +
   2.151 +    for (i = 0; i < size; i += PAGE_SIZE) {
   2.152 +        void *page = img + i;
   2.153 +        xen_pfn_t pfn = (paddr + i) >> PAGE_SHIFT;
   2.154 +        xen_pfn_t mfn = page_array[pfn];
   2.155 +
   2.156 +        rc = xc_copy_to_domain_page(xc_handle, domid, mfn, page);
   2.157 +        if (rc < 0) {
   2.158 +            perror("xc_copy_to_domain_page");
   2.159 +            break;
   2.160 +        }
   2.161 +    }
   2.162 +    return rc;
   2.163 +}
   2.164 +
   2.165 +/* XXX be more flexible about placement in memory */
   2.166 +static int load_dtb(
   2.167 +    int xc_handle,
   2.168 +    int domid,
   2.169 +    const char *dtb_path,
   2.170 +    unsigned long dtb_addr,
   2.171 +    struct domain_setup_info *dsi,
   2.172 +    xen_pfn_t *page_array)
   2.173 +{
   2.174 +    uint8_t *img;
   2.175 +    unsigned long dtb_size;
   2.176 +    int rc = 0;
   2.177 +
   2.178 +    img = load_file(dtb_path, &dtb_size);
   2.179 +    if (img == NULL) {
   2.180 +        rc = -1;
   2.181 +        goto out;
   2.182 +    }
   2.183 +
   2.184 +    VERBOSE(printf("copying device tree to 0x%lx[0x%lx]\n",
   2.185 +            dtb_addr, dtb_size));
   2.186 +    rc = install_image(xc_handle, domid, page_array, img, dtb_addr, dtb_size);
   2.187 +
   2.188 +out:
   2.189 +    free(img);
   2.190 +    return rc;
   2.191 +}
   2.192 +
   2.193 +unsigned long spin_list[] = {
   2.194 +#if 0
   2.195 +    0x100,
   2.196 +    0x200,
   2.197 +    0x300,
   2.198 +    0x380,
   2.199 +    0x400,
   2.200 +    0x480,
   2.201 +    0x500,
   2.202 +    0x700,
   2.203 +    0x900,
   2.204 +    0xc00,
   2.205 +#endif
   2.206 +    0
   2.207 +};
   2.208 +
   2.209 +/* XXX yes, this is a hack */
   2.210 +static void hack_kernel_img(char *img)
   2.211 +{
   2.212 +    const off_t file_offset = 0x10000;
   2.213 +    unsigned long *addr = spin_list;
   2.214 +
   2.215 +    while (*addr) {
   2.216 +        uint32_t *instruction = (uint32_t *)(img + *addr + file_offset);
   2.217 +        printf("installing spin loop at %lx (%x)\n", *addr, *instruction);
   2.218 +        *instruction = 0x48000000;
   2.219 +        addr++;
   2.220 +    }
   2.221 +}
   2.222 +
   2.223 +static int load_kernel(
   2.224 +    int xc_handle,
   2.225 +    int domid,
   2.226 +    const char *kernel_path,
   2.227 +    struct domain_setup_info *dsi,
   2.228 +    xen_pfn_t *page_array)
   2.229 +{
   2.230 +    struct load_funcs load_funcs;
   2.231 +    char *kernel_img;
   2.232 +    unsigned long kernel_size;
   2.233 +    int rc;
   2.234 +
   2.235 +    /* load the kernel ELF file */
   2.236 +    kernel_img = load_file(kernel_path, &kernel_size);
   2.237 +    if (kernel_img == NULL) {
   2.238 +        rc = -1;
   2.239 +        goto out;
   2.240 +    }
   2.241 +
   2.242 +    hack_kernel_img(kernel_img);
   2.243 +
   2.244 +    VERBOSE(printf("probe_elf\n"));
   2.245 +    rc = probe_elf(kernel_img, kernel_size, &load_funcs);
   2.246 +    if (rc < 0) {
   2.247 +        rc = -1;
   2.248 +        printf("%s is not an ELF file\n", kernel_path);
   2.249 +        goto out;
   2.250 +    }
   2.251 +
   2.252 +    VERBOSE(printf("parseimage\n"));
   2.253 +    rc = (load_funcs.parseimage)(kernel_img, kernel_size, dsi);
   2.254 +    if (rc < 0) {
   2.255 +        rc = -1;
   2.256 +        goto out;
   2.257 +    }
   2.258 +
   2.259 +    VERBOSE(printf("loadimage\n"));
   2.260 +    (load_funcs.loadimage)(kernel_img, kernel_size, xc_handle, domid,
   2.261 +            page_array, dsi);
   2.262 +
   2.263 +    VERBOSE(printf("  v_start     %016"PRIx64"\n", dsi->v_start));
   2.264 +    VERBOSE(printf("  v_end       %016"PRIx64"\n", dsi->v_end));
   2.265 +    VERBOSE(printf("  v_kernstart %016"PRIx64"\n", dsi->v_kernstart));
   2.266 +    VERBOSE(printf("  v_kernend   %016"PRIx64"\n", dsi->v_kernend));
   2.267 +    VERBOSE(printf("  v_kernentry %016"PRIx64"\n", dsi->v_kernentry));
   2.268 +
   2.269 +out:
   2.270 +    free(kernel_img);
   2.271 +    return rc;
   2.272 +}
   2.273 +
   2.274 +static int load_initrd(
   2.275 +    int xc_handle,
   2.276 +    int domid,
   2.277 +    xen_pfn_t *page_array,
   2.278 +    const char *initrd_path,
   2.279 +    unsigned long *base,
   2.280 +    unsigned long *len)
   2.281 +{
   2.282 +    uint8_t *initrd_img;
   2.283 +    int rc = -1;
   2.284 +
   2.285 +    /* load the initrd file */
   2.286 +    initrd_img = load_file(initrd_path, len);
   2.287 +    if (initrd_img == NULL)
   2.288 +        return -1;
   2.289 +
   2.290 +    VERBOSE(printf("copying initrd to 0x%lx[0x%lx]\n", INITRD_ADDR, *len));
   2.291 +    if (install_image(xc_handle, domid, page_array, initrd_img, INITRD_ADDR,
   2.292 +                *len))
   2.293 +        goto out;
   2.294 +
   2.295 +    *base = INITRD_ADDR;
   2.296 +    rc = 0;
   2.297 +
   2.298 +out:
   2.299 +    free(initrd_img);
   2.300 +    return rc;
   2.301 +}
   2.302 +
   2.303 +static unsigned long create_start_info(start_info_t *si,
   2.304 +        unsigned int console_evtchn, unsigned int store_evtchn)
   2.305 +{
   2.306 +    unsigned long eomem;
   2.307 +    unsigned long si_addr;
   2.308 +
   2.309 +    memset(si, 0, sizeof(*si));
   2.310 +    snprintf(si->magic, sizeof(si->magic), "xen-%d.%d-powerpc64HV", 3, 0);
   2.311 +
   2.312 +    eomem = MEMSIZE;
   2.313 +    si->nr_pages = eomem >> PAGE_SHIFT;
   2.314 +    si->shared_info = eomem - (PAGE_SIZE * 1);
   2.315 +    si->store_mfn = si->nr_pages - 2;
   2.316 +    si->store_evtchn = store_evtchn;
   2.317 +    si->console_mfn = si->nr_pages - 3;
   2.318 +    si->console_evtchn = console_evtchn;
   2.319 +    si_addr = eomem - (PAGE_SIZE * 4);
   2.320 +
   2.321 +    return si_addr;
   2.322 +}
   2.323 +
   2.324 +static int get_page_array(int xc_handle, int domid, xen_pfn_t **page_array)
   2.325 +{
   2.326 +    int nr_pages;
   2.327 +    int rc;
   2.328 +
   2.329 +    VERBOSE(printf("xc_get_tot_pages\n"));
   2.330 +    nr_pages = xc_get_tot_pages(xc_handle, domid);
   2.331 +    VERBOSE(printf("  0x%x\n", nr_pages));
   2.332 +
   2.333 +    *page_array = malloc(nr_pages * sizeof(xen_pfn_t));
   2.334 +    if (*page_array == NULL) {
   2.335 +        perror("malloc");
   2.336 +        return -1;
   2.337 +    }
   2.338 +
   2.339 +    VERBOSE(printf("xc_get_pfn_list\n"));
   2.340 +    rc = xc_get_pfn_list(xc_handle, domid, *page_array, nr_pages);
   2.341 +    if (rc != nr_pages) {
   2.342 +        perror("Could not get the page frame list");
   2.343 +        return -1;
   2.344 +    }
   2.345 +
   2.346 +    return 0;
   2.347 +}
   2.348 +
   2.349 +int xc_linux_build(int xc_handle,
   2.350 +                   uint32_t domid,
   2.351 +                   const char *image_name,
   2.352 +                   const char *initrd_name,
   2.353 +                   const char *cmdline,
   2.354 +                   const char *features,
   2.355 +                   unsigned long flags,
   2.356 +                   unsigned int store_evtchn,
   2.357 +                   unsigned long *store_mfn,
   2.358 +                   unsigned int console_evtchn,
   2.359 +                   unsigned long *console_mfn)
   2.360 +{
   2.361 +    struct domain_setup_info dsi;
   2.362 +    xen_pfn_t *page_array = NULL;
   2.363 +    unsigned long kern_addr;
   2.364 +    unsigned long dtb_addr;
   2.365 +    unsigned long si_addr;
   2.366 +    unsigned long initrd_base = 0;
   2.367 +    unsigned long initrd_len = 0;
   2.368 +    start_info_t si;
   2.369 +    int rc = 0;
   2.370 +
   2.371 +    if (get_page_array(xc_handle, domid, &page_array)) {
   2.372 +        rc = -1;
   2.373 +        goto out;
   2.374 +    }
   2.375 +
   2.376 +    if (load_kernel(xc_handle, domid, image_name, &dsi, page_array)) {
   2.377 +        rc = -1;
   2.378 +        goto out;
   2.379 +    }
   2.380 +    kern_addr = 0;
   2.381 +
   2.382 +    if (initrd_name && initrd_name[0] != '\0' &&
   2.383 +        load_initrd(xc_handle, domid, page_array, initrd_name, &initrd_base,
   2.384 +                &initrd_len)) {
   2.385 +        rc = -1;
   2.386 +        goto out;
   2.387 +    }
   2.388 +    /* XXX install initrd addr/len into device tree */
   2.389 +
   2.390 +    dtb_addr = (16 << 20);
   2.391 +    if (load_dtb(xc_handle, domid, "DomU.dtb", dtb_addr, &dsi, page_array)) {
   2.392 +        dtb_addr = 0;
   2.393 +    }
   2.394 +
   2.395 +    si_addr = create_start_info(&si, store_evtchn, console_evtchn);
   2.396 +    *console_mfn = si.console_mfn;
   2.397 +    *store_mfn = si.store_mfn;
   2.398 +    if (install_image(xc_handle, domid, page_array, &si, si_addr,
   2.399 +                sizeof(start_info_t))) {
   2.400 +        rc = -1;
   2.401 +        goto out;
   2.402 +    }
   2.403 +
   2.404 +    if (init_boot_vcpu(xc_handle, domid, &dsi, dtb_addr, kern_addr)) {
   2.405 +        rc = -1;
   2.406 +        goto out;
   2.407 +    }
   2.408 +
   2.409 +out:
   2.410 +    return rc;
   2.411 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/xen/arch/powerpc/0opt.c	Fri Jul 14 10:47:50 2006 +0100
     3.3 @@ -0,0 +1,28 @@
     3.4 +/*
     3.5 + * This program is free software; you can redistribute it and/or modify
     3.6 + * it under the terms of the GNU General Public License as published by
     3.7 + * the Free Software Foundation; either version 2 of the License, or
     3.8 + * (at your option) any later version.
     3.9 + *
    3.10 + * This program is distributed in the hope that it will be useful,
    3.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.13 + * GNU General Public License for more details.
    3.14 + *
    3.15 + * You should have received a copy of the GNU General Public License
    3.16 + * along with this program; if not, write to the Free Software
    3.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    3.18 + *
    3.19 + * Copyright (C) IBM Corp. 2005
    3.20 + *
    3.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
    3.22 + */
    3.23 +
    3.24 +#include <xen/config.h>
    3.25 +#include <asm/misc.h>
    3.26 +
    3.27 +extern void __cmpxchg_called_with_bad_pointer(void);
    3.28 +void __cmpxchg_called_with_bad_pointer(void)
    3.29 +{
    3.30 +    trap();
    3.31 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/xen/arch/powerpc/Makefile	Fri Jul 14 10:47:50 2006 +0100
     4.3 @@ -0,0 +1,117 @@
     4.4 +ifneq ($(DOM0_IMAGE),)
     4.5 +builtin_dom0 := y
     4.6 +endif
     4.7 +
     4.8 +subdir-$(HAS_PPC64) += powerpc64
     4.9 +subdir-y += papr
    4.10 +
    4.11 +obj-y += audit.o
    4.12 +obj-y += bitops.o
    4.13 +obj-y += boot_of.o
    4.14 +obj-y += dart.o
    4.15 +obj-y += dart_u3.o
    4.16 +obj-y += dart_u4.o
    4.17 +obj-y += delay.o
    4.18 +obj-y += dom0_ops.o
    4.19 +obj-y += domain_build.o
    4.20 +obj-y += domain.o
    4.21 +obj-y += exceptions.o
    4.22 +obj-y += external.o
    4.23 +obj-y += float.o
    4.24 +obj-y += hcalls.o
    4.25 +obj-y += htab.o
    4.26 +obj-y += iommu.o
    4.27 +obj-y += irq.o
    4.28 +obj-y += mambo.o
    4.29 +obj-y += mm.o
    4.30 +obj-y += mpic.o
    4.31 +obj-y += mpic_init.o
    4.32 +obj-y += of-devtree.o
    4.33 +obj-y += of-devwalk.o
    4.34 +obj-y += ofd_fixup.o
    4.35 +obj-y += physdev.o
    4.36 +obj-y += rtas.o
    4.37 +obj-y += setup.o
    4.38 +obj-y += smp.o
    4.39 +obj-y += time.o
    4.40 +obj-y += usercopy.o
    4.41 +
    4.42 +obj-$(debug) += 0opt.o
    4.43 +obj-$(crash_debug) += gdbstub.o
    4.44 +obj-$(builtin_dom0) += dom0.o
    4.45 +
    4.46 +obj-y += firmware_image.o
    4.47 +
    4.48 +obj-y += elf32.o
    4.49 +
    4.50 +# These are extra warnings like for the arch/ppc directory but may not
    4.51 +# allow the rest of the tree to build.
    4.52 +PPC_C_WARNINGS += -Wundef -Wmissing-prototypes -Wmissing-declarations
    4.53 +CFLAGS += $(PPC_C_WARNINGS)
    4.54 +
    4.55 +LINK=0x3000000
    4.56 +boot32_link_base = $(LINK)
    4.57 +xen_link_offset  = 100
    4.58 +xen_link_base    = $(patsubst %000,%$(xen_link_offset),$(LINK))
    4.59 +
    4.60 +#
    4.61 +# The following flags are fed to gcc in order to link several
    4.62 +# objects into a single ELF segment and to not link in any additional
    4.63 +# objects that gcc would normally like to
    4.64 +#
    4.65 +OMAGIC = -N -nodefaultlibs -nostartfiles
    4.66 +
    4.67 +firmware: of_handler/built_in.o $(TARGET_SUBARCH)/memcpy.o of-devtree.o
    4.68 +	$(CC) $(CFLAGS) $(OMAGIC) -e __ofh_start -Wl,-Ttext,0x0 $^ -o $@
    4.69 +
    4.70 +firmware_image: firmware
    4.71 +	$(CROSS_COMPILE)objcopy --output-target=binary $< $@
    4.72 +
    4.73 +firmware_image.o: firmware_image
    4.74 +	$(CROSS_COMPILE)objcopy --input-target=binary \
    4.75 +		--output-target=elf64-powerpc \
    4.76 +		--binary-architecture=powerpc \
    4.77 +		--redefine-sym _binary_$<_start=$(@:%.o=%)_start \
    4.78 +		--redefine-sym _binary_$<_end=$(@:%.o=%)_end \
    4.79 +		--redefine-sym _binary_$<_size=$(@:%.o=%)_size  $< $@
    4.80 +
    4.81 +#
    4.82 +# Hacks for included C files
    4.83 +#
    4.84 +irq.o: ../x86/irq.c
    4.85 +physdev.o: ../x86/physdev.c
    4.86 +
    4.87 +HDRS += $(wildcard *.h)
    4.88 +
    4.89 +start.o: boot/start.S
    4.90 +	$(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $@
    4.91 +
    4.92 +$(TARGET)-syms: start.o $(ALL_OBJS) xen.lds
    4.93 +	$(CC) $(CFLAGS) $(OMAGIC) -Wl,-Ttext,$(xen_link_base),-T,xen.lds start.o $(ALL_OBJS) -o $@
    4.94 +
    4.95 +$(TARGET).bin: $(TARGET)-syms
    4.96 +	$(CROSS_COMPILE)objcopy --output-target=binary $< $@
    4.97 +
    4.98 +$(TARGET).bin.o: $(TARGET).bin
    4.99 +	$(CROSS_COMPILE)objcopy --input-target=binary \
   4.100 +		--output-target=elf32-powerpc \
   4.101 +		--binary-architecture=powerpc  $< $@
   4.102 +
   4.103 +boot32.o: boot/boot32.S
   4.104 +	$(CC) -m32 -Wa,-a32,-mppc64bridge \
   4.105 +		-D__ASSEMBLY__ -D__BRIDGE64__ $(CFLAGS) -c $< -o $@
   4.106 +
   4.107 +$(TARGET): boot32.o $(TARGET).bin.o
   4.108 +	$(CC) -m32 -N -Wl,-melf32ppclinux -static -nostdlib \
   4.109 +		-Wl,-Ttext,$(boot32_link_base)  -Wl,-Tdata,$(xen_link_base) \
   4.110 +		$(CFLAGS) $^ -o $@
   4.111 +
   4.112 +asm-offsets.s: $(TARGET_SUBARCH)/asm-offsets.c $(HDRS)
   4.113 +	$(CC) $(CFLAGS) -S -o $@ $<
   4.114 +
   4.115 +dom0.bin: $(DOM0_IMAGE)
   4.116 +	cp $< $@
   4.117 +
   4.118 +clean::
   4.119 +	$(MAKE) -f $(BASEDIR)/Rules.mk -C of_handler clean
   4.120 +	rm -f firmware firmware_image dom0.bin
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/xen/arch/powerpc/Rules.mk	Fri Jul 14 10:47:50 2006 +0100
     5.3 @@ -0,0 +1,51 @@
     5.4 +HAS_PPC64 := y
     5.5 +
     5.6 +CC := $(CROSS_COMPILE)gcc
     5.7 +LD := $(CROSS_COMPILE)ld
     5.8 +
     5.9 +# These are goodess that applies to all source.
    5.10 +C_WARNINGS := -Wpointer-arith -Wredundant-decls
    5.11 +
    5.12 +# _no_ common code can have packed data structures or we are in touble.
    5.13 +C_WARNINGS += -Wpacked
    5.14 +
    5.15 +CFLAGS := -m64 -ffreestanding -fno-builtin -fno-common -fno-strict-aliasing
    5.16 +CFLAGS += -iwithprefix include -Wall -Werror -pipe
    5.17 +CFLAGS += -I$(BASEDIR)/include
    5.18 +CFLAGS += -I$(BASEDIR)/include/asm-powerpc/mach-generic
    5.19 +CFLAGS += -I$(BASEDIR)/include/asm-powerpc/mach-default
    5.20 +CFLAGS += $(C_WARNINGS)
    5.21 +CFLAGS += -msoft-float -O2
    5.22 +CFLAGS-$(debug) += -O0 # last one wins
    5.23 +CFLAGS-$(papr_vterm) += -DPAPR_VDEVICE -DPAPR_VTERM
    5.24 +
    5.25 +LDFLAGS += -m elf64ppc
    5.26 +
    5.27 +#
    5.28 +# command to embed a binary inside a .o
    5.29 +#
    5.30 +%.o: %.bin
    5.31 +	$(CROSS_COMPILE)objcopy --input-target=binary \
    5.32 +		--output-target=elf64-powerpc \
    5.33 +		--binary-architecture=powerpc \
    5.34 +		--redefine-sym _binary_$*_bin_start=$*_start \
    5.35 +		--redefine-sym _binary_$*_bin_end=$*_end \
    5.36 +		--redefine-sym _binary_$*_bin_size=$*_size \
    5.37 +		$< $@
    5.38 +
    5.39 +# Test for at least GCC v3.2.x.
    5.40 +gcc-ver = $(shell $(CC) -dumpversion | sed -e 's/^\(.\)\.\(.\)\.\(.\)/\$(1)/')
    5.41 +ifeq ($(call gcc-ver,1),1)
    5.42 +$(error gcc-1.x.x unsupported - upgrade to at least gcc-3.2.x)
    5.43 +endif
    5.44 +ifeq ($(call gcc-ver,1),2)
    5.45 +$(error gcc-2.x.x unsupported - upgrade to at least gcc-3.2.x)
    5.46 +endif
    5.47 +ifeq ($(call gcc-ver,1),3)
    5.48 +ifeq ($(call gcc-ver,2),0)
    5.49 +$(error gcc-3.0.x unsupported - upgrade to at least gcc-3.2.x)
    5.50 +endif
    5.51 +ifeq ($(call gcc-ver,2),1)
    5.52 +$(error gcc-3.1.x unsupported - upgrade to at least gcc-3.2.x)
    5.53 +endif
    5.54 +endif
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xen/arch/powerpc/audit.c	Fri Jul 14 10:47:50 2006 +0100
     6.3 @@ -0,0 +1,45 @@
     6.4 +/*
     6.5 + * This program is free software; you can redistribute it and/or modify
     6.6 + * it under the terms of the GNU General Public License as published by
     6.7 + * the Free Software Foundation; either version 2 of the License, or
     6.8 + * (at your option) any later version.
     6.9 + *
    6.10 + * This program is distributed in the hope that it will be useful,
    6.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.13 + * GNU General Public License for more details.
    6.14 + *
    6.15 + * You should have received a copy of the GNU General Public License
    6.16 + * along with this program; if not, write to the Free Software
    6.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    6.18 + *
    6.19 + * Copyright (C) IBM Corp. 2005
    6.20 + *
    6.21 + * Authors: Hollis Blanchard <hollisb@us.ibm.com>
    6.22 + */
    6.23 +
    6.24 +#ifndef NDEBUG
    6.25 +#include <xen/lib.h>
    6.26 +#include <xen/sched.h>
    6.27 +
    6.28 +extern void audit_domain(struct domain *d);
    6.29 +extern void audit_domains(void);
    6.30 +extern void audit_domains_key(unsigned char key);
    6.31 +
    6.32 +void audit_domain(struct domain *d)
    6.33 +{
    6.34 +    panic("%s unimplemented\n", __func__);
    6.35 +}
    6.36 +
    6.37 +void audit_domains(void)
    6.38 +{
    6.39 +    struct domain *d;
    6.40 +    for_each_domain ( d )
    6.41 +        audit_domain(d);
    6.42 +}
    6.43 +
    6.44 +void audit_domains_key(unsigned char key)
    6.45 +{
    6.46 +    audit_domains();
    6.47 +}
    6.48 +#endif
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/xen/arch/powerpc/bitops.c	Fri Jul 14 10:47:50 2006 +0100
     7.3 @@ -0,0 +1,94 @@
     7.4 +/* from linux/arch/powerpc/lib/bitops.c */
     7.5 +
     7.6 +#include <asm/types.h>
     7.7 +#include <asm/bitops.h>
     7.8 +
     7.9 +#define BITOP_WORD(nr)      ((nr) / BITS_PER_LONG)
    7.10 +
    7.11 +/**
    7.12 + * find_next_bit - find the next set bit in a memory region
    7.13 + * @addr: The address to base the search on
    7.14 + * @offset: The bitnumber to start searching at
    7.15 + * @size: The maximum size to search
    7.16 + */
    7.17 +unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
    7.18 +			    unsigned long offset)
    7.19 +{
    7.20 +	const unsigned long *p = addr + BITOP_WORD(offset);
    7.21 +	unsigned long result = offset & ~(BITS_PER_LONG-1);
    7.22 +	unsigned long tmp;
    7.23 +
    7.24 +	if (offset >= size)
    7.25 +		return size;
    7.26 +	size -= result;
    7.27 +	offset %= BITS_PER_LONG;
    7.28 +	if (offset) {
    7.29 +		tmp = *(p++);
    7.30 +		tmp &= (~0UL << offset);
    7.31 +		if (size < BITS_PER_LONG)
    7.32 +			goto found_first;
    7.33 +		if (tmp)
    7.34 +			goto found_middle;
    7.35 +		size -= BITS_PER_LONG;
    7.36 +		result += BITS_PER_LONG;
    7.37 +	}
    7.38 +	while (size & ~(BITS_PER_LONG-1)) {
    7.39 +		if ((tmp = *(p++)))
    7.40 +			goto found_middle;
    7.41 +		result += BITS_PER_LONG;
    7.42 +		size -= BITS_PER_LONG;
    7.43 +	}
    7.44 +	if (!size)
    7.45 +		return result;
    7.46 +	tmp = *p;
    7.47 +
    7.48 +found_first:
    7.49 +	tmp &= (~0UL >> (BITS_PER_LONG - size));
    7.50 +	if (tmp == 0UL)		/* Are any bits set? */
    7.51 +		return result + size;	/* Nope. */
    7.52 +found_middle:
    7.53 +	return result + __ffs(tmp);
    7.54 +}
    7.55 +
    7.56 +/*
    7.57 + * This implementation of find_{first,next}_zero_bit was stolen from
    7.58 + * Linus' asm-alpha/bitops.h.
    7.59 + */
    7.60 +unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
    7.61 +				 unsigned long offset)
    7.62 +{
    7.63 +	const unsigned long *p = addr + BITOP_WORD(offset);
    7.64 +	unsigned long result = offset & ~(BITS_PER_LONG-1);
    7.65 +	unsigned long tmp;
    7.66 +
    7.67 +	if (offset >= size)
    7.68 +		return size;
    7.69 +	size -= result;
    7.70 +	offset %= BITS_PER_LONG;
    7.71 +	if (offset) {
    7.72 +		tmp = *(p++);
    7.73 +		tmp |= ~0UL >> (BITS_PER_LONG - offset);
    7.74 +		if (size < BITS_PER_LONG)
    7.75 +			goto found_first;
    7.76 +		if (~tmp)
    7.77 +			goto found_middle;
    7.78 +		size -= BITS_PER_LONG;
    7.79 +		result += BITS_PER_LONG;
    7.80 +	}
    7.81 +	while (size & ~(BITS_PER_LONG-1)) {
    7.82 +		if (~(tmp = *(p++)))
    7.83 +			goto found_middle;
    7.84 +		result += BITS_PER_LONG;
    7.85 +		size -= BITS_PER_LONG;
    7.86 +	}
    7.87 +	if (!size)
    7.88 +		return result;
    7.89 +	tmp = *p;
    7.90 +
    7.91 +found_first:
    7.92 +	tmp |= ~0UL << size;
    7.93 +	if (tmp == ~0UL)	/* Are any bits zero? */
    7.94 +		return result + size;	/* Nope. */
    7.95 +found_middle:
    7.96 +	return result + ffz(tmp);
    7.97 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/xen/arch/powerpc/boot/boot32.S	Fri Jul 14 10:47:50 2006 +0100
     8.3 @@ -0,0 +1,75 @@
     8.4 +/*
     8.5 + * Copyright (C) 2005 Jimi Xenidis <jimix@watson.ibm.com>, IBM Corporation
     8.6 + *
     8.7 + * This program is free software; you can redistribute it and/or modify
     8.8 + * it under the terms of the GNU General Public License as published by
     8.9 + * the Free Software Foundation; either version 2 of the License, or
    8.10 + * (at your option) any later version.
    8.11 + * 
    8.12 + * This program is distributed in the hope that it will be useful,
    8.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.15 + * GNU General Public License for more details.
    8.16 + * 
    8.17 + * You should have received a copy of the GNU General Public License
    8.18 + * along with this program; if not, write to the Free Software
    8.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
    8.20 + *
    8.21 + */
    8.22 +	
    8.23 +### 32 bit strapping code so Of will like us
    8.24 +	.section	".text"
    8.25 +	.align 3
    8.26 +	.globl _start
    8.27 +		
    8.28 +_start:
    8.29 +	## Double word align the MSR value below
    8.30 +	nop
    8.31 +	bl _real_start
    8.32 +	## static value for MSR
    8.33 +	.llong 0x9000000000001000
    8.34 +
    8.35 +	## see also docs/reference/ppc/msr.txt
    8.36 +##bit C  Hex               Name Desc
    8.37 +##  0 63 80000000 00000000 SF   64-bit Mode
    8.38 +##  3 60 10000000 00000000 HV   Hypervisor State iff PR = 0 in hypervisor state.
    8.39 +## 51 12 00000000 00001000 ME   Machine Check Enable
    8.40 +
    8.41 +_real_start:		
    8.42 +	# pass the original msr as argument to hype_init
    8.43 +	mfmsr   8
    8.44 +
    8.45 +	## Set PC
    8.46 +	li	21, 0
    8.47 +	oris	21, 21, _hype64@h
    8.48 +	ori	21, 21, _hype64@l
    8.49 +#ifdef __BRIDGE64__
    8.50 +	## In 64bit we use rfid to switch from 32bit to 64 bit
    8.51 +	mtsrr0	21
    8.52 +
    8.53 +	## Set MSR
    8.54 +	mflr	21
    8.55 +	ld	22, 0(21)
    8.56 +	mtsrr1	22
    8.57 +	bl __leap
    8.58 +	/* should never return */
    8.59 +	trap
    8.60 +__leap:		
    8.61 +	rfid
    8.62 +#else
    8.63 +	mtctr 21
    8.64 +	bctrl
    8.65 +	/* should never return */
    8.66 +	trap
    8.67 +#endif
    8.68 +
    8.69 +	
    8.70 +_real_end:
    8.71 +	.data
    8.72 +	.align 3
    8.73 +	## Hypervisor starts here, at the first data address
    8.74 +	## linker magic positions _hype64 0x100 after _start
    8.75 +	## hype/ppc64/Makefile.isa 
    8.76 +_hype64:		
    8.77 +
    8.78 +
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/xen/arch/powerpc/boot/start.S	Fri Jul 14 10:47:50 2006 +0100
     9.3 @@ -0,0 +1,51 @@
     9.4 +/*
     9.5 + * Copyright (C) 2005 Jimi Xenidis <jimix@watson.ibm.com>, IBM Corporation
     9.6 + *
     9.7 + * This program is free software; you can redistribute it and/or modify
     9.8 + * it under the terms of the GNU General Public License as published by
     9.9 + * the Free Software Foundation; either version 2 of the License, or
    9.10 + * (at your option) any later version.
    9.11 + * 
    9.12 + * This program is distributed in the hope that it will be useful,
    9.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.15 + * GNU General Public License for more details.
    9.16 + * 
    9.17 + * You should have received a copy of the GNU General Public License
    9.18 + * along with this program; if not, write to the Free Software
    9.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
    9.20 + *
    9.21 + */
    9.22 +
    9.23 +#include <asm/config.h>
    9.24 +#include <asm/processor.h>
    9.25 +#include <asm/page.h>
    9.26 +
    9.27 +    .globl _start
    9.28 +_start:
    9.29 +    /* load up the stack */
    9.30 +    SET_REG_TO_LABEL(r1, cpu0_stack)
    9.31 +
    9.32 +    /* call the init function */
    9.33 +    LOADADDR(r21,__start_xen_ppc)
    9.34 +
    9.35 +#ifdef __PPC64__
    9.36 +    ld r2, 8(r21)
    9.37 +    ld r21, 0(r21)
    9.38 +#endif
    9.39 +    mtctr r21
    9.40 +    bctrl
    9.41 +    /* should never return */
    9.42 +    trap
    9.43 +
    9.44 +    /* Note! GDB 6.3 makes the very stupid assumption that PC > SP means we are
    9.45 +     * in a Linux signal trampoline, and it begins groping for a struct
    9.46 +     * rt_sigframe on the stack. Naturally, this fails miserably for our
    9.47 +     * backtrace. To work around this behavior, we must make certain that our
    9.48 +     * stack is always above our text, e.g. in the data section. */
    9.49 +    .data /* DO NOT REMOVE; see GDB note above */
    9.50 +    .align 4
    9.51 +cpu0_stack_bottom:
    9.52 +    .space STACK_SIZE
    9.53 +cpu0_stack:
    9.54 +    .space STACK_FRAME_OVERHEAD
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/xen/arch/powerpc/boot_of.c	Fri Jul 14 10:47:50 2006 +0100
    10.3 @@ -0,0 +1,1016 @@
    10.4 +/*
    10.5 + * This program is free software; you can redistribute it and/or modify
    10.6 + * it under the terms of the GNU General Public License as published by
    10.7 + * the Free Software Foundation; either version 2 of the License, or
    10.8 + * (at your option) any later version.
    10.9 + *
   10.10 + * This program is distributed in the hope that it will be useful,
   10.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10.13 + * GNU General Public License for more details.
   10.14 + *
   10.15 + * You should have received a copy of the GNU General Public License
   10.16 + * along with this program; if not, write to the Free Software
   10.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   10.18 + *
   10.19 + * Copyright (C) IBM Corp. 2005
   10.20 + *
   10.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   10.22 + */
   10.23 +
   10.24 +#include <xen/config.h>
   10.25 +#include <xen/init.h>
   10.26 +#include <xen/lib.h>
   10.27 +#include <xen/multiboot.h>
   10.28 +#include <xen/compile.h>
   10.29 +#include <xen/spinlock.h>
   10.30 +#include <xen/serial.h>
   10.31 +#include <xen/time.h>
   10.32 +#include <asm/page.h>
   10.33 +#include <asm/io.h>
   10.34 +#include "exceptions.h"
   10.35 +#include "of-devtree.h"
   10.36 +
   10.37 +static ulong of_vec;
   10.38 +static ulong of_msr;
   10.39 +static int of_out;
   10.40 +static ofdn_t boot_cpu;
   10.41 +static char bootargs[256];
   10.42 +
   10.43 +extern struct ns16550_defaults ns16550;
   10.44 +
   10.45 +#undef OF_DEBUG
   10.46 +
   10.47 +#ifdef OF_DEBUG
   10.48 +#define DBG(args...) of_printf(args)
   10.49 +#else
   10.50 +#define DBG(args...)
   10.51 +#endif
   10.52 +
   10.53 +#define of_panic(MSG...) \
   10.54 +    do { of_printf(MSG); of_printf("\nHANG\n"); for (;;); } while (0)
   10.55 +
   10.56 +struct of_service {
   10.57 +    u32 ofs_service;
   10.58 +    u32 ofs_nargs;
   10.59 +    u32 ofs_nrets;
   10.60 +    u32 ofs_args[10];
   10.61 +};
   10.62 +
   10.63 +static int bof_chosen;
   10.64 +
   10.65 +static struct of_service s;
   10.66 +extern s32 prom_call(void *arg, ulong rtas_base, ulong func, ulong msr);
   10.67 +
   10.68 +static int __init of_call(
   10.69 +    const char *service, u32 nargs, u32 nrets, s32 rets[], ...)
   10.70 +{
   10.71 +    int rc;
   10.72 +
   10.73 +    if (of_vec != 0) {
   10.74 +        va_list args;
   10.75 +        int i;
   10.76 +
   10.77 +        memset(&s, 0, sizeof (s));
   10.78 +        s.ofs_service = (ulong)service;
   10.79 +        s.ofs_nargs = nargs;
   10.80 +        s.ofs_nrets = nrets;
   10.81 +        s.ofs_nargs = nargs;
   10.82 +
   10.83 +        /* copy all the params into the args array */
   10.84 +        va_start(args, rets);
   10.85 +
   10.86 +        for (i = 0; i < nargs; i++) {
   10.87 +            s.ofs_args[i] = va_arg(args, u32);
   10.88 +        }
   10.89 +
   10.90 +        va_end(args);
   10.91 +
   10.92 +        rc = prom_call(&s, 0, of_vec, of_msr);
   10.93 +
   10.94 +        /* yes always to the copy, just in case */
   10.95 +        for (i = 0; i < nrets; i++) {
   10.96 +            rets[i] = s.ofs_args[i + nargs];
   10.97 +        }
   10.98 +    } else {
   10.99 +        rc = OF_FAILURE;
  10.100 +    }
  10.101 +    return rc;
  10.102 +}
  10.103 +
  10.104 +/* popular OF methods */
  10.105 +static int __init _of_write(int ih, const char *addr, u32 len)
  10.106 +{
  10.107 +    int rets[1] = { OF_FAILURE };
  10.108 +    if (of_call("write", 3, 1, rets, ih, addr, len) == OF_FAILURE) {
  10.109 +        return OF_FAILURE;
  10.110 +    }
  10.111 +    return rets[0];
  10.112 +}
  10.113 +
  10.114 +/* popular OF methods */
  10.115 +static int __init of_write(int ih, const char *addr, u32 len)
  10.116 +{
  10.117 +    int rc;
  10.118 +    int i = 0;
  10.119 +    int sum = 0;
  10.120 +
  10.121 +    while (i < len) {
  10.122 +        if (addr[i] == '\n') {
  10.123 +            if (i > 0) {
  10.124 +                rc = _of_write(ih, addr, i);
  10.125 +                if (rc == OF_FAILURE)
  10.126 +                    return rc;
  10.127 +                sum += rc;
  10.128 +            }
  10.129 +            rc = _of_write(ih, "\r\n", 2);
  10.130 +            if (rc == OF_FAILURE)
  10.131 +                return rc;
  10.132 +            sum += rc;
  10.133 +            i++;
  10.134 +            addr += i;
  10.135 +            len -= i;
  10.136 +            i = 0;
  10.137 +            continue;
  10.138 +        }
  10.139 +        i++;
  10.140 +    }
  10.141 +    if (len > 0) {
  10.142 +        rc = _of_write(ih, addr, len);
  10.143 +        if (rc == OF_FAILURE)
  10.144 +            return rc;
  10.145 +        sum += rc;
  10.146 +    }
  10.147 +            
  10.148 +    return sum;
  10.149 +}
  10.150 +
  10.151 +static int of_printf(const char *fmt, ...)
  10.152 +    __attribute__ ((format (printf, 1, 2)));
  10.153 +static int __init of_printf(const char *fmt, ...)
  10.154 +{
  10.155 +    static char buf[1024];
  10.156 +    va_list args;
  10.157 +    int sz;
  10.158 +
  10.159 +    if (of_out == 0) {
  10.160 +        return OF_FAILURE;
  10.161 +    }
  10.162 +
  10.163 +    va_start(args, fmt);
  10.164 +
  10.165 +    sz = vsnprintf(buf, sizeof (buf), fmt, args);
  10.166 +    if (sz <= sizeof (buf)) {
  10.167 +        of_write(of_out, buf, sz);
  10.168 +    } else {
  10.169 +        static const char trunc[] = "\n(TRUNCATED)\n";
  10.170 +
  10.171 +        sz = sizeof (buf);
  10.172 +        of_write(of_out, buf, sz);
  10.173 +        of_write(of_out, trunc, sizeof (trunc));
  10.174 +    }
  10.175 +    return sz;
  10.176 +}
  10.177 +
  10.178 +static int __init of_finddevice(const char *devspec)
  10.179 +{
  10.180 +    int rets[1] = { OF_FAILURE };
  10.181 +
  10.182 +    of_call("finddevice", 1, 1, rets, devspec);
  10.183 +    if (rets[0] == OF_FAILURE) {
  10.184 +        DBG("finddevice %s -> FAILURE %d\n",devspec,rets[0]);
  10.185 +        return OF_FAILURE;
  10.186 +    }
  10.187 +    DBG("finddevice %s -> %d\n",devspec, rets[0]);
  10.188 +    return rets[0];
  10.189 +}
  10.190 +
  10.191 +static int __init of_getprop(int ph, const char *name, void *buf, u32 buflen)
  10.192 +{
  10.193 +    int rets[1] = { OF_FAILURE };
  10.194 +
  10.195 +    of_call("getprop", 4, 1, rets, ph, name, buf, buflen);
  10.196 +
  10.197 +    if (rets[0] == OF_FAILURE) {
  10.198 +        DBG("getprop 0x%x %s -> FAILURE\n", ph, name);
  10.199 +        return OF_FAILURE;
  10.200 +    }
  10.201 +
  10.202 +    DBG("getprop 0x%x %s -> 0x%x (%s)\n", ph, name, rets[0], (char *)buf);
  10.203 +    return rets[0];
  10.204 +}
  10.205 +
  10.206 +static int __init of_setprop(
  10.207 +    int ph, const char *name, const void *buf, u32 buflen)
  10.208 +{
  10.209 +    int rets[1] = { OF_FAILURE };
  10.210 +
  10.211 +    of_call("setprop", 4, 1, rets, ph, name, buf, buflen);
  10.212 +
  10.213 +    if (rets[0] == OF_FAILURE) {
  10.214 +        DBG("setprop 0x%x %s -> FAILURE\n", ph, name);
  10.215 +        return OF_FAILURE;
  10.216 +    }
  10.217 +
  10.218 +    DBG("setprop 0x%x %s -> %s\n", ph, name, (char *)buf);
  10.219 +    return rets[0];
  10.220 +}
  10.221 +
  10.222 +/*
  10.223 + * returns 0 if there are no children (of spec)
  10.224 + */
  10.225 +static int __init of_getchild(int ph)
  10.226 +{
  10.227 +    int rets[1] = { OF_FAILURE };
  10.228 +
  10.229 +    of_call("child", 1, 1, rets, ph);
  10.230 +    DBG("getchild 0x%x -> 0x%x\n", ph, rets[0]);
  10.231 +
  10.232 +    return rets[0];
  10.233 +}
  10.234 +
  10.235 +/*
  10.236 + * returns 0 is there are no peers
  10.237 + */
  10.238 +static int __init of_getpeer(int ph)
  10.239 +{
  10.240 +    int rets[1] = { OF_FAILURE };
  10.241 +
  10.242 +    of_call("peer", 1, 1, rets, ph);
  10.243 +    DBG("getpeer 0x%x -> 0x%x\n", ph, rets[0]);
  10.244 +
  10.245 +    return rets[0];
  10.246 +}
  10.247 +
  10.248 +static int __init of_getproplen(int ph, const char *name)
  10.249 +{
  10.250 +    int rets[1] = { OF_FAILURE };
  10.251 +
  10.252 +    of_call("getproplen", 2, 1, rets, ph, name);
  10.253 +    if (rets[0] == OF_FAILURE) {
  10.254 +        DBG("getproplen 0x%x %s -> FAILURE\n", ph, name);
  10.255 +        return OF_FAILURE;
  10.256 +    }
  10.257 +    DBG("getproplen 0x%x %s -> 0x%x\n", ph, name, rets[0]);
  10.258 +    return rets[0];
  10.259 +}
  10.260 +
  10.261 +static int __init of_package_to_path(int ph, char *buffer, u32 buflen)
  10.262 +{
  10.263 +    int rets[1] = { OF_FAILURE };
  10.264 +
  10.265 +    of_call("package-to-path", 3, 1, rets, ph, buffer, buflen);
  10.266 +    if (rets[0] == OF_FAILURE) {
  10.267 +        DBG("%s 0x%x -> FAILURE\n", __func__, ph);
  10.268 +        return OF_FAILURE;
  10.269 +    }
  10.270 +    DBG("%s 0x%x %s -> 0x%x\n", __func__, ph, buffer, rets[0]);
  10.271 +    if (rets[0] <= buflen)
  10.272 +        buffer[rets[0]] = '\0';
  10.273 +    return rets[0];
  10.274 +}
  10.275 +
  10.276 +static int __init of_nextprop(int ph, const char *name, void *buf)
  10.277 +{
  10.278 +    int rets[1] = { OF_FAILURE };
  10.279 +
  10.280 +    of_call("nextprop", 3, 1, rets, ph, name, buf);
  10.281 +
  10.282 +    if (rets[0] == OF_FAILURE) {
  10.283 +        DBG("nextprop 0x%x %s -> FAILURE\n", ph, name);
  10.284 +        return OF_FAILURE;
  10.285 +    }
  10.286 +
  10.287 +    DBG("nextprop 0x%x %s -> %s\n", ph, name, (char *)buf);
  10.288 +    return rets[0];
  10.289 +}
  10.290 +
  10.291 +static int __init of_instance_to_path(int ih, char *buffer, u32 buflen)
  10.292 +{
  10.293 +    int rets[1] = { OF_FAILURE };
  10.294 +
  10.295 +    if (of_call("instance-to-path", 3, 1, rets, ih, buffer, buflen)
  10.296 +         == OF_FAILURE)
  10.297 +        return OF_FAILURE;
  10.298 +
  10.299 +    if (rets[0] <= buflen)
  10.300 +        buffer[rets[0]] = '\0';
  10.301 +    return rets[0];
  10.302 +}
  10.303 +
  10.304 +static int __init of_start_cpu(int cpu, u32 pc, u32 reg)
  10.305 +{
  10.306 +    int rets[1] = { OF_FAILURE };
  10.307 +
  10.308 +    if ( of_call("start-cpu", 3, 0, rets, cpu, pc, reg) == OF_FAILURE )
  10.309 +        return OF_FAILURE;
  10.310 +
  10.311 +    return rets[0];
  10.312 +}
  10.313 +
  10.314 +static void __init of_test(const char *of_method_name)
  10.315 +{
  10.316 +    int rets[1] = { OF_FAILURE };
  10.317 +    
  10.318 +    of_call("test", 1, 1, rets, of_method_name);
  10.319 +    if (rets[0] == OF_FAILURE ) {
  10.320 +        of_printf("Warning: possibly no OF method %s.\n"
  10.321 +                  "(Ignore this warning on PIBS.)\n", of_method_name);
  10.322 +    }
  10.323 +}
  10.324 +
  10.325 +static int __init of_claim(void * virt, u32 size)
  10.326 +{
  10.327 +    int rets[1] = { OF_FAILURE };
  10.328 +    
  10.329 +    of_call("claim", 3, 1, rets, virt, size, 0/*align*/);
  10.330 +    if (rets[0] == OF_FAILURE) {
  10.331 +        DBG("%s 0x%p 0x%08x -> FAIL\n", __func__, virt, size);
  10.332 +        return OF_FAILURE;
  10.333 +    }
  10.334 +
  10.335 +    DBG("%s 0x%p 0x%08x -> 0x%x\n", __func__, virt, size, rets[0]);
  10.336 +    return rets[0];
  10.337 +}
  10.338 +
  10.339 +static int __init of_instance_to_package(int ih)
  10.340 +{
  10.341 +    int rets[1] = { OF_FAILURE };
  10.342 +
  10.343 +    of_call("instance-to-package", 1, 1, rets, ih);
  10.344 +    if (rets[0] == OF_FAILURE)
  10.345 +        return OF_FAILURE;
  10.346 +
  10.347 +    return rets[0];
  10.348 +}
  10.349 +
  10.350 +static int __init of_getparent(int ph)
  10.351 +{
  10.352 +    int rets[1] = { OF_FAILURE };
  10.353 +
  10.354 +    of_call("parent", 1, 1, rets, ph);
  10.355 +
  10.356 +    DBG("getparent 0x%x -> 0x%x\n", ph, rets[0]);
  10.357 +    return rets[0];
  10.358 +}
  10.359 +
  10.360 +static void boot_of_probemem(multiboot_info_t *mbi)
  10.361 +{
  10.362 +    int root;
  10.363 +    int p;
  10.364 +    u32 addr_cells = 1;
  10.365 +    u32 size_cells = 1;
  10.366 +    int rc;
  10.367 +    int mcount = 0;
  10.368 +    static memory_map_t mmap[16];
  10.369 +
  10.370 +    root = of_finddevice("/");
  10.371 +    p = of_getchild(root);
  10.372 +
  10.373 +    /* code is writen to assume sizes of 1 */
  10.374 +    of_getprop(root, "#address-cells", &addr_cells, sizeof (addr_cells));
  10.375 +    of_getprop(root, "#size-cells", &size_cells, sizeof (size_cells));
  10.376 +    DBG("%s: address_cells=%d  size_cells=%d\n",
  10.377 +                    __func__, addr_cells, size_cells);
  10.378 +    
  10.379 +    do {
  10.380 +        const char memory[] = "memory";
  10.381 +        char type[32];
  10.382 +
  10.383 +        type[0] = '\0';
  10.384 +
  10.385 +        of_getprop(p, "device_type", type, sizeof (type));
  10.386 +        if (strncmp(type, memory, sizeof (memory)) == 0) {
  10.387 +            u32 reg[48];  
  10.388 +            u32 al, ah, ll, lh;
  10.389 +            int r;
  10.390 +
  10.391 +            rc = of_getprop(p, "reg", reg, sizeof (reg));
  10.392 +            if (rc == OF_FAILURE) {
  10.393 +                of_panic("no reg property for memory node: 0x%x.\n", p);
  10.394 +            }
  10.395 +            int l = rc/sizeof(u32); /* number reg element */
  10.396 +            DBG("%s: number of bytes in property 'reg' %d\n",
  10.397 +                            __func__, rc);
  10.398 +            
  10.399 +            r = 0;
  10.400 +            while (r < l) {
  10.401 +                al = ah = ll = lh = 0;
  10.402 +                if (addr_cells == 2) {
  10.403 +                    ah = reg[r++];
  10.404 +                    if (r >= l)
  10.405 +                        break;  /* partial line.  Skip  */
  10.406 +                    al = reg[r++];
  10.407 +                    if (r >= l)
  10.408 +                        break;  /* partial line.  Skip */
  10.409 +                } else {
  10.410 +                    al = reg[r++];
  10.411 +                    if (r >= l)
  10.412 +                        break;  /* partial line.  Skip */
  10.413 +                }
  10.414 +                if (size_cells == 2) {
  10.415 +                    lh = reg[r++];
  10.416 +                    if (r >= l)
  10.417 +                        break;  /* partial line.  Skip */
  10.418 +                    ll = reg[r++];
  10.419 +                } else {
  10.420 +                    ll = reg[r++];
  10.421 +                }
  10.422 +
  10.423 +                if ((ll != 0) || (lh != 0)) {
  10.424 +                    mmap[mcount].size = 20; /* - size field */
  10.425 +                    mmap[mcount].type = 1; /* Regular ram */
  10.426 +                    mmap[mcount].length_high = lh;
  10.427 +                    mmap[mcount].length_low = ll;
  10.428 +                    mmap[mcount].base_addr_high = ah;
  10.429 +                    mmap[mcount].base_addr_low = al;
  10.430 +                    of_printf("%s: memory 0x%016lx[0x%08lx]\n",
  10.431 +                      __func__,
  10.432 +                      (u64)(((u64)mmap[mcount].base_addr_high << 32)
  10.433 +                            | mmap[mcount].base_addr_low),
  10.434 +                      (u64)(((u64)mmap[mcount].length_high << 32)
  10.435 +                            | mmap[mcount].length_low));
  10.436 +                    ++mcount;
  10.437 +                }
  10.438 +            }
  10.439 +        }
  10.440 +        p = of_getpeer(p);
  10.441 +    } while (p != OF_FAILURE && p != 0);
  10.442 +
  10.443 +    if (mcount > 0) {
  10.444 +        mbi->flags |= MBI_MEMMAP;
  10.445 +        mbi->mmap_length = sizeof (mmap[0]) * mcount;
  10.446 +        mbi->mmap_addr = (ulong)mmap;
  10.447 +    }
  10.448 +}
  10.449 +
  10.450 +static void boot_of_bootargs(multiboot_info_t *mbi)
  10.451 +{
  10.452 +    int rc;
  10.453 +
  10.454 +    rc = of_getprop(bof_chosen, "bootargs", &bootargs, sizeof (bootargs));
  10.455 +    if (rc == OF_FAILURE) {
  10.456 +        strcpy(bootargs, "xen");
  10.457 +    }
  10.458 +
  10.459 +    mbi->flags |= MBI_CMDLINE;
  10.460 +    mbi->cmdline = (u32)bootargs;
  10.461 +
  10.462 +    of_printf("bootargs = %s\n", bootargs);
  10.463 +}
  10.464 +
  10.465 +static int save_props(void *m, ofdn_t n, int pkg)
  10.466 +{
  10.467 +    int ret;
  10.468 +    char name[128];
  10.469 +    int result = 1;
  10.470 +    int found_name = 0;
  10.471 +    int found_device_type = 0;
  10.472 +    const char name_str[] = "name";
  10.473 +    const char devtype_str[] = "device_type";
  10.474 +
  10.475 +    /* get first */
  10.476 +    result = of_nextprop(pkg, 0, name);
  10.477 +
  10.478 +    while (result > 0) {
  10.479 +        int sz;
  10.480 +        u64 obj[1024];
  10.481 +
  10.482 +        sz = of_getproplen(pkg, name);
  10.483 +        if (sz >= 0) {
  10.484 +            ret = OF_SUCCESS;
  10.485 +        } else {
  10.486 +            ret = OF_FAILURE;
  10.487 +        }
  10.488 +
  10.489 +        if (ret == OF_SUCCESS) {
  10.490 +            int actual = 0;
  10.491 +            ofdn_t pos;
  10.492 +
  10.493 +            if (sz > 0) {
  10.494 +                if (sz > sizeof (obj)) {
  10.495 +                    of_panic("obj array not big enough for 0x%x\n", sz);
  10.496 +                }
  10.497 +                actual = of_getprop(pkg, name, obj, sz);
  10.498 +                if (actual > sz) of_panic("obj too small");
  10.499 +            }
  10.500 +
  10.501 +            if (strncmp(name, name_str, sizeof(name_str)) == 0) {
  10.502 +                found_name = 1;
  10.503 +            }
  10.504 +
  10.505 +            if (strncmp(name, devtype_str, sizeof(devtype_str)) == 0) {
  10.506 +                found_device_type = 1;
  10.507 +            }
  10.508 +
  10.509 +            pos = ofd_prop_add(m, n, name, obj, actual);
  10.510 +            if (pos == 0) of_panic("prop_create");
  10.511 +        }
  10.512 +
  10.513 +        result = of_nextprop(pkg, name, name);
  10.514 +    }
  10.515 +
  10.516 +    return 1;
  10.517 +}
  10.518 +
  10.519 +
  10.520 +static void do_pkg(void *m, ofdn_t n, int p, char *path, size_t psz)
  10.521 +{
  10.522 +    int pnext;
  10.523 +    ofdn_t nnext;
  10.524 +    int sz;
  10.525 +
  10.526 +retry:
  10.527 +    save_props(m, n, p);
  10.528 +
  10.529 +    /* do children first */
  10.530 +    pnext = of_getchild(p);
  10.531 +
  10.532 +    if (pnext != 0) {
  10.533 +        sz = of_package_to_path(pnext, path, psz);
  10.534 +        if (sz == OF_FAILURE) of_panic("bad path\n");
  10.535 +
  10.536 +        nnext = ofd_node_child_create(m, n, path, sz);
  10.537 +        if (nnext == 0) of_panic("out of mem\n");
  10.538 +
  10.539 +        do_pkg(m, nnext, pnext, path, psz);
  10.540 +    }
  10.541 +
  10.542 +    /* do peer */
  10.543 +    pnext = of_getpeer(p);
  10.544 +
  10.545 +    if (pnext != 0) {
  10.546 +        sz = of_package_to_path(pnext, path, psz);
  10.547 +
  10.548 +        nnext = ofd_node_peer_create(m, n, path, sz);
  10.549 +        if (nnext <= 0) of_panic("out of space in OFD tree.\n");
  10.550 +
  10.551 +        n = nnext;
  10.552 +        p = pnext;
  10.553 +        goto retry;
  10.554 +    }
  10.555 +}
  10.556 +
  10.557 +static int pkg_save(void *mem)
  10.558 +{
  10.559 +    int root;
  10.560 +    char path[256];
  10.561 +    int r;
  10.562 +
  10.563 +    path[0]='/';
  10.564 +    path[1]='\0';
  10.565 +
  10.566 +    /* get root */
  10.567 +    root = of_getpeer(0);
  10.568 +    if (root == OF_FAILURE) of_panic("no root package\n");
  10.569 +
  10.570 +    do_pkg(mem, OFD_ROOT, root, path, sizeof(path));
  10.571 +
  10.572 +    r = (((ofdn_t *)mem)[1] + 1) * sizeof (u64);
  10.573 +
  10.574 +    of_printf("%s: saved device tree in 0x%x bytes\n", __func__, r);
  10.575 +
  10.576 +    return r;
  10.577 +}
  10.578 +
  10.579 +static int boot_of_fixup_refs(void *mem)
  10.580 +{
  10.581 +    static const char *fixup_props[] = {
  10.582 +        "interrupt-parent",
  10.583 +    };
  10.584 +    int i;
  10.585 +    int count = 0;
  10.586 +
  10.587 +    for (i = 0; i < ARRAY_SIZE(fixup_props); i++) {
  10.588 +        ofdn_t c;
  10.589 +        const char *name = fixup_props[i];
  10.590 +
  10.591 +        c = ofd_node_find_by_prop(mem, OFD_ROOT, name, NULL, 0);
  10.592 +        while (c > 0) {
  10.593 +            const char *path;
  10.594 +            int rp;
  10.595 +            int ref;
  10.596 +            ofdn_t dp;
  10.597 +            int rc;
  10.598 +            ofdn_t upd;
  10.599 +            char ofpath[256];
  10.600 +
  10.601 +            path = ofd_node_path(mem, c);
  10.602 +            if (path == NULL) of_panic("no path to found prop: %s\n", name);
  10.603 +
  10.604 +            rp = of_finddevice(path);
  10.605 +            if (rp == OF_FAILURE)
  10.606 +                of_panic("no real device for: name %s, path %s\n",
  10.607 +                          name, path);
  10.608 +            /* Note: In theory 0 is a valid node handle but it is highly
  10.609 +             * unlikely.
  10.610 +             */
  10.611 +            if (rp == 0) {
  10.612 +                of_panic("%s: of_finddevice returns 0 for path %s\n",
  10.613 +                                    __func__, path);
  10.614 +            } 
  10.615 +
  10.616 +            rc = of_getprop(rp, name, &ref, sizeof(ref));
  10.617 +            if ((rc == OF_FAILURE) || (rc == 0))
  10.618 +                of_panic("no prop: name %s, path %s, device 0x%x\n",
  10.619 +                         name, path, rp);
  10.620 +
  10.621 +            rc = of_package_to_path(ref, ofpath, sizeof (ofpath));
  10.622 +            if (rc == OF_FAILURE)
  10.623 +                of_panic("no package: name %s, path %s, device 0x%x,\n"
  10.624 +                         "ref 0x%x\n", name, path, rp, ref);
  10.625 +
  10.626 +            dp = ofd_node_find(mem, ofpath);
  10.627 +            if (dp <= 0) of_panic("no ofd node for OF node[0x%x]: %s\n",
  10.628 +                                  ref, ofpath);
  10.629 +
  10.630 +            ref = dp;
  10.631 +
  10.632 +            upd = ofd_prop_add(mem, c, name, &ref, sizeof(ref));
  10.633 +            if (upd <= 0) of_panic("update failed: %s\n", name);
  10.634 +
  10.635 +#ifdef DEBUG
  10.636 +            of_printf("%s: %s/%s -> %s\n", __func__,
  10.637 +                    path, name, ofpath);
  10.638 +#endif
  10.639 +            ++count;
  10.640 +            c = ofd_node_find_next(mem, c);
  10.641 +        }
  10.642 +    }
  10.643 +    return count;
  10.644 +}
  10.645 +
  10.646 +static int boot_of_fixup_chosen(void *mem)
  10.647 +{
  10.648 +    int ch;
  10.649 +    ofdn_t dn;
  10.650 +    ofdn_t dc;
  10.651 +    int val;
  10.652 +    int rc;
  10.653 +    char ofpath[256];
  10.654 +
  10.655 +    ch = of_finddevice("/chosen");
  10.656 +    if (ch == OF_FAILURE) of_panic("/chosen not found\n");
  10.657 +
  10.658 +    rc = of_getprop(ch, "cpu", &val, sizeof (val));
  10.659 +
  10.660 +    if (rc != OF_FAILURE) {
  10.661 +        rc = of_instance_to_path(val, ofpath, sizeof (ofpath));
  10.662 +
  10.663 +        if (rc > 0) {
  10.664 +            dn = ofd_node_find(mem, ofpath);
  10.665 +            if (dn <= 0) of_panic("no node for: %s\n", ofpath);
  10.666 +
  10.667 +            boot_cpu = dn;
  10.668 +            val = dn;
  10.669 +
  10.670 +            dn = ofd_node_find(mem, "/chosen");
  10.671 +            if (dn <= 0) of_panic("no /chosen node\n");
  10.672 +
  10.673 +            dc = ofd_prop_add(mem, dn, "cpu", &val, sizeof (val));
  10.674 +            if (dc <= 0) of_panic("could not fix /chosen/cpu\n");
  10.675 +            rc = 1;
  10.676 +        } else {
  10.677 +            of_printf("*** can't find path to booting cpu, "
  10.678 +                    "SMP is disabled\n");
  10.679 +            boot_cpu = -1;
  10.680 +        }
  10.681 +    }
  10.682 +    return rc;
  10.683 +}
  10.684 +
  10.685 +static ulong space_base;
  10.686 +static ulong find_space(u32 size, ulong align, multiboot_info_t *mbi)
  10.687 +{
  10.688 +    memory_map_t *map = (memory_map_t *)((ulong)mbi->mmap_addr);
  10.689 +    ulong eomem = ((u64)map->length_high << 32) | (u64)map->length_low;
  10.690 +    ulong base;
  10.691 +
  10.692 +    of_printf("%s base=0x%016lx  eomem=0x%016lx  size=0x%08x  align=0x%lx\n",
  10.693 +                    __func__, space_base, eomem, size, align);
  10.694 +    base = ALIGN_UP(space_base, PAGE_SIZE);
  10.695 +    if ((base + size) >= 0x4000000) return 0;
  10.696 +    if (base + size > eomem) of_panic("not enough RAM\n");
  10.697 +
  10.698 +    if (size == 0) return base;
  10.699 +    if (of_claim((void*)base, size) != OF_FAILURE) {
  10.700 +        space_base = base + size;
  10.701 +        return base;
  10.702 +    } else {
  10.703 +        for(base += 0x100000; (base+size) < 0x4000000; base += 0x100000) {
  10.704 +            of_printf("Trying 0x%016lx\n", base);
  10.705 +            if (of_claim((void*)base, size) != OF_FAILURE) {
  10.706 +                space_base = base + size;
  10.707 +                return base;
  10.708 +            }
  10.709 +        }
  10.710 +        return 0;
  10.711 +    }
  10.712 +}
  10.713 +
  10.714 +/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges
  10.715 + * property.  The values are bad, and it doesn't even have the
  10.716 + * right number of cells. */
  10.717 +
  10.718 +static void __init boot_of_fix_maple(void)
  10.719 +{
  10.720 +    int isa;
  10.721 +    const char *ranges = "ranges";
  10.722 +    u32 isa_ranges[3];
  10.723 +    const u32 isa_test[] = { 0x00000001, 0xf4000000, 0x00010000 };
  10.724 +    const u32 isa_fixed[] = {
  10.725 +        0x00000001,
  10.726 +        0x00000000,
  10.727 +        0x00000000, /* 0xf4000000, matt says this */
  10.728 +        0x00000000,
  10.729 +        0x00000000,
  10.730 +        0x00010000
  10.731 +    };
  10.732 +
  10.733 +    isa = of_finddevice("/ht@0/isa@4");
  10.734 +    if (isa != OF_FAILURE) {
  10.735 +        if (of_getproplen(isa, ranges) == sizeof (isa_test)) {
  10.736 +            of_getprop(isa, ranges, isa_ranges, sizeof (isa_ranges));
  10.737 +            if (memcmp(isa_ranges, isa_test, sizeof (isa_test)) == 0) {
  10.738 +                int rc;
  10.739 +
  10.740 +                of_printf("OF: fixing bogus ISA range on maple\n");
  10.741 +                rc = of_setprop(isa, ranges, isa_fixed, sizeof (isa_fixed));
  10.742 +                if (rc == OF_FAILURE) {
  10.743 +                    of_panic("of_setprop() failed\n");
  10.744 +                }
  10.745 +            }
  10.746 +        }
  10.747 +    }
  10.748 +}
  10.749 +    
  10.750 +static int __init boot_of_serial(void *oftree)
  10.751 +{
  10.752 +    int n;
  10.753 +    int p;
  10.754 +    int rc;
  10.755 +    u32 val[3];
  10.756 +    char buf[128];
  10.757 +
  10.758 +    n = of_instance_to_package(of_out);
  10.759 +    if (n == OF_FAILURE) {
  10.760 +        of_panic("instance-to-package of /chosen/stdout: failed\n");
  10.761 +    }
  10.762 +
  10.763 +    /* prune this from the oftree */
  10.764 +    rc = of_package_to_path(n, buf, sizeof(buf));
  10.765 +    if (rc == OF_FAILURE) {
  10.766 +        of_panic("package-to-path of /chosen/stdout: failed\n");
  10.767 +    }
  10.768 +    of_printf("Pruning from devtree: %s\n"
  10.769 +              "  since Xen will be using it for console\n", buf);
  10.770 +    rc = ofd_prune_path(oftree, buf);
  10.771 +    if (rc < 0) {
  10.772 +        of_panic("prune path \"%s\" failed\n", buf);
  10.773 +    }
  10.774 +    
  10.775 +
  10.776 +    p = of_getparent(n);
  10.777 +    if (p == OF_FAILURE) {
  10.778 +        of_panic("no parent for: 0x%x\n", n);
  10.779 +    }
  10.780 +
  10.781 +    buf[0] = '\0';
  10.782 +    of_getprop(p, "device_type", buf, sizeof (buf));
  10.783 +    if (strstr(buf, "isa") == NULL) {
  10.784 +        of_panic("only ISA UARTS supported\n");
  10.785 +    }
  10.786 +
  10.787 +    /* should get this from devtree */
  10.788 +    isa_io_base = 0xf4000000;
  10.789 +    of_printf("%s: ISA base: 0x%lx\n", __func__, isa_io_base);
  10.790 +
  10.791 +    buf[0] = '\0';
  10.792 +    of_getprop(n, "device_type", buf, sizeof (buf));
  10.793 +    if (strstr(buf, "serial") == NULL) {
  10.794 +        of_panic("only UARTS supported\n");
  10.795 +    }
  10.796 +
  10.797 +    rc = of_getprop(n, "reg", val, sizeof (val));
  10.798 +    if (rc == OF_FAILURE) {
  10.799 +        of_panic("%s: no location for serial port\n", __func__);
  10.800 +    }
  10.801 +    ns16550.io_base = val[1];
  10.802 +
  10.803 +    ns16550.baud = BAUD_AUTO;
  10.804 +    ns16550.data_bits = 8;
  10.805 +    ns16550.parity = 'n';
  10.806 +    ns16550.stop_bits = 1;
  10.807 +
  10.808 +    rc = of_getprop(n, "interrupts", val, sizeof (val));
  10.809 +    if (rc == OF_FAILURE) {
  10.810 +        of_printf("%s: no ISRC, forcing poll mode\n", __func__);
  10.811 +        ns16550.irq = 0;
  10.812 +    } else {
  10.813 +        ns16550.irq = val[0];
  10.814 +        of_printf("%s: ISRC=0x%x, but forcing poll mode\n",
  10.815 +                  __func__, ns16550.irq);
  10.816 +        ns16550.irq = 0;
  10.817 +    }
  10.818 +
  10.819 +    return 1;
  10.820 +}
  10.821 +
  10.822 +static void boot_of_module(ulong r3, ulong r4, multiboot_info_t *mbi)
  10.823 +{
  10.824 +    static module_t mods[3];
  10.825 +    void *oftree;
  10.826 +    ulong oftree_sz = 48 * PAGE_SIZE;
  10.827 +    char *mod0_start;
  10.828 +    ulong mod0_size;
  10.829 +    ulong mod0;
  10.830 +    static const char sepr[] = " -- ";
  10.831 +    extern char dom0_start[] __attribute__ ((weak));
  10.832 +    extern char dom0_size[] __attribute__ ((weak));
  10.833 +    const char *p;
  10.834 +
  10.835 +    if ((r3 > 0) && (r4 > 0)) {
  10.836 +        /* was it handed to us in registers ? */
  10.837 +        mod0_start = (void *)r3;
  10.838 +        mod0_size = r4;
  10.839 +    } else {
  10.840 +        /* see if it is in the boot params */
  10.841 +        p = strstr((char *)((ulong)mbi->cmdline), "dom0_start=");
  10.842 +        if ( p != NULL) {
  10.843 +            p += 11;
  10.844 +            mod0_start = (char *)simple_strtoul(p, NULL, 0);
  10.845 +
  10.846 +            p = strstr((char *)((ulong)mbi->cmdline), "dom0_size=");
  10.847 +            p += 10;
  10.848 +            mod0_size = simple_strtoul(p, NULL, 0);
  10.849 +
  10.850 +            of_printf("mod0: %o %c %c %c\n",
  10.851 +                      mod0_start[0],
  10.852 +                      mod0_start[1],
  10.853 +                      mod0_start[2],
  10.854 +                      mod0_start[3]);
  10.855 +
  10.856 +        } else if ( ((ulong)dom0_start != 0) && ((ulong)dom0_size != 0) ) {
  10.857 +            /* was it linked in ? */
  10.858 +        
  10.859 +            mod0_start = dom0_start;
  10.860 +            mod0_size = (ulong)dom0_size;
  10.861 +            of_printf("%s: linked in module copied after _end "
  10.862 +                      "(start 0x%p size 0x%lx)\n",
  10.863 +                      __func__, mod0_start, mod0_size);
  10.864 +        } else {
  10.865 +            mod0_start = _end;
  10.866 +            mod0_size = 0;
  10.867 +        }
  10.868 +    }
  10.869 +
  10.870 +    space_base = (ulong)_end;
  10.871 +    mod0 = find_space(mod0_size, PAGE_SIZE, mbi);
  10.872 +
  10.873 +    /* three cases
  10.874 +     * 1) mod0_size is not 0 and the image can be copied
  10.875 +     * 2) mod0_size is not 0 and the image cannot be copied
  10.876 +     * 3) mod0_size is 0
  10.877 +     */
  10.878 +    if (mod0_size > 0) {
  10.879 +        if (mod0 != 0) {
  10.880 +            memcpy((void *)mod0, mod0_start, mod0_size);
  10.881 +            mods[0].mod_start = mod0;
  10.882 +            mods[0].mod_end = mod0 + mod0_size;
  10.883 +        } else {
  10.884 +            of_panic("No space to copy mod0\n");
  10.885 +        }
  10.886 +    } else {
  10.887 +        mods[0].mod_start = mod0;
  10.888 +        mods[0].mod_end = mod0;
  10.889 +    }
  10.890 +
  10.891 +    of_printf("%s: mod[0] @ 0x%016x[0x%x]\n", __func__,
  10.892 +              mods[0].mod_start, mods[0].mod_end);
  10.893 +    p = strstr((char *)(ulong)mbi->cmdline, sepr);
  10.894 +    if (p != NULL) {
  10.895 +        p += sizeof (sepr) - 1;
  10.896 +        mods[0].string = (u32)(ulong)p;
  10.897 +        of_printf("%s: mod[0].string: %s\n", __func__, p);
  10.898 +    }
  10.899 +
  10.900 +    /* snapshot the tree */
  10.901 +    oftree = (void*)find_space(oftree_sz, PAGE_SIZE, mbi);
  10.902 +    if (oftree == 0) of_panic("Could not allocate OFD tree\n");
  10.903 +
  10.904 +    of_printf("creating oftree\n");
  10.905 +    of_test("package-to-path");
  10.906 +    ofd_create(oftree, oftree_sz);
  10.907 +    pkg_save(oftree);
  10.908 +
  10.909 +    boot_of_fixup_refs(oftree);
  10.910 +    boot_of_fixup_chosen(oftree);
  10.911 +
  10.912 +    ofd_walk(oftree, OFD_ROOT, /* add_hype_props */ NULL, 2);
  10.913 +
  10.914 +    mods[1].mod_start = (ulong)oftree;
  10.915 +    mods[1].mod_end = mods[1].mod_start + oftree_sz;
  10.916 +    of_printf("%s: mod[1] @ 0x%016x[0x%x]\n", __func__,
  10.917 +              mods[1].mod_start, mods[1].mod_end);
  10.918 +
  10.919 +
  10.920 +    mbi->flags |= MBI_MODULES;
  10.921 +    mbi->mods_count = 2;
  10.922 +    mbi->mods_addr = (u32)mods;
  10.923 +
  10.924 +    boot_of_serial(oftree);
  10.925 +}
  10.926 +
  10.927 +static int __init boot_of_cpus(void)
  10.928 +{
  10.929 +    int cpus;
  10.930 +    int cpu;
  10.931 +    int result;
  10.932 +    u32 cpu_clock[2];
  10.933 +
  10.934 +    cpus = of_finddevice("/cpus");
  10.935 +    cpu = of_getchild(cpus);
  10.936 +    result = of_getprop(cpu, "timebase-frequency", &timebase_freq,
  10.937 +            sizeof(timebase_freq));
  10.938 +    if (result == OF_FAILURE) {
  10.939 +        of_panic("Couldn't get timebase frequency!\n");
  10.940 +    }
  10.941 +    of_printf("OF: timebase-frequency = %d Hz\n", timebase_freq);
  10.942 +
  10.943 +    result = of_getprop(cpu, "clock-frequency", &cpu_clock, sizeof(cpu_clock));
  10.944 +    if (result == OF_FAILURE || (result !=4 && result != 8)) {
  10.945 +        of_panic("Couldn't get clock frequency!\n");
  10.946 +    }
  10.947 +    cpu_khz = cpu_clock[0];
  10.948 +    if (result == 8) {
  10.949 +        cpu_khz <<= 32;
  10.950 +        cpu_khz |= cpu_clock[1];
  10.951 +    }
  10.952 +    cpu_khz /= 1000;
  10.953 +    of_printf("OF: clock-frequency = %ld KHz\n", cpu_khz);
  10.954 +
  10.955 +    /* FIXME: should not depend on the boot CPU bring the first child */
  10.956 +    cpu = of_getpeer(cpu);
  10.957 +    while (cpu > 0) {
  10.958 +        of_start_cpu(cpu, (ulong)spin_start, 0);
  10.959 +        cpu = of_getpeer(cpu);
  10.960 +    }
  10.961 +    return 1;
  10.962 +}
  10.963 +
  10.964 +static int __init boot_of_rtas(void)
  10.965 +{
  10.966 +    return 1;
  10.967 +}
  10.968 +
  10.969 +multiboot_info_t __init *boot_of_init(
  10.970 +        ulong r3, ulong r4, ulong vec, ulong r6, ulong r7, ulong orig_msr)
  10.971 +{
  10.972 +    static multiboot_info_t mbi;
  10.973 +
  10.974 +    of_vec = vec;
  10.975 +    of_msr = orig_msr;
  10.976 +
  10.977 +    bof_chosen = of_finddevice("/chosen");
  10.978 +    of_getprop(bof_chosen, "stdout", &of_out, sizeof (of_out));
  10.979 +
  10.980 +    of_printf("%s\n", "---------------------------------------------------");
  10.981 +    of_printf("OF: Xen/PPC version %d.%d%s (%s@%s) (%s) %s\n",
  10.982 +              XEN_VERSION, XEN_SUBVERSION, XEN_EXTRAVERSION,
  10.983 +              XEN_COMPILE_BY, XEN_COMPILE_DOMAIN,
  10.984 +              XEN_COMPILER, XEN_COMPILE_DATE);
  10.985 +
  10.986 +    of_printf("%s args: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n"
  10.987 +            "boot msr: 0x%lx\n",
  10.988 +            __func__,
  10.989 +            r3, r4, vec, r6, r7, orig_msr);
  10.990 +
  10.991 +    if ((vec >= (ulong)_start) && (vec <= (ulong)_end)) {
  10.992 +        of_printf("Hmm.. OF[0x%lx] seems to have stepped on our image "
  10.993 +                "that ranges: %p .. %p.\n HANG!\n",
  10.994 +                vec, _start, _end);
  10.995 +    }
  10.996 +    of_printf("%s: _start %p _end %p 0x%lx\n", __func__, _start, _end, r6);
  10.997 +
  10.998 +    boot_of_fix_maple();
  10.999 +    boot_of_probemem(&mbi);
 10.1000 +    boot_of_bootargs(&mbi);
 10.1001 +    boot_of_module(r3, r4, &mbi);
 10.1002 +    boot_of_cpus();
 10.1003 +    boot_of_rtas();
 10.1004 +
 10.1005 +    /* end of OF */
 10.1006 +    of_call("quiesce", 0, 0, NULL);
 10.1007 +
 10.1008 +    return &mbi;
 10.1009 +}
 10.1010 +
 10.1011 +/*
 10.1012 + * Local variables:
 10.1013 + * mode: C
 10.1014 + * c-set-style: "BSD"
 10.1015 + * c-basic-offset: 4
 10.1016 + * tab-width: 4
 10.1017 + * indent-tabs-mode: nil
 10.1018 + * End:
 10.1019 + */
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/xen/arch/powerpc/dart.c	Fri Jul 14 10:47:50 2006 +0100
    11.3 @@ -0,0 +1,299 @@
    11.4 +/*
    11.5 + * This program is free software; you can redistribute it and/or modify
    11.6 + * it under the terms of the GNU General Public License as published by
    11.7 + * the Free Software Foundation; either version 2 of the License, or
    11.8 + * (at your option) any later version.
    11.9 + *
   11.10 + * This program is distributed in the hope that it will be useful,
   11.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11.13 + * GNU General Public License for more details.
   11.14 + *
   11.15 + * You should have received a copy of the GNU General Public License
   11.16 + * along with this program; if not, write to the Free Software
   11.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   11.18 + *
   11.19 + * Copyright (C) IBM Corp. 2005
   11.20 + *
   11.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   11.22 + */
   11.23 +
   11.24 +#include <xen/config.h>
   11.25 +#include <xen/types.h>
   11.26 +#include <xen/mm.h>
   11.27 +#include <asm/cache.h>
   11.28 +#include <xen/init.h>
   11.29 +#include "tce.h"
   11.30 +#include "iommu.h"
   11.31 +#include "dart.h"
   11.32 +#include "oftree.h"
   11.33 +#include "of-devtree.h"
   11.34 +
   11.35 +#undef DEBUG
   11.36 +#ifdef DEBUG
   11.37 +#define DBG(fmt...) printk(fmt)
   11.38 +static int dbg_after;
   11.39 +#define DBG_SET_AFTER dbg_after = 1;
   11.40 +#define DBG_AFTER(fmt...) if (dbg_after) DBG(fmt)
   11.41 +#else
   11.42 +#define DBG(fmt...)
   11.43 +#define DBG_SET_AFTER
   11.44 +#define DBG_AFTER(fmt...)
   11.45 +#endif
   11.46 +
   11.47 +/* Max size of 512 pages */
   11.48 +#define U3_LOG_MAX_PAGES 9
   11.49 +
   11.50 +#define DART_DEF_BASE   0xf8033000UL
   11.51 +#define DART_NONE 0
   11.52 +#define DART_U3 3
   11.53 +#define DART_U4 4
   11.54 +#define DART_WRITE 0x1
   11.55 +#define DART_READ 0x2
   11.56 +
   11.57 +static ulong dummy_page;
   11.58 +static ulong dart_entries;
   11.59 +static struct dart_ops *dops;
   11.60 +static u32 *dart_table;
   11.61 +
   11.62 +union dart_entry {
   11.63 +    u32 de_word;
   11.64 +    struct {
   11.65 +        u32 de_v:1;             /* valid */
   11.66 +        u32 de_rp:1;             /* read protected*/
   11.67 +        u32 de_wp:1;             /* write protected*/
   11.68 +        u32 _de_res:5;
   11.69 +        u32 de_ppn:24;         /* 24 bit Physical Page Number
   11.70 +                                 * representing address [28:51] */
   11.71 +    } de_bits;
   11.72 +};
   11.73 +
   11.74 +struct dma_window {
   11.75 +    u32 dw_liobn;
   11.76 +    u32 dw_base_hi;
   11.77 +    u64 dw_base;
   11.78 +    u64 dw_size;
   11.79 +};
   11.80 +
   11.81 +struct dart_info {
   11.82 +    struct dma_window di_window;
   11.83 +    ulong di_base;
   11.84 +    int di_model;
   11.85 +};
   11.86 +
   11.87 +static u32 dart_encode(int perm, ulong rpn)
   11.88 +{
   11.89 +    union dart_entry e;
   11.90 +
   11.91 +    e.de_word = 0;
   11.92 +    e.de_bits.de_v = 1;
   11.93 +    e.de_bits.de_ppn = rpn;
   11.94 +
   11.95 +    /* protect the page */
   11.96 +    e.de_bits.de_rp = 1;
   11.97 +    e.de_bits.de_wp = 1;
   11.98 +    if (perm & DART_READ) {
   11.99 +        e.de_bits.de_rp = 0;
  11.100 +    }
  11.101 +    if (perm & DART_WRITE) {
  11.102 +        e.de_bits.de_wp = 0;
  11.103 +    }
  11.104 +
  11.105 +    return e.de_word;
  11.106 +}
  11.107 +
  11.108 +static void dart_fill(ulong index, int perm, ulong rpg, ulong num_pg)
  11.109 +{
  11.110 +    u32 volatile *entry = dart_table + index;
  11.111 +    ulong i = 0;
  11.112 +    ulong last_flush = 0;
  11.113 +
  11.114 +    while (1) {
  11.115 +        entry[i] = dart_encode(perm, rpg);
  11.116 +        ++i;
  11.117 +        ++rpg;
  11.118 +        if (i == num_pg) break;
  11.119 +
  11.120 +        if (((ulong)&entry[i]) % CACHE_LINE_SIZE == 0) {
  11.121 +            last_flush = (ulong)&entry[i - 1];
  11.122 +            dcbst(last_flush);
  11.123 +        }
  11.124 +    }
  11.125 +    dcbst((ulong) &entry[i - 1]);
  11.126 +}
  11.127 +
  11.128 +static void dart_clear(ulong index, ulong num_pg)
  11.129 +{
  11.130 +    u32 *entry = dart_table + index;
  11.131 +    ulong i = 0;
  11.132 +    ulong rpg = dummy_page;
  11.133 +    ulong last_flush = 0;
  11.134 +
  11.135 +    while (1) {
  11.136 +        entry[i] = dart_encode(DART_READ | DART_WRITE, rpg);
  11.137 +        ++i;
  11.138 +        if (i == num_pg) break;
  11.139 +
  11.140 +        if (((ulong)&entry[i]) % CACHE_LINE_SIZE == 0) {
  11.141 +            last_flush = (ulong)&entry[i - 1];
  11.142 +            dcbst(last_flush);
  11.143 +        }
  11.144 +    }
  11.145 +    dcbst((ulong)&entry[i - 1]);
  11.146 +}
  11.147 +
  11.148 +static int dart_put(ulong ioba, union tce tce)
  11.149 +{
  11.150 +    ulong index = ioba >> PAGE_SHIFT;
  11.151 +
  11.152 +    if (index > dart_entries) {
  11.153 +        return -1;
  11.154 +    }
  11.155 +
  11.156 +    if (tce.tce_bits.tce_vlps  != 0 || tce.tce_bits.tce_lpx != 0) {
  11.157 +        panic("no support for large TCEs\n");
  11.158 +    }
  11.159 +
  11.160 +    if (tce.tce_bits.tce_read == 0 &&
  11.161 +        tce.tce_bits.tce_write == 0) {
  11.162 +        /* the TCE table is inited by the domain by a bunch of 0
  11.163 +         * perminssion puts.  We are only interesting in debugging the
  11.164 +         * ones after the first put */
  11.165 +        DBG_AFTER(">DART[0x%lx] clear\n", index);
  11.166 +        dart_clear(index, 1);
  11.167 +    } else {
  11.168 +        unsigned perm = 0;
  11.169 +
  11.170 +        if (tce.tce_bits.tce_read)
  11.171 +            perm |= DART_READ;
  11.172 +        if (tce.tce_bits.tce_write)
  11.173 +            perm |= DART_WRITE;
  11.174 +
  11.175 +        DBG("<DART[0x%lx]: ioba: 0x%lx perm:%x[%c%c] rpn:0x%lx\n",
  11.176 +            index, ioba, perm,
  11.177 +            (perm & DART_READ) ? 'R' : '-',
  11.178 +            (perm & DART_WRITE) ? 'W' : '-',
  11.179 +            (ulong)tce.tce_bits.tce_rpn);
  11.180 +        DBG_SET_AFTER;
  11.181 +
  11.182 +        dart_fill(index, perm, tce.tce_bits.tce_rpn, 1);
  11.183 +    }
  11.184 +    dops->do_inv_entry(tce.tce_bits.tce_rpn);
  11.185 +    
  11.186 +    return 0;
  11.187 +}
  11.188 +
  11.189 +static int find_dart(struct dart_info *di)
  11.190 +{
  11.191 +    int rc;
  11.192 +    void *ofd_p;
  11.193 +    ofdn_t n;
  11.194 +    char compat[128];
  11.195 +
  11.196 +
  11.197 +    if (on_mambo()) {
  11.198 +        /* mambo has no dart */
  11.199 +        DBG("%s: Mambo does not support a dart\n", __func__);
  11.200 +        return -1;
  11.201 +    }
  11.202 +
  11.203 +    ofd_p = (void *)oftree;
  11.204 +    n = ofd_node_find(ofd_p, "/ht");
  11.205 +    if (n <= 0)
  11.206 +        return -1;
  11.207 +
  11.208 +    /* get the defaults from the HT node model */
  11.209 +    rc = ofd_getprop(ofd_p, n, "compatible", compat, sizeof (compat));
  11.210 +    if (rc <= 0)
  11.211 +        return -1;
  11.212 +
  11.213 +    di->di_base = DART_DEF_BASE;
  11.214 +
  11.215 +    if (strstr(compat, "u3")) {
  11.216 +        di->di_model = DART_U3;
  11.217 +    } else if (strstr(compat, "u4")) {
  11.218 +        di->di_model = DART_U4;
  11.219 +    } else {
  11.220 +        DBG("%s: not a U3 or U4\n", __func__);
  11.221 +        return -1;
  11.222 +    }
  11.223 +    /* FIXME: this should actually be the HT reg value */
  11.224 +    di->di_window.dw_liobn = 0;
  11.225 +    di->di_window.dw_base_hi = 0;
  11.226 +    di->di_window.dw_base = 0;
  11.227 +
  11.228 +    /* lets see if the devtree has more info */
  11.229 +    n = ofd_node_find(ofd_p, "/dart");
  11.230 +    if (n > 0) {
  11.231 +        ulong base;
  11.232 +
  11.233 +        rc = ofd_getprop(ofd_p, n, "compatible", compat, sizeof (compat));
  11.234 +        if (rc > 0) {
  11.235 +            if (strstr(compat, "u4")) {
  11.236 +                di->di_model = DART_U4;
  11.237 +            }
  11.238 +        }
  11.239 +
  11.240 +        rc = ofd_getprop(ofd_p, n, "reg", &base, sizeof (base));
  11.241 +        if (rc > 0) {
  11.242 +            di->di_base = base;
  11.243 +        }
  11.244 +    }
  11.245 +    return 0;
  11.246 +}
  11.247 +
  11.248 +static int init_dart(void)
  11.249 +{
  11.250 +    ulong log_pgs;
  11.251 +    void *ofd_p;
  11.252 +    ofdn_t n;
  11.253 +    struct dart_info di;
  11.254 +
  11.255 +    if (find_dart(&di))
  11.256 +        return 0;
  11.257 +
  11.258 +    /* Max size of 512 pages == 2MB == 1<<21. That siz is good enough for U4 */
  11.259 +    log_pgs = U3_LOG_MAX_PAGES;
  11.260 +    dart_table = alloc_xenheap_pages(log_pgs);
  11.261 +    BUG_ON(dart_table == NULL);
  11.262 +
  11.263 +    dart_entries = (1UL << (log_pgs + PAGE_SHIFT)) / sizeof (union dart_entry);
  11.264 +    di.di_window.dw_size = dart_entries << PAGE_SHIFT;
  11.265 +
  11.266 +    /* Linux uses a dummy page, filling "empty" DART entries with a
  11.267 +       reference to this page to capture stray DMA's */
  11.268 +    dummy_page = (ulong)alloc_xenheap_pages(1);
  11.269 +    memset((void *)dummy_page, 0, PAGE_SIZE);
  11.270 +    dummy_page >>= PAGE_SHIFT;
  11.271 +
  11.272 +    printk("Initializing DART 0x%lx: tbl: %p[0x%lx] entries: 0x%lx\n",
  11.273 +           di.di_base, dart_table, 1UL << log_pgs, dart_entries);
  11.274 +           
  11.275 +    /* register this iommu */
  11.276 +    iommu_register(di.di_window.dw_liobn, dart_put);
  11.277 +
  11.278 +    switch (di.di_model) {
  11.279 +    case DART_U3:
  11.280 +        dops = u3_init(di.di_base, (ulong)dart_table, 1UL << log_pgs);
  11.281 +        break;
  11.282 +    case DART_U4:
  11.283 +        dops = u4_init(di.di_base, (ulong)dart_table, 1UL << log_pgs);
  11.284 +        break;
  11.285 +    }
  11.286 +
  11.287 +    dart_clear(0, dart_entries);
  11.288 +    dops->do_inv_all();
  11.289 +
  11.290 +    /* fix up the devtree */
  11.291 +    ofd_p = (void *)oftree;
  11.292 +    n = ofd_node_find(ofd_p, "/ht");
  11.293 +    if (n > 0) {
  11.294 +        di.di_window.dw_size = dart_entries << PAGE_SHIFT;
  11.295 +        ofd_prop_add(ofd_p, n, "ibm,dma-window", &di.di_window,
  11.296 +                     sizeof (di.di_window));
  11.297 +    } else {
  11.298 +        panic("%s: no /ht node\n", __func__);
  11.299 +    }
  11.300 +    return 0;
  11.301 +}
  11.302 +__initcall(init_dart);
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/xen/arch/powerpc/dart.h	Fri Jul 14 10:47:50 2006 +0100
    12.3 @@ -0,0 +1,36 @@
    12.4 +/*
    12.5 + * This program is free software; you can redistribute it and/or modify
    12.6 + * it under the terms of the GNU General Public License as published by
    12.7 + * the Free Software Foundation; either version 2 of the License, or
    12.8 + * (at your option) any later version.
    12.9 + *
   12.10 + * This program is distributed in the hope that it will be useful,
   12.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   12.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12.13 + * GNU General Public License for more details.
   12.14 + *
   12.15 + * You should have received a copy of the GNU General Public License
   12.16 + * along with this program; if not, write to the Free Software
   12.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   12.18 + *
   12.19 + * Copyright (C) IBM Corp. 2005
   12.20 + *
   12.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   12.22 + */
   12.23 +
   12.24 +#ifndef _DART_H
   12.25 +#define _DART_H
   12.26 +
   12.27 +#include <xen/config.h>
   12.28 +#include <xen/types.h>
   12.29 +
   12.30 +struct dart_ops {
   12.31 +    void (*do_inv_all)(void);
   12.32 +    void (*do_inv_entry)(ulong pg);
   12.33 +};
   12.34 +
   12.35 +extern struct dart_ops *u3_init(ulong base, ulong table, ulong dart_pages);
   12.36 +extern struct dart_ops *u4_init(ulong base, ulong table, ulong dart_pages);
   12.37 +
   12.38 +#endif /* _DART_H */
   12.39 +
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/xen/arch/powerpc/dart_u3.c	Fri Jul 14 10:47:50 2006 +0100
    13.3 @@ -0,0 +1,108 @@
    13.4 +/*
    13.5 + * This program is free software; you can redistribute it and/or modify
    13.6 + * it under the terms of the GNU General Public License as published by
    13.7 + * the Free Software Foundation; either version 2 of the License, or
    13.8 + * (at your option) any later version.
    13.9 + *
   13.10 + * This program is distributed in the hope that it will be useful,
   13.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13.13 + * GNU General Public License for more details.
   13.14 + *
   13.15 + * You should have received a copy of the GNU General Public License
   13.16 + * along with this program; if not, write to the Free Software
   13.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   13.18 + *
   13.19 + * Copyright (C) IBM Corp. 2005
   13.20 + *
   13.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   13.22 + */
   13.23 +
   13.24 +#undef DEBUG
   13.25 +
   13.26 +#include <xen/config.h>
   13.27 +#include <xen/types.h>
   13.28 +#include <xen/sched.h>
   13.29 +#include <xen/mm.h>
   13.30 +#include <public/xen.h>
   13.31 +#include <asm/io.h>
   13.32 +#include <asm/current.h>
   13.33 +#include "tce.h"
   13.34 +#include "iommu.h"
   13.35 +#include "dart.h"
   13.36 +
   13.37 +union dart_ctl {
   13.38 +    u32 dc_word;
   13.39 +    struct {
   13.40 +        u32 dc_base:20;
   13.41 +        u32 dc_stop_access:1;
   13.42 +        u32 dc_invtlb:1;
   13.43 +        u32 dc_enable:1;
   13.44 +        u32 dc_size:9;
   13.45 +    } reg;
   13.46 +};
   13.47 +
   13.48 +static u32 volatile *dart_ctl_reg;
   13.49 +
   13.50 +static void u3_inv_all(void)
   13.51 +{
   13.52 +    union dart_ctl dc;
   13.53 +    ulong r = 0;
   13.54 +    int l = 0;
   13.55 +
   13.56 +    for (;;) {
   13.57 +        dc.dc_word = in_32(dart_ctl_reg);
   13.58 +        dc.reg.dc_invtlb = 1;
   13.59 +        out_32(dart_ctl_reg, dc.dc_word);
   13.60 +
   13.61 +    do {
   13.62 +        dc.dc_word = in_32(dart_ctl_reg);
   13.63 +        r++;
   13.64 +    } while ((dc.reg.dc_invtlb == 1) && (r < (1 << l)));
   13.65 +
   13.66 +        if (r == (1 << l)) {
   13.67 +            if (l < 4) {
   13.68 +                l++;
   13.69 +                dc.dc_word = in_32(dart_ctl_reg);
   13.70 +                dc.reg.dc_invtlb = 0;
   13.71 +                out_32(dart_ctl_reg, dc.dc_word);
   13.72 +                continue;
   13.73 +            } else {
   13.74 +                panic(" broken U3???\n");
   13.75 +            }
   13.76 +        }
   13.77 +        return;
   13.78 +    }
   13.79 +}
   13.80 +
   13.81 +static void u3_inv_entry(ulong pg)
   13.82 +{
   13.83 +    /* sadly single entry invalidation has been reported not to work */
   13.84 +    u3_inv_all();
   13.85 +}
   13.86 +
   13.87 +static struct dart_ops u3_ops = {
   13.88 +    .do_inv_all = u3_inv_all,
   13.89 +    .do_inv_entry = u3_inv_entry,
   13.90 +};
   13.91 +
   13.92 +struct dart_ops *u3_init(ulong base, ulong table, ulong dart_pages)
   13.93 +{
   13.94 +    union dart_ctl dc;
   13.95 +
   13.96 +    dart_ctl_reg = (u32 *)base;
   13.97 +
   13.98 +    dc.dc_word = 0;
   13.99 +
  13.100 +    dc.reg.dc_base = table >> PAGE_SHIFT;
  13.101 +    dc.reg.dc_size = dart_pages;
  13.102 +    dc.reg.dc_enable = 1;
  13.103 +
  13.104 +
  13.105 +    printk("Initializing DART Model U3: reg: %p word: %x\n",
  13.106 +           dart_ctl_reg, dc.dc_word);
  13.107 +
  13.108 +    out_32(dart_ctl_reg, dc.dc_word);
  13.109 +
  13.110 +    return &u3_ops;
  13.111 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/xen/arch/powerpc/dart_u4.c	Fri Jul 14 10:47:50 2006 +0100
    14.3 @@ -0,0 +1,177 @@
    14.4 +/*
    14.5 + * This program is free software; you can redistribute it and/or modify
    14.6 + * it under the terms of the GNU General Public License as published by
    14.7 + * the Free Software Foundation; either version 2 of the License, or
    14.8 + * (at your option) any later version.
    14.9 + *
   14.10 + * This program is distributed in the hope that it will be useful,
   14.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14.13 + * GNU General Public License for more details.
   14.14 + *
   14.15 + * You should have received a copy of the GNU General Public License
   14.16 + * along with this program; if not, write to the Free Software
   14.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   14.18 + *
   14.19 + * Copyright (C) IBM Corp. 2005
   14.20 + *
   14.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   14.22 + */
   14.23 +
   14.24 +#undef DEBUG
   14.25 +
   14.26 +#include <xen/config.h>
   14.27 +#include <xen/types.h>
   14.28 +#include <xen/sched.h>
   14.29 +#include <xen/init.h>
   14.30 +#include <xen/mm.h>
   14.31 +#include <public/xen.h>
   14.32 +#include <asm/io.h>
   14.33 +#include <asm/current.h>
   14.34 +#include "tce.h"
   14.35 +#include "iommu.h"
   14.36 +#include "dart.h"
   14.37 +
   14.38 +#define TOO_MANY_RETRIES ~0
   14.39 +
   14.40 +union dart_ctl {
   14.41 +    u32 dc_word;
   14.42 +    struct {
   14.43 +        u32 dc_darten:1;      /* DART Enable (0:disabled) */
   14.44 +        u32 dc_ione:1;        /* Invalidate one DART TLB entry (using ILPN) */
   14.45 +        u32 dc_iall:1;        /* Invalidate all DART TLB entries */
   14.46 +        u32 dc_idle:1;        /* DART is idle */
   14.47 +        u32 dc_peen:1;        /* Parity Checking is enabled */
   14.48 +        u32 dc_ilpn:27;       /* 27-bit Logical Page Address for 
   14.49 +                               * invalidating one TLB entry */
   14.50 +    } dc_bits;
   14.51 +};
   14.52 +
   14.53 +union dart_base {
   14.54 +    u32 db_word;
   14.55 +    struct {
   14.56 +        u32 _db_resv:8;
   14.57 +        u32 db_dartbase:24;     /* Base Address of DART (4K byte Alignment) */
   14.58 +    } db_bits;
   14.59 +};
   14.60 +
   14.61 +union dart_size {
   14.62 +    u32 ds_word;
   14.63 +    struct {
   14.64 +        u32 _ds_resv:15;
   14.65 +        u32 ds_dartsize:17;     /* Size of Dart in 4K-Byte Pages */
   14.66 +    } ds_bits;
   14.67 +};
   14.68 +
   14.69 +union dart_excp {
   14.70 +    u32 de_word;
   14.71 +    struct {
   14.72 +        u32 de_rqsrc:1;    /* Request Source.  [0:PCIE, 1:HT] */
   14.73 +        u32 de_lpn:27;     /* 27–bit Logical Address of Exception [25:51] */
   14.74 +        u32 de_rqop:1;     /* Request operation.  [0:Read, 1:Write] */
   14.75 +        u32 de_xcd:3;      /* Exception code */
   14.76 +    } de_bits;
   14.77 +};
   14.78 +
   14.79 +struct dart {
   14.80 +    /* 0x00 */
   14.81 +    union dart_ctl d_dartcntl;
   14.82 +    u32 _pad0x04_0x10[3];
   14.83 +    /* 0x10 */
   14.84 +    union dart_base d_dartbase;
   14.85 +    u32 _pad0x14_0x20[3];
   14.86 +    /* 0x20 */
   14.87 +    union dart_size d_dartsize;
   14.88 +    u32 _pad0x24_0x30[3];
   14.89 +    /* 0x30 */
   14.90 +    union dart_excp d_dartexcp;
   14.91 +    u32 _pad0x34_0x40[3];
   14.92 +};
   14.93 +
   14.94 +static volatile struct dart *dart;
   14.95 +
   14.96 +static void u4_inv_all(void)
   14.97 +{
   14.98 +    union dart_ctl dc;
   14.99 +    ulong r = 0;
  14.100 +    int l = 0;
  14.101 +
  14.102 +    for (;;) {
  14.103 +        dc.dc_word = in_32(&dart->d_dartcntl.dc_word);
  14.104 +        dc.dc_bits.dc_iall = 1;
  14.105 +        out_32(&dart->d_dartcntl.dc_word, dc.dc_word);
  14.106 +
  14.107 +        do {
  14.108 +            dc.dc_word = in_32(&dart->d_dartcntl.dc_word);
  14.109 +            r++;
  14.110 +        } while ((dc.dc_bits.dc_iall == 1) && (r < (1 << l)));
  14.111 +
  14.112 +        if (r == (1 << l)) {
  14.113 +            if (l < 4) {
  14.114 +                l++;
  14.115 +                dc.dc_word = in_32(&dart->d_dartcntl.dc_word);
  14.116 +                dc.dc_bits.dc_iall = 0;
  14.117 +                out_32(&dart->d_dartcntl.dc_word, dc.dc_word);
  14.118 +                continue;
  14.119 +            } else {
  14.120 +                panic(" broken U4???\n");
  14.121 +            }
  14.122 +        }
  14.123 +        return;
  14.124 +    }
  14.125 +}
  14.126 +
  14.127 +static void u4_inv_entry(ulong pgn)
  14.128 +{
  14.129 +    union dart_ctl dc;
  14.130 +    ulong retries = 0;
  14.131 +
  14.132 +    dc.dc_word = in_32(&dart->d_dartcntl.dc_word);
  14.133 +    dc.dc_bits.dc_ilpn = pgn;
  14.134 +    dc.dc_bits.dc_ione = 1;
  14.135 +    out_32(&dart->d_dartcntl.dc_word, dc.dc_word);
  14.136 +
  14.137 +    /* wait for completion */
  14.138 +    /* FIXME: since we do this from the HV do we need to wait?! */
  14.139 +    do {
  14.140 +        dc.dc_word = in_32(&dart->d_dartcntl.dc_word);
  14.141 +        retries++;
  14.142 +        if (retries > 1000000)
  14.143 +            panic("WAY! too long\n");
  14.144 +    } while (dc.dc_bits.dc_ione != 0);
  14.145 +}
  14.146 +
  14.147 +static struct dart_ops u4_ops = {
  14.148 +    .do_inv_all = u4_inv_all,
  14.149 +    .do_inv_entry = u4_inv_entry,
  14.150 +};
  14.151 +
  14.152 +struct dart_ops *u4_init(ulong base, ulong table, ulong dart_pages)
  14.153 +{
  14.154 +    union dart_base db;
  14.155 +    union dart_size ds;
  14.156 +    union dart_ctl dc;
  14.157 +
  14.158 +    dart = (struct dart *)base;
  14.159 +
  14.160 +    db.db_word = 0;
  14.161 +    db.db_bits.db_dartbase = table >> PAGE_SHIFT;
  14.162 +
  14.163 +    ds.ds_word = 0;
  14.164 +    ds.ds_bits.ds_dartsize = dart_pages;
  14.165 +
  14.166 +    dc.dc_word = in_32(&dart->d_dartcntl.dc_word);
  14.167 +    if (dc.dc_bits.dc_darten == 1) {
  14.168 +        panic("%s: dart is already enabled: 0x%x\n", __func__, dc.dc_word);
  14.169 +    }
  14.170 +    dc.dc_bits.dc_darten = 1;   /* enable it */
  14.171 +
  14.172 +    printk("Initializing DART Model U4: ctl: 0x%x base: 0x%x size: 0x%x\n",
  14.173 +           dc.dc_word, db.db_word, ds.ds_word);
  14.174 +
  14.175 +    out_32(&dart->d_dartbase.db_word, db.db_word);
  14.176 +    out_32(&dart->d_dartsize.ds_word, ds.ds_word);
  14.177 +    out_32(&dart->d_dartcntl.dc_word, dc.dc_word);
  14.178 +
  14.179 +    return &u4_ops;
  14.180 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/xen/arch/powerpc/delay.c	Fri Jul 14 10:47:50 2006 +0100
    15.3 @@ -0,0 +1,37 @@
    15.4 +/*
    15.5 + * This program is free software; you can redistribute it and/or modify
    15.6 + * it under the terms of the GNU General Public License as published by
    15.7 + * the Free Software Foundation; either version 2 of the License, or
    15.8 + * (at your option) any later version.
    15.9 + *
   15.10 + * This program is distributed in the hope that it will be useful,
   15.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   15.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15.13 + * GNU General Public License for more details.
   15.14 + *
   15.15 + * You should have received a copy of the GNU General Public License
   15.16 + * along with this program; if not, write to the Free Software
   15.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   15.18 + *
   15.19 + * Copyright (C) IBM Corp. 2005
   15.20 + *
   15.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   15.22 + */
   15.23 +
   15.24 +#include <xen/config.h>
   15.25 +#include <xen/delay.h>
   15.26 +#include <xen/time.h>
   15.27 +#include <asm/processor.h>
   15.28 +
   15.29 +void udelay(unsigned long usecs)
   15.30 +{
   15.31 +    ulong ticks = usecs * ticks_per_usec;
   15.32 +    ulong s;
   15.33 +    ulong e;
   15.34 +
   15.35 +    s = get_timebase();
   15.36 +    do {
   15.37 +        asm volatile("or 1,1,1"); /* also puts the thread to low priority */
   15.38 +        e = get_timebase();
   15.39 +    } while ((e-s) < ticks);
   15.40 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/xen/arch/powerpc/dom0_ops.c	Fri Jul 14 10:47:50 2006 +0100
    16.3 @@ -0,0 +1,87 @@
    16.4 +/*
    16.5 + * This program is free software; you can redistribute it and/or modify
    16.6 + * it under the terms of the GNU General Public License as published by
    16.7 + * the Free Software Foundation; either version 2 of the License, or
    16.8 + * (at your option) any later version.
    16.9 + *
   16.10 + * This program is distributed in the hope that it will be useful,
   16.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16.13 + * GNU General Public License for more details.
   16.14 + *
   16.15 + * You should have received a copy of the GNU General Public License
   16.16 + * along with this program; if not, write to the Free Software
   16.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   16.18 + *
   16.19 + * Copyright (C) IBM Corp. 2005
   16.20 + *
   16.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   16.22 + */
   16.23 +
   16.24 +#include <xen/config.h>
   16.25 +#include <xen/types.h>
   16.26 +#include <xen/lib.h>
   16.27 +#include <xen/sched.h>
   16.28 +#include <xen/guest_access.h>
   16.29 +#include <public/xen.h>
   16.30 +#include <public/dom0_ops.h>
   16.31 +
   16.32 +extern void arch_getdomaininfo_ctxt(struct vcpu *v, vcpu_guest_context_t *c);
   16.33 +extern long arch_do_dom0_op(struct dom0_op *op, XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op);
   16.34 +
   16.35 +void arch_getdomaininfo_ctxt(struct vcpu *v, vcpu_guest_context_t *c)
   16.36 +{ 
   16.37 +    memcpy(&c->user_regs, &v->arch.ctxt, sizeof(struct cpu_user_regs));
   16.38 +    /* XXX fill in rest of vcpu_guest_context_t */
   16.39 +}
   16.40 +
   16.41 +long arch_do_dom0_op(struct dom0_op *op, XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op)
   16.42 +{
   16.43 +    long ret = 0;
   16.44 +
   16.45 +    switch (op->cmd) {
   16.46 +    case DOM0_GETMEMLIST: {
   16.47 +        /* XXX 64M hackage */
   16.48 +        const int memsize = (64UL<<20);
   16.49 +        int domain_pfns = memsize>>12;
   16.50 +        int max_pfns = op->u.getmemlist.max_pfns;
   16.51 +        int domid = op->u.getmemlist.domain;
   16.52 +        int i;
   16.53 +
   16.54 +        for (i = 0; (i < max_pfns) && (i < domain_pfns); i++) {
   16.55 +            xen_pfn_t mfn = (((domid + 1) * memsize) >> 12) + i;
   16.56 +            if (copy_to_guest_offset(op->u.getmemlist.buffer, i, &mfn, 1)) {
   16.57 +                ret = -EFAULT;
   16.58 +                break;
   16.59 +            }
   16.60 +        }
   16.61 +        op->u.getmemlist.num_pfns = i;
   16.62 +        copy_to_guest(u_dom0_op, op, 1);
   16.63 +    }
   16.64 +    break;
   16.65 +
   16.66 +    case DOM0_PHYSINFO:
   16.67 +    {
   16.68 +        dom0_physinfo_t *pi = &op->u.physinfo;
   16.69 +
   16.70 +        pi->threads_per_core = 1;
   16.71 +        pi->cores_per_socket = 1;
   16.72 +        pi->sockets_per_node = 1;
   16.73 +        pi->nr_nodes         = 1;
   16.74 +        pi->total_pages      = total_pages;
   16.75 +        pi->free_pages       = avail_domheap_pages();
   16.76 +        pi->cpu_khz          = cpu_khz;
   16.77 +        memset(pi->hw_cap, 0, sizeof(pi->hw_cap));
   16.78 +        ret = 0;
   16.79 +        if ( copy_to_guest(u_dom0_op, op, 1) )
   16.80 +            ret = -EFAULT;
   16.81 +    }
   16.82 +    break;
   16.83 +
   16.84 +    default:
   16.85 +        ret = -ENOSYS;
   16.86 +        break;
   16.87 +    }
   16.88 +
   16.89 +    return ret;
   16.90 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/xen/arch/powerpc/domain.c	Fri Jul 14 10:47:50 2006 +0100
    17.3 @@ -0,0 +1,251 @@
    17.4 +/*
    17.5 + * This program is free software; you can redistribute it and/or modify
    17.6 + * it under the terms of the GNU General Public License as published by
    17.7 + * the Free Software Foundation; either version 2 of the License, or
    17.8 + * (at your option) any later version.
    17.9 + *
   17.10 + * This program is distributed in the hope that it will be useful,
   17.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   17.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17.13 + * GNU General Public License for more details.
   17.14 + *
   17.15 + * You should have received a copy of the GNU General Public License
   17.16 + * along with this program; if not, write to the Free Software
   17.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   17.18 + *
   17.19 + * Copyright (C) IBM Corp. 2005, 2006
   17.20 + *
   17.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   17.22 + */
   17.23 +
   17.24 +#include <stdarg.h>
   17.25 +#include <xen/config.h>
   17.26 +#include <xen/lib.h>
   17.27 +#include <xen/sched.h>
   17.28 +#include <xen/mm.h>
   17.29 +#include <xen/serial.h>
   17.30 +#include <xen/domain.h>
   17.31 +#include <xen/console.h>
   17.32 +#include <xen/reboot.h>
   17.33 +#include <asm/htab.h>
   17.34 +#include <asm/current.h>
   17.35 +#include <asm/hcalls.h>
   17.36 +
   17.37 +extern void idle_loop(void);
   17.38 +
   17.39 +#define next_arg(fmt, args) ({                                              \
   17.40 +    unsigned long __arg;                                                    \
   17.41 +    switch ( *(fmt)++ )                                                     \
   17.42 +    {                                                                       \
   17.43 +    case 'i': __arg = (unsigned long)va_arg(args, unsigned int);  break;    \
   17.44 +    case 'l': __arg = (unsigned long)va_arg(args, unsigned long); break;    \
   17.45 +    case 'p': __arg = (unsigned long)va_arg(args, void *);        break;    \
   17.46 +    case 'h': __arg = (unsigned long)va_arg(args, void *);        break;    \
   17.47 +    default:  __arg = 0; BUG();                                             \
   17.48 +    }                                                                       \
   17.49 +    __arg;                                                                  \
   17.50 +})
   17.51 +
   17.52 +unsigned long hypercall_create_continuation(unsigned int op,
   17.53 +        const char *format, ...)
   17.54 +{
   17.55 +    struct cpu_user_regs *regs = guest_cpu_user_regs();
   17.56 +    const char *p = format;
   17.57 +    va_list args;
   17.58 +    int gprnum = 4;
   17.59 +    int i;
   17.60 +
   17.61 +    va_start(args, format);
   17.62 +
   17.63 +    regs->pc -= 4; /* re-execute 'sc' */
   17.64 +
   17.65 +    for (i = 0; *p != '\0'; i++) {
   17.66 +        regs->gprs[gprnum++] = next_arg(p, args);
   17.67 +    }
   17.68 +
   17.69 +    va_end(args);
   17.70 +
   17.71 +    /* As luck would have it, we use the same register for hcall opcodes and
   17.72 +     * for hcall return values. The return value from this function is placed
   17.73 +     * in r3 on return, so modifying regs->gprs[3] would have no effect. */
   17.74 +    return XEN_MARK(op);
   17.75 +}
   17.76 +
   17.77 +int arch_domain_create(struct domain *d)
   17.78 +{
   17.79 +
   17.80 +    if (d->domain_id == IDLE_DOMAIN_ID) {
   17.81 +        d->shared_info = (void *)alloc_xenheap_page();
   17.82 +        clear_page(d->shared_info);
   17.83 +
   17.84 +        return 0;
   17.85 +    }
   17.86 +
   17.87 +    /* XXX the hackage... hardcode 64M domains */
   17.88 +    d->arch.rma_base = (64<<20) * (d->domain_id + 1);
   17.89 +    d->arch.rma_size = (64<<20);
   17.90 +
   17.91 +    printk("clearing RMO: 0x%lx[0x%lx]\n", d->arch.rma_base, d->arch.rma_size);
   17.92 +    memset((void*)d->arch.rma_base, 0, d->arch.rma_size);
   17.93 +
   17.94 +    htab_alloc(d, LOG_DEFAULT_HTAB_BYTES);
   17.95 +
   17.96 +    d->shared_info = (shared_info_t *)
   17.97 +        (rma_addr(&d->arch, RMA_SHARED_INFO) + d->arch.rma_base);
   17.98 +
   17.99 +    d->arch.large_page_sizes = 1;
  17.100 +    d->arch.large_page_shift[0] = 24; /* 16 M for 970s */
  17.101 +
  17.102 +    return 0;
  17.103 +}
  17.104 +
  17.105 +void arch_domain_destroy(struct domain *d)
  17.106 +{
  17.107 +    unimplemented();
  17.108 +}
  17.109 +
  17.110 +void machine_halt(void)
  17.111 +{
  17.112 +    printf("machine_halt called: spinning....\n");
  17.113 +    console_start_sync();
  17.114 +    while(1);
  17.115 +}
  17.116 +
  17.117 +void machine_restart(char * __unused)
  17.118 +{
  17.119 +    printf("machine_restart called: spinning....\n");
  17.120 +    console_start_sync();
  17.121 +    while(1);
  17.122 +}
  17.123 +
  17.124 +struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id)
  17.125 +{
  17.126 +    struct vcpu *v;
  17.127 +
  17.128 +    if ( (v = xmalloc(struct vcpu)) == NULL )
  17.129 +        return NULL;
  17.130 +
  17.131 +    memset(v, 0, sizeof(*v));
  17.132 +    v->vcpu_id = vcpu_id;
  17.133 +
  17.134 +    return v;
  17.135 +}
  17.136 +
  17.137 +void free_vcpu_struct(struct vcpu *v)
  17.138 +{
  17.139 +    BUG_ON(v->next_in_list != NULL);
  17.140 +    if ( v->vcpu_id != 0 )
  17.141 +        v->domain->vcpu[v->vcpu_id - 1]->next_in_list = NULL;
  17.142 +    xfree(v);
  17.143 +}
  17.144 +
  17.145 +int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_t *c)
  17.146 +{ 
  17.147 +    memcpy(&v->arch.ctxt, &c->user_regs, sizeof(c->user_regs));
  17.148 +
  17.149 +    set_bit(_VCPUF_initialised, &v->vcpu_flags);
  17.150 +
  17.151 +    cpu_init_vcpu(v);
  17.152 +
  17.153 +    return 0;
  17.154 +}
  17.155 +
  17.156 +void dump_pageframe_info(struct domain *d)
  17.157 +{
  17.158 +    struct page_info *page;
  17.159 +
  17.160 +    printk("Memory pages belonging to domain %u:\n", d->domain_id);
  17.161 +
  17.162 +    if ( d->tot_pages >= 10 )
  17.163 +    {
  17.164 +        printk("    DomPage list too long to display\n");
  17.165 +    }
  17.166 +    else
  17.167 +    {
  17.168 +        list_for_each_entry ( page, &d->page_list, list )
  17.169 +        {
  17.170 +            printk("    DomPage %p: mfn=%p, caf=%016lx, taf=%" PRtype_info "\n",
  17.171 +                   _p(page_to_maddr(page)), _p(page_to_mfn(page)),
  17.172 +                   page->count_info, page->u.inuse.type_info);
  17.173 +        }
  17.174 +    }
  17.175 +
  17.176 +    list_for_each_entry ( page, &d->xenpage_list, list )
  17.177 +    {
  17.178 +        printk("    XenPage %p: mfn=%p, caf=%016lx, taf=%" PRtype_info "\n",
  17.179 +               _p(page_to_maddr(page)), _p(page_to_mfn(page)),
  17.180 +               page->count_info, page->u.inuse.type_info);
  17.181 +    }
  17.182 +}
  17.183 +
  17.184 +
  17.185 +void context_switch(struct vcpu *prev, struct vcpu *next)
  17.186 +{
  17.187 +    struct cpu_user_regs *stack_regs = guest_cpu_user_regs();
  17.188 +    cpumask_t dirty_mask = next->vcpu_dirty_cpumask;
  17.189 +    unsigned int cpu = smp_processor_id();
  17.190 +
  17.191 +#if 0
  17.192 +    printf("%s: dom %x to dom %x\n", __func__, prev->domain->domain_id,
  17.193 +            next->domain->domain_id);
  17.194 +#endif
  17.195 +
  17.196 +    /* Allow at most one CPU at a time to be dirty. */
  17.197 +    ASSERT(cpus_weight(dirty_mask) <= 1);
  17.198 +    if (unlikely(!cpu_isset(cpu, dirty_mask) && !cpus_empty(dirty_mask)))
  17.199 +    {
  17.200 +        /* Other cpus call __sync_lazy_execstate from flush ipi handler. */
  17.201 +        if (!cpus_empty(next->vcpu_dirty_cpumask))
  17.202 +            flush_tlb_mask(next->vcpu_dirty_cpumask);
  17.203 +    }
  17.204 +
  17.205 +    /* copy prev guest state off the stack into its vcpu */
  17.206 +    memcpy(&prev->arch.ctxt, stack_regs, sizeof(struct cpu_user_regs));
  17.207 +
  17.208 +    set_current(next);
  17.209 +
  17.210 +    /* copy next guest state onto the stack */
  17.211 +    memcpy(stack_regs, &next->arch.ctxt, sizeof(struct cpu_user_regs));
  17.212 +
  17.213 +    /* save old domain state */
  17.214 +    save_sprs(prev);
  17.215 +    save_float(prev);
  17.216 +    save_segments(prev);
  17.217 +
  17.218 +    context_saved(prev);
  17.219 +
  17.220 +    /* load up new domain */
  17.221 +    load_sprs(next);
  17.222 +    load_float(next);
  17.223 +    load_segments(next);
  17.224 +
  17.225 +    mtsdr1(next->domain->arch.htab.sdr1);
  17.226 +    local_flush_tlb(); /* XXX maybe flush_tlb_mask? */
  17.227 +
  17.228 +    if (is_idle_vcpu(next)) {
  17.229 +        reset_stack_and_jump(idle_loop);
  17.230 +    }
  17.231 +
  17.232 +    reset_stack_and_jump(full_resume);
  17.233 +    /* not reached */
  17.234 +}
  17.235 +
  17.236 +void continue_running(struct vcpu *same)
  17.237 +{
  17.238 +    /* nothing to do */
  17.239 +}
  17.240 +
  17.241 +void sync_vcpu_execstate(struct vcpu *v)
  17.242 +{
  17.243 +    /* XXX for now, for domain destruction, make this non-fatal */
  17.244 +    printf("%s: called\n", __func__);
  17.245 +}
  17.246 +
  17.247 +void domain_relinquish_resources(struct domain *d)
  17.248 +{
  17.249 +    /* nothing to do? */
  17.250 +}
  17.251 +
  17.252 +void arch_dump_domain_info(struct domain *d)
  17.253 +{
  17.254 +}
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/xen/arch/powerpc/domain_build.c	Fri Jul 14 10:47:50 2006 +0100
    18.3 @@ -0,0 +1,285 @@
    18.4 +/*
    18.5 + * This program is free software; you can redistribute it and/or modify
    18.6 + * it under the terms of the GNU General Public License as published by
    18.7 + * the Free Software Foundation; either version 2 of the License, or
    18.8 + * (at your option) any later version.
    18.9 + *
   18.10 + * This program is distributed in the hope that it will be useful,
   18.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   18.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18.13 + * GNU General Public License for more details.
   18.14 + *
   18.15 + * You should have received a copy of the GNU General Public License
   18.16 + * along with this program; if not, write to the Free Software
   18.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   18.18 + *
   18.19 + * Copyright (C) IBM Corp. 2005
   18.20 + *
   18.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   18.22 + */
   18.23 +
   18.24 +#include <xen/config.h>
   18.25 +#include <xen/lib.h>
   18.26 +#include <xen/elf.h>
   18.27 +#include <xen/sched.h>
   18.28 +#include <xen/init.h>
   18.29 +#include <xen/ctype.h>
   18.30 +#include <xen/iocap.h>
   18.31 +#include <xen/compile.h>
   18.32 +#include <asm/processor.h>
   18.33 +#include <asm/papr.h>
   18.34 +#include "oftree.h"
   18.35 +
   18.36 +extern int parseelfimage_32(struct domain_setup_info *dsi);
   18.37 +extern int loadelfimage_32(struct domain_setup_info *dsi);
   18.38 +
   18.39 +/* opt_dom0_mem: memory allocated to domain 0. */
   18.40 +static unsigned int opt_dom0_mem;
   18.41 +static void parse_dom0_mem(char *s)
   18.42 +{
   18.43 +    unsigned long long bytes = parse_size_and_unit(s);
   18.44 +    /* If no unit is specified we default to kB units, not bytes. */
   18.45 +    if (isdigit(s[strlen(s)-1]))
   18.46 +        opt_dom0_mem = (unsigned int)bytes;
   18.47 +    else
   18.48 +        opt_dom0_mem = (unsigned int)(bytes >> 10);
   18.49 +}
   18.50 +custom_param("dom0_mem", parse_dom0_mem);
   18.51 +
   18.52 +int elf_sanity_check(Elf_Ehdr *ehdr)
   18.53 +{
   18.54 +    if (IS_ELF(*ehdr))
   18.55 +        /* we are happy with either */
   18.56 +        if ((ehdr->e_ident[EI_CLASS] == ELFCLASS32
   18.57 +             && ehdr->e_machine == EM_PPC)
   18.58 +            || (ehdr->e_ident[EI_CLASS] == ELFCLASS64
   18.59 +                && ehdr->e_machine == EM_PPC64)) {
   18.60 +            if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB
   18.61 +                && ehdr->e_type == ET_EXEC)
   18.62 +                return 1;
   18.63 +        }
   18.64 +    printk("DOM0 image is not a Xen-compatible Elf image.\n");
   18.65 +    return 0;
   18.66 +}
   18.67 +
   18.68 +/* adapted from common/elf.c */
   18.69 +#define RM_MASK(a,l) ((a) & ((1UL << (l)) - 1))
   18.70 +
   18.71 +static int rm_loadelfimage_64(struct domain_setup_info *dsi, ulong rma)
   18.72 +{
   18.73 +    char *elfbase = (char *)dsi->image_addr;
   18.74 +    Elf64_Ehdr *ehdr = (Elf64_Ehdr *)dsi->image_addr;
   18.75 +    Elf64_Phdr *phdr;
   18.76 +    int h;
   18.77 +  
   18.78 +    for (h = 0; h < ehdr->e_phnum; h++ ) 
   18.79 +    {
   18.80 +        phdr = (Elf64_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
   18.81 +        if (!((phdr->p_type == PT_LOAD) &&
   18.82 +             ((phdr->p_flags & (PF_W|PF_X)) != 0)))
   18.83 +            continue;
   18.84 +
   18.85 +        if (phdr->p_filesz != 0)
   18.86 +            memcpy((char *)(rma + RM_MASK(phdr->p_paddr, 42)),
   18.87 +                   elfbase + phdr->p_offset, 
   18.88 +                   phdr->p_filesz);
   18.89 +        if (phdr->p_memsz > phdr->p_filesz)
   18.90 +            memset((char *)(rma + RM_MASK(phdr->p_paddr, 42) + phdr->p_filesz),
   18.91 +                   0, phdr->p_memsz - phdr->p_filesz);
   18.92 +    }
   18.93 +
   18.94 +#ifdef NOT_YET
   18.95 +    loadelfsymtab(dsi, 1);
   18.96 +#endif
   18.97 +
   18.98 +    return 0;
   18.99 +}
  18.100 +
  18.101 +int construct_dom0(struct domain *d,
  18.102 +                   unsigned long image_start, unsigned long image_len, 
  18.103 +                   unsigned long initrd_start, unsigned long initrd_len,
  18.104 +                   char *cmdline)
  18.105 +{
  18.106 +    int rc;
  18.107 +    struct vcpu *v = d->vcpu[0];
  18.108 +    struct domain_setup_info dsi;
  18.109 +    ulong dst;
  18.110 +    u64 *ofh_tree;
  18.111 +    ulong rma_sz = d->arch.rma_size;
  18.112 +    ulong rma = d->arch.rma_base;
  18.113 +    start_info_t *si;
  18.114 +    ulong eomem;
  18.115 +    int am64 = 1;
  18.116 +    ulong msr;
  18.117 +    ulong pc;
  18.118 +    ulong r2;
  18.119 +
  18.120 +    /* Sanity! */
  18.121 +    BUG_ON(d->domain_id != 0);
  18.122 +    BUG_ON(d->vcpu[0] == NULL);
  18.123 +
  18.124 +    cpu_init_vcpu(v);
  18.125 +
  18.126 +    memset(&dsi, 0, sizeof(struct domain_setup_info));
  18.127 +    dsi.image_addr = image_start;
  18.128 +    dsi.image_len  = image_len;
  18.129 +
  18.130 +    if ((rc = parseelfimage(&dsi)) != 0) {
  18.131 +        if ((rc = parseelfimage_32(&dsi)) != 0)
  18.132 +            return rc;
  18.133 +        am64 = 0;
  18.134 +    }
  18.135 +
  18.136 +    /* elf contains virtual addresses that can have the upper bits
  18.137 +     * masked while running in real mode, so we do the masking as well
  18.138 +     * as well */
  18.139 +    dsi.v_kernstart = RM_MASK(dsi.v_kernstart, 42);
  18.140 +    dsi.v_kernend = RM_MASK(dsi.v_kernend, 42);
  18.141 +    dsi.v_kernentry = RM_MASK(dsi.v_kernentry, 42);
  18.142 +
  18.143 +    if (dsi.xen_section_string == NULL) {
  18.144 +        printk("Not a Xen-ELF image: '__xen_guest' section not found.\n");
  18.145 +        return -EINVAL;
  18.146 +    }
  18.147 +    printk("*** LOADING DOMAIN 0 ***\n");
  18.148 +
  18.149 +    /* By default DOM0 is allocated all available memory. */
  18.150 +    d->max_pages = ~0U;
  18.151 +    d->tot_pages = (d->arch.rma_size >> PAGE_SHIFT);
  18.152 +
  18.153 +    ASSERT( image_len < rma_sz );
  18.154 +
  18.155 +    si = (start_info_t *)(rma_addr(&d->arch, RMA_START_INFO) + rma);
  18.156 +    printk("xen_start_info: %p\n", si);
  18.157 +
  18.158 +    sprintf(si->magic, "xen-%i.%i-powerpc%d%s",
  18.159 +            XEN_VERSION, XEN_SUBVERSION, BITS_PER_LONG, "HV");
  18.160 +    si->flags = SIF_PRIVILEGED | SIF_INITDOMAIN;
  18.161 +
  18.162 +    si->shared_info = ((ulong)d->shared_info) - rma;
  18.163 +    printk("shared_info: 0x%lx,%p\n", si->shared_info, d->shared_info);
  18.164 +
  18.165 +    eomem = si->shared_info;
  18.166 +
  18.167 +    /* allow dom0 to access all of system RAM */
  18.168 +    d->arch.logical_base_pfn = 128 << (20 - PAGE_SHIFT); /* 128 MB */
  18.169 +    d->arch.logical_end_pfn = max_page;
  18.170 +
  18.171 +    /* number of pages accessible */
  18.172 +    si->nr_pages = rma_sz >> PAGE_SHIFT;
  18.173 +
  18.174 +    si->pt_base = 0;
  18.175 +    si->nr_pt_frames = 0;
  18.176 +    si->mfn_list = 0;
  18.177 +
  18.178 +    /* OF usually sits here:
  18.179 +     *   - Linux needs it to be loaded before the vmlinux or initrd
  18.180 +     *   - AIX demands it to be @ 32M.
  18.181 +     */
  18.182 +    dst = (32 << 20);
  18.183 +
  18.184 +    /* put stack below everything */
  18.185 +    v->arch.ctxt.gprs[1] = dst - STACK_FRAME_OVERHEAD;
  18.186 +
  18.187 +    /* copy relative to Xen */
  18.188 +    dst += rma;
  18.189 +
  18.190 +    ASSERT((dst - rma) + (ulong)firmware_image_size < eomem);
  18.191 +    printk("loading OFH: 0x%lx, RMA: 0x%lx\n", dst, dst - rma);
  18.192 +    memcpy((void *)dst, firmware_image_start, (ulong)firmware_image_size);
  18.193 +
  18.194 +    v->arch.ctxt.gprs[5] = (dst - rma);
  18.195 +    ofh_tree = (u64 *)(dst + 0x10);
  18.196 +    ASSERT(*ofh_tree == 0xdeadbeef00000000);
  18.197 +
  18.198 +    /* accomodate for a modest bss section */
  18.199 +    dst = ALIGN_UP(dst + (ulong)firmware_image_size + PAGE_SIZE, PAGE_SIZE);
  18.200 +    ASSERT((dst - rma) + oftree_len < eomem);
  18.201 +
  18.202 +    *ofh_tree = dst - rma;
  18.203 +    printk("loading OFD: 0x%lx RMA: 0x%lx, 0x%lx\n", dst, dst - rma,
  18.204 +           oftree_len);
  18.205 +    memcpy((void *)dst, (void *)oftree, oftree_len);
  18.206 +
  18.207 +    dst = ALIGN_UP(dst + oftree_len, PAGE_SIZE);
  18.208 +
  18.209 +    if (am64) {
  18.210 +        ulong kbase;
  18.211 +        ulong *fdesc;
  18.212 +
  18.213 +        printk("loading 64-bit Dom0: 0x%lx, in RMA:0x%lx\n", dst, dst - rma);
  18.214 +        rm_loadelfimage_64(&dsi, dst);
  18.215 +
  18.216 +        kbase = dst;
  18.217 +        /* move dst to end of bss */
  18.218 +        dst = ALIGN_UP(dsi.v_kernend + dst, PAGE_SIZE);
  18.219 +
  18.220 +        if ( initrd_len > 0 ) {
  18.221 +            ASSERT( (dst - rma) + image_len < eomem );
  18.222 +
  18.223 +            printk("loading initrd: 0x%lx, 0x%lx\n", dst, initrd_len);
  18.224 +            memcpy((void *)dst, (void *)initrd_start, initrd_len);
  18.225 +
  18.226 +            si->mod_start = dst - rma;
  18.227 +            si->mod_len = image_len;
  18.228 +
  18.229 +            dst = ALIGN_UP(dst + initrd_len, PAGE_SIZE);
  18.230 +        } else {
  18.231 +            printk("no initrd\n");
  18.232 +            si->mod_start = 0;
  18.233 +            si->mod_len = 0;
  18.234 +        }
  18.235 +        /* it may be a function descriptor */
  18.236 +        fdesc = (ulong *)(dsi.v_kernstart + dsi.v_kernentry + kbase);
  18.237 +
  18.238 +        if (fdesc[2] == 0
  18.239 +            && ((fdesc[0] >= dsi.v_kernstart)
  18.240 +                && (fdesc[0] < dsi.v_kernend)) /* text entry is in range */
  18.241 +            && ((fdesc[1] >= dsi.v_kernstart)  /* toc can be > image */
  18.242 +                && (fdesc[1] < (dsi.v_kernend + (0x7fff * sizeof (ulong)))))) {
  18.243 +            /* it is almost certainly a function descriptor */
  18.244 +            pc = RM_MASK(fdesc[0], 42) + kbase - rma;
  18.245 +            r2 = RM_MASK(fdesc[1], 42) + kbase - rma;
  18.246 +        } else {
  18.247 +            pc = ((ulong)fdesc) - rma;
  18.248 +            r2 = 0;
  18.249 +        }
  18.250 +        msr = MSR_SF;
  18.251 +    } else {
  18.252 +        printk("loading 32-bit Dom0: 0x%lx, in RMA:0x%lx\n",
  18.253 +               dsi.v_kernstart + rma, dsi.v_kernstart);
  18.254 +        dsi.v_start = rma;
  18.255 +        loadelfimage_32(&dsi);
  18.256 +
  18.257 +        pc = dsi.v_kernentry;
  18.258 +        r2 = 0;
  18.259 +        msr = 0;
  18.260 +    }
  18.261 +
  18.262 +    v->arch.ctxt.gprs[3] = si->mod_start;
  18.263 +    v->arch.ctxt.gprs[4] = si->mod_len;
  18.264 +
  18.265 +    memset(si->cmd_line, 0, sizeof(si->cmd_line));
  18.266 +    if ( cmdline != NULL )
  18.267 +        strncpy((char *)si->cmd_line, cmdline, sizeof(si->cmd_line)-1);
  18.268 +
  18.269 +    v->arch.ctxt.msr = msr;
  18.270 +    v->arch.ctxt.pc = pc;
  18.271 +    v->arch.ctxt.gprs[2] = r2;
  18.272 +
  18.273 +    printk("DOM: pc = 0x%lx, r2 = 0x%lx\n", pc, r2);
  18.274 +
  18.275 +    ofd_dom0_fixup(d, *ofh_tree + rma, si, dst - rma);
  18.276 +
  18.277 +    set_bit(_VCPUF_initialised, &v->vcpu_flags);
  18.278 +
  18.279 +    rc = 0;
  18.280 +
  18.281 +    /* DOM0 is permitted full I/O capabilities. */
  18.282 +    rc |= iomem_permit_access(dom0, 0UL, ~0UL);
  18.283 +    rc |= irqs_permit_access(dom0, 0, NR_IRQS-1);
  18.284 +
  18.285 +    BUG_ON(rc != 0);
  18.286 +
  18.287 +    return 0;
  18.288 +}
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/xen/arch/powerpc/elf32.c	Fri Jul 14 10:47:50 2006 +0100
    19.3 @@ -0,0 +1,5 @@
    19.4 +#define parseelfimage parseelfimage_32
    19.5 +#define loadelfimage loadelfimage_32
    19.6 +#define ELFSIZE 32
    19.7 +#include "../../common/elf.c"
    19.8 +
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/xen/arch/powerpc/exceptions.c	Fri Jul 14 10:47:50 2006 +0100
    20.3 @@ -0,0 +1,87 @@
    20.4 +/*
    20.5 + * This program is free software; you can redistribute it and/or modify
    20.6 + * it under the terms of the GNU General Public License as published by
    20.7 + * the Free Software Foundation; either version 2 of the License, or
    20.8 + * (at your option) any later version.
    20.9 + *
   20.10 + * This program is distributed in the hope that it will be useful,
   20.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   20.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   20.13 + * GNU General Public License for more details.
   20.14 + *
   20.15 + * You should have received a copy of the GNU General Public License
   20.16 + * along with this program; if not, write to the Free Software
   20.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   20.18 + *
   20.19 + * Copyright (C) IBM Corp. 2005, 2006
   20.20 + *
   20.21 + * Authors: Hollis Blanchard <hollisb@us.ibm.com>
   20.22 + */
   20.23 +
   20.24 +#include <xen/config.h>
   20.25 +#include <xen/softirq.h>
   20.26 +#include <xen/sched.h>
   20.27 +#include <xen/serial.h>
   20.28 +#include <xen/gdbstub.h>
   20.29 +#include <public/xen.h>
   20.30 +#include <asm/time.h>
   20.31 +
   20.32 +#undef DEBUG
   20.33 +#define HDEC_PREEMPT
   20.34 +
   20.35 +extern ulong ppc_do_softirq(ulong orig_msr);
   20.36 +extern void do_timer(struct cpu_user_regs *regs);
   20.37 +extern void do_dec(struct cpu_user_regs *regs);
   20.38 +extern void program_exception(struct cpu_user_regs *regs, unsigned long cookie);
   20.39 +
   20.40 +int hdec_sample = 0;
   20.41 +
   20.42 +void do_timer(struct cpu_user_regs *regs)
   20.43 +{
   20.44 +    /* XXX this is just here to keep HDEC from firing until
   20.45 +     * reprogram_ac_timer() sets the proper next-tick time */
   20.46 +    mthdec(timebase_freq);
   20.47 +
   20.48 +#ifdef HDEC_PREEMPT
   20.49 +    raise_softirq(TIMER_SOFTIRQ);
   20.50 +#endif
   20.51 +#ifdef DEBUG
   20.52 +    {
   20.53 +        int d;
   20.54 +        if (regs->msr & MSR_HV) {
   20.55 +            d = -1;
   20.56 +        } else {
   20.57 +            d = get_current()->domain->domain_id;
   20.58 +        }
   20.59 +        extern char serial_getc_nb(int handle);
   20.60 +        if (0 && serial_getc_nb(0) > 0) {
   20.61 +            printk("H: pc: 0x%lx lr: 0x%lx \n", regs->pc, regs->lr);
   20.62 +        }
   20.63 +        if (hdec_sample)  {
   20.64 +            printk("H: pc: 0x%lx lr: 0x%lx \n", regs->pc, regs->lr);
   20.65 +            hdec_sample = 0;
   20.66 +        }
   20.67 +    }
   20.68 +#endif
   20.69 +}
   20.70 +
   20.71 +void do_dec(struct cpu_user_regs *regs)
   20.72 +{
   20.73 +    if (!(regs->msr & MSR_HV)) {
   20.74 +        panic("HV dec from domain\n");
   20.75 +    }
   20.76 +    printk("DEC_HV: pc: 0x%lx lr: 0x%lx \n", regs->pc, regs->lr);
   20.77 +    mtdec(INT_MAX);
   20.78 +}
   20.79 +
   20.80 +void program_exception(struct cpu_user_regs *regs, unsigned long cookie)
   20.81 +{
   20.82 +#ifdef CRASH_DEBUG
   20.83 +    __trap_to_gdb(regs, cookie);
   20.84 +#else /* CRASH_DEBUG */
   20.85 +    show_registers(regs);
   20.86 +    printk("dar 0x%016lx, dsisr 0x%08x\n", mfdar(), mfdsisr());
   20.87 +    printk("hid4 0x%016lx\n", regs->hid4);
   20.88 +    panic("%s: 0x%lx\n", __func__, cookie);
   20.89 +#endif /* CRASH_DEBUG */
   20.90 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/xen/arch/powerpc/exceptions.h	Fri Jul 14 10:47:50 2006 +0100
    21.3 @@ -0,0 +1,57 @@
    21.4 +/*
    21.5 + * This program is free software; you can redistribute it and/or modify
    21.6 + * it under the terms of the GNU General Public License as published by
    21.7 + * the Free Software Foundation; either version 2 of the License, or
    21.8 + * (at your option) any later version.
    21.9 + *
   21.10 + * This program is distributed in the hope that it will be useful,
   21.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   21.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   21.13 + * GNU General Public License for more details.
   21.14 + *
   21.15 + * You should have received a copy of the GNU General Public License
   21.16 + * along with this program; if not, write to the Free Software
   21.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   21.18 + *
   21.19 + * Copyright (C) IBM Corp. 2005
   21.20 + *
   21.21 + * Authors: Hollis Blanchard <hollisb@us.ibm.com>
   21.22 + */
   21.23 +
   21.24 +#ifndef _ARCH_PPC_EXCEPTIONS_H_
   21.25 +#define _ARCH_PPC_EXCEPTIONS_H_
   21.26 +
   21.27 +#include <xen/types.h>
   21.28 +#include <public/xen.h>
   21.29 +#include <xen/multiboot.h>
   21.30 +
   21.31 +extern void do_hcall(struct cpu_user_regs *regs);
   21.32 +extern void do_IRQ(struct cpu_user_regs *regs);
   21.33 +extern void deliver_ee(struct cpu_user_regs *regs);
   21.34 +extern void do_external(struct cpu_user_regs *regs);
   21.35 +extern void init_IRQ(void);
   21.36 +extern void ack_APIC_irq(void);
   21.37 +extern int ioapic_guest_read(unsigned long physbase, unsigned int reg, u32 *pval);
   21.38 +extern int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val);
   21.39 +extern void __start_xen_ppc(
   21.40 +    ulong r3, ulong r4, ulong r5, ulong r6, ulong r7, ulong orig_msr);
   21.41 +extern  multiboot_info_t *boot_of_init(ulong r3, ulong r4, ulong vec, ulong r6, ulong r7, ulong orig_msr);
   21.42 +
   21.43 +extern void do_timer(struct cpu_user_regs *regs);
   21.44 +extern void do_dec(struct cpu_user_regs *regs);
   21.45 +extern void program_exception(
   21.46 +    struct cpu_user_regs *regs, unsigned long cookie);
   21.47 +
   21.48 +extern long xen_hvcall_jump(struct cpu_user_regs *regs, ulong address);
   21.49 +extern void *mambo_memset(void *, int, ulong);
   21.50 +extern void *mambo_memcpy(void *, const void *, ulong);
   21.51 +
   21.52 +extern ulong *__hypercall_table[];
   21.53 +
   21.54 +extern char exception_vectors[];
   21.55 +extern char exception_vectors_end[];
   21.56 +extern int spin_start[];
   21.57 +extern int firmware_image_start[0];
   21.58 +extern int firmware_image_size[0];
   21.59 +
   21.60 +#endif
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/xen/arch/powerpc/external.c	Fri Jul 14 10:47:50 2006 +0100
    22.3 @@ -0,0 +1,247 @@
    22.4 +/*
    22.5 + * This program is free software; you can redistribute it and/or modify
    22.6 + * it under the terms of the GNU General Public License as published by
    22.7 + * the Free Software Foundation; either version 2 of the License, or
    22.8 + * (at your option) any later version.
    22.9 + *
   22.10 + * This program is distributed in the hope that it will be useful,
   22.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   22.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   22.13 + * GNU General Public License for more details.
   22.14 + *
   22.15 + * You should have received a copy of the GNU General Public License
   22.16 + * along with this program; if not, write to the Free Software
   22.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   22.18 + *
   22.19 + * Copyright (C) IBM Corp. 2005, 2006
   22.20 + *
   22.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   22.22 + */
   22.23 +
   22.24 +#include <xen/config.h>
   22.25 +#include <xen/types.h>
   22.26 +#include <xen/sched.h>
   22.27 +#include <xen/lib.h>
   22.28 +#include <xen/event.h>
   22.29 +#include <xen/irq.h>
   22.30 +#include <public/xen.h>
   22.31 +#include <asm/current.h>
   22.32 +#include <asm/hardirq.h>
   22.33 +#include <asm/mpic.h>
   22.34 +#include "mpic_init.h"
   22.35 +#include "exceptions.h"
   22.36 +
   22.37 +#undef DEBUG
   22.38 +#ifdef DEBUG
   22.39 +#define DBG(fmt...) printk(fmt)
   22.40 +#else
   22.41 +#define DBG(fmt...)
   22.42 +#endif
   22.43 +
   22.44 +int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
   22.45 +
   22.46 +unsigned long io_apic_irqs;
   22.47 +int ioapic_ack_new = 1;
   22.48 +
   22.49 +static struct hw_interrupt_type *hc_irq;
   22.50 +
   22.51 +/* deliver_ee: called with interrupts off when resuming every vcpu */
   22.52 +void deliver_ee(struct cpu_user_regs *regs)
   22.53 +{
   22.54 +    const ulong srr_mask = ~(MSR_IR | MSR_DR | MSR_FE0 | MSR_FE1 | MSR_EE |
   22.55 +                             MSR_RI |
   22.56 +                             MSR_BE | MSR_FP | MSR_PMM | MSR_PR | MSR_SE);
   22.57 +
   22.58 +    BUG_ON(mfmsr() & MSR_EE);
   22.59 +    BUG_ON(regs->msr & MSR_HV);
   22.60 +
   22.61 +    if (!local_events_need_delivery())
   22.62 +        return;
   22.63 +
   22.64 +    /* XXX OS error: EE was set but RI was not. We could trigger a machine
   22.65 +     * check, or kill the domain... for now just crash Xen so we notice. */
   22.66 +    BUG_ON(!(regs->msr & MSR_RI));
   22.67 +
   22.68 +    regs->srr0 = regs->pc;
   22.69 +    /* zero SRR1[33:36] and SRR1[42:47] */
   22.70 +    regs->srr1 = regs->msr & ~0x00000000783f0000;
   22.71 +    regs->pc = 0x500;
   22.72 +    regs->msr &= srr_mask;
   22.73 +    regs->msr |= MSR_SF | MSR_ME;
   22.74 +
   22.75 +    DBG("<HV: pc=0x%lx, msr=0x%lx\n", regs->pc, regs->msr);
   22.76 +}
   22.77 +
   22.78 +void do_external(struct cpu_user_regs *regs)
   22.79 +{
   22.80 +    int vec;
   22.81 +
   22.82 +    BUG_ON(!(regs->msr & MSR_EE));
   22.83 +    BUG_ON(mfmsr() & MSR_EE);
   22.84 +
   22.85 +    vec = xen_mpic_get_irq(regs);
   22.86 +
   22.87 +    if (vec != -1) {
   22.88 +        DBG("EE:0x%lx isrc: %d\n", regs->msr, vec);
   22.89 +        regs->entry_vector = vec;
   22.90 +        do_IRQ(regs);
   22.91 +
   22.92 +        BUG_ON(mfmsr() & MSR_EE);
   22.93 +    }
   22.94 +}
   22.95 +
   22.96 +static int xen_local_irq(unsigned int irq)
   22.97 +{
   22.98 +    irq_desc_t *desc;
   22.99 +    unsigned int vector;
  22.100 +
  22.101 +    vector = irq_to_vector(irq);
  22.102 +    desc = &irq_desc[vector];
  22.103 +
  22.104 +    return !(desc->status & IRQ_GUEST);
  22.105 +}
  22.106 +
  22.107 +static unsigned int xen_startup_irq(unsigned int irq)
  22.108 +{
  22.109 +    DBG("%s(%d)\n", __func__, irq);
  22.110 +    if (xen_local_irq(irq)) {
  22.111 +        return hc_irq->startup(irq);
  22.112 +    }
  22.113 +    return 0;
  22.114 +}
  22.115 +
  22.116 +static void xen_shutdown_irq(unsigned int irq)
  22.117 +{
  22.118 +    DBG("%s(%d)\n", __func__, irq);
  22.119 +    if (xen_local_irq(irq)) {
  22.120 +        hc_irq->shutdown(irq);
  22.121 +    }
  22.122 +}
  22.123 +
  22.124 +static void xen_enable_irq(unsigned int irq)
  22.125 +{
  22.126 +    DBG("%s(%d)\n", __func__, irq);
  22.127 +    if (xen_local_irq(irq)) {
  22.128 +        hc_irq->enable(irq);
  22.129 +    }
  22.130 +}
  22.131 +
  22.132 +static void xen_disable_irq(unsigned int irq)
  22.133 +{
  22.134 +    DBG("%s(%d)\n", __func__, irq);
  22.135 +    if (xen_local_irq(irq)) {
  22.136 +        hc_irq->disable(irq);
  22.137 +    }
  22.138 +}
  22.139 +    
  22.140 +static void xen_ack_irq(unsigned int irq)
  22.141 +{
  22.142 +    DBG("%s(%d)\n", __func__, irq);
  22.143 +    if (xen_local_irq(irq)) {
  22.144 +        if (hc_irq->ack) hc_irq->ack(irq);
  22.145 +    }
  22.146 +}
  22.147 +
  22.148 +static void xen_end_irq(unsigned int irq)
  22.149 +{
  22.150 +    DBG("%s(%d)\n", __func__, irq);
  22.151 +    if (xen_local_irq(irq)) {
  22.152 +        hc_irq->end(irq);
  22.153 +    }
  22.154 +}
  22.155 +
  22.156 +static void xen_set_affinity(unsigned int irq, cpumask_t mask)
  22.157 +{
  22.158 +    DBG("%s(%d)\n", __func__, irq);
  22.159 +    if (xen_local_irq(irq)) {
  22.160 +        if (hc_irq->set_affinity) hc_irq->set_affinity(irq, mask);
  22.161 +    }
  22.162 +}
  22.163 +
  22.164 +static struct hw_interrupt_type xen_irq = {
  22.165 +    .startup = xen_startup_irq,
  22.166 +    .enable = xen_enable_irq,
  22.167 +    .disable = xen_disable_irq,
  22.168 +    .shutdown = xen_shutdown_irq,
  22.169 +    .ack = xen_ack_irq,
  22.170 +    .end = xen_end_irq,
  22.171 +    .set_affinity = xen_set_affinity,
  22.172 +};
  22.173 +
  22.174 +void init_IRQ(void)
  22.175 +{
  22.176 +    hc_irq = xen_mpic_init(&xen_irq);
  22.177 +}
  22.178 +
  22.179 +void ack_APIC_irq(void)
  22.180 +{
  22.181 +    printk("%s: EOI the whole MPIC?\n", __func__);
  22.182 +    for (;;);
  22.183 +}
  22.184 +
  22.185 +void ack_bad_irq(unsigned int irq)
  22.186 +{
  22.187 +    printk("unexpected IRQ trap at vector %02x\n", irq);
  22.188 +    /*
  22.189 +     * Currently unexpected vectors happen only on SMP and APIC.
  22.190 +     * We _must_ ack these because every local APIC has only N
  22.191 +     * irq slots per priority level, and a 'hanging, unacked' IRQ
  22.192 +     * holds up an irq slot - in excessive cases (when multiple
  22.193 +     * unexpected vectors occur) that might lock up the APIC
  22.194 +     * completely.
  22.195 +     */
  22.196 +    ack_APIC_irq();
  22.197 +}
  22.198 +
  22.199 +extern void dump_ioapic_irq_info(void);
  22.200 +void dump_ioapic_irq_info(void)
  22.201 +{
  22.202 +    printk("%s: can't dump yet\n", __func__);
  22.203 +}
  22.204 +
  22.205 +/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
  22.206 +u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };
  22.207 +int assign_irq_vector(int irq)
  22.208 +{
  22.209 +    static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
  22.210 +
  22.211 +    BUG_ON(irq >= NR_IRQ_VECTORS);
  22.212 +    if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0)
  22.213 +        return IO_APIC_VECTOR(irq);
  22.214 +next:
  22.215 +    current_vector += 8;
  22.216 +
  22.217 +    /* Skip the hypercall vector. */
  22.218 +    if (current_vector == HYPERCALL_VECTOR)
  22.219 +        goto next;
  22.220 +
  22.221 +    /* Skip the Linux/BSD fast-trap vector. */
  22.222 +    if (current_vector == FAST_TRAP)
  22.223 +        goto next;
  22.224 +
  22.225 +    if (current_vector >= FIRST_SYSTEM_VECTOR) {
  22.226 +        offset++;
  22.227 +        if (!(offset%8))
  22.228 +            return -ENOSPC;
  22.229 +        current_vector = FIRST_DEVICE_VECTOR + offset;
  22.230 +    }
  22.231 +
  22.232 +    vector_irq[current_vector] = irq;
  22.233 +    if (irq != AUTO_ASSIGN)
  22.234 +        IO_APIC_VECTOR(irq) = current_vector;
  22.235 +
  22.236 +    return current_vector;
  22.237 +}
  22.238 +
  22.239 +int ioapic_guest_read(unsigned long physbase, unsigned int reg, u32 *pval)
  22.240 +{
  22.241 +    BUG_ON(pval != pval);
  22.242 +
  22.243 +    return 0;
  22.244 +}
  22.245 +
  22.246 +int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
  22.247 +{
  22.248 +    BUG_ON(val != val);
  22.249 +    return 0;
  22.250 +}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/xen/arch/powerpc/float.S	Fri Jul 14 10:47:50 2006 +0100
    23.3 @@ -0,0 +1,243 @@
    23.4 +/*
    23.5 + * Copyright (C) 2005 Jimi Xenidis <jimix@watson.ibm.com>, IBM Corporation
    23.6 + *
    23.7 + * This program is free software; you can redistribute it and/or modify
    23.8 + * it under the terms of the GNU General Public License as published by
    23.9 + * the Free Software Foundation; either version 2 of the License, or
   23.10 + * (at your option) any later version.
   23.11 + * 
   23.12 + * This program is distributed in the hope that it will be useful,
   23.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   23.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   23.15 + * GNU General Public License for more details.
   23.16 + * 
   23.17 + * You should have received a copy of the GNU General Public License
   23.18 + * along with this program; if not, write to the Free Software
   23.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   23.20 + */
   23.21 +
   23.22 +#include <asm/config.h>
   23.23 +#include <asm/asm-offsets.h>
   23.24 +#include <asm/reg_defs.h>
   23.25 +#include <asm/msr.h>
   23.26 +#include <asm/processor.h>
   23.27 +
   23.28 +#ifdef HAS_FLOAT
   23.29 +save_fp:
   23.30 +	addi	r4, r3, VCPU_fprs - FPR_WIDTH
   23.31 +	stfdu	fr0,FPR_WIDTH(r4)
   23.32 +	stfdu	fr1,FPR_WIDTH(r4)
   23.33 +	stfdu	fr2,FPR_WIDTH(r4)
   23.34 +	stfdu	fr3,FPR_WIDTH(r4)
   23.35 +	stfdu	fr4,FPR_WIDTH(r4)
   23.36 +	stfdu	fr5,FPR_WIDTH(r4)
   23.37 +	stfdu	fr6,FPR_WIDTH(r4)
   23.38 +	stfdu	fr7,FPR_WIDTH(r4)
   23.39 +	stfdu	fr8,FPR_WIDTH(r4)
   23.40 +	stfdu	fr9,FPR_WIDTH(r4)
   23.41 +	stfdu	fr10,FPR_WIDTH(r4)
   23.42 +	stfdu	fr11,FPR_WIDTH(r4)
   23.43 +	stfdu	fr12,FPR_WIDTH(r4)
   23.44 +	stfdu	fr13,FPR_WIDTH(r4)
   23.45 +	stfdu	fr14,FPR_WIDTH(r4)
   23.46 +	stfdu	fr15,FPR_WIDTH(r4)
   23.47 +	stfdu	fr16,FPR_WIDTH(r4)
   23.48 +	stfdu	fr17,FPR_WIDTH(r4)
   23.49 +	stfdu	fr18,FPR_WIDTH(r4)
   23.50 +	stfdu	fr19,FPR_WIDTH(r4)
   23.51 +	stfdu	fr20,FPR_WIDTH(r4)
   23.52 +	stfdu	fr21,FPR_WIDTH(r4)
   23.53 +	stfdu	fr22,FPR_WIDTH(r4)
   23.54 +	stfdu	fr23,FPR_WIDTH(r4)
   23.55 +	stfdu	fr24,FPR_WIDTH(r4)
   23.56 +	stfdu	fr25,FPR_WIDTH(r4)
   23.57 +	stfdu	fr26,FPR_WIDTH(r4)
   23.58 +	stfdu	fr27,FPR_WIDTH(r4)
   23.59 +	stfdu	fr28,FPR_WIDTH(r4)
   23.60 +	stfdu	fr29,FPR_WIDTH(r4)
   23.61 +	stfdu	fr30,FPR_WIDTH(r4)
   23.62 +	stfdu	fr31,FPR_WIDTH(r4)
   23.63 +	mffs	fr0
   23.64 +	stfd	fr0,VCPU_fpscr(r3)
   23.65 +	blr
   23.66 +
   23.67 +load_fp:
   23.68 +	lfd	fr0,VCPU_fpscr(r3)
   23.69 +	mtfsf	0xff,fr0
   23.70 +
   23.71 +	addi	r4, r3, VCPU_fprs - FPR_WIDTH
   23.72 +	lfdu	fr0,FPR_WIDTH(r4)
   23.73 +	lfdu	fr1,FPR_WIDTH(r4)
   23.74 +	lfdu	fr2,FPR_WIDTH(r4)
   23.75 +	lfdu	fr3,FPR_WIDTH(r4)
   23.76 +	lfdu	fr4,FPR_WIDTH(r4)
   23.77 +	lfdu	fr5,FPR_WIDTH(r4)
   23.78 +	lfdu	fr6,FPR_WIDTH(r4)
   23.79 +	lfdu	fr7,FPR_WIDTH(r4)
   23.80 +	lfdu	fr8,FPR_WIDTH(r4)
   23.81 +	lfdu	fr9,FPR_WIDTH(r4)
   23.82 +	lfdu	fr10,FPR_WIDTH(r4)
   23.83 +	lfdu	fr11,FPR_WIDTH(r4)
   23.84 +	lfdu	fr12,FPR_WIDTH(r4)
   23.85 +	lfdu	fr13,FPR_WIDTH(r4)
   23.86 +	lfdu	fr14,FPR_WIDTH(r4)
   23.87 +	lfdu	fr15,FPR_WIDTH(r4)
   23.88 +	lfdu	fr16,FPR_WIDTH(r4)
   23.89 +	lfdu	fr17,FPR_WIDTH(r4)
   23.90 +	lfdu	fr18,FPR_WIDTH(r4)
   23.91 +	lfdu	fr19,FPR_WIDTH(r4)
   23.92 +	lfdu	fr20,FPR_WIDTH(r4)
   23.93 +	lfdu	fr21,FPR_WIDTH(r4)
   23.94 +	lfdu	fr22,FPR_WIDTH(r4)
   23.95 +	lfdu	fr23,FPR_WIDTH(r4)
   23.96 +	lfdu	fr24,FPR_WIDTH(r4)
   23.97 +	lfdu	fr25,FPR_WIDTH(r4)
   23.98 +	lfdu	fr26,FPR_WIDTH(r4)
   23.99 +	lfdu	fr27,FPR_WIDTH(r4)
  23.100 +	lfdu	fr28,FPR_WIDTH(r4)
  23.101 +	lfdu	fr29,FPR_WIDTH(r4)
  23.102 +	lfdu	fr30,FPR_WIDTH(r4)
  23.103 +	lfdu	fr31,FPR_WIDTH(r4)
  23.104 +	blr
  23.105 +#endif /* HAS_FLOAT */
  23.106 +
  23.107 +#ifdef HAS_VMX
  23.108 +
  23.109 +#define VCPU_vr(n) (VCPU_vrs + ((n) * 16))
  23.110 +
  23.111 +/*
  23.112 + * We cannot rely on the domain to correctly use VRSAVE
  23.113 + * so it is required that all VMX registers are saved and restored.
  23.114 + */
  23.115 +save_vmx:
  23.116 +	mfspr	r0,SPRN_VRSAVE
  23.117 +	stw	r0,VCPU_vrsave(r3)
  23.118 +
  23.119 +	addi r0,r3,VCPU_vr(0);	stvxl	vr0,0,r0
  23.120 +	addi r0,r3,VCPU_vr(1);	stvxl	vr1,0,r0
  23.121 +	addi r0,r3,VCPU_vr(2);	stvxl	vr2,0,r0
  23.122 +	addi r0,r3,VCPU_vr(3);	stvxl	vr3,0,r0
  23.123 +	addi r0,r3,VCPU_vr(4);	stvxl	vr4,0,r0
  23.124 +	addi r0,r3,VCPU_vr(5);	stvxl	vr5,0,r0
  23.125 +	addi r0,r3,VCPU_vr(6);	stvxl	vr6,0,r0
  23.126 +	addi r0,r3,VCPU_vr(7);	stvxl	vr7,0,r0
  23.127 +	addi r0,r3,VCPU_vr(8);	stvxl	vr8,0,r0
  23.128 +
  23.129 +	/*
  23.130 +	 * By now vr0 should be pushed out so now is a good time to
  23.131 +	 * get the VRSCR which can take a long time and has no dependcies
  23.132 +	 * on the following operations.
  23.133 +	 */
  23.134 +	mfvscr	vr0
  23.135 +	addi r0,r3,VCPU_vscr ;	stvxl	vr0,0,r0
  23.136 +
  23.137 +	addi r0,r3,VCPU_vr(9);	stvxl	vr9,0,r0
  23.138 +	addi r0,r3,VCPU_vr(10);	stvxl	vr10,0,r0
  23.139 +	addi r0,r3,VCPU_vr(11);	stvxl	vr11,0,r0
  23.140 +	addi r0,r3,VCPU_vr(12);	stvxl	vr12,0,r0
  23.141 +	addi r0,r3,VCPU_vr(13);	stvxl	vr13,0,r0
  23.142 +	addi r0,r3,VCPU_vr(14);	stvxl	vr14,0,r0
  23.143 +	addi r0,r3,VCPU_vr(15);	stvxl	vr15,0,r0
  23.144 +	addi r0,r3,VCPU_vr(16);	stvxl	vr16,0,r0
  23.145 +	addi r0,r3,VCPU_vr(17);	stvxl	vr17,0,r0
  23.146 +	addi r0,r3,VCPU_vr(18);	stvxl	vr18,0,r0
  23.147 +	addi r0,r3,VCPU_vr(19);	stvxl	vr19,0,r0
  23.148 +	addi r0,r3,VCPU_vr(20);	stvxl	vr20,0,r0
  23.149 +	addi r0,r3,VCPU_vr(21);	stvxl	vr21,0,r0
  23.150 +	addi r0,r3,VCPU_vr(22);	stvxl	vr22,0,r0
  23.151 +	addi r0,r3,VCPU_vr(23);	stvxl	vr23,0,r0
  23.152 +	addi r0,r3,VCPU_vr(24);	stvxl	vr24,0,r0
  23.153 +	addi r0,r3,VCPU_vr(25);	stvxl	vr25,0,r0
  23.154 +	addi r0,r3,VCPU_vr(26);	stvxl	vr26,0,r0
  23.155 +	addi r0,r3,VCPU_vr(27);	stvxl	vr27,0,r0
  23.156 +	addi r0,r3,VCPU_vr(28);	stvxl	vr28,0,r0
  23.157 +	addi r0,r3,VCPU_vr(29);	stvxl	vr29,0,r0
  23.158 +	addi r0,r3,VCPU_vr(30);	stvxl	vr30,0,r0
  23.159 +	addi r0,r3,VCPU_vr(31);	stvxl	vr31,0,r0
  23.160 +	blr
  23.161 +
  23.162 +load_vmx:
  23.163 +	lwz	r0,VCPU_vrsave(r3)
  23.164 +	mtspr	SPRN_VRSAVE,r0
  23.165 +
  23.166 +	/*
  23.167 +	 * This operation can take a long time so we use vr31 to
  23.168 +	 * eliminate the depency on r0 for the next load
  23.169 +	 */
  23.170 +	addi r0,r3,VCPU_vscr ;	lvxl	vr31,0,r0
  23.171 +	mtvscr	vr31
  23.172 +
  23.173 +	addi r0,r3,VCPU_vr(0);	lvxl	vr0,0,r0
  23.174 +	addi r0,r3,VCPU_vr(1);	lvxl	vr1,0,r0
  23.175 +	addi r0,r3,VCPU_vr(2);	lvxl	vr2,0,r0
  23.176 +	addi r0,r3,VCPU_vr(3);	lvxl	vr3,0,r0
  23.177 +	addi r0,r3,VCPU_vr(4);	lvxl	vr4,0,r0
  23.178 +	addi r0,r3,VCPU_vr(5);	lvxl	vr5,0,r0
  23.179 +	addi r0,r3,VCPU_vr(6);	lvxl	vr6,0,r0
  23.180 +	addi r0,r3,VCPU_vr(7);	lvxl	vr7,0,r0
  23.181 +	addi r0,r3,VCPU_vr(8);	lvxl	vr8,0,r0
  23.182 +	addi r0,r3,VCPU_vr(9);	lvxl	vr9,0,r0
  23.183 +	addi r0,r3,VCPU_vr(10);	lvxl	vr10,0,r0
  23.184 +	addi r0,r3,VCPU_vr(11);	lvxl	vr11,0,r0
  23.185 +	addi r0,r3,VCPU_vr(12);	lvxl	vr12,0,r0
  23.186 +	addi r0,r3,VCPU_vr(13);	lvxl	vr13,0,r0
  23.187 +	addi r0,r3,VCPU_vr(14);	lvxl	vr14,0,r0
  23.188 +	addi r0,r3,VCPU_vr(15);	lvxl	vr15,0,r0
  23.189 +	addi r0,r3,VCPU_vr(16);	lvxl	vr16,0,r0
  23.190 +	addi r0,r3,VCPU_vr(17);	lvxl	vr17,0,r0
  23.191 +	addi r0,r3,VCPU_vr(18);	lvxl	vr18,0,r0
  23.192 +	addi r0,r3,VCPU_vr(19);	lvxl	vr19,0,r0
  23.193 +	addi r0,r3,VCPU_vr(20);	lvxl	vr20,0,r0
  23.194 +	addi r0,r3,VCPU_vr(21);	lvxl	vr21,0,r0
  23.195 +	addi r0,r3,VCPU_vr(22);	lvxl	vr22,0,r0
  23.196 +	addi r0,r3,VCPU_vr(23);	lvxl	vr23,0,r0
  23.197 +	addi r0,r3,VCPU_vr(24);	lvxl	vr24,0,r0
  23.198 +	addi r0,r3,VCPU_vr(25);	lvxl	vr25,0,r0
  23.199 +	addi r0,r3,VCPU_vr(26);	lvxl	vr26,0,r0
  23.200 +	addi r0,r3,VCPU_vr(27);	lvxl	vr27,0,r0
  23.201 +	addi r0,r3,VCPU_vr(28);	lvxl	vr28,0,r0
  23.202 +	addi r0,r3,VCPU_vr(29);	lvxl	vr29,0,r0
  23.203 +	addi r0,r3,VCPU_vr(30);	lvxl	vr30,0,r0
  23.204 +	addi r0,r3,VCPU_vr(31);	lvxl	vr31,0,r0
  23.205 +	blr
  23.206 +#endif /* HAS_VMX */
  23.207 +
  23.208 +/* void save_float(struct exec_domain *ed) */
  23.209 +_GLOBAL(save_float)
  23.210 +	mflr	r8
  23.211 +#ifdef HAS_FLOAT
  23.212 +	mfmsr	r9		# save msr
  23.213 +	ori	r0,r9,MSR_FP	# turn on FPU
  23.214 +	mtmsr	r0
  23.215 +	bl	save_fp		# uses r3, r4
  23.216 +	mtmsr	r9		# restore msr
  23.217 +#endif /* HAS_FLOAT */
  23.218 +#ifdef HAS_VMX
  23.219 +	mfmsr	r9		# save msr
  23.220 +	oris	r0,r9,MSR_VMX@h	# turn on VMX
  23.221 +	mtmsr	r0
  23.222 +	bl	save_vmx	# uses r3
  23.223 +	mtmsr	r9		# restore msr
  23.224 +#endif /* HAS_VMX */
  23.225 +	mtlr	r8
  23.226 +	blr
  23.227 +
  23.228 +/* void load_float(struct exec_domain *ed) */
  23.229 +_GLOBAL(load_float)
  23.230 +	mflr	r8
  23.231 +#ifdef HAS_FLOAT
  23.232 +	mfmsr	r9		# save msr
  23.233 +	ori	r0,r9,MSR_FP	# turn on FPU
  23.234 +	mtmsr	r0
  23.235 +	bl	load_fp	# uses r3, r4
  23.236 +	mtmsr	r9		# restore msr
  23.237 +#endif /* HAS_FLOAT */
  23.238 +#ifdef HAS_VMX
  23.239 +	mfmsr	r9		# save msr
  23.240 +	oris	r0,r9,MSR_VMX@h	# turn on VMX
  23.241 +	mtmsr	r0
  23.242 +	bl	load_vmx	# uses r3
  23.243 +	mtmsr	r9		# restore msr
  23.244 +#endif /* HAS_VMX */
  23.245 +	mtlr	r8
  23.246 +	blr
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/xen/arch/powerpc/gdbstub.c	Fri Jul 14 10:47:50 2006 +0100
    24.3 @@ -0,0 +1,207 @@
    24.4 +/*
    24.5 + * This program is free software; you can redistribute it and/or modify
    24.6 + * it under the terms of the GNU General Public License as published by
    24.7 + * the Free Software Foundation; either version 2 of the License, or
    24.8 + * (at your option) any later version.
    24.9 + *
   24.10 + * This program is distributed in the hope that it will be useful,
   24.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   24.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   24.13 + * GNU General Public License for more details.
   24.14 + *
   24.15 + * You should have received a copy of the GNU General Public License
   24.16 + * along with this program; if not, write to the Free Software
   24.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   24.18 + *
   24.19 + * Copyright (C) IBM Corp. 2005
   24.20 + *
   24.21 + * Authors: Hollis Blanchard <hollisb@us.ibm.com>
   24.22 + */
   24.23 +
   24.24 +#include <xen/types.h>
   24.25 +#include <xen/lib.h>
   24.26 +#include <xen/gdbstub.h>
   24.27 +#include <public/xen.h>
   24.28 +#include <asm/msr.h>
   24.29 +#include <asm/bitops.h>
   24.30 +#include <asm/cache.h>
   24.31 +#include <asm/processor.h>
   24.32 +
   24.33 +asm(".globl trap_instruction\n"
   24.34 +        "trap_instruction:\n"
   24.35 +        "trap\n");
   24.36 +extern u32 trap_instruction[];
   24.37 +
   24.38 +static unsigned int dec_entry;
   24.39 +static unsigned int hdec_entry;
   24.40 +
   24.41 +static inline ulong
   24.42 +gdb_ppc_0x700(struct cpu_user_regs *state)
   24.43 +{
   24.44 +    ulong instr;
   24.45 +
   24.46 +    switch (state->msr & MSR_TRAP_BITS) {
   24.47 +        case MSR_TRAP_FE:
   24.48 +            return SIGFPE;
   24.49 +        case MSR_TRAP_IOP:
   24.50 +        case MSR_TRAP_PRIV:
   24.51 +            return SIGILL;
   24.52 +        case MSR_TRAP:
   24.53 +            instr = *((u32 *)state->pc);
   24.54 +
   24.55 +            /* if this was a hardcoded trap in the source, step past it */
   24.56 +            if (instr == *trap_instruction) {
   24.57 +                state->pc += sizeof (u32);
   24.58 +            }
   24.59 +            return SIGTRAP;
   24.60 +    }
   24.61 +    return SIGBUS;
   24.62 +}
   24.63 +
   24.64 +u16 gdb_arch_signal_num(struct cpu_user_regs *regs, unsigned long cookie)
   24.65 +{
   24.66 +    /* exception type identifies, trap or bad address */
   24.67 +    switch (cookie) {
   24.68 +        case 0x200: /* Machine Check */
   24.69 +            return SIGTERM;
   24.70 +        case 0x300: /* DSI */
   24.71 +        case 0x380: /* Data SLB */
   24.72 +        case 0x400: /* ISI */
   24.73 +        case 0x480: /* Instruction SLB */
   24.74 +            return SIGSEGV;
   24.75 +        case 0x600: /* Alignment SLB */
   24.76 +            return SIGBUS;
   24.77 +        case 0x700: /* Program */
   24.78 +            return gdb_ppc_0x700(regs);
   24.79 +        case 0x800: /* Float */
   24.80 +            return SIGFPE;
   24.81 +        case 0x900: /* Decrementer */
   24.82 +            return SIGALRM; /* is this right? */
   24.83 +        case 0xd00: /* TRAP */
   24.84 +            return SIGTRAP;
   24.85 +        case 0xe00: /* FP */
   24.86 +            return SIGFPE;
   24.87 +    }
   24.88 +    return SIGBUS;
   24.89 +}
   24.90 +
   24.91 +void
   24.92 +gdb_arch_resume(struct cpu_user_regs *regs,
   24.93 +                unsigned long addr, unsigned long type,
   24.94 +                struct gdb_context *ctx)
   24.95 +{
   24.96 +    if (addr != ~((ulong)0)) {
   24.97 +        regs->pc = addr;
   24.98 +    }
   24.99 +
  24.100 +    if (type == GDB_CONTINUE) {
  24.101 +        regs->msr &= ~MSR_SE;
  24.102 +    } else {
  24.103 +        regs->msr |= MSR_SE;
  24.104 +    }
  24.105 +}
  24.106 +
  24.107 +void 
  24.108 +gdb_arch_read_reg(unsigned long regnum, struct cpu_user_regs *regs,
  24.109 +                  struct gdb_context *ctx)
  24.110 +{
  24.111 +    unimplemented();
  24.112 +    gdb_send_reply("", ctx);
  24.113 +}
  24.114 +
  24.115 +void
  24.116 +gdb_arch_read_reg_array(struct cpu_user_regs *state, struct gdb_context *ctx)
  24.117 +{
  24.118 +    ulong i = 0;
  24.119 +
  24.120 +    for (i = 0; i < 32; ++i) {
  24.121 +        gdb_write_to_packet_hex(state->gprs[i], sizeof(state->gprs[i]), ctx);
  24.122 +    }
  24.123 +    /* Avoid floating point for now */
  24.124 +    for (i = 0; i < 32; ++i) {
  24.125 +        gdb_write_to_packet_hex(0, sizeof(u64), ctx);
  24.126 +    }
  24.127 +    gdb_write_to_packet_hex(state->pc, sizeof (state->pc), ctx);
  24.128 +    gdb_write_to_packet_hex(state->msr, sizeof (state->msr), ctx);
  24.129 +    gdb_write_to_packet_hex(state->cr, sizeof (state->cr), ctx);
  24.130 +    gdb_write_to_packet_hex(state->lr, sizeof (state->lr), ctx);
  24.131 +    gdb_write_to_packet_hex(state->ctr, sizeof (state->ctr), ctx);
  24.132 +    gdb_write_to_packet_hex(state->xer, sizeof (u32), ctx);
  24.133 +    gdb_write_to_packet_hex(0, sizeof(u32), ctx); /* fpscr */
  24.134 +    gdb_send_packet(ctx);
  24.135 +}
  24.136 +
  24.137 +void
  24.138 +gdb_arch_write_reg_array(struct cpu_user_regs *regs, const char *buf,
  24.139 +                         struct gdb_context *ctx)
  24.140 +{
  24.141 +    ulong i;
  24.142 +
  24.143 +    for (i = 0; i < 32; ++i) {
  24.144 +        regs->gprs[i] = str2ulong(buf, sizeof (ulong));
  24.145 +        buf += sizeof (regs->gprs[0]) * 2;
  24.146 +    }
  24.147 +    /* Avoid floating point for now */
  24.148 +    for (i = 0; i < 32; ++i) {
  24.149 +        buf += sizeof (u64) * 2;
  24.150 +    }
  24.151 +
  24.152 +    regs->pc = str2ulong(buf, sizeof (regs->pc));
  24.153 +    buf += sizeof (regs->pc) * 2;
  24.154 +    regs->msr = str2ulong(buf, sizeof (regs->msr));
  24.155 +    buf += sizeof (regs->msr) * 2;
  24.156 +    regs->cr = str2ulong(buf, sizeof (regs->cr));
  24.157 +    buf += sizeof (regs->cr) * 2;
  24.158 +    regs->lr = str2ulong(buf, sizeof (regs->lr));
  24.159 +    buf += sizeof (regs->lr) * 2;
  24.160 +    regs->ctr = str2ulong(buf, sizeof (regs->ctr));
  24.161 +    buf += sizeof (regs->ctr) * 2;
  24.162 +    regs->xer = str2ulong(buf, sizeof (u32));
  24.163 +    buf += sizeof (u32) * 2;
  24.164 +}
  24.165 +
  24.166 +unsigned int
  24.167 +gdb_arch_copy_from_user(void *dest, const void *src, unsigned len)
  24.168 +{
  24.169 +    memcpy(dest, src, len);
  24.170 +    return 0;
  24.171 +}
  24.172 +
  24.173 +unsigned int
  24.174 +gdb_arch_copy_to_user(void *dest, const void *src, unsigned len)
  24.175 +{
  24.176 +    memcpy(dest, src, len);
  24.177 +    synchronize_caches((ulong)dest, len);
  24.178 +    return 0;
  24.179 +}
  24.180 +
  24.181 +void
  24.182 +gdb_arch_print_state(struct cpu_user_regs *state)
  24.183 +{
  24.184 +    int i = 0;
  24.185 +    printk("PC: 0x%016lx MSR: 0x%016lx\n", state->pc, state->msr);
  24.186 +    printk("LR: 0x%016lx CTR: 0x%016lx\n", state->lr, state->ctr);
  24.187 +    /* XXX
  24.188 +       printk("DAR: 0x%016lx DSISR: 0x%016lx\n", state->dar, state->dsisr);
  24.189 +       */
  24.190 +    printk("CR: 0x%08x XER: 0x%016lx\n", state->cr, state->xer);
  24.191 +    for (; i < 32; i+=4) {
  24.192 +        printk("%02d: 0x%016lx 0x%016lx 0x%016lx 0x%016lx\n",
  24.193 +                i, state->gprs[i], state->gprs[i+1],
  24.194 +                state->gprs[i+2], state->gprs[i+3]);
  24.195 +    }
  24.196 +}
  24.197 +
  24.198 +void
  24.199 +gdb_arch_enter(struct cpu_user_regs *state)
  24.200 +{
  24.201 +    dec_entry = mfdec();
  24.202 +    hdec_entry = mfhdec();
  24.203 +}
  24.204 +
  24.205 +void
  24.206 +gdb_arch_exit(struct cpu_user_regs *state)
  24.207 +{
  24.208 +    mtdec(dec_entry);
  24.209 +    mthdec(hdec_entry);
  24.210 +}
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/xen/arch/powerpc/hcalls.c	Fri Jul 14 10:47:50 2006 +0100
    25.3 @@ -0,0 +1,172 @@
    25.4 +/*
    25.5 + * This program is free software; you can redistribute it and/or modify
    25.6 + * it under the terms of the GNU General Public License as published by
    25.7 + * the Free Software Foundation; either version 2 of the License, or
    25.8 + * (at your option) any later version.
    25.9 + *
   25.10 + * This program is distributed in the hope that it will be useful,
   25.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   25.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   25.13 + * GNU General Public License for more details.
   25.14 + *
   25.15 + * You should have received a copy of the GNU General Public License
   25.16 + * along with this program; if not, write to the Free Software
   25.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   25.18 + *
   25.19 + * Copyright (C) IBM Corp. 2005
   25.20 + *
   25.21 + * Authors: Hollis Blanchard <hollisb@us.ibm.com>
   25.22 + */
   25.23 +
   25.24 +#include <xen/config.h>
   25.25 +#include <xen/types.h>
   25.26 +#include <xen/sched.h>
   25.27 +#include <xen/lib.h>
   25.28 +#include <xen/init.h>
   25.29 +#include <xen/multicall.h>
   25.30 +#include <public/xen.h>
   25.31 +#include <asm/current.h>
   25.32 +#include <asm/papr.h>
   25.33 +#include <asm/hcalls.h>
   25.34 +#include <asm/debugger.h>
   25.35 +#include <asm/msr.h>
   25.36 +#include "exceptions.h"
   25.37 +
   25.38 +u32 *papr_hcalls;               /* PAPR Hypervisor Calls */
   25.39 +u32 *hypercall_table;           /* Xen Hypervisor Calls */
   25.40 +
   25.41 +static void hcall_papr(ulong num, struct cpu_user_regs *regs)
   25.42 +{
   25.43 +    u32 address;
   25.44 +
   25.45 +    if (regs->msr & MSR_PR) {
   25.46 +        regs->gprs[3] = H_Privilege;
   25.47 +        return;
   25.48 +    }
   25.49 +
   25.50 +    if ((num & 0x3) || (num > RPA_HCALL_END)) {
   25.51 +        regs->gprs[3] = H_Parameter;
   25.52 +        return;
   25.53 +    }
   25.54 +
   25.55 +    address = papr_hcalls[num/4];
   25.56 +    papr_hcall_jump(regs, address);
   25.57 +}
   25.58 +
   25.59 +static void hcall_xen(ulong num, struct cpu_user_regs *regs)
   25.60 +{
   25.61 +    u32 address;
   25.62 +
   25.63 +    if (regs->msr & MSR_PR) {
   25.64 +        regs->gprs[3] = -EPERM;
   25.65 +        return;
   25.66 +    }
   25.67 +
   25.68 +    if ((num >= NR_hypercalls)) {
   25.69 +        regs->gprs[3] = -ENOSYS;
   25.70 +        return;
   25.71 +    }
   25.72 +    address = hypercall_table[num];
   25.73 +    if (address == 0) {
   25.74 +        printk("unsupported Xen hypercall: 0x%lx\n", num);
   25.75 +        regs->gprs[3] = -ENOSYS;
   25.76 +        return;
   25.77 +    }
   25.78 +
   25.79 +    regs->gprs[3] = xen_hvcall_jump(regs, address);
   25.80 +}
   25.81 +
   25.82 +void do_multicall_call(multicall_entry_t *call)
   25.83 +{
   25.84 +    struct cpu_user_regs regs;
   25.85 +
   25.86 +    regs.gprs[3] = call->args[0];
   25.87 +    regs.gprs[4] = call->args[1];
   25.88 +    regs.gprs[5] = call->args[2];
   25.89 +    regs.gprs[6] = call->args[3];
   25.90 +    regs.gprs[7] = call->args[4];
   25.91 +    regs.gprs[8] = call->args[5];
   25.92 +
   25.93 +    hcall_xen(call->op, &regs);
   25.94 +
   25.95 +    call->result = regs.gprs[3];
   25.96 +}
   25.97 +
   25.98 +void do_hcall(struct cpu_user_regs *regs)
   25.99 +{
  25.100 +    ulong num = regs->gprs[3];
  25.101 +
  25.102 +    local_irq_enable();
  25.103 +
  25.104 +    if ((num & XEN_MARK(0)) == XEN_MARK(0)) {
  25.105 +        /* it's a Xen call */
  25.106 +        num &= ~XEN_MARK(0);
  25.107 +        hcall_xen(num, regs);
  25.108 +    } else {
  25.109 +        /* it's a PAPR call */
  25.110 +        hcall_papr(num, regs);
  25.111 +    }
  25.112 +}
  25.113 +
  25.114 +static void do_ni_papr_hypercall(struct cpu_user_regs *regs)
  25.115 +{
  25.116 +    struct vcpu *v = get_current();
  25.117 +
  25.118 +    printk("unsupported hcall 0x%lx was called by dom0x%x\n",
  25.119 +            regs->gprs[3], v->domain->domain_id);
  25.120 +    debugger_trap_immediate();
  25.121 +
  25.122 +    regs->gprs[3] = H_Parameter;
  25.123 +}
  25.124 +
  25.125 +/* store low 32 bits of 64-bit address in hcall table (this is safe because we
  25.126 + * know we will not link above 4GB). We don't need to preserve the TOC
  25.127 + * because that only changes when calling dynamically linked objects. */
  25.128 +static void register_papr_hcall(ulong num, hcall_handler_t handler)
  25.129 +{
  25.130 +    int index = num/4;
  25.131 +
  25.132 +    papr_hcalls[index] = (u32)(*(u64 *)handler);
  25.133 +}
  25.134 +
  25.135 +static void init_papr_hcalls(void)
  25.136 +{
  25.137 +    inithcall_t *hcall;
  25.138 +    int i;
  25.139 +
  25.140 +    /* initialize PAPR hcall table */
  25.141 +    papr_hcalls = xmalloc_array(u32, RPA_HCALL_END/4);
  25.142 +    ASSERT(papr_hcalls != NULL);
  25.143 +    for (i = 0; i <= RPA_HCALL_END; i += 4)
  25.144 +        register_papr_hcall(i, do_ni_papr_hypercall);
  25.145 +
  25.146 +    /* register the PAPR hcalls */
  25.147 +    for (hcall = &__inithcall_start; hcall < &__inithcall_end; hcall++) {
  25.148 +        register_papr_hcall(hcall->number, hcall->handler);
  25.149 +    }
  25.150 +}
  25.151 +
  25.152 +static void init_hypercall_table(void)
  25.153 +{
  25.154 +    int i;
  25.155 +
  25.156 +    hypercall_table = xmalloc_array(u32, NR_hypercalls);
  25.157 +    ASSERT(hypercall_table != NULL);
  25.158 +
  25.159 +    for (i = 0; i < NR_hypercalls; i++) {
  25.160 +        if (__hypercall_table[i] == NULL ) {
  25.161 +            hypercall_table[i] = 0;
  25.162 +        } else {
  25.163 +            hypercall_table[i] = (u32)(*__hypercall_table[i]);
  25.164 +        }
  25.165 +    }
  25.166 +}
  25.167 +
  25.168 +static int init_hcalls(void)
  25.169 +{
  25.170 +    init_papr_hcalls();
  25.171 +    init_hypercall_table();
  25.172 +
  25.173 +    return 0;
  25.174 +}
  25.175 +__initcall(init_hcalls);
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/xen/arch/powerpc/htab.c	Fri Jul 14 10:47:50 2006 +0100
    26.3 @@ -0,0 +1,69 @@
    26.4 +/*
    26.5 + * This program is free software; you can redistribute it and/or modify
    26.6 + * it under the terms of the GNU General Public License as published by
    26.7 + * the Free Software Foundation; either version 2 of the License, or
    26.8 + * (at your option) any later version.
    26.9 + *
   26.10 + * This program is distributed in the hope that it will be useful,
   26.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   26.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   26.13 + * GNU General Public License for more details.
   26.14 + *
   26.15 + * You should have received a copy of the GNU General Public License
   26.16 + * along with this program; if not, write to the Free Software
   26.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   26.18 + *
   26.19 + * Copyright (C) IBM Corp. 2005
   26.20 + *
   26.21 + * Authors: Hollis Blanchard <hollisb@us.ibm.com>
   26.22 + */
   26.23 +
   26.24 +#include <xen/config.h>
   26.25 +#include <xen/sched.h>
   26.26 +
   26.27 +static ulong htab_calc_sdr1(ulong htab_addr, ulong log_htab_size)
   26.28 +{
   26.29 +    ulong sdr1_htabsize;
   26.30 +
   26.31 +    ASSERT((htab_addr & ((1UL << log_htab_size) - 1)) == 0);
   26.32 +    ASSERT(log_htab_size <= SDR1_HTABSIZE_MAX);
   26.33 +    ASSERT(log_htab_size >= HTAB_MIN_LOG_SIZE);
   26.34 +
   26.35 +    sdr1_htabsize = log_htab_size - LOG_PTEG_SIZE - SDR1_HTABSIZE_BASEBITS;
   26.36 +
   26.37 +    return (htab_addr | (sdr1_htabsize & SDR1_HTABSIZE_MASK));
   26.38 +}
   26.39 +
   26.40 +void htab_alloc(struct domain *d, int log_htab_bytes)
   26.41 +{
   26.42 +    ulong htab_raddr;
   26.43 +    ulong htab_bytes = 1UL << log_htab_bytes;
   26.44 +
   26.45 +    /* XXX use alloc_domheap_pages instead? */
   26.46 +    htab_raddr = (ulong)alloc_xenheap_pages(log_htab_bytes - PAGE_SHIFT);
   26.47 +    ASSERT(htab_raddr != 0);
   26.48 +    /* XXX check alignment guarantees */
   26.49 +    ASSERT((htab_raddr & (htab_bytes-1)) == 0);
   26.50 +
   26.51 +    /* XXX slow. move memset out to service partition? */
   26.52 +    memset((void *)htab_raddr, 0, htab_bytes);
   26.53 +
   26.54 +    d->arch.htab.log_num_ptes = log_htab_bytes - LOG_PTE_SIZE;
   26.55 +    d->arch.htab.sdr1 = htab_calc_sdr1(htab_raddr, log_htab_bytes);
   26.56 +    d->arch.htab.map = (union pte *)htab_raddr;
   26.57 +    d->arch.htab.shadow = xmalloc_array(ulong,
   26.58 +                                        1UL << d->arch.htab.log_num_ptes);
   26.59 +    ASSERT(d->arch.htab.shadow != NULL);
   26.60 +
   26.61 +    printf("%s: dom%x sdr1: %lx\n", __func__, d->domain_id, d->arch.htab.sdr1);
   26.62 +}
   26.63 +
   26.64 +void htab_free(struct domain *d)
   26.65 +{
   26.66 +    ulong htab_raddr = GET_HTAB(d);
   26.67 +
   26.68 +    free_xenheap_pages((void *)htab_raddr,
   26.69 +                       (1UL << d->arch.htab.log_num_ptes) << LOG_PTE_SIZE);
   26.70 +    xfree(d->arch.htab.shadow);
   26.71 +}
   26.72 +
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/xen/arch/powerpc/iommu.c	Fri Jul 14 10:47:50 2006 +0100
    27.3 @@ -0,0 +1,79 @@
    27.4 +/*
    27.5 + * This program is free software; you can redistribute it and/or modify
    27.6 + * it under the terms of the GNU General Public License as published by
    27.7 + * the Free Software Foundation; either version 2 of the License, or
    27.8 + * (at your option) any later version.
    27.9 + *
   27.10 + * This program is distributed in the hope that it will be useful,
   27.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   27.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   27.13 + * GNU General Public License for more details.
   27.14 + *
   27.15 + * You should have received a copy of the GNU General Public License
   27.16 + * along with this program; if not, write to the Free Software
   27.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   27.18 + *
   27.19 + * Copyright (C) IBM Corp. 2005
   27.20 + *
   27.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   27.22 + */
   27.23 +
   27.24 +#undef DEBUG
   27.25 +
   27.26 +#include <xen/config.h>
   27.27 +#include <xen/types.h>
   27.28 +#include <xen/sched.h>
   27.29 +#include <xen/init.h>
   27.30 +#include <xen/mm.h>
   27.31 +#include <asm/current.h>
   27.32 +#include <asm/papr.h>
   27.33 +#include <asm/hcalls.h>
   27.34 +#include <public/xen.h>
   27.35 +#include "tce.h"
   27.36 +#include "iommu.h"
   27.37 +
   27.38 +struct iommu_funcs {
   27.39 +    int (*iommu_put)(ulong, union tce);
   27.40 +};
   27.41 +
   27.42 +/* individual host bridges */
   27.43 +static struct iommu_funcs iommu_phbs[16];
   27.44 +static u32 iommu_phbs_num = ARRAY_SIZE(iommu_phbs);
   27.45 +
   27.46 +int iommu_put(u32 buid, ulong ioba, union tce tce)
   27.47 +{
   27.48 +    struct vcpu *v = get_current();
   27.49 +    struct domain *d = v->domain;
   27.50 +
   27.51 +    if (buid < iommu_phbs_num && iommu_phbs[buid].iommu_put != NULL) {
   27.52 +        ulong pfn;
   27.53 +        ulong mfn;
   27.54 +        int mtype;
   27.55 +
   27.56 +        pfn = tce.tce_bits.tce_rpn;
   27.57 +        mfn = pfn2mfn(d, pfn, &mtype);
   27.58 +        if (mtype != 0) {
   27.59 +            panic("we don't do non-RMO memory yet\n");
   27.60 +        }
   27.61 +
   27.62 +#ifdef DEBUG
   27.63 +        printk("%s: ioba=0x%lx pfn=0x%lx mfn=0x%lx\n", __func__,
   27.64 +               ioba, pfn, mfn);
   27.65 +#endif
   27.66 +        tce.tce_bits.tce_rpn = mfn;
   27.67 +
   27.68 +        return iommu_phbs[buid].iommu_put(ioba, tce);
   27.69 +    }
   27.70 +    return -1;
   27.71 +}
   27.72 +
   27.73 +int iommu_register(u32 buid, int (*put)(ulong ioba, union tce ltce))
   27.74 +{
   27.75 +
   27.76 +    if (buid < iommu_phbs_num && iommu_phbs[buid].iommu_put == NULL) {
   27.77 +        iommu_phbs[0].iommu_put = put;
   27.78 +        return 0;
   27.79 +    }
   27.80 +    panic("bad IOMMU registration\n");
   27.81 +    return -1;
   27.82 +}
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/xen/arch/powerpc/iommu.h	Fri Jul 14 10:47:50 2006 +0100
    28.3 @@ -0,0 +1,28 @@
    28.4 +/*
    28.5 + * This program is free software; you can redistribute it and/or modify
    28.6 + * it under the terms of the GNU General Public License as published by
    28.7 + * the Free Software Foundation; either version 2 of the License, or
    28.8 + * (at your option) any later version.
    28.9 + *
   28.10 + * This program is distributed in the hope that it will be useful,
   28.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   28.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   28.13 + * GNU General Public License for more details.
   28.14 + *
   28.15 + * You should have received a copy of the GNU General Public License
   28.16 + * along with this program; if not, write to the Free Software
   28.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   28.18 + *
   28.19 + * Copyright (C) IBM Corp. 2005
   28.20 + *
   28.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   28.22 + */
   28.23 +
   28.24 +#ifndef _IOMMU_H
   28.25 +#define _IOMMU_H
   28.26 +
   28.27 +extern int iommu_put(u32 buid, ulong ioba, union tce tce);
   28.28 +extern int iommu_register(u32 buid, int (*put)(ulong, union tce));
   28.29 +
   28.30 +#endif /* _IOMMU_H */
   28.31 +
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/xen/arch/powerpc/irq.c	Fri Jul 14 10:47:50 2006 +0100
    29.3 @@ -0,0 +1,22 @@
    29.4 +/*
    29.5 + * This program is free software; you can redistribute it and/or modify
    29.6 + * it under the terms of the GNU General Public License as published by
    29.7 + * the Free Software Foundation; either version 2 of the License, or
    29.8 + * (at your option) any later version.
    29.9 + *
   29.10 + * This program is distributed in the hope that it will be useful,
   29.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   29.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   29.13 + * GNU General Public License for more details.
   29.14 + *
   29.15 + * You should have received a copy of the GNU General Public License
   29.16 + * along with this program; if not, write to the Free Software
   29.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   29.18 + *
   29.19 + * Copyright (C) IBM Corp. 2005
   29.20 + *
   29.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   29.22 + */
   29.23 +
   29.24 +#include "exceptions.h"
   29.25 +#include "../x86/irq.c"
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/xen/arch/powerpc/mambo.S	Fri Jul 14 10:47:50 2006 +0100
    30.3 @@ -0,0 +1,64 @@
    30.4 +/*
    30.5 + * Copyright (C) 2005 Jimi Xenidis <jimix@watson.ibm.com>, IBM Corporation
    30.6 + *
    30.7 + * This program is free software; you can redistribute it and/or modify
    30.8 + * it under the terms of the GNU General Public License as published by
    30.9 + * the Free Software Foundation; either version 2 of the License, or
   30.10 + * (at your option) any later version.
   30.11 + * 
   30.12 + * This program is distributed in the hope that it will be useful,
   30.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   30.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   30.15 + * GNU General Public License for more details.
   30.16 + * 
   30.17 + * You should have received a copy of the GNU General Public License
   30.18 + * along with this program; if not, write to the Free Software
   30.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   30.20 + *
   30.21 + */
   30.22 +
   30.23 +#include <asm/config.h>
   30.24 +#include <asm/processor.h>
   30.25 +
   30.26 +_GLOBAL(mambo_callthru)
   30.27 +	.long 0x000eaeb0
   30.28 +	blr
   30.29 +
   30.30 +_GLOBAL(mambo_write)
   30.31 +	mr	r5, r4
   30.32 +	mr	r4, r3
   30.33 +	li	r3, 0		# Write console code
   30.34 +	
   30.35 +	li	r6, 0
   30.36 +	/* need to fix return value */
   30.37 +	mflr	r7
   30.38 +	bl	_ENTRY(mambo_callthru)
   30.39 +	mtlr	r7
   30.40 +	mr	r3, r5
   30.41 +	blr
   30.42 +
   30.43 +_GLOBAL(mambo_memset)
   30.44 +	mr	r6, r5
   30.45 +	mr	r5, r4
   30.46 +	mr	r4, r3
   30.47 +	li	r3, 0x47	# memset
   30.48 +	/* need to fix return value */
   30.49 +	mflr	r7
   30.50 +	bl	_ENTRY(mambo_callthru)
   30.51 +	mtlr	r7
   30.52 +	mr	r3, r4
   30.53 +	blr
   30.54 +
   30.55 +_GLOBAL(mambo_memcpy)
   30.56 +	mr	r6, r5
   30.57 +	mr	r5, r4
   30.58 +	mr	r4, r3
   30.59 +	li	r3, 0x45 # memcpy
   30.60 +	/* need to fix return value */
   30.61 +	mflr	r7
   30.62 +	bl	_ENTRY(mambo_callthru)
   30.63 +	mtlr	r7
   30.64 +	mr	r3, r4
   30.65 +	blr
   30.66 +
   30.67 +	
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/xen/arch/powerpc/mm.c	Fri Jul 14 10:47:50 2006 +0100
    31.3 @@ -0,0 +1,141 @@
    31.4 +/*
    31.5 + * This program is free software; you can redistribute it and/or modify
    31.6 + * it under the terms of the GNU General Public License as published by
    31.7 + * the Free Software Foundation; either version 2 of the License, or
    31.8 + * (at your option) any later version.
    31.9 + *
   31.10 + * This program is distributed in the hope that it will be useful,
   31.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   31.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   31.13 + * GNU General Public License for more details.
   31.14 + *
   31.15 + * You should have received a copy of the GNU General Public License
   31.16 + * along with this program; if not, write to the Free Software
   31.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   31.18 + *
   31.19 + * Copyright (C) IBM Corp. 2005
   31.20 + *
   31.21 + * Authors: Hollis Blanchard <hollisb@us.ibm.com>
   31.22 + */
   31.23 +
   31.24 +#include <xen/config.h>
   31.25 +#include <xen/mm.h>
   31.26 +#include <xen/kernel.h>
   31.27 +#include <xen/sched.h>
   31.28 +#include <asm/misc.h>
   31.29 +#include <asm/init.h>
   31.30 +#include <asm/page.h>
   31.31 +
   31.32 +/* Frame table and its size in pages. */
   31.33 +struct page_info *frame_table;
   31.34 +unsigned long frame_table_size;
   31.35 +unsigned long max_page;
   31.36 +unsigned long total_pages;
   31.37 +
   31.38 +int create_grant_host_mapping(
   31.39 +    unsigned long addr, unsigned long frame, unsigned int flags)
   31.40 +{
   31.41 +    panic("%s called\n", __func__);
   31.42 +    return 1;
   31.43 +}
   31.44 +
   31.45 +int destroy_grant_host_mapping(
   31.46 +    unsigned long addr, unsigned long frame, unsigned int flags)
   31.47 +{
   31.48 +    panic("%s called\n", __func__);
   31.49 +    return 1;
   31.50 +}
   31.51 +
   31.52 +int steal_page(struct domain *d, struct page_info *page, unsigned int memflags)
   31.53 +{
   31.54 +    panic("%s called\n", __func__);
   31.55 +    return 1;
   31.56 +}
   31.57 +
   31.58 +
   31.59 +int get_page_type(struct page_info *page, u32 type)
   31.60 +{
   31.61 +    panic("%s called\n", __func__);
   31.62 +    return 1;
   31.63 +}
   31.64 +
   31.65 +void put_page_type(struct page_info *page)
   31.66 +{
   31.67 +    panic("%s called\n", __func__);
   31.68 +}
   31.69 +
   31.70 +void __init init_frametable(void)
   31.71 +{
   31.72 +    unsigned long p;
   31.73 +
   31.74 +    frame_table_size = PFN_UP(max_page * sizeof(struct page_info));
   31.75 +
   31.76 +    p = alloc_boot_pages(min(frame_table_size, 4UL << 20), 1);
   31.77 +    if (p == 0)
   31.78 +        panic("Not enough memory for frame table\n");
   31.79 +
   31.80 +    frame_table = (struct page_info *)(p << PAGE_SHIFT);
   31.81 +    frame_table_size = (frame_table_size + PAGE_SIZE - 1) & PAGE_MASK;
   31.82 +
   31.83 +    memset(frame_table, 0, frame_table_size);
   31.84 +}
   31.85 +
   31.86 +long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
   31.87 +{
   31.88 +    printk("%s: no PPC specific memory ops\n", __func__);
   31.89 +    return -ENOSYS;
   31.90 +}
   31.91 +
   31.92 +void clear_page(void *page)
   31.93 +{
   31.94 +    if (on_mambo()) {
   31.95 +        extern void *mambo_memset(void *,int ,__kernel_size_t);
   31.96 +        mambo_memset(page, 0, PAGE_SIZE);
   31.97 +    } else {
   31.98 +        memset(page, 0, PAGE_SIZE);
   31.99 +    }
  31.100 +}
  31.101 +
  31.102 +extern void copy_page(void *dp, void *sp)
  31.103 +{
  31.104 +    if (on_mambo()) {
  31.105 +        extern void *mambo_memcpy(void *,const void *,__kernel_size_t);
  31.106 +        mambo_memcpy(dp, sp, PAGE_SIZE);
  31.107 +    } else {
  31.108 +        memcpy(dp, sp, PAGE_SIZE);
  31.109 +    }
  31.110 +}
  31.111 +
  31.112 +ulong pfn2mfn(struct domain *d, long pfn, int *type)
  31.113 +{
  31.114 +    ulong rma_base_mfn = d->arch.rma_base >> PAGE_SHIFT;
  31.115 +    ulong rma_size_mfn = d->arch.rma_size >> PAGE_SHIFT;
  31.116 +    ulong mfn;
  31.117 +    int t;
  31.118 +
  31.119 +    if (pfn < rma_size_mfn) {
  31.120 +        mfn = pfn + rma_base_mfn;
  31.121 +        t = PFN_TYPE_RMA;
  31.122 +    } else if (pfn >= d->arch.logical_base_pfn &&
  31.123 +               pfn < d->arch.logical_end_pfn) {
  31.124 +        if (test_bit(_DOMF_privileged, &d->domain_flags)) {
  31.125 +            /* This hack allows dom0 to map all memory, necessary to
  31.126 +             * initialize domU state. */
  31.127 +            mfn = pfn;
  31.128 +        } else {
  31.129 +            panic("we do not handle the logical area yet\n");
  31.130 +            mfn = 0;
  31.131 +        }
  31.132 +
  31.133 +        t = PFN_TYPE_LOGICAL;
  31.134 +    } else {
  31.135 +        /* don't know */
  31.136 +        mfn = pfn;
  31.137 +        t = PFN_TYPE_IO;
  31.138 +    }
  31.139 +
  31.140 +    if (type != NULL)
  31.141 +        *type = t;
  31.142 +
  31.143 +    return mfn;
  31.144 +}
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/xen/arch/powerpc/mpic.c	Fri Jul 14 10:47:50 2006 +0100
    32.3 @@ -0,0 +1,1109 @@
    32.4 +/*
    32.5 + *  arch/powerpc/kernel/mpic.c
    32.6 + *
    32.7 + *  Driver for interrupt controllers following the OpenPIC standard, the
    32.8 + *  common implementation beeing IBM's MPIC. This driver also can deal
    32.9 + *  with various broken implementations of this HW.
   32.10 + *
   32.11 + *  Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp.
   32.12 + *
   32.13 + *  This file is subject to the terms and conditions of the GNU General Public
   32.14 + *  License.  See the file COPYING in the main directory of this archive
   32.15 + *  for more details.
   32.16 + */
   32.17 +
   32.18 +/* XXX Xen hacks ... */
   32.19 +/* make this generic */
   32.20 +
   32.21 +#define le32_to_cpu(x) \
   32.22 +({ \
   32.23 +	__u32 __x = (x); \
   32.24 +	((__u32)( \
   32.25 +		(((__u32)(__x) & (__u32)0x000000ffUL) << 24) | \
   32.26 +		(((__u32)(__x) & (__u32)0x0000ff00UL) <<  8) | \
   32.27 +		(((__u32)(__x) & (__u32)0x00ff0000UL) >>  8) | \
   32.28 +		(((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); \
   32.29 +})
   32.30 +
   32.31 +
   32.32 +#define alloc_bootmem(x) xmalloc_bytes(x)
   32.33 +#define request_irq(irq, handler, f, devname, dev_id) \
   32.34 +    panic("IPI requested: %d: %p: %s: %p\n", irq, handler, devname, dev_id)
   32.35 +
   32.36 +typedef int irqreturn_t;
   32.37 +
   32.38 +#define IRQ_NONE	(0)
   32.39 +#define IRQ_HANDLED	(1)
   32.40 +#define IRQ_RETVAL(x)	((x) != 0)
   32.41 +
   32.42 +#define IRQ_SENSE_MASK		0x1
   32.43 +#define IRQ_SENSE_LEVEL		0x1	/* interrupt on active level */
   32.44 +#define IRQ_SENSE_EDGE		0x0	/* interrupt triggered by edge */
   32.45 +
   32.46 +#define IRQ_POLARITY_MASK	0x2
   32.47 +#define IRQ_POLARITY_POSITIVE	0x2	/* high level or low->high edge */
   32.48 +#define IRQ_POLARITY_NEGATIVE	0x0	/* low level or high->low edge */
   32.49 +
   32.50 +#define CONFIG_IRQ_ALL_CPUS 0
   32.51 +#define distribute_irqs	CONFIG_IRQ_ALL_CPUS
   32.52 +#define CONFIG_MPIC_BROKEN_U3
   32.53 +
   32.54 +#define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
   32.55 +#define PCI_FUNC(devfn) ((devfn) & 0x07)
   32.56 +#define PCI_HEADER_TYPE		0x0e	/* 8 bits */
   32.57 +#define PCI_VENDOR_ID		0x00	/* 16 bits */
   32.58 +#define PCI_VENDOR_ID_AMD 0x1022
   32.59 +#define PCI_CAPABILITY_LIST	0x34	/* Offset of first capability list entry */
   32.60 +#define PCI_CAP_LIST_NEXT	1	/* Next capability in the list */
   32.61 +#define PCI_CAP_LIST_ID		0	/* Capability ID */
   32.62 +#define  PCI_CAP_ID_HT_IRQCONF	0x08	/* HyperTransport IRQ Configuration */
   32.63 +#define PCI_STATUS		0x06	/* 16 bits */
   32.64 +#define  PCI_STATUS_CAP_LIST	0x10	/* Support Capability List */
   32.65 +#define MSG_ALL 0x8001
   32.66 +#define MSG_ALL_BUT_SELF 0x8000
   32.67 +
   32.68 +/* keeps file even closer to the original */
   32.69 +#define pt_regs cpu_user_regs
   32.70 +/* XXX ... Xen hacks */
   32.71 +
   32.72 +#undef DEBUG
   32.73 +#undef DEBUG_IPI
   32.74 +#undef DEBUG_IRQ
   32.75 +#undef DEBUG_LOW
   32.76 +
   32.77 +#include <xen/config.h>
   32.78 +#include <xen/types.h>
   32.79 +#include <xen/kernel.h>
   32.80 +#include <xen/init.h>
   32.81 +#include <xen/irq.h>
   32.82 +#include <xen/smp.h>
   32.83 +#ifndef __XEN__ 
   32.84 +#include <linux/interrupt.h>
   32.85 +#include <linux/bootmem.h>
   32.86 +#endif
   32.87 +#include <xen/spinlock.h>
   32.88 +#ifndef __XEN__
   32.89 +#include <asm/pci.h>
   32.90 +
   32.91 +#include <asm/ptrace.h>
   32.92 +#include <asm/signal.h>
   32.93 +#endif
   32.94 +#include <asm/io.h>
   32.95 +#ifndef __XEN__
   32.96 +#include <asm/pgtable.h>
   32.97 +#include <asm/irq.h>
   32.98 +#include <asm/machdep.h>
   32.99 +#endif
  32.100 +#include <asm/mpic.h>
  32.101 +#include <asm/smp.h>
  32.102 +
  32.103 +static inline void smp_message_recv(int msg, struct pt_regs *regs)
  32.104 +{
  32.105 +    return;
  32.106 +}
  32.107 +
  32.108 +#ifdef DEBUG
  32.109 +#define DBG(fmt...) printk(fmt)
  32.110 +#else
  32.111 +#define DBG(fmt...)
  32.112 +#endif
  32.113 +
  32.114 +static struct mpic *mpics;
  32.115 +static struct mpic *mpic_primary;
  32.116 +static DEFINE_SPINLOCK(mpic_lock);
  32.117 +
  32.118 +#ifdef CONFIG_PPC32	/* XXX for now */
  32.119 +#ifdef CONFIG_IRQ_ALL_CPUS
  32.120 +#define distribute_irqs	(1)
  32.121 +#else
  32.122 +#define distribute_irqs	(0)
  32.123 +#endif
  32.124 +#endif
  32.125 +
  32.126 +/*
  32.127 + * Register accessor functions
  32.128 + */
  32.129 +
  32.130 +
  32.131 +static inline u32 _mpic_read(unsigned int be, volatile u32 __iomem *base,
  32.132 +			    unsigned int reg)
  32.133 +{
  32.134 +	if (be)
  32.135 +		return in_be32(base + (reg >> 2));
  32.136 +	else
  32.137 +		return in_le32(base + (reg >> 2));
  32.138 +}
  32.139 +
  32.140 +static inline void _mpic_write(unsigned int be, volatile u32 __iomem *base,
  32.141 +			      unsigned int reg, u32 value)
  32.142 +{
  32.143 +	if (be)
  32.144 +		out_be32(base + (reg >> 2), value);
  32.145 +	else
  32.146 +		out_le32(base + (reg >> 2), value);
  32.147 +}
  32.148 +
  32.149 +static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)
  32.150 +{
  32.151 +	unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0;
  32.152 +	unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
  32.153 +
  32.154 +	if (mpic->flags & MPIC_BROKEN_IPI)
  32.155 +		be = !be;
  32.156 +	return _mpic_read(be, mpic->gregs, offset);
  32.157 +}
  32.158 +
  32.159 +static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value)
  32.160 +{
  32.161 +	unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
  32.162 +
  32.163 +	_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value);
  32.164 +}
  32.165 +
  32.166 +static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)
  32.167 +{
  32.168 +	unsigned int cpu = 0;
  32.169 +
  32.170 +	if (mpic->flags & MPIC_PRIMARY)
  32.171 +		cpu = hard_smp_processor_id();
  32.172 +
  32.173 +	return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg);
  32.174 +}
  32.175 +
  32.176 +static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value)
  32.177 +{
  32.178 +	unsigned int cpu = 0;
  32.179 +
  32.180 +	if (mpic->flags & MPIC_PRIMARY)
  32.181 +		cpu = hard_smp_processor_id();
  32.182 +
  32.183 +	_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg, value);
  32.184 +}
  32.185 +
  32.186 +static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigned int reg)
  32.187 +{
  32.188 +	unsigned int	isu = src_no >> mpic->isu_shift;
  32.189 +	unsigned int	idx = src_no & mpic->isu_mask;
  32.190 +
  32.191 +	return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
  32.192 +			  reg + (idx * MPIC_IRQ_STRIDE));
  32.193 +}
  32.194 +
  32.195 +static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
  32.196 +				   unsigned int reg, u32 value)
  32.197 +{
  32.198 +	unsigned int	isu = src_no >> mpic->isu_shift;
  32.199 +	unsigned int	idx = src_no & mpic->isu_mask;
  32.200 +
  32.201 +	_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
  32.202 +		    reg + (idx * MPIC_IRQ_STRIDE), value);
  32.203 +}
  32.204 +
  32.205 +#define mpic_read(b,r)		_mpic_read(mpic->flags & MPIC_BIG_ENDIAN,(b),(r))
  32.206 +#define mpic_write(b,r,v)	_mpic_write(mpic->flags & MPIC_BIG_ENDIAN,(b),(r),(v))
  32.207 +#define mpic_ipi_read(i)	_mpic_ipi_read(mpic,(i))
  32.208 +#define mpic_ipi_write(i,v)	_mpic_ipi_write(mpic,(i),(v))
  32.209 +#define mpic_cpu_read(i)	_mpic_cpu_read(mpic,(i))
  32.210 +#define mpic_cpu_write(i,v)	_mpic_cpu_write(mpic,(i),(v))
  32.211 +#define mpic_irq_read(s,r)	_mpic_irq_read(mpic,(s),(r))
  32.212 +#define mpic_irq_write(s,r,v)	_mpic_irq_write(mpic,(s),(r),(v))
  32.213 +
  32.214 +
  32.215 +/*
  32.216 + * Low level utility functions
  32.217 + */
  32.218 +
  32.219 +
  32.220 +
  32.221 +/* Check if we have one of those nice broken MPICs with a flipped endian on
  32.222 + * reads from IPI registers
  32.223 + */
  32.224 +static void __init mpic_test_broken_ipi(struct mpic *mpic)
  32.225 +{
  32.226 +	u32 r;
  32.227 +
  32.228 +	mpic_write(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0, MPIC_VECPRI_MASK);
  32.229 +	r = mpic_read(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0);
  32.230 +
  32.231 +	if (r == le32_to_cpu(MPIC_VECPRI_MASK)) {
  32.232 +		printk(KERN_INFO "mpic: Detected reversed IPI registers\n");
  32.233 +		mpic->flags |= MPIC_BROKEN_IPI;
  32.234 +	}
  32.235 +}
  32.236 +
  32.237 +#ifdef CONFIG_MPIC_BROKEN_U3
  32.238 +
  32.239 +/* Test if an interrupt is sourced from HyperTransport (used on broken U3s)
  32.240 + * to force the edge setting on the MPIC and do the ack workaround.
  32.241 + */
  32.242 +static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source)
  32.243 +{
  32.244 +	if (source >= 128 || !mpic->fixups)
  32.245 +		return 0;
  32.246 +	return mpic->fixups[source].base != NULL;
  32.247 +}
  32.248 +
  32.249 +
  32.250 +static inline void mpic_ht_end_irq(struct mpic *mpic, unsigned int source)
  32.251 +{
  32.252 +	struct mpic_irq_fixup *fixup = &mpic->fixups[source];
  32.253 +
  32.254 +	if (fixup->applebase) {
  32.255 +		unsigned int soff = (fixup->index >> 3) & ~3;
  32.256 +		unsigned int mask = 1U << (fixup->index & 0x1f);
  32.257 +		writel(mask, fixup->applebase + soff);
  32.258 +	} else {
  32.259 +		spin_lock(&mpic->fixup_lock);
  32.260 +		writeb(0x11 + 2 * fixup->index, fixup->base + 2);
  32.261 +		writel(fixup->data, fixup->base + 4);
  32.262 +		spin_unlock(&mpic->fixup_lock);
  32.263 +	}
  32.264 +}
  32.265 +
  32.266 +static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source,
  32.267 +				      unsigned int irqflags)
  32.268 +{
  32.269 +	struct mpic_irq_fixup *fixup = &mpic->fixups[source];
  32.270 +	unsigned long flags;
  32.271 +	u32 tmp;
  32.272 +
  32.273 +	if (fixup->base == NULL)
  32.274 +		return;
  32.275 +
  32.276 +	DBG("startup_ht_interrupt(%u, %u) index: %d\n",
  32.277 +	    source, irqflags, fixup->index);
  32.278 +	spin_lock_irqsave(&mpic->fixup_lock, flags);
  32.279 +	/* Enable and configure */
  32.280 +	writeb(0x10 + 2 * fixup->index, fixup->base + 2);
  32.281 +	tmp = readl(fixup->base + 4);
  32.282 +	tmp &= ~(0x23U);
  32.283 +	if (irqflags & IRQ_LEVEL)
  32.284 +		tmp |= 0x22;
  32.285 +	writel(tmp, fixup->base + 4);
  32.286 +	spin_unlock_irqrestore(&mpic->fixup_lock, flags);
  32.287 +}
  32.288 +
  32.289 +static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
  32.290 +				       unsigned int irqflags)
  32.291 +{
  32.292 +	struct mpic_irq_fixup *fixup = &mpic->fixups[source];
  32.293 +	unsigned long flags;
  32.294 +	u32 tmp;
  32.295 +
  32.296 +	if (fixup->base == NULL)
  32.297 +		return;
  32.298 +
  32.299 +	DBG("shutdown_ht_interrupt(%u, %u)\n", source, irqflags);
  32.300 +
  32.301 +	/* Disable */
  32.302 +	spin_lock_irqsave(&mpic->fixup_lock, flags);
  32.303 +	writeb(0x10 + 2 * fixup->index, fixup->base + 2);
  32.304 +	tmp = readl(fixup->base + 4);
  32.305 +	tmp |= 1;
  32.306 +	writel(tmp, fixup->base + 4);
  32.307 +	spin_unlock_irqrestore(&mpic->fixup_lock, flags);
  32.308 +}
  32.309 +
  32.310 +static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
  32.311 +				    unsigned int devfn, u32 vdid)
  32.312 +{
  32.313 +	int i, irq, n;
  32.314 +	u8 __iomem *base;
  32.315 +	u32 tmp;
  32.316 +	u8 pos;
  32.317 +
  32.318 +	for (pos = readb(devbase + PCI_CAPABILITY_LIST); pos != 0;
  32.319 +	     pos = readb(devbase + pos + PCI_CAP_LIST_NEXT)) {
  32.320 +		u8 id = readb(devbase + pos + PCI_CAP_LIST_ID);
  32.321 +		if (id == PCI_CAP_ID_HT_IRQCONF) {
  32.322 +			id = readb(devbase + pos + 3);
  32.323 +			if (id == 0x80)
  32.324 +				break;
  32.325 +		}
  32.326 +	}
  32.327 +	if (pos == 0)
  32.328 +		return;
  32.329 +
  32.330 +	base = devbase + pos;
  32.331 +	writeb(0x01, base + 2);
  32.332 +	n = (readl(base + 4) >> 16) & 0xff;
  32.333 +
  32.334 +	printk(KERN_INFO "mpic:   - HT:%02x.%x [0x%02x] vendor %04x device %04x"
  32.335 +	       " has %d irqs\n",
  32.336 +	       devfn >> 3, devfn & 0x7, pos, vdid & 0xffff, vdid >> 16, n + 1);
  32.337 +
  32.338 +	for (i = 0; i <= n; i++) {
  32.339 +		writeb(0x10 + 2 * i, base + 2);
  32.340 +		tmp = readl(base + 4);
  32.341 +		irq = (tmp >> 16) & 0xff;
  32.342 +		DBG("HT PIC index 0x%x, irq 0x%x, tmp: %08x\n", i, irq, tmp);
  32.343 +		/* mask it , will be unmasked later */
  32.344 +		tmp |= 0x1;
  32.345 +		writel(tmp, base + 4);
  32.346 +		mpic->fixups[irq].index = i;
  32.347 +		mpic->fixups[irq].base = base;
  32.348 +		/* Apple HT PIC has a non-standard way of doing EOIs */
  32.349 +		if ((vdid & 0xffff) == 0x106b)
  32.350 +			mpic->fixups[irq].applebase = devbase + 0x60;
  32.351 +		else
  32.352 +			mpic->fixups[irq].applebase = NULL;
  32.353 +		writeb(0x11 + 2 * i, base + 2);
  32.354 +		mpic->fixups[irq].data = readl(base + 4) | 0x80000000;
  32.355 +	}
  32.356 +}
  32.357 + 
  32.358 +
  32.359 +static void __init mpic_scan_ht_pics(struct mpic *mpic)
  32.360 +{
  32.361 +	unsigned int devfn;
  32.362 +	u8 __iomem *cfgspace;
  32.363 +
  32.364 +	printk(KERN_INFO "mpic: Setting up HT PICs workarounds for U3/U4\n");
  32.365 +
  32.366 +	/* Allocate fixups array */
  32.367 +	mpic->fixups = alloc_bootmem(128 * sizeof(struct mpic_irq_fixup));
  32.368 +	BUG_ON(mpic->fixups == NULL);
  32.369 +	memset(mpic->fixups, 0, 128 * sizeof(struct mpic_irq_fixup));
  32.370 +
  32.371 +	/* Init spinlock */
  32.372 +	spin_lock_init(&mpic->fixup_lock);
  32.373 +
  32.374 +	/* Map U3 config space. We assume all IO-APICs are on the primary bus
  32.375 +	 * so we only need to map 64kB.
  32.376 +	 */
  32.377 +	cfgspace = ioremap(0xf2000000, 0x10000);
  32.378 +	BUG_ON(cfgspace == NULL);
  32.379 +
  32.380 +	/* Now we scan all slots. We do a very quick scan, we read the header
  32.381 +	 * type, vendor ID and device ID only, that's plenty enough
  32.382 +	 */
  32.383 +	for (devfn = 0; devfn < 0x100; devfn++) {
  32.384 +		u8 __iomem *devbase = cfgspace + (devfn << 8);
  32.385 +		u8 hdr_type = readb(devbase + PCI_HEADER_TYPE);
  32.386 +		u32 l = readl(devbase + PCI_VENDOR_ID);
  32.387 +		u16 s;
  32.388 +
  32.389 +		DBG("devfn %x, l: %x\n", devfn, l);
  32.390 +
  32.391 +		/* If no device, skip */
  32.392 +		if (l == 0xffffffff || l == 0x00000000 ||
  32.393 +		    l == 0x0000ffff || l == 0xffff0000)
  32.394 +			goto next;
  32.395 +		/* Check if is supports capability lists */
  32.396 +		s = readw(devbase + PCI_STATUS);
  32.397 +		if (!(s & PCI_STATUS_CAP_LIST))
  32.398 +			goto next;
  32.399 +
  32.400 +		mpic_scan_ht_pic(mpic, devbase, devfn, l);
  32.401 +
  32.402 +	next:
  32.403 +		/* next device, if function 0 */
  32.404 +		if (PCI_FUNC(devfn) == 0 && (hdr_type & 0x80) == 0)
  32.405 +			devfn += 7;
  32.406 +	}
  32.407 +}
  32.408 +
  32.409 +#endif /* CONFIG_MPIC_BROKEN_U3 */
  32.410 +
  32.411 +
  32.412 +/* Find an mpic associated with a given linux interrupt */
  32.413 +static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi)
  32.414 +{
  32.415 +	struct mpic *mpic = mpics;
  32.416 +
  32.417 +	while(mpic) {
  32.418 +		/* search IPIs first since they may override the main interrupts */
  32.419 +		if (irq >= mpic->ipi_offset && irq < (mpic->ipi_offset + 4)) {
  32.420 +			if (is_ipi)
  32.421 +				*is_ipi = 1;
  32.422 +			return mpic;
  32.423 +		}
  32.424 +		if (irq >= mpic->irq_offset &&
  32.425 +		    irq < (mpic->irq_offset + mpic->irq_count)) {
  32.426 +			if (is_ipi)
  32.427 +				*is_ipi = 0;
  32.428 +			return mpic;
  32.429 +		}
  32.430 +		mpic = mpic -> next;
  32.431 +	}
  32.432 +	return NULL;
  32.433 +}
  32.434 +
  32.435 +/* Convert a cpu mask from logical to physical cpu numbers. */
  32.436 +static inline u32 mpic_physmask(u32 cpumask)
  32.437 +{
  32.438 +	int i;
  32.439 +	u32 mask = 0;
  32.440 +
  32.441 +	for (i = 0; i < NR_CPUS; ++i, cpumask >>= 1)
  32.442 +		mask |= (cpumask & 1) << get_hard_smp_processor_id(i);
  32.443 +	return mask;
  32.444 +}
  32.445 +
  32.446 +#ifdef CONFIG_SMP
  32.447 +/* Get the mpic structure from the IPI number */
  32.448 +static inline struct mpic * mpic_from_ipi(unsigned int ipi)
  32.449 +{
  32.450 +	return container_of(irq_desc[ipi].handler, struct mpic, hc_ipi);
  32.451 +}
  32.452 +#endif
  32.453 +
  32.454 +/* Get the mpic structure from the irq number */
  32.455 +static inline struct mpic * mpic_from_irq(unsigned int irq)
  32.456 +{
  32.457 +	return container_of(irq_desc[irq].handler, struct mpic, hc_irq);
  32.458 +}
  32.459 +
  32.460 +/* Send an EOI */
  32.461 +static inline void mpic_eoi(struct mpic *mpic)
  32.462 +{
  32.463 +	mpic_cpu_write(MPIC_CPU_EOI, 0);
  32.464 +	(void)mpic_cpu_read(MPIC_CPU_WHOAMI);
  32.465 +}
  32.466 +
  32.467 +#ifdef CONFIG_SMP
  32.468 +static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
  32.469 +{
  32.470 +	struct mpic *mpic = dev_id;
  32.471 +
  32.472 +	smp_message_recv(irq - mpic->ipi_offset, regs);
  32.473 +	return IRQ_HANDLED;
  32.474 +}
  32.475 +#endif /* CONFIG_SMP */
  32.476 +
  32.477 +/*
  32.478 + * Linux descriptor level callbacks
  32.479 + */
  32.480 +
  32.481 +
  32.482 +static void mpic_enable_irq(unsigned int irq)
  32.483 +{
  32.484 +	unsigned int loops = 100000;
  32.485 +	struct mpic *mpic = mpic_from_irq(irq);
  32.486 +	unsigned int src = irq - mpic->irq_offset;
  32.487 +
  32.488 +	DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
  32.489 +
  32.490 +	mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
  32.491 +		       mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) &
  32.492 +		       ~MPIC_VECPRI_MASK);
  32.493 +
  32.494 +	/* make sure mask gets to controller before we return to user */
  32.495 +	do {
  32.496 +		if (!loops--) {
  32.497 +			printk(KERN_ERR "mpic_enable_irq timeout\n");
  32.498 +			break;
  32.499 +		}
  32.500 +	} while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);	
  32.501 +
  32.502 +#ifdef CONFIG_MPIC_BROKEN_U3
  32.503 +	if (mpic->flags & MPIC_BROKEN_U3) {
  32.504 +		unsigned int src = irq - mpic->irq_offset;
  32.505 +		if (mpic_is_ht_interrupt(mpic, src) &&
  32.506 +		    (irq_desc[irq].status & IRQ_LEVEL))
  32.507 +			mpic_ht_end_irq(mpic, src);
  32.508 +	}
  32.509 +#endif /* CONFIG_MPIC_BROKEN_U3 */
  32.510 +}
  32.511 +
  32.512 +static unsigned int mpic_startup_irq(unsigned int irq)
  32.513 +{
  32.514 +#ifdef CONFIG_MPIC_BROKEN_U3
  32.515 +	struct mpic *mpic = mpic_from_irq(irq);
  32.516 +	unsigned int src = irq - mpic->irq_offset;
  32.517 +#endif /* CONFIG_MPIC_BROKEN_U3 */
  32.518 +
  32.519 +	mpic_enable_irq(irq);
  32.520 +
  32.521 +#ifdef CONFIG_MPIC_BROKEN_U3
  32.522 +	if (mpic_is_ht_interrupt(mpic, src))
  32.523 +		mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status);
  32.524 +#endif /* CONFIG_MPIC_BROKEN_U3 */
  32.525 +
  32.526 +	return 0;
  32.527 +}
  32.528 +
  32.529 +static void mpic_disable_irq(unsigned int irq)
  32.530 +{
  32.531 +	unsigned int loops = 100000;
  32.532 +	struct mpic *mpic = mpic_from_irq(irq);
  32.533 +	unsigned int src = irq - mpic->irq_offset;
  32.534 +
  32.535 +	DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
  32.536 +
  32.537 +	mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
  32.538 +		       mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) |
  32.539 +		       MPIC_VECPRI_MASK);
  32.540 +
  32.541 +	/* make sure mask gets to controller before we return to user */
  32.542 +	do {
  32.543 +		if (!loops--) {
  32.544 +			printk(KERN_ERR "mpic_enable_irq timeout\n");
  32.545 +			break;
  32.546 +		}
  32.547 +	} while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
  32.548 +}
  32.549 +
  32.550 +static void mpic_shutdown_irq(unsigned int irq)
  32.551 +{
  32.552 +#ifdef CONFIG_MPIC_BROKEN_U3
  32.553 +	struct mpic *mpic = mpic_from_irq(irq);
  32.554 +	unsigned int src = irq - mpic->irq_offset;
  32.555 +
  32.556 +	if (mpic_is_ht_interrupt(mpic, src))
  32.557 +		mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status);
  32.558 +
  32.559 +#endif /* CONFIG_MPIC_BROKEN_U3 */
  32.560 +
  32.561 +	mpic_disable_irq(irq);
  32.562 +}
  32.563 +
  32.564 +static void mpic_end_irq(unsigned int irq)
  32.565 +{
  32.566 +	struct mpic *mpic = mpic_from_irq(irq);
  32.567 +
  32.568 +#ifdef DEBUG_IRQ
  32.569 +	DBG("%s: end_irq: %d\n", mpic->name, irq);
  32.570 +#endif
  32.571 +	/* We always EOI on end_irq() even for edge interrupts since that
  32.572 +	 * should only lower the priority, the MPIC should have properly
  32.573 +	 * latched another edge interrupt coming in anyway
  32.574 +	 */
  32.575 +
  32.576 +#ifdef CONFIG_MPIC_BROKEN_U3
  32.577 +	if (mpic->flags & MPIC_BROKEN_U3) {
  32.578 +		unsigned int src = irq - mpic->irq_offset;
  32.579 +		if (mpic_is_ht_interrupt(mpic, src) &&
  32.580 +		    (irq_desc[irq].status & IRQ_LEVEL))
  32.581 +			mpic_ht_end_irq(mpic, src);
  32.582 +	}
  32.583 +#endif /* CONFIG_MPIC_BROKEN_U3 */
  32.584 +
  32.585 +	mpic_eoi(mpic);
  32.586 +}
  32.587 +
  32.588 +#ifdef CONFIG_SMP
  32.589 +
  32.590 +static void mpic_enable_ipi(unsigned int irq)
  32.591 +{
  32.592 +	struct mpic *mpic = mpic_from_ipi(irq);
  32.593 +	unsigned int src = irq - mpic->ipi_offset;
  32.594 +
  32.595 +	DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src);
  32.596 +	mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
  32.597 +}
  32.598 +
  32.599 +static void mpic_disable_ipi(unsigned int irq)
  32.600 +{
  32.601 +	/* NEVER disable an IPI... that's just plain wrong! */
  32.602 +}
  32.603 +
  32.604 +static void mpic_end_ipi(unsigned int irq)
  32.605 +{
  32.606 +	struct mpic *mpic = mpic_from_ipi(irq);
  32.607 +
  32.608 +	/*
  32.609 +	 * IPIs are marked IRQ_PER_CPU. This has the side effect of
  32.610 +	 * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from
  32.611 +	 * applying to them. We EOI them late to avoid re-entering.
  32.612 +	 * We mark IPI's with SA_INTERRUPT as they must run with
  32.613 +	 * irqs disabled.
  32.614 +	 */
  32.615 +	mpic_eoi(mpic);
  32.616 +}
  32.617 +
  32.618 +#endif /* CONFIG_SMP */
  32.619 +
  32.620 +static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
  32.621 +{
  32.622 +	struct mpic *mpic = mpic_from_irq(irq);
  32.623 +
  32.624 +	cpumask_t tmp;
  32.625 +
  32.626 +	cpus_and(tmp, cpumask, cpu_online_map);
  32.627 +
  32.628 +	mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_DESTINATION,
  32.629 +		       mpic_physmask(cpus_addr(tmp)[0]));	
  32.630 +}
  32.631 +
  32.632 +
  32.633 +/*
  32.634 + * Exported functions
  32.635 + */
  32.636 +
  32.637 +
  32.638 +struct mpic * __init mpic_alloc(unsigned long phys_addr,
  32.639 +				unsigned int flags,
  32.640 +				unsigned int isu_size,
  32.641 +				unsigned int irq_offset,
  32.642 +				unsigned int irq_count,
  32.643 +				unsigned int ipi_offset,
  32.644 +				unsigned char *senses,
  32.645 +				unsigned int senses_count,
  32.646 +				const char *name)
  32.647 +{
  32.648 +	struct mpic	*mpic;
  32.649 +	u32		reg;
  32.650 +	const char	*vers;
  32.651 +	int		i;
  32.652 +
  32.653 +	mpic = alloc_bootmem(sizeof(struct mpic));
  32.654 +	if (mpic == NULL)
  32.655 +		return NULL;
  32.656 +	
  32.657 +
  32.658 +	memset(mpic, 0, sizeof(struct mpic));
  32.659 +	mpic->name = name;
  32.660 +
  32.661 +	mpic->hc_irq.typename = name;
  32.662 +	mpic->hc_irq.startup = mpic_startup_irq;
  32.663 +	mpic->hc_irq.shutdown = mpic_shutdown_irq;
  32.664 +	mpic->hc_irq.enable = mpic_enable_irq;
  32.665 +	mpic->hc_irq.disable = mpic_disable_irq;
  32.666 +	mpic->hc_irq.end = mpic_end_irq;
  32.667 +	if (flags & MPIC_PRIMARY)
  32.668 +		mpic->hc_irq.set_affinity = mpic_set_affinity;
  32.669 +#ifdef CONFIG_SMP
  32.670 +	mpic->hc_ipi.typename = name;
  32.671 +	mpic->hc_ipi.enable = mpic_enable_ipi;
  32.672 +	mpic->hc_ipi.disable = mpic_disable_ipi;
  32.673 +	mpic->hc_ipi.end = mpic_end_ipi;
  32.674 +#endif /* CONFIG_SMP */
  32.675 +
  32.676 +	mpic->flags = flags;
  32.677 +	mpic->isu_size = isu_size;
  32.678 +	mpic->irq_offset = irq_offset;
  32.679 +	mpic->irq_count = irq_count;
  32.680 +	mpic->ipi_offset = ipi_offset;
  32.681 +	mpic->num_sources = 0; /* so far */
  32.682 +	mpic->senses = senses;
  32.683 +	mpic->senses_count = senses_count;
  32.684 +
  32.685 +	/* Map the global registers */
  32.686 +	mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000);
  32.687 +	mpic->tmregs = mpic->gregs + ((MPIC_TIMER_BASE - MPIC_GREG_BASE) >> 2);
  32.688 +	BUG_ON(mpic->gregs == NULL);
  32.689 +
  32.690 +	/* Reset */
  32.691 +	if (flags & MPIC_WANTS_RESET) {
  32.692 +		mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
  32.693 +			   mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
  32.694 +			   | MPIC_GREG_GCONF_RESET);
  32.695 +		while( mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
  32.696 +		       & MPIC_GREG_GCONF_RESET)
  32.697 +			mb();
  32.698 +	}
  32.699 +
  32.700 +	/* Read feature register, calculate num CPUs and, for non-ISU
  32.701 +	 * MPICs, num sources as well. On ISU MPICs, sources are counted
  32.702 +	 * as ISUs are added
  32.703 +	 */
  32.704 +	reg = mpic_read(mpic->gregs, MPIC_GREG_FEATURE_0);
  32.705 +	mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK)
  32.706 +			  >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
  32.707 +	if (isu_size == 0)
  32.708 +		mpic->num_sources = ((reg & MPIC_GREG_FEATURE_LAST_SRC_MASK)
  32.709 +				     >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
  32.710 +
  32.711 +	/* Map the per-CPU registers */
  32.712 +	for (i = 0; i < mpic->num_cpus; i++) {
  32.713 +		mpic->cpuregs[i] = ioremap(phys_addr + MPIC_CPU_BASE +
  32.714 +					   i * MPIC_CPU_STRIDE, 0x1000);
  32.715 +		BUG_ON(mpic->cpuregs[i] == NULL);
  32.716 +	}
  32.717 +
  32.718 +	/* Initialize main ISU if none provided */
  32.719 +	if (mpic->isu_size == 0) {
  32.720 +		mpic->isu_size = mpic->num_sources;
  32.721 +		mpic->isus[0] = ioremap(phys_addr + MPIC_IRQ_BASE,
  32.722 +					MPIC_IRQ_STRIDE * mpic->isu_size);
  32.723 +		BUG_ON(mpic->isus[0] == NULL);
  32.724 +	}
  32.725 +	mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
  32.726 +	mpic->isu_mask = (1 << mpic->isu_shift) - 1;
  32.727 +
  32.728 +	/* Display version */
  32.729 +	switch (reg & MPIC_GREG_FEATURE_VERSION_MASK) {
  32.730 +	case 1:
  32.731 +		vers = "1.0";
  32.732 +		break;
  32.733 +	case 2:
  32.734 +		vers = "1.2";
  32.735 +		break;
  32.736 +	case 3:
  32.737 +		vers = "1.3";
  32.738 +		break;
  32.739 +	default:
  32.740 +		vers = "<unknown>";
  32.741 +		break;
  32.742 +	}
  32.743 +	printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %lx, max %d CPUs\n",
  32.744 +	       name, vers, phys_addr, mpic->num_cpus);
  32.745 +	printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n", mpic->isu_size,
  32.746 +	       mpic->isu_shift, mpic->isu_mask);
  32.747 +
  32.748 +	mpic->next = mpics;
  32.749 +	mpics = mpic;
  32.750 +
  32.751 +	if (flags & MPIC_PRIMARY)
  32.752 +		mpic_primary = mpic;
  32.753 +
  32.754 +	return mpic;
  32.755 +}
  32.756 +
  32.757 +void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
  32.758 +			    unsigned long phys_addr)
  32.759 +{
  32.760 +	unsigned int isu_first = isu_num * mpic->isu_size;
  32.761 +
  32.762 +	BUG_ON(isu_num >= MPIC_MAX_ISU);
  32.763 +
  32.764 +	mpic->isus[isu_num] = ioremap(phys_addr, MPIC_IRQ_STRIDE * mpic->isu_size);
  32.765 +	if ((isu_first + mpic->isu_size) > mpic->num_sources)
  32.766 +		mpic->num_sources = isu_first + mpic->isu_size;
  32.767 +}
  32.768 +
  32.769 +void __init mpic_setup_cascade(unsigned int irq, mpic_cascade_t handler,
  32.770 +			       void *data)
  32.771 +{
  32.772 +	struct mpic *mpic = mpic_find(irq, NULL);
  32.773 +	unsigned long flags;
  32.774 +
  32.775 +	/* Synchronization here is a bit dodgy, so don't try to replace cascade
  32.776 +	 * interrupts on the fly too often ... but normally it's set up at boot.
  32.777 +	 */
  32.778 +	spin_lock_irqsave(&mpic_lock, flags);
  32.779 +	if (mpic->cascade)	       
  32.780 +		mpic_disable_irq(mpic->cascade_vec + mpic->irq_offset);
  32.781 +	mpic->cascade = NULL;
  32.782 +	wmb();
  32.783 +	mpic->cascade_vec = irq - mpic->irq_offset;
  32.784 +	mpic->cascade_data = data;
  32.785 +	wmb();
  32.786 +	mpic->cascade = handler;
  32.787 +	mpic_enable_irq(irq);
  32.788 +	spin_unlock_irqrestore(&mpic_lock, flags);
  32.789 +}
  32.790 +
  32.791 +void __init mpic_init(struct mpic *mpic)
  32.792 +{
  32.793 +	int i;
  32.794 +
  32.795 +	BUG_ON(mpic->num_sources == 0);
  32.796 +
  32.797 +	printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources);
  32.798 +
  32.799 +	/* Set current processor priority to max */
  32.800 +	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
  32.801 +
  32.802 +	/* Initialize timers: just disable them all */
  32.803 +	for (i = 0; i < 4; i++) {
  32.804 +		mpic_write(mpic->tmregs,
  32.805 +			   i * MPIC_TIMER_STRIDE + MPIC_TIMER_DESTINATION, 0);
  32.806 +		mpic_write(mpic->tmregs,
  32.807 +			   i * MPIC_TIMER_STRIDE + MPIC_TIMER_VECTOR_PRI,
  32.808 +			   MPIC_VECPRI_MASK |
  32.809 +			   (MPIC_VEC_TIMER_0 + i));
  32.810 +	}
  32.811 +
  32.812 +	/* Initialize IPIs to our reserved vectors and mark them disabled for now */
  32.813 +	mpic_test_broken_ipi(mpic);
  32.814 +	for (i = 0; i < 4; i++) {
  32.815 +		mpic_ipi_write(i,
  32.816 +			       MPIC_VECPRI_MASK |
  32.817 +			       (10 << MPIC_VECPRI_PRIORITY_SHIFT) |
  32.818 +			       (MPIC_VEC_IPI_0 + i));
  32.819 +#ifdef CONFIG_SMP
  32.820 +		if (!(mpic->flags & MPIC_PRIMARY))
  32.821 +			continue;
  32.822 +		irq_desc[mpic->ipi_offset+i].status |= IRQ_PER_CPU;
  32.823 +		irq_desc[mpic->ipi_offset+i].handler = &mpic->hc_ipi;
  32.824 +#endif /* CONFIG_SMP */
  32.825 +	}
  32.826 +
  32.827 +	/* Initialize interrupt sources */
  32.828 +	if (mpic->irq_count == 0)
  32.829 +		mpic->irq_count = mpic->num_sources;
  32.830 +
  32.831 +#ifdef CONFIG_MPIC_BROKEN_U3
  32.832 +	/* Do the HT PIC fixups on U3 broken mpic */
  32.833 +	DBG("MPIC flags: %x\n", mpic->flags);
  32.834 +	if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY))
  32.835 +		mpic_scan_ht_pics(mpic);
  32.836 +#endif /* CONFIG_MPIC_BROKEN_U3 */
  32.837 +
  32.838 +	for (i = 0; i < mpic->num_sources; i++) {
  32.839 +		/* start with vector = source number, and masked */
  32.840 +		u32 vecpri = MPIC_VECPRI_MASK | i | (8 << MPIC_VECPRI_PRIORITY_SHIFT);
  32.841 +		int level = 0;
  32.842 +		
  32.843 +		/* if it's an IPI, we skip it */
  32.844 +		if ((mpic->irq_offset + i) >= (mpic->ipi_offset + i) &&
  32.845 +		    (mpic->irq_offset + i) <  (mpic->ipi_offset + i + 4))
  32.846 +			continue;
  32.847 +
  32.848 +		/* do senses munging */
  32.849 +		if (mpic->senses && i < mpic->senses_count) {
  32.850 +			if (mpic->senses[i] & IRQ_SENSE_LEVEL)
  32.851 +				vecpri |= MPIC_VECPRI_SENSE_LEVEL;
  32.852 +			if (mpic->senses[i] & IRQ_POLARITY_POSITIVE)
  32.853 +				vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
  32.854 +		} else
  32.855 +			vecpri |= MPIC_VECPRI_SENSE_LEVEL;
  32.856 +
  32.857 +		/* remember if it was a level interrupts */
  32.858 +		level = (vecpri & MPIC_VECPRI_SENSE_LEVEL);
  32.859 +
  32.860 +		/* deal with broken U3 */
  32.861 +		if (mpic->flags & MPIC_BROKEN_U3) {
  32.862 +#ifdef CONFIG_MPIC_BROKEN_U3
  32.863 +			if (mpic_is_ht_interrupt(mpic, i)) {
  32.864 +				vecpri &= ~(MPIC_VECPRI_SENSE_MASK |
  32.865 +					    MPIC_VECPRI_POLARITY_MASK);
  32.866 +				vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
  32.867 +			}
  32.868 +#else
  32.869 +			printk(KERN_ERR "mpic: BROKEN_U3 set, but CONFIG doesn't match\n");
  32.870 +#endif
  32.871 +		}
  32.872 +
  32.873 +		DBG("setup source %d, vecpri: %08x, level: %d\n", i, vecpri,
  32.874 +		    (level != 0));
  32.875 +
  32.876 +		/* init hw */
  32.877 +		mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri);
  32.878 +		mpic_irq_write(i, MPIC_IRQ_DESTINATION,
  32.879 +			       1 << hard_smp_processor_id());
  32.880 +
  32.881 +		/* init linux descriptors */
  32.882 +		if (i < mpic->irq_count) {
  32.883 +			irq_desc[mpic->irq_offset+i].status = level ? IRQ_LEVEL : 0;
  32.884 +			irq_desc[mpic->irq_offset+i].handler = &mpic->hc_irq;
  32.885 +		}
  32.886 +	}
  32.887 +	
  32.888 +	/* Init spurrious vector */
  32.889 +	mpic_write(mpic->gregs, MPIC_GREG_SPURIOUS, MPIC_VEC_SPURRIOUS);
  32.890 +
  32.891 +	/* Disable 8259 passthrough */
  32.892 +	mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
  32.893 +		   mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
  32.894 +		   | MPIC_GREG_GCONF_8259_PTHROU_DIS);
  32.895 +
  32.896 +	/* Set current processor priority to 0 */
  32.897 +	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
  32.898 +}
  32.899 +
  32.900 +
  32.901 +
  32.902 +void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
  32.903 +{
  32.904 +	unsigned is_ipi;
  32.905 +	struct mpic *mpic = mpic_find(irq, &is_ipi);
  32.906 +	unsigned long flags;
  32.907 +	u32 reg;
  32.908 +
  32.909 +	spin_lock_irqsave(&mpic_lock, flags);
  32.910 +	if (is_ipi) {
  32.911 +		reg = mpic_ipi_read(irq - mpic->ipi_offset) &
  32.912 +			~MPIC_VECPRI_PRIORITY_MASK;
  32.913 +		mpic_ipi_write(irq - mpic->ipi_offset,
  32.914 +			       reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
  32.915 +	} else {
  32.916 +		reg = mpic_irq_read(irq - mpic->irq_offset,MPIC_IRQ_VECTOR_PRI)
  32.917 +			& ~MPIC_VECPRI_PRIORITY_MASK;
  32.918 +		mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI,
  32.919 +			       reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
  32.920 +	}
  32.921 +	spin_unlock_irqrestore(&mpic_lock, flags);
  32.922 +}
  32.923 +
  32.924 +unsigned int mpic_irq_get_priority(unsigned int irq)
  32.925 +{
  32.926 +	unsigned is_ipi;
  32.927 +	struct mpic *mpic = mpic_find(irq, &is_ipi);
  32.928 +	unsigned long flags;
  32.929 +	u32 reg;
  32.930 +
  32.931 +	spin_lock_irqsave(&mpic_lock, flags);
  32.932 +	if (is_ipi)
  32.933 +		reg = mpic_ipi_read(irq - mpic->ipi_offset);
  32.934 +	else
  32.935 +		reg = mpic_irq_read(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI);
  32.936 +	spin_unlock_irqrestore(&mpic_lock, flags);
  32.937 +	return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT;
  32.938 +}
  32.939 +
  32.940 +void mpic_setup_this_cpu(void)
  32.941 +{
  32.942 +#ifdef CONFIG_SMP
  32.943 +	struct mpic *mpic = mpic_primary;
  32.944 +	unsigned long flags;
  32.945 +	u32 msk = 1 << hard_smp_processor_id();
  32.946 +	unsigned int i;
  32.947 +
  32.948 +	BUG_ON(mpic == NULL);
  32.949 +
  32.950 +	DBG("%s: setup_this_cpu(%d)\n", mpic->name, hard_smp_processor_id());
  32.951 +
  32.952 +	spin_lock_irqsave(&mpic_lock, flags);
  32.953 +
  32.954 + 	/* let the mpic know we want intrs. default affinity is 0xffffffff
  32.955 +	 * until changed via /proc. That's how it's done on x86. If we want
  32.956 +	 * it differently, then we should make sure we also change the default
  32.957 +	 * values of irq_affinity in irq.c.
  32.958 + 	 */
  32.959 +	if (distribute_irqs) {
  32.960 +	 	for (i = 0; i < mpic->num_sources ; i++)
  32.961 +			mpic_irq_write(i, MPIC_IRQ_DESTINATION,
  32.962 +				mpic_irq_read(i, MPIC_IRQ_DESTINATION) | msk);
  32.963 +	}
  32.964 +
  32.965 +	/* Set current processor priority to 0 */
  32.966 +	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
  32.967 +
  32.968 +	spin_unlock_irqrestore(&mpic_lock, flags);
  32.969 +#endif /* CONFIG_SMP */
  32.970 +}
  32.971 +
  32.972 +int mpic_cpu_get_priority(void)
  32.973 +{
  32.974 +	struct mpic *mpic = mpic_primary;
  32.975 +
  32.976 +	return mpic_cpu_read(MPIC_CPU_CURRENT_TASK_PRI);
  32.977 +}
  32.978 +
  32.979 +void mpic_cpu_set_priority(int prio)
  32.980 +{
  32.981 +	struct mpic *mpic = mpic_primary;
  32.982 +
  32.983 +	prio &= MPIC_CPU_TASKPRI_MASK;
  32.984 +	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, prio);
  32.985 +}
  32.986 +
  32.987 +/*
  32.988 + * XXX: someone who knows mpic should check this.
  32.989 + * do we need to eoi the ipi including for kexec cpu here (see xics comments)?
  32.990 + * or can we reset the mpic in the new kernel?
  32.991 + */
  32.992 +void mpic_teardown_this_cpu(int secondary)
  32.993 +{
  32.994 +	struct mpic *mpic = mpic_primary;
  32.995 +	unsigned long flags;
  32.996 +	u32 msk = 1 << hard_smp_processor_id();
  32.997 +	unsigned int i;
  32.998 +
  32.999 +	BUG_ON(mpic == NULL);
 32.1000 +
 32.1001 +	DBG("%s: teardown_this_cpu(%d)\n", mpic->name, hard_smp_processor_id());
 32.1002 +	spin_lock_irqsave(&mpic_lock, flags);
 32.1003 +
 32.1004 +	/* let the mpic know we don't want intrs.  */
 32.1005 +	for (i = 0; i < mpic->num_sources ; i++)
 32.1006 +		mpic_irq_write(i, MPIC_IRQ_DESTINATION,
 32.1007 +			mpic_irq_read(i, MPIC_IRQ_DESTINATION) & ~msk);
 32.1008 +
 32.1009 +	/* Set current processor priority to max */
 32.1010 +	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
 32.1011 +
 32.1012 +	spin_unlock_irqrestore(&mpic_lock, flags);
 32.1013 +}
 32.1014 +
 32.1015 +
 32.1016 +void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)
 32.1017 +{
 32.1018 +	struct mpic *mpic = mpic_primary;
 32.1019 +
 32.1020 +	BUG_ON(mpic == NULL);
 32.1021 +
 32.1022 +#ifdef DEBUG_IPI
 32.1023 +	DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);
 32.1024 +#endif
 32.1025 +
 32.1026 +	mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10,
 32.1027 +		       mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
 32.1028 +}
 32.1029 +
 32.1030 +int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs)
 32.1031 +{
 32.1032 +	u32 irq;
 32.1033 +
 32.1034 +	irq = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;
 32.1035 +#ifdef DEBUG_LOW
 32.1036 +	DBG("%s: get_one_irq(): %d\n", mpic->name, irq);
 32.1037 +#endif
 32.1038 +	if (mpic->cascade && irq == mpic->cascade_vec) {
 32.1039 +#ifdef DEBUG_LOW
 32.1040 +		DBG("%s: cascading ...\n", mpic->name);
 32.1041 +#endif
 32.1042 +		irq = mpic->cascade(regs, mpic->cascade_data);
 32.1043 +		mpic_eoi(mpic);
 32.1044 +		return irq;
 32.1045 +	}
 32.1046 +	if (unlikely(irq == MPIC_VEC_SPURRIOUS))
 32.1047 +		return -1;
 32.1048 +	if (irq < MPIC_VEC_IPI_0) {
 32.1049 +#ifdef DEBUG_IRQ
 32.1050 +		DBG("%s: irq %d\n", mpic->name, irq + mpic->irq_offset);
 32.1051 +#endif
 32.1052 +		return irq + mpic->irq_offset;
 32.1053 +	}
 32.1054 +#ifdef DEBUG_IPI
 32.1055 +       	DBG("%s: ipi %d !\n", mpic->name, irq - MPIC_VEC_IPI_0);
 32.1056 +#endif
 32.1057 +	return irq - MPIC_VEC_IPI_0 + mpic->ipi_offset;
 32.1058 +}
 32.1059 +
 32.1060 +int mpic_get_irq(struct pt_regs *regs)
 32.1061 +{
 32.1062 +	struct mpic *mpic = mpic_primary;
 32.1063 +
 32.1064 +	BUG_ON(mpic == NULL);
 32.1065 +
 32.1066 +	return mpic_get_one_irq(mpic, regs);
 32.1067 +}
 32.1068 +
 32.1069 +
 32.1070 +#ifdef CONFIG_SMP
 32.1071 +void mpic_request_ipis(void)
 32.1072 +{
 32.1073 +	struct mpic *mpic = mpic_primary;
 32.1074 +
 32.1075 +	BUG_ON(mpic == NULL);
 32.1076 +	
 32.1077 +	printk("requesting IPIs ... \n");
 32.1078 +
 32.1079 +	/* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */
 32.1080 +	request_irq(mpic->ipi_offset+0, mpic_ipi_action, SA_INTERRUPT,
 32.1081 +		    "IPI0 (call function)", mpic);
 32.1082 +	request_irq(mpic->ipi_offset+1, mpic_ipi_action, SA_INTERRUPT,
 32.1083 +		   "IPI1 (reschedule)", mpic);
 32.1084 +	request_irq(mpic->ipi_offset+2, mpic_ipi_action, SA_INTERRUPT,
 32.1085 +		   "IPI2 (unused)", mpic);
 32.1086 +	request_irq(mpic->ipi_offset+3, mpic_ipi_action, SA_INTERRUPT,
 32.1087 +		   "IPI3 (debugger break)", mpic);
 32.1088 +
 32.1089 +	printk("IPIs requested... \n");
 32.1090 +}
 32.1091 +
 32.1092 +void smp_mpic_message_pass(int target, int msg)
 32.1093 +{
 32.1094 +	/* make sure we're sending something that translates to an IPI */
 32.1095 +	if ((unsigned int)msg > 3) {
 32.1096 +		printk("SMP %d: smp_message_pass: unknown msg %d\n",
 32.1097 +		       smp_processor_id(), msg);
 32.1098 +		return;
 32.1099 +	}
 32.1100 +	switch (target) {
 32.1101 +	case MSG_ALL:
 32.1102 +		mpic_send_ipi(msg, 0xffffffff);
 32.1103 +		break;
 32.1104 +	case MSG_ALL_BUT_SELF:
 32.1105 +		mpic_send_ipi(msg, 0xffffffff & ~(1 << smp_processor_id()));
 32.1106 +		break;
 32.1107 +	default:
 32.1108 +		mpic_send_ipi(msg, 1 << target);
 32.1109 +		break;
 32.1110 +	}
 32.1111 +}
 32.1112 +#endif /* CONFIG_SMP */
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/xen/arch/powerpc/mpic_init.c	Fri Jul 14 10:47:50 2006 +0100
    33.3 @@ -0,0 +1,390 @@
    33.4 +/*
    33.5 + * This program is free software; you can redistribute it and/or modify
    33.6 + * it under the terms of the GNU General Public License as published by
    33.7 + * the Free Software Foundation; either version 2 of the License, or
    33.8 + * (at your option) any later version.
    33.9 + *
   33.10 + * This program is distributed in the hope that it will be useful,
   33.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   33.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   33.13 + * GNU General Public License for more details.
   33.14 + *
   33.15 + * You should have received a copy of the GNU General Public License
   33.16 + * along with this program; if not, write to the Free Software
   33.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   33.18 + *
   33.19 + * Copyright (C) IBM Corp. 2005
   33.20 + *
   33.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   33.22 + */
   33.23 +
   33.24 +#include <xen/config.h>
   33.25 +#include <xen/init.h>
   33.26 +#include <xen/lib.h>
   33.27 +#include <xen/compile.h>
   33.28 +#include <asm/mpic.h>
   33.29 +#include "mpic_init.h"
   33.30 +#include "oftree.h"
   33.31 +#include "of-devtree.h"
   33.32 +
   33.33 +#undef DEBUG
   33.34 +#ifdef DEBUG
   33.35 +#define DBG(fmt...) printk(fmt)
   33.36 +#else
   33.37 +#define DBG(fmt...)
   33.38 +#endif
   33.39 +
   33.40 +#define PANIC(fmt...) DBG(fmt)
   33.41 +
   33.42 +static struct mpic *mpic;
   33.43 +static unsigned long opic_addr;
   33.44 +static unsigned int opic_flags;
   33.45 +
   33.46 +/*
   33.47 + * from OF_IEEE_1275
   33.48 + *
   33.49 + * pg 175, property "ranges"
   33.50 + *
   33.51 + * The number of integers in each size entry is determined by the
   33.52 + * value of the #size-cells property of this node (the node in which
   33.53 + * the ranges property appears) or 1 if the #size-cells property is
   33.54 + * absent.
   33.55 + *
   33.56 + *
   33.57 + * pg 177, property "reg"
   33.58 + *
   33.59 + * The number of integers in each size entry is determined by the
   33.60 + * value of the "#size-cells" property in the parent node.  If the
   33.61 + * parent node has no such property, the value is one.
   33.62 + */
   33.63 +static unsigned long reg2(void *oft_p, ofdn_t c)
   33.64 +{
   33.65 +    int rc;
   33.66 +    /* the struct isa_reg_property is for a value of 2 for
   33.67 +     * #address-cells and a value of 1 for #size-cells (of the
   33.68 +     * parent).
   33.69 +     */
   33.70 +    struct isa_reg_property {
   33.71 +        u32 space;
   33.72 +        u32 address;
   33.73 +        u32 size;
   33.74 +    } isa_reg;
   33.75 +
   33.76 +    rc = ofd_getprop(oft_p, c, "reg", &isa_reg, sizeof(isa_reg));
   33.77 +
   33.78 +    DBG("%s: reg property address=0x%08x  size=0x%08x\n", __func__,
   33.79 +                    isa_reg.address, isa_reg.size);
   33.80 +    return isa_reg.address;
   33.81 +}
   33.82 +
   33.83 +static unsigned long reg1(void *oft_p, ofdn_t c)
   33.84 +{
   33.85 +    int rc;
   33.86 +    /* the struct reg_property32 is for a value of 1 for
   33.87 +     * #address-cells and a value of 1 for #size-cells.
   33.88 +     */
   33.89 +    struct reg_property32 {
   33.90 +        u32 address;
   33.91 +        u32 size;
   33.92 +    } reg;
   33.93 +
   33.94 +    rc = ofd_getprop(oft_p, c, "reg", &reg, sizeof(reg));
   33.95 +
   33.96 +    DBG("%s: reg property address=0x%08x  size=0x%08x\n", __func__,
   33.97 +                        reg.address, reg.size);
   33.98 +    return reg.address;
   33.99 +}
  33.100 +
  33.101 +static unsigned long find_reg_addr_from_node(void *oft_p, ofdn_t c)
  33.102 +{
  33.103 +    int p_len;
  33.104 +    unsigned long reg_addr = 0;
  33.105 +    u32 size_c = 1;
  33.106 +    u32 addr_c = 2;
  33.107 +    ofdn_t parent;
  33.108 +
  33.109 +    if (c == OFD_ROOT) {
  33.110 +        parent = c;
  33.111 +    } else {
  33.112 +        parent = ofd_node_parent(oft_p, c);
  33.113 +    }
  33.114 +
  33.115 +    p_len = ofd_getprop(oft_p, parent, "#size-cells", &size_c, sizeof(size_c));
  33.116 +    DBG("%s size is %d\n", __func__, size_c);
  33.117 +
  33.118 +    p_len = ofd_getprop(oft_p, parent, "#address-cells", &addr_c,
  33.119 +                        sizeof(addr_c));
  33.120 +    DBG("%s address is %d\n", __func__, addr_c);
  33.121 +
  33.122 +    if ( 1 != size_c ) {
  33.123 +        PANIC("Unsupported size for reg property\n");
  33.124 +    }
  33.125 +    
  33.126 +    if ( 1 == addr_c) {
  33.127 +        reg_addr = reg1(oft_p, c);
  33.128 +    } else if ( 2 == addr_c ) {
  33.129 +        reg_addr = reg2(oft_p, c);
  33.130 +    } else {
  33.131 +        PANIC("Unsupported address size for reg property\n");
  33.132 +    }
  33.133 +    DBG("%s: address 0x%lx\n", __func__, reg_addr);
  33.134 +    return reg_addr;
  33.135 +}
  33.136 +
  33.137 +/*
  33.138 + * from OF_IEEE_1275
  33.139 + *
  33.140 + * pg 175, property "ranges"
  33.141 + * 
  33.142 + * The ranges property value is a sequence of child-phys parent-phys
  33.143 + * size specifications. Child-phys is an address, encoded as with
  33.144 + * encode-phys, in the child address space. Parent-phys is an address
  33.145 + * (likewise encoded as with encode-phys) in the parent address
  33.146 + * space. Size is a list of integers, each encoded as with encode-int,
  33.147 + * denoting the length of the child's address range.
  33.148 + */
  33.149 +static unsigned long find_ranges_addr_from_node(void *oft_p, ofdn_t c)
  33.150 +{
  33.151 +    unsigned long ranges_addr = 0;
  33.152 +    int ranges_i;
  33.153 +    ofdn_t parent;
  33.154 +    u32 addr_c = 2;
  33.155 +    u32 ranges[64];
  33.156 +    int p_len;
  33.157 +
  33.158 +    parent = ofd_node_parent(oft_p, c);
  33.159 +    parent = ofd_node_parent(oft_p, parent);
  33.160 +
  33.161 +    p_len = ofd_getprop(oft_p, parent, "ranges", &ranges, sizeof(ranges));
  33.162 +    DBG("%s: ranges\n", __func__);
  33.163 +    int i; for (i=0; i<p_len; i++) {DBG("%08x ", ranges[i]);}
  33.164 +    DBG("\n");
  33.165 +
  33.166 +    p_len = ofd_getprop(oft_p, parent, "#address-cells",
  33.167 +                        &addr_c, sizeof(addr_c));
  33.168 +    DBG("%s address is %d\n", __func__, addr_c);
  33.169 +    ranges_i = addr_c;  /* skip over the child address */
  33.170 +    
  33.171 +    DBG("%s address is %d\n", __func__, addr_c);
  33.172 +    switch (addr_c) {
  33.173 +    case 1: 
  33.174 +        ranges_addr = ranges[ranges_i];
  33.175 +        break;
  33.176 +    case 2:
  33.177 +        ranges_addr = (((u64)ranges[ranges_i]) << 32) |
  33.178 +                      ranges[ranges_i + 1];
  33.179 +        break;
  33.180 +    case 3:  /* the G5 case, how to squeeze 96 bits into 64 */
  33.181 +        ranges_addr = (((u64)ranges[ranges_i+1]) << 32) |
  33.182 +                      ranges[ranges_i + 2];
  33.183 +        break;
  33.184 +    case 4:
  33.185 +        ranges_addr = (((u64)ranges[ranges_i+2]) << 32) |
  33.186 +                      ranges[ranges_i + 4];
  33.187 +        break;
  33.188 +    default:
  33.189 +        PANIC("#address-cells out of range\n");
  33.190 +        break;
  33.191 +    }
  33.192 +    
  33.193 +    DBG("%s: address 0x%lx\n", __func__, ranges_addr);
  33.194 +    return ranges_addr;
  33.195 +}
  33.196 +
  33.197 +static unsigned long find_pic_address_from_node(void *oft_p, ofdn_t c)
  33.198 +{
  33.199 +    unsigned long reg_addr, range_addr, addr;
  33.200 +
  33.201 +    /*
  33.202 +     * The address is the sum of the address in the reg property of this node
  33.203 +     * and the ranges property of the granparent node.
  33.204 +     */
  33.205 +    reg_addr = find_reg_addr_from_node(oft_p, c);
  33.206 +    range_addr = find_ranges_addr_from_node(oft_p, c);
  33.207 +    addr = reg_addr + range_addr;
  33.208 +    DBG("%s: address 0x%lx\n", __func__, addr);
  33.209 +    return addr;
  33.210 +}
  33.211 +
  33.212 +static unsigned int find_pic_flags_from_node(void *oft_p, ofdn_t c)
  33.213 +{
  33.214 +    int be_len;
  33.215 +    unsigned int flags = 0;
  33.216 +
  33.217 +    /* does it have the property big endian? */
  33.218 +    be_len = ofd_getprop(oft_p, c, "big_endian", NULL, 0);
  33.219 +    if (be_len >= 0) {
  33.220 +        DBG("%s: Big Endian found\n", __func__);
  33.221 +        flags |= MPIC_BIG_ENDIAN;
  33.222 +    }
  33.223 +    DBG("%s: flags 0x%x\n", __func__, flags);
  33.224 +    return flags;
  33.225 +}
  33.226 +
  33.227 +static int find_mpic_simple_probe(void *oft_p)
  33.228 +{
  33.229 +    u32 addr_cells;
  33.230 +    int rc;
  33.231 +    u32 addr[2];
  33.232 +
  33.233 +    rc = ofd_getprop(oft_p, OFD_ROOT, "#address-cells",
  33.234 +                     &addr_cells, sizeof(addr_cells));
  33.235 +    if ( rc < 0 ) {
  33.236 +        /* if the property does not exist use its default value, 2 */
  33.237 +        addr_cells = 2;
  33.238 +    }
  33.239 +
  33.240 +    rc = ofd_getprop(oft_p, OFD_ROOT, "platform-open-pic", addr, sizeof(addr));
  33.241 +    if (rc < 0) {
  33.242 +        return rc;
  33.243 +    }
  33.244 +
  33.245 +    opic_addr = addr[0];
  33.246 +    if (addr_cells == 2) {
  33.247 +        opic_addr <<= 32;
  33.248 +        opic_addr |= addr[1];
  33.249 +    }
  33.250 +    DBG("%s: found OpenPIC at: 0x%lx\n", __func__, opic_addr);
  33.251 +    /* we did not really find the pic device, only its address. 
  33.252 +     * We use big endian and broken u3 by default.
  33.253 +     */
  33.254 +    opic_flags |= MPIC_BIG_ENDIAN | MPIC_BROKEN_U3;
  33.255 +    return 0;
  33.256 +}
  33.257 +
  33.258 +static int find_mpic_canonical_probe(void *oft_p)
  33.259 +{
  33.260 +    ofdn_t c;
  33.261 +    const char mpic_type[] = "open-pic";
  33.262 +    /* some paths are special and we cannot find the address
  33.263 +     * by the usual method */
  33.264 +    const char *excluded_paths[] = { "/interrupt-controller" };
  33.265 +
  33.266 +    /*
  33.267 +     * Search through the OFD tree for all devices of type 'open_pic'.
  33.268 +     * We select the one without an 'interrupt' property.
  33.269 +     */
  33.270 +    c = ofd_node_find_by_prop(oft_p, OFD_ROOT, "device_type", mpic_type,
  33.271 +                                        sizeof(mpic_type));
  33.272 +    while (c > 0) {
  33.273 +        int int_len;
  33.274 +        int good_mpic;
  33.275 +        const char * path = ofd_node_path(oft_p, c);
  33.276 +
  33.277 +        good_mpic = 0;
  33.278 +        int_len = ofd_getprop(oft_p, c, "interrupts", NULL, 0);
  33.279 +        if (int_len < 0) {
  33.280 +            int i;
  33.281 +
  33.282 +            /* there is no property interrupt.  This could be the pic */
  33.283 +            DBG("%s: potential OpenPIC in: %s\n", __func__, path);
  33.284 +            good_mpic = 1;
  33.285 +
  33.286 +            for (i = 0; i < ARRAY_SIZE(excluded_paths) && good_mpic; i++) {
  33.287 +                const char *excluded_path = excluded_paths[i];
  33.288 +                if (!strncmp(path, excluded_path, strlen(excluded_path)))
  33.289 +                    good_mpic = 0;
  33.290 +            }
  33.291 +        }
  33.292 +
  33.293 +        if (good_mpic) {
  33.294 +            DBG("%s: found OpenPIC in: %s\n", __func__, path);
  33.295 +            opic_addr = find_pic_address_from_node(oft_p, c);
  33.296 +            opic_flags = find_pic_flags_from_node(oft_p, c);
  33.297 +            return 0;
  33.298 +        }
  33.299 +
  33.300 +        c = ofd_node_find_next(oft_p, c);
  33.301 +    }
  33.302 +
  33.303 +    DBG("%s: Could not find a pic\n", __func__);
  33.304 +    return -1;
  33.305 +}
  33.306 +
  33.307 +static int find_mpic(void)
  33.308 +{
  33.309 +    void *oft_p;
  33.310 +    int rc;
  33.311 +
  33.312 +    opic_addr = (unsigned long)-1;
  33.313 +    opic_flags = 0;
  33.314 +
  33.315 +    oft_p = (void *)oftree;
  33.316 +    rc = find_mpic_simple_probe(oft_p);
  33.317 +
  33.318 +    if (rc < 0) {
  33.319 +        DBG("%s: Searching for pic ...\n", __func__);
  33.320 +        rc = find_mpic_canonical_probe(oft_p);
  33.321 +    }
  33.322 +
  33.323 +    return rc;
  33.324 +}
  33.325 +
  33.326 +static struct hw_interrupt_type hc_irq;
  33.327 +
  33.328 +struct hw_interrupt_type *xen_mpic_init(struct hw_interrupt_type *xen_irq)
  33.329 +{
  33.330 +    unsigned int isu_size;
  33.331 +    unsigned int irq_offset;
  33.332 +    unsigned int irq_count;
  33.333 +    unsigned int ipi_offset;
  33.334 +    unsigned char *senses;
  33.335 +    unsigned int senses_count;
  33.336 +
  33.337 +    printk("%s: start\n", __func__);
  33.338 +
  33.339 +    io_apic_irqs = ~0;  /* all IRQs go through IOAPIC */
  33.340 +	irq_vector[0] = FIRST_DEVICE_VECTOR;
  33.341 +	vector_irq[FIRST_DEVICE_VECTOR] = 0;
  33.342 +
  33.343 +    isu_size = 0;
  33.344 +    irq_offset = 0;
  33.345 +    irq_count = 128;
  33.346 +    ipi_offset = 128;
  33.347 +    senses = NULL;
  33.348 +    senses_count = 0;
  33.349 +
  33.350 +    if (find_mpic()) {
  33.351 +        printk("%s: ERROR: Could not find open pic.\n", __func__);
  33.352 +        return NULL;
  33.353 +    }
  33.354 +
  33.355 +    mpic = mpic_alloc(opic_addr,
  33.356 +                      opic_flags | MPIC_PRIMARY | MPIC_WANTS_RESET,
  33.357 +                      isu_size, irq_offset, irq_count,
  33.358 +                      ipi_offset, senses, senses_count, "Xen-U3-MPIC");
  33.359 +
  33.360 +    BUG_ON(mpic == NULL);
  33.361 +    mpic_init(mpic);
  33.362 +
  33.363 +    hc_irq.startup = mpic->hc_irq.startup;
  33.364 +    mpic->hc_irq.startup = xen_irq->startup;
  33.365 +
  33.366 +    hc_irq.enable = mpic->hc_irq.enable;
  33.367 +    mpic->hc_irq.enable = xen_irq->enable;
  33.368 +
  33.369 +    hc_irq.disable = mpic->hc_irq.disable;
  33.370 +    mpic->hc_irq.disable = xen_irq->disable;
  33.371 +
  33.372 +    hc_irq.shutdown = mpic->hc_irq.shutdown;
  33.373 +    mpic->hc_irq.shutdown = xen_irq->shutdown;
  33.374 +
  33.375 +    hc_irq.ack = mpic->hc_irq.ack;
  33.376 +    mpic->hc_irq.ack = xen_irq->ack;
  33.377 +
  33.378 +    hc_irq.end = mpic->hc_irq.end;
  33.379 +    mpic->hc_irq.end = xen_irq->end;
  33.380 +
  33.381 +    hc_irq.set_affinity = mpic->hc_irq.set_affinity;
  33.382 +    mpic->hc_irq.set_affinity = xen_irq->set_affinity;
  33.383 +
  33.384 +    printk("%s: success\n", __func__);
  33.385 +    return &hc_irq;
  33.386 +}
  33.387 +
  33.388 +int xen_mpic_get_irq(struct cpu_user_regs *regs)
  33.389 +{
  33.390 +    BUG_ON(mpic == NULL);
  33.391 +
  33.392 +	return mpic_get_one_irq(mpic, regs);
  33.393 +}
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/xen/arch/powerpc/mpic_init.h	Fri Jul 14 10:47:50 2006 +0100
    34.3 @@ -0,0 +1,29 @@
    34.4 +/*
    34.5 + * This program is free software; you can redistribute it and/or modify
    34.6 + * it under the terms of the GNU General Public License as published by
    34.7 + * the Free Software Foundation; either version 2 of the License, or
    34.8 + * (at your option) any later version.
    34.9 + *
   34.10 + * This program is distributed in the hope that it will be useful,
   34.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   34.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   34.13 + * GNU General Public License for more details.
   34.14 + *
   34.15 + * You should have received a copy of the GNU General Public License
   34.16 + * along with this program; if not, write to the Free Software
   34.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   34.18 + *
   34.19 + * Copyright (C) IBM Corp. 2005
   34.20 + *
   34.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   34.22 + */
   34.23 +
   34.24 +#ifndef _MPIC_INIT_H
   34.25 +#define _MPIC_INIT_H
   34.26 +
   34.27 +extern struct hw_interrupt_type *xen_mpic_init(
   34.28 +    struct hw_interrupt_type *xen_irq);
   34.29 +
   34.30 +extern int xen_mpic_get_irq(struct cpu_user_regs *regs);
   34.31 +
   34.32 +#endif  /* #ifndef _MPIC_INIT_H */
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/xen/arch/powerpc/of-devtree.c	Fri Jul 14 10:47:50 2006 +0100
    35.3 @@ -0,0 +1,1088 @@
    35.4 +/*
    35.5 + * This program is free software; you can redistribute it and/or modify
    35.6 + * it under the terms of the GNU General Public License as published by
    35.7 + * the Free Software Foundation; either version 2 of the License, or
    35.8 + * (at your option) any later version.
    35.9 + *
   35.10 + * This program is distributed in the hope that it will be useful,
   35.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   35.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   35.13 + * GNU General Public License for more details.
   35.14 + *
   35.15 + * You should have received a copy of the GNU General Public License
   35.16 + * along with this program; if not, write to the Free Software
   35.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   35.18 + *
   35.19 + * Copyright (C) IBM Corp. 2005
   35.20 + *
   35.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   35.22 + */
   35.23 +
   35.24 +/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
   35.25 + * This code is intended to be used but relocatable routines So PLEASE
   35.26 + * do not place any global data here including const integrals or
   35.27 + * literals.
   35.28 + * The local assert() is ok for string literal usage.. but thats it.
   35.29 + */
   35.30 +
   35.31 +
   35.32 +#include <xen/config.h>
   35.33 +#include <xen/init.h>
   35.34 +#include <xen/lib.h>
   35.35 +#include "of-devtree.h"
   35.36 +
   35.37 +static int (*ofd_write)(const char *, size_t len) = NULL;
   35.38 +
   35.39 +void ofd_init(int (*write)(const char *, size_t len))
   35.40 +{
   35.41 +    ofd_write = write;
   35.42 +}
   35.43 +                  
   35.44 +
   35.45 +static void ofd_stop(void)
   35.46 +{
   35.47 +    for ( ; ; ) ;
   35.48 +}
   35.49 +
   35.50 +/* this is so it can be called from anywhere */
   35.51 +static void ofd_assprint(int line)
   35.52 +{
   35.53 +    char a[13];
   35.54 +    char num[20];
   35.55 +    int i;
   35.56 +
   35.57 +    a[0]  = '\n';
   35.58 +    a[1]  = '\n';
   35.59 +    a[2]  = 'O';
   35.60 +    a[3]  = 'F';
   35.61 +    a[4]  = 'D';
   35.62 +    a[5]  = ':';
   35.63 +    a[6]  = 'A';
   35.64 +    a[7]  = 'S';
   35.65 +    a[8]  = 'S';
   35.66 +    a[9]  = 'E';
   35.67 +    a[10] = 'R';
   35.68 +    a[11] = 'T';
   35.69 +    a[12] = ':';
   35.70 +
   35.71 +
   35.72 +    ofd_write(a, sizeof (a) - 1);
   35.73 +    
   35.74 +    /* put the number in backwards */
   35.75 +    i = 0;
   35.76 +    while ( line > 0 ) {
   35.77 +        num[i++] = '0' + (line % 10);
   35.78 +        line /= 10;
   35.79 +    }
   35.80 +    /* print it */
   35.81 +    /* number */
   35.82 +    while (i-- > 0) {
   35.83 +        ofd_write(&num[i], 1);
   35.84 +    }
   35.85 +    ofd_write("\n", 1);
   35.86 +
   35.87 +    ofd_stop();
   35.88 +}
   35.89 +
   35.90 +#ifdef assert
   35.91 +#undef assert
   35.92 +#endif
   35.93 +
   35.94 +#define assert(EX)                                              \
   35.95 +    do {                                                        \
   35.96 +        if ( !(EX) ) {                                          \
   35.97 +            ofd_assprint(__LINE__);                             \
   35.98 +        }                                                       \
   35.99 +    } while (0)
  35.100 +
  35.101 +/*
  35.102 + * We treat memory like an array of u64.  For the sake of
  35.103 + * compactness we assume that a short is big enough as an index.
  35.104 + */
  35.105 +struct ofd_node {
  35.106 +    ofdn_t on_ima;
  35.107 +    ofdn_t on_parent;
  35.108 +    ofdn_t on_child;
  35.109 +    ofdn_t on_peer;
  35.110 +    ofdn_t on_io;
  35.111 +    ofdn_t on_next;     /* for search lists */
  35.112 +    ofdn_t on_prev;
  35.113 +    ofdn_t on_prop;
  35.114 +    u32 on_pathlen;
  35.115 +    u32 on_last;
  35.116 +    char on_path[0];
  35.117 +};
  35.118 +
  35.119 +struct ofd_prop {
  35.120 +    ofdn_t op_ima;
  35.121 +    ofdn_t op_next;
  35.122 +    u32 op_objsz;
  35.123 +    u32 op_namesz;
  35.124 +    /* must have 64bit alignment */
  35.125 +    char op_data[0]  __attribute__ ((aligned(8)));
  35.126 +};
  35.127 +
  35.128 +struct ofd_io {
  35.129 +    ofdn_t oi_ima;
  35.130 +    ofdn_t oi_node;
  35.131 +    u64 oi_open   __attribute__ ((aligned(8)));
  35.132 +};
  35.133 +
  35.134 +struct ofd_free {
  35.135 +    ofdn_t of_cells;
  35.136 +    ofdn_t of_next;
  35.137 +};
  35.138 +
  35.139 +struct ofd_mem {
  35.140 +    ofdn_t om_num;
  35.141 +    ofdn_t om_next;
  35.142 +    ofdn_t om_free;     /* Future site of a free list */
  35.143 +    ofdn_t _om_pad;
  35.144 +    u64 om_mem[0] __attribute__((aligned(8)));
  35.145 +};
  35.146 +
  35.147 +#define NODE_PAT    0x0f01
  35.148 +#define PROP_PAT    0x0f03
  35.149 +#define IO_PAT      0x0f05
  35.150 +
  35.151 +
  35.152 +size_t ofd_size(void *mem)
  35.153 +{
  35.154 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.155 +    size_t sz;
  35.156 +
  35.157 +    sz = m->om_next * sizeof (u64) + sizeof(*m);
  35.158 +    return sz;
  35.159 +}
  35.160 +
  35.161 +size_t ofd_space(void *mem)
  35.162 +{
  35.163 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.164 +    size_t sz;
  35.165 +
  35.166 +    sz = m->om_num * sizeof (u64);
  35.167 +    return sz;
  35.168 +}
  35.169 +
  35.170 +
  35.171 +static int ofd_pathsplit_right(const char *s, int c, size_t max)
  35.172 +{
  35.173 +    int i = 0;
  35.174 +
  35.175 +    if ( max == 0 ) {
  35.176 +        --max;
  35.177 +    }
  35.178 +    
  35.179 +    while ( *s != '\0' && *s != c && max != 0 ) {
  35.180 +        ++i;
  35.181 +        ++s;
  35.182 +        --max;
  35.183 +    }
  35.184 +    return i;
  35.185 +}
  35.186 +
  35.187 +static int ofd_pathsplit_left(const char *p, int c, size_t len)
  35.188 +{
  35.189 +    const char *s;
  35.190 +
  35.191 +    if ( len > 0 ) {
  35.192 +        /* move s to the end */
  35.193 +        s = p + len - 1;
  35.194 +
  35.195 +        /* len could include a null */
  35.196 +        if ( *s == '\0' ) {
  35.197 +            --s;
  35.198 +        }
  35.199 +        while ( s >= p ) {
  35.200 +            if ( *s == c ) {
  35.201 +                ++s;
  35.202 +                break;
  35.203 +            }
  35.204 +            --s;
  35.205 +        }
  35.206 +        if ( s < p ) {
  35.207 +            return 0;
  35.208 +        }
  35.209 +        return (s - p);
  35.210 +    }
  35.211 +    return 0;
  35.212 +}
  35.213 +
  35.214 +void *ofd_create(void *mem, size_t sz)
  35.215 +{
  35.216 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.217 +    struct ofd_node *n;
  35.218 +    size_t sum;
  35.219 +    ofdn_t cells;
  35.220 +
  35.221 +    if ( sz < (sizeof (*n) * 4) ) {
  35.222 +        return NULL;
  35.223 +    }
  35.224 +
  35.225 +    memset(mem, 0, sz);
  35.226 +
  35.227 +    m->om_num = (sz - sizeof(*m)) / sizeof (u64);
  35.228 +
  35.229 +    /* skip the first cell */
  35.230 +    m->om_next = OFD_ROOT;
  35.231 +    n = (struct ofd_node *)&m->om_mem[m->om_next];
  35.232 +    n->on_ima = NODE_PAT;
  35.233 +    n->on_pathlen = 2;
  35.234 +    n->on_last = 1;
  35.235 +    n->on_path[0] = '/';
  35.236 +    n->on_path[1] = '\0';
  35.237 +
  35.238 +    sum = sizeof (*n) + 2; /* Don't forget the path */
  35.239 +    cells = (sum + sizeof (m->om_mem[0]) - 1) / sizeof (m->om_mem[0]);
  35.240 +    m->om_next += cells;
  35.241 +
  35.242 +    return m;
  35.243 +}
  35.244 +
  35.245 +static struct ofd_node *ofd_node_get(struct ofd_mem *m, ofdn_t n)
  35.246 +{
  35.247 +    if ( n < m->om_next ) {
  35.248 +        struct ofd_node *r;
  35.249 +
  35.250 +        r = (struct ofd_node *)&m->om_mem[n];
  35.251 +        if ( r->on_ima == NODE_PAT ) {
  35.252 +            return r;
  35.253 +        }
  35.254 +    }
  35.255 +    return NULL;
  35.256 +}
  35.257 +
  35.258 +ofdn_t ofd_node_parent(void *mem, ofdn_t n)
  35.259 +{
  35.260 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.261 +    struct ofd_node *r = ofd_node_get(m, n);
  35.262 +
  35.263 +    if ( r == NULL) return 0;
  35.264 +    return r->on_parent;
  35.265 +}
  35.266 +
  35.267 +ofdn_t ofd_node_peer(void *mem, ofdn_t n)
  35.268 +{
  35.269 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.270 +    struct ofd_node *r;
  35.271 +
  35.272 +    if ( n == 0 ) {
  35.273 +        return OFD_ROOT;
  35.274 +    }
  35.275 +
  35.276 +    r = ofd_node_get(m, n);
  35.277 +    if ( r == NULL) return 0;
  35.278 +    return r->on_peer;
  35.279 +}
  35.280 +
  35.281 +const char *ofd_node_path(void *mem, ofdn_t n)
  35.282 +{
  35.283 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.284 +    struct ofd_node *r = ofd_node_get(m, n);
  35.285 +
  35.286 +    if ( r == NULL) return NULL;
  35.287 +    return r->on_path;
  35.288 +}
  35.289 +
  35.290 +static ofdn_t ofd_node_prop(void *mem, ofdn_t n)
  35.291 +{
  35.292 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.293 +    struct ofd_node *r = ofd_node_get(m, n);
  35.294 +
  35.295 +    if ( r == NULL) return 0;
  35.296 +    return r->on_prop;
  35.297 +}
  35.298 +
  35.299 +ofdn_t ofd_node_child(void *mem, ofdn_t p)
  35.300 +{
  35.301 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.302 +    struct ofd_node *r = ofd_node_get(m, p);
  35.303 +
  35.304 +    if ( r == NULL) return 0;
  35.305 +    return r->on_child;
  35.306 +}
  35.307 +
  35.308 +int ofd_node_to_path(void *mem, ofdn_t p, void *buf, size_t sz)
  35.309 +{
  35.310 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.311 +    struct ofd_node *r = ofd_node_get(m, p);
  35.312 +
  35.313 +    if ( sz > r->on_pathlen ) {
  35.314 +        sz = r->on_pathlen;
  35.315 +    }
  35.316 +
  35.317 +    memcpy(buf, r->on_path, sz);
  35.318 +
  35.319 +    if ( r == NULL) return -1;
  35.320 +    return r->on_pathlen;
  35.321 +}
  35.322 +
  35.323 +static int ofd_check(void *p, size_t l)
  35.324 +{
  35.325 +    int i;
  35.326 +    u64 *v = (u64 *)p;
  35.327 +
  35.328 +    for ( i = 0; i < l; i++ ) {
  35.329 +        if ( v[i] != 0ULL ) {
  35.330 +            return 0;
  35.331 +        }
  35.332 +    }
  35.333 +    return 1;
  35.334 +}
  35.335 +
  35.336 +
  35.337 +
  35.338 +static ofdn_t ofd_node_create(
  35.339 +    struct ofd_mem *m, const char *path, size_t pathlen)
  35.340 +{
  35.341 +    struct ofd_node *n;
  35.342 +    ofdn_t pos;
  35.343 +    size_t sum = pathlen + 1 + sizeof (*n); /* add trailing zero to path */
  35.344 +    ofdn_t cells = (sum + sizeof(m->om_mem[0]) - 1) / sizeof(m->om_mem[0]);
  35.345 +
  35.346 +    if ( m->om_next + cells >= m->om_num ) {
  35.347 +        return 0;
  35.348 +    }
  35.349 +
  35.350 +    pos = m->om_next;
  35.351 +        
  35.352 +    assert(ofd_check(&m->om_mem[pos], cells)); /* non-zero */
  35.353 +    m->om_next += cells;
  35.354 +
  35.355 +    n = (struct ofd_node *)&m->om_mem[pos];
  35.356 +    assert(n->on_ima == 0); /* new node not empty */
  35.357 +
  35.358 +    n->on_ima = NODE_PAT;
  35.359 +    n->on_peer = 0;
  35.360 +    n->on_child = 0;
  35.361 +    n->on_io = 0;
  35.362 +    n->on_pathlen = pathlen;
  35.363 +    n->on_last = ofd_pathsplit_left(path, '/', pathlen);
  35.364 +    strncpy(n->on_path, path, pathlen);
  35.365 +    n->on_path[n->on_pathlen] = 0;
  35.366 +
  35.367 +    return pos;
  35.368 +}
  35.369 +
  35.370 +/* prunes a node and all its children simply by wasting memory and
  35.371 + * unlinking it from the tree */
  35.372 +int ofd_node_prune(void *mem, ofdn_t node)
  35.373 +{
  35.374 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.375 +    struct ofd_node *n;
  35.376 +    struct ofd_node *p;
  35.377 +
  35.378 +    n = ofd_node_get(m, node);
  35.379 +    if (n == NULL) return -1;
  35.380 +
  35.381 +    p = ofd_node_get(m, n->on_parent);
  35.382 +    assert(p != NULL);
  35.383 +
  35.384 +    if ( p->on_child == node ) {
  35.385 +        /* easy case */
  35.386 +        p->on_child = n->on_peer;
  35.387 +    } else {
  35.388 +        struct ofd_node *s;
  35.389 +
  35.390 +        s = ofd_node_get(m, p->on_child);
  35.391 +        assert(s != NULL);
  35.392 +        while ( s->on_peer != node ) {
  35.393 +            s = ofd_node_get(m, s->on_peer);
  35.394 +            assert(s != NULL);
  35.395 +        }
  35.396 +        s->on_peer = n->on_peer;
  35.397 +    }
  35.398 +    return 1;
  35.399 +}
  35.400 +
  35.401 +ofdn_t ofd_prune_path(void *m, const char *path)
  35.402 +{
  35.403 +    ofdn_t n;
  35.404 +    int rc = -1;
  35.405 +    while ((n = ofd_node_find(m, path)) > 0) {
  35.406 +        rc = ofd_node_prune(m, n);
  35.407 +    }
  35.408 +
  35.409 +    return rc;
  35.410 +}
  35.411 +
  35.412 +ofdn_t ofd_node_child_create(
  35.413 +    void *mem, ofdn_t parent, const char *path, size_t pathlen)
  35.414 +{
  35.415 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.416 +    struct ofd_node *p;
  35.417 +    struct ofd_node *n;
  35.418 +    ofdn_t pos;
  35.419 +
  35.420 +    p = ofd_node_get(m, parent);
  35.421 +    if (p == NULL) return  0;
  35.422 +
  35.423 +    pos = ofd_node_create(m, path, pathlen);
  35.424 +    n = ofd_node_get(m, pos);
  35.425 +    assert(n != NULL);
  35.426 +
  35.427 +    assert(p->on_child == 0); /* child exists */
  35.428 +    if ( p->on_child == 0 ) {
  35.429 +        p->on_child = pos;
  35.430 +        n->on_parent = parent;
  35.431 +    } else {
  35.432 +        pos = 0;
  35.433 +    }
  35.434 +
  35.435 +    return pos;
  35.436 +}
  35.437 +
  35.438 +ofdn_t ofd_node_peer_create(
  35.439 +    void *mem, ofdn_t sibling, const char *path, size_t pathlen)
  35.440 +{
  35.441 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.442 +    struct ofd_node *s;
  35.443 +    struct ofd_node *n;
  35.444 +    ofdn_t pos;
  35.445 +
  35.446 +    s = ofd_node_get(m, sibling);
  35.447 +    if (s == NULL) return 0;
  35.448 +
  35.449 +    pos = ofd_node_create(m, path, pathlen);
  35.450 +    n = ofd_node_get(m, pos);
  35.451 +    assert(n != NULL);
  35.452 +
  35.453 +    if ( s->on_peer == 0 ) {
  35.454 +        s->on_peer = pos;
  35.455 +        n->on_parent = s->on_parent;
  35.456 +    } else {
  35.457 +        assert(0); /* peer exists */
  35.458 +        pos = 0;
  35.459 +    }
  35.460 +    return pos;
  35.461 +}
  35.462 +
  35.463 +static ofdn_t ofd_node_peer_last(void *mem, ofdn_t c)
  35.464 +{
  35.465 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.466 +    struct ofd_node *n;
  35.467 +
  35.468 +    n = ofd_node_get(m, c);
  35.469 +    if (n == NULL) return 0;
  35.470 +
  35.471 +    while ( n->on_peer > 0 ) {
  35.472 +        c = n->on_peer;
  35.473 +        n = ofd_node_get(m, c);
  35.474 +        assert(n != NULL);
  35.475 +    }
  35.476 +
  35.477 +    return c;
  35.478 +}
  35.479 +
  35.480 +static ofdn_t ofd_node_walk(struct ofd_mem *m, ofdn_t p, const char *s)
  35.481 +{
  35.482 +    struct ofd_node *np;
  35.483 +    ofdn_t n;
  35.484 +    ofdn_t r;
  35.485 +
  35.486 +    if ( *s == '/' ) {
  35.487 +        ++s;
  35.488 +        if ( *s == '\0' ) {
  35.489 +            assert(0); /* ends in / */
  35.490 +            return 0;
  35.491 +        }
  35.492 +    }
  35.493 +
  35.494 +    np = ofd_node_get(m, p);
  35.495 +    if (np == NULL) return 0;
  35.496 +
  35.497 +    r = p;
  35.498 +    do {
  35.499 +        int last = np->on_last;
  35.500 +        size_t lsz = np->on_pathlen - last;
  35.501 +        size_t sz;
  35.502 +
  35.503 +        sz = ofd_pathsplit_right(s, '/', 0);
  35.504 +        
  35.505 +        if ( lsz > 0 && strncmp(s, &np->on_path[last], sz) == 0 ) {
  35.506 +            if ( s[sz] == '\0' ) {
  35.507 +                return r;
  35.508 +            }
  35.509 +            /* there is more to the path */
  35.510 +            n = ofd_node_child(m, p);
  35.511 +            if ( n != 0 ) {
  35.512 +                r = ofd_node_walk(m, n, &s[sz]);
  35.513 +                return r;
  35.514 +            }
  35.515 +            /* there are no children */
  35.516 +            return 0;
  35.517 +        }
  35.518 +    } while ( 0 );
  35.519 +
  35.520 +    /*
  35.521 +     * we know that usually we are only serching for top level peers
  35.522 +     * so we do peers first peer
  35.523 +     */
  35.524 +    n = ofd_node_peer(m, p);
  35.525 +    if ( n > 0 ) {
  35.526 +        r = ofd_node_walk(m, n, s);
  35.527 +    } else {
  35.528 +        r = 0;
  35.529 +    }
  35.530 +
  35.531 +    return r;
  35.532 +}
  35.533 +
  35.534 +
  35.535 +ofdn_t ofd_node_find(void *mem, const char *devspec)
  35.536 +{
  35.537 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.538 +    ofdn_t n = OFD_ROOT;
  35.539 +    const char *s = devspec;
  35.540 +    size_t sz;
  35.541 +
  35.542 +    if ( s == NULL || s[0] == '\0' ) {
  35.543 +        return OFD_ROOT;
  35.544 +    }
  35.545 +
  35.546 +    if ( s[0] != '/' ) {
  35.547 +        size_t asz;
  35.548 +
  35.549 +        /* get the component length */
  35.550 +        sz = ofd_pathsplit_right(s, '/', 0);
  35.551 +
  35.552 +        /* check for an alias */
  35.553 +        asz = ofd_pathsplit_right(s, ':', sz);
  35.554 +
  35.555 +        if ( s[asz] == ':' ) {
  35.556 +            /*
  35.557 +             * s points to an alias and &s[sz] points to the alias
  35.558 +             * args.
  35.559 +             */
  35.560 +            assert(0); /* aliases no supported */
  35.561 +            return 0;
  35.562 +        }
  35.563 +    } else if ( s[1] == '\0' ) {
  35.564 +        return n;
  35.565 +    }
  35.566 +
  35.567 +    n = ofd_node_child(m, n);
  35.568 +    if ( n == 0 ) {
  35.569 +        return 0;
  35.570 +    }
  35.571 +
  35.572 +    return ofd_node_walk(m, n, s);
  35.573 +}
  35.574 +
  35.575 +
  35.576 +static struct ofd_prop *ofd_prop_get(struct ofd_mem *m, ofdn_t p)
  35.577 +{
  35.578 +    if ( p < m->om_next ) {
  35.579 +        struct ofd_prop *r;
  35.580 +
  35.581 +        r = (struct ofd_prop *)&m->om_mem[p];
  35.582 +        if ( r->op_ima == PROP_PAT ) {
  35.583 +            return r;
  35.584 +        }
  35.585 +        assert(r->op_ima == PROP_PAT); /* bad object */
  35.586 +    }
  35.587 +    return NULL;
  35.588 +}
  35.589 +
  35.590 +static ofdn_t ofd_prop_create(
  35.591 +    struct ofd_mem *m,
  35.592 +    ofdn_t node,
  35.593 +    const char *name,
  35.594 +    const void *src,
  35.595 +    size_t sz)
  35.596 +{
  35.597 +    struct ofd_node *n;
  35.598 +    struct ofd_prop *p;
  35.599 +    size_t len = strlen(name) + 1;
  35.600 +    size_t sum = sizeof (*p) + sz + len;
  35.601 +    ofdn_t cells;
  35.602 +    char *dst;
  35.603 +    ofdn_t pos;
  35.604 +
  35.605 +    cells = (sum + sizeof (m->om_mem[0]) - 1) / sizeof (m->om_mem[0]);
  35.606 +
  35.607 +    if ( m->om_next + cells >= m->om_num ) {
  35.608 +        return 0;
  35.609 +    }
  35.610 +
  35.611 +    /* actual data structure */
  35.612 +    pos = m->om_next;
  35.613 +    assert(ofd_check(&m->om_mem[pos], cells)); /* non-zero */
  35.614 +
  35.615 +    p = (struct ofd_prop *)&m->om_mem[pos];
  35.616 +    m->om_next += cells;
  35.617 +
  35.618 +    assert(p->op_ima == 0); /* new node not empty */
  35.619 +    p->op_ima = PROP_PAT;
  35.620 +    p->op_next = 0;
  35.621 +    p->op_objsz = sz;
  35.622 +    p->op_namesz = len;
  35.623 +
  35.624 +    /* the rest of the data */
  35.625 +    dst = p->op_data;
  35.626 +
  35.627 +    /* zero what will be the pad, cheap and cannot hurt */
  35.628 +    m->om_mem[m->om_next - 1] = 0;
  35.629 +
  35.630 +    if ( sz > 0 ) {
  35.631 +        /* some props have no data, just a name */
  35.632 +        memcpy(dst, src, sz);
  35.633 +        dst += sz;
  35.634 +    }
  35.635 +
  35.636 +    memcpy(dst, name, len);
  35.637 +
  35.638 +    /* now place it in the tree */
  35.639 +    n = ofd_node_get(m, node);
  35.640 +    assert(n != NULL);
  35.641 +
  35.642 +    if ( n->on_prop == 0 ) {
  35.643 +        n->on_prop = pos;
  35.644 +    } else {
  35.645 +        ofdn_t pn = n->on_prop;
  35.646 +        struct ofd_prop *nxt;
  35.647 +
  35.648 +        for (;;) {
  35.649 +            nxt = ofd_prop_get(m, pn);
  35.650 +            if (nxt->op_next == 0) {
  35.651 +                nxt->op_next = pos;
  35.652 +                break;
  35.653 +            }
  35.654 +            pn = nxt->op_next;
  35.655 +        }
  35.656 +    }
  35.657 +
  35.658 +    return pos;
  35.659 +}
  35.660 +
  35.661 +void ofd_prop_remove(void *mem, ofdn_t node, ofdn_t prop)
  35.662 +{
  35.663 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.664 +    struct ofd_node *n = ofd_node_get(m, node);
  35.665 +    struct ofd_prop *p = ofd_prop_get(m, prop);
  35.666 +
  35.667 +    if (n == NULL) return;
  35.668 +    if (p == NULL) return;
  35.669 +
  35.670 +    if ( n->on_prop == prop ) {
  35.671 +        n->on_prop = p->op_next;
  35.672 +    } else {
  35.673 +        ofdn_t pn = n->on_prop;
  35.674 +        struct ofd_prop *nxt;
  35.675 +
  35.676 +        for ( ; ; ) {
  35.677 +            nxt = ofd_prop_get(m, pn);
  35.678 +            if ( nxt->op_next == prop ) {
  35.679 +                nxt->op_next = p->op_next;
  35.680 +                break;
  35.681 +            }
  35.682 +            pn = nxt->op_next;
  35.683 +        }
  35.684 +    }
  35.685 +    return;
  35.686 +}
  35.687 +
  35.688 +ofdn_t ofd_prop_find(void *mem, ofdn_t n, const char *name)
  35.689 +{
  35.690 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.691 +    ofdn_t p = ofd_node_prop(m, n);
  35.692 +    struct ofd_prop *r;
  35.693 +    char *s;
  35.694 +    size_t len;
  35.695 +
  35.696 +    if ( name == NULL || *name == '\0' ) {
  35.697 +        return OFD_ROOT;
  35.698 +    }
  35.699 +
  35.700 +    len = strlen(name) + 1;
  35.701 +    
  35.702 +    while ( p != 0 ) {
  35.703 +        r = ofd_prop_get(m, p);
  35.704 +        s = &r->op_data[r->op_objsz];
  35.705 +        if ( len == r->op_namesz ) {
  35.706 +            if ( strncmp(name, s, r->op_namesz) == 0 ) {
  35.707 +                break;
  35.708 +            }
  35.709 +        }
  35.710 +        p = r->op_next;
  35.711 +    }
  35.712 +    return p;
  35.713 +}
  35.714 +
  35.715 +static ofdn_t ofd_prop_next(struct ofd_mem *m, ofdn_t n, const char *prev)
  35.716 +{
  35.717 +    ofdn_t p;
  35.718 +
  35.719 +    if ( prev == NULL || *prev == '\0' ) {
  35.720 +        /* give the first */
  35.721 +        p = ofd_node_prop(m, n);
  35.722 +    } else {
  35.723 +        struct ofd_prop *r;
  35.724 +
  35.725 +        /* look for the name */
  35.726 +        p = ofd_prop_find(m, n, prev);
  35.727 +        if ( p != 0 ) {
  35.728 +            /* get the data for prev */
  35.729 +            r = ofd_prop_get(m, p);
  35.730 +
  35.731 +            /* now get next */
  35.732 +            p = r->op_next;
  35.733 +        } else {
  35.734 +            p = -1;
  35.735 +        }
  35.736 +    }
  35.737 +
  35.738 +    return p;
  35.739 +}
  35.740 +
  35.741 +ofdn_t ofd_nextprop(void *mem, ofdn_t n, const char *prev, char *name)
  35.742 +{
  35.743 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.744 +    ofdn_t p = ofd_prop_next(m, n, prev);
  35.745 +    struct ofd_prop *r;
  35.746 +    char *s;
  35.747 +
  35.748 +    if ( p > 0 ) {
  35.749 +        r = ofd_prop_get(m, p);
  35.750 +        s = &r->op_data[r->op_objsz];
  35.751 +        memcpy(name, s, r->op_namesz);
  35.752 +    }
  35.753 +
  35.754 +    return p;
  35.755 +}
  35.756 +
  35.757 +/*
  35.758 + * It is valid to call with NULL pointers, in case you want only one
  35.759 + * cell size.
  35.760 + */
  35.761 +int ofd_getcells(void* mem, ofdn_t n, u32* addr_cells, u32* size_cells)
  35.762 +{
  35.763 +    if ( addr_cells != NULL ) *addr_cells = 0;
  35.764 +    if ( size_cells != NULL ) *size_cells = 0;
  35.765 +
  35.766 +retry:
  35.767 +    if ( addr_cells  != NULL && *addr_cells == 0 ) {
  35.768 +        ofd_getprop(mem, n, "#address-cells",
  35.769 +                addr_cells, sizeof(u32));
  35.770 +    }
  35.771 +
  35.772 +    if ( size_cells != NULL && *size_cells == 0 ) {
  35.773 +        ofd_getprop(mem, n, "#size-cells", size_cells, sizeof(u32));
  35.774 +    }
  35.775 +
  35.776 +    if ( ( size_cells != NULL && *size_cells == 0 )
  35.777 +            || ( addr_cells != NULL && *addr_cells == 0 ) ) {
  35.778 +        if ( n != OFD_ROOT ) {
  35.779 +            n = ofd_node_parent(mem, n);
  35.780 +            goto retry;
  35.781 +        }
  35.782 +        return -1;
  35.783 +    }
  35.784 +
  35.785 +    return 1;
  35.786 +}
  35.787 +
  35.788 +int ofd_getprop(void *mem, ofdn_t n, const char *name, void *buf, size_t sz)
  35.789 +{
  35.790 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.791 +    ofdn_t p = ofd_prop_find(m, n, name);
  35.792 +    struct ofd_prop *r;
  35.793 +
  35.794 +    if ( p == 0 ) {
  35.795 +        return -1;
  35.796 +    }
  35.797 +
  35.798 +    r = ofd_prop_get(m, p);
  35.799 +
  35.800 +    if ( sz > r->op_objsz ) {
  35.801 +        sz = r->op_objsz;
  35.802 +    }
  35.803 +    memcpy(buf, r->op_data, sz);
  35.804 +
  35.805 +    return r->op_objsz;
  35.806 +}
  35.807 +
  35.808 +int ofd_getproplen(void *mem, ofdn_t n, const char *name)
  35.809 +{
  35.810 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.811 +    ofdn_t p = ofd_prop_find(m, n, name);
  35.812 +    struct ofd_prop *r;
  35.813 +
  35.814 +    if ( p == 0 ) {
  35.815 +        return -1;
  35.816 +    }
  35.817 +
  35.818 +    r = ofd_prop_get(m, p);
  35.819 +
  35.820 +    return r->op_objsz;
  35.821 +}
  35.822 +
  35.823 +static ofdn_t ofd_prop_set(
  35.824 +    void *mem, ofdn_t n, const char *name, const void *src, size_t sz)
  35.825 +{
  35.826 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.827 +    ofdn_t p = ofd_prop_find(m, n, name);
  35.828 +    struct ofd_prop *r;
  35.829 +    char *dst;
  35.830 +
  35.831 +    r = ofd_prop_get(m, p);
  35.832 +
  35.833 +    if ( sz <= r->op_objsz ) {
  35.834 +        /* we can reuse */
  35.835 +        memcpy(r->op_data, src, sz);
  35.836 +        if ( sz < r->op_objsz ) {
  35.837 +            /* need to move name */
  35.838 +            dst = r->op_data + sz;
  35.839 +            /*
  35.840 +             * use the name arg size we may have overlap with the
  35.841 +             * original
  35.842 +             */
  35.843 +            memcpy(dst, name, r->op_namesz);
  35.844 +            r->op_objsz = sz;
  35.845 +        }
  35.846 +    } else {
  35.847 +        /*
  35.848 +         * Sadly, we remove from the list, wasting the space and then
  35.849 +         * we can creat a new one
  35.850 +         */
  35.851 +        ofd_prop_remove(m, n, p);
  35.852 +        p = ofd_prop_create(mem, n, name, src, sz);
  35.853 +    }
  35.854 +
  35.855 +    return p;
  35.856 +}
  35.857 +
  35.858 +int ofd_setprop(
  35.859 +    void *mem, ofdn_t n, const char *name, const void *buf, size_t sz)
  35.860 +{
  35.861 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.862 +    ofdn_t r;
  35.863 +
  35.864 +    r = ofd_prop_find(m, n, name);
  35.865 +    if ( r == 0 ) {
  35.866 +        r = ofd_prop_create(mem, n, name, buf, sz);
  35.867 +    } else {
  35.868 +        r = ofd_prop_set(mem, n, name, buf, sz);
  35.869 +    }
  35.870 +
  35.871 +    if ( r > 0 ) {
  35.872 +        struct ofd_prop *pp = ofd_prop_get(m, r);
  35.873 +        return pp->op_objsz;
  35.874 +    }
  35.875 +
  35.876 +    return OF_FAILURE;
  35.877 +}
  35.878 +
  35.879 +
  35.880 +static ofdn_t ofd_find_by_prop(
  35.881 +    struct ofd_mem *m,
  35.882 +    ofdn_t head,
  35.883 +    ofdn_t *prev_p,
  35.884 +    ofdn_t n,
  35.885 +    const char *name,
  35.886 +    const void *val,
  35.887 +    size_t sz)
  35.888 +{
  35.889 +    struct ofd_node *np;
  35.890 +    struct ofd_prop *pp;
  35.891 +    ofdn_t p;
  35.892 +
  35.893 +retry:
  35.894 +    p = ofd_prop_find(m, n, name);
  35.895 +
  35.896 +    if ( p > 0 ) {
  35.897 +        int match = 0;
  35.898 +
  35.899 +        /* a property exists by that name */
  35.900 +        if ( val == NULL ) {
  35.901 +            match = 1;
  35.902 +        } else {
  35.903 +            /* need to compare values */
  35.904 +            pp = ofd_prop_get(m, p);
  35.905 +            if ( sz == pp->op_objsz
  35.906 +                 && memcmp(pp->op_data, val, sz) == 0 ) {
  35.907 +                match = 1;
  35.908 +            }
  35.909 +        }
  35.910 +        if ( match == 1 ) {
  35.911 +            if ( *prev_p >= 0 ) {
  35.912 +                np = ofd_node_get(m, *prev_p);
  35.913 +                np->on_next = n;
  35.914 +            } else {
  35.915 +                head = n;
  35.916 +            }
  35.917 +            np = ofd_node_get(m, n);
  35.918 +            np->on_prev = *prev_p;
  35.919 +            np->on_next = -1;
  35.920 +            *prev_p = n;
  35.921 +        }
  35.922 +    }
  35.923 +
  35.924 +    p = ofd_node_child(m, n);
  35.925 +    if ( p > 0 ) {
  35.926 +        head = ofd_find_by_prop(m, head, prev_p, p, name, val, sz);
  35.927 +    }
  35.928 +
  35.929 +    p = ofd_node_peer(m, n);
  35.930 +    if ( p > 0 ) {
  35.931 +        n = p;
  35.932 +        goto retry;
  35.933 +    }
  35.934 +
  35.935 +    return head;
  35.936 +}
  35.937 +
  35.938 +ofdn_t ofd_node_find_by_prop(
  35.939 +    void *mem,
  35.940 +    ofdn_t n,
  35.941 +    const char *name,
  35.942 +    const void *val,
  35.943 +    size_t sz)
  35.944 +{
  35.945 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.946 +
  35.947 +    if ( n <= 0 ) {
  35.948 +        n = OFD_ROOT;
  35.949 +    }
  35.950 +
  35.951 +    ofdn_t prev = -1;
  35.952 +    return ofd_find_by_prop(m, -1, &prev, n, name, val, sz);
  35.953 +}
  35.954 +
  35.955 +ofdn_t ofd_node_find_next(void *mem, ofdn_t n)
  35.956 +{
  35.957 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.958 +    struct ofd_node *np;
  35.959 +
  35.960 +    np = ofd_node_get(m, n);
  35.961 +
  35.962 +    if (np == NULL) return 0;
  35.963 +    return np->on_next;
  35.964 +}
  35.965 +
  35.966 +ofdn_t ofd_node_find_prev(void *mem, ofdn_t n)
  35.967 +{
  35.968 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.969 +    struct ofd_node *np;
  35.970 +
  35.971 +    np = ofd_node_get(m, n);
  35.972 +    if (np == NULL) return 0;
  35.973 +
  35.974 +    return np->on_prev;
  35.975 +}
  35.976 +
  35.977 +ofdn_t ofd_io_create(void *mem, ofdn_t node, u64 open)
  35.978 +{
  35.979 +    struct ofd_mem *m = (struct ofd_mem *)mem;
  35.980 +    struct ofd_node *n;
  35.981 +    struct ofd_io *i;
  35.982 +    ofdn_t pos;
  35.983 +    ofdn_t cells;
  35.984 +
  35.985 +    cells = (sizeof (*i) + sizeof (m->om_mem[0]) - 1) / sizeof(m->om_mem[0]);
  35.986 +
  35.987 +    n = ofd_node_get(m, node);
  35.988 +    if ( n == NULL ) return 0;
  35.989 +
  35.990 +    if ( m->om_next + cells >= m->om_num ) {
  35.991 +        return 0;
  35.992 +    }
  35.993 +
  35.994 +    pos = m->om_next;
  35.995 +    assert(ofd_check(&m->om_mem[pos], cells)); /* non-zero */
  35.996 +
  35.997 +    m->om_next += cells;
  35.998 +    
  35.999 +    i = (struct ofd_io *)&m->om_mem[pos];
 35.1000 +    assert(i->oi_ima == 0); /* new node not empty */
 35.1001 +
 35.1002 +    i->oi_ima = IO_PAT;
 35.1003 +    i->oi_node = node;
 35.1004 +    i->oi_open = open;
 35.1005 +
 35.1006 +    n->on_io = pos;
 35.1007 +
 35.1008 +    return pos;
 35.1009 +}
 35.1010 +
 35.1011 +static struct ofd_io *ofd_io_get(struct ofd_mem *m, ofdn_t i)
 35.1012 +{
 35.1013 +    if ( i < m->om_next ) {
 35.1014 +        struct ofd_io *r;
 35.1015 +
 35.1016 +        r = (struct ofd_io *)&m->om_mem[i];
 35.1017 +        if ( r->oi_ima == IO_PAT ) {
 35.1018 +            return r;
 35.1019 +        }
 35.1020 +        assert(r->oi_ima == IO_PAT); /* bad object */
 35.1021 +    }
 35.1022 +
 35.1023 +    return NULL;
 35.1024 +}
 35.1025 +
 35.1026 +ofdn_t ofd_node_io(void *mem, ofdn_t n)
 35.1027 +{
 35.1028 +    struct ofd_mem *m = (struct ofd_mem *)mem;
 35.1029 +    struct ofd_node *r = ofd_node_get(m, n);
 35.1030 +
 35.1031 +    if (r == NULL) return 0;
 35.1032 +    return r->on_io;
 35.1033 +}
 35.1034 +
 35.1035 +uint ofd_io_open(void *mem, ofdn_t n)
 35.1036 +{
 35.1037 +    struct ofd_mem *m = (struct ofd_mem *)mem;
 35.1038 +    struct ofd_io *r = ofd_io_get(m, n);
 35.1039 +
 35.1040 +    if (r == NULL) return 0;
 35.1041 +    return r->oi_open;
 35.1042 +}
 35.1043 +
 35.1044 +void ofd_io_close(void *mem, ofdn_t n)
 35.1045 +{
 35.1046 +    struct ofd_mem *m = (struct ofd_mem *)mem;
 35.1047 +    struct ofd_io *o = ofd_io_get(m, n);
 35.1048 +    struct ofd_node *r = ofd_node_get(m, o->oi_node);
 35.1049 +
 35.1050 +    assert(o != NULL);
 35.1051 +    assert(r != NULL);
 35.1052 +    o->oi_open = 0;
 35.1053 +    r->on_io = 0;
 35.1054 +}
 35.1055 +
 35.1056 +ofdn_t ofd_node_add(void *m, ofdn_t p, const char *path, size_t sz)
 35.1057 +{
 35.1058 +    ofdn_t n;
 35.1059 +
 35.1060 +    n = ofd_node_child(m, p);
 35.1061 +    if ( n > 0 ) {
 35.1062 +        n = ofd_node_peer_last(m, n);
 35.1063 +        if ( n > 0 ) {
 35.1064 +            n = ofd_node_peer_create(m, n, path, sz);
 35.1065 +        }
 35.1066 +    } else {
 35.1067 +        n = ofd_node_child_create(m, p, path, sz);
 35.1068 +    }
 35.1069 +
 35.1070 +    return n;
 35.1071 +}
 35.1072 +
 35.1073 +ofdn_t ofd_prop_add(
 35.1074 +    void *mem,
 35.1075 +    ofdn_t n,
 35.1076 +    const char *name,
 35.1077 +    const void *buf,
 35.1078 +    size_t sz)
 35.1079 +{
 35.1080 +    struct ofd_mem *m = (struct ofd_mem *)mem;
 35.1081 +    ofdn_t r;
 35.1082 +
 35.1083 +    r = ofd_prop_find(m, n, name);
 35.1084 +    if ( r == 0 ) {
 35.1085 +        r = ofd_prop_create(mem, n, name, buf, sz);
 35.1086 +    } else {
 35.1087 +        r = ofd_prop_set(mem, n, name, buf, sz);
 35.1088 +    }
 35.1089 +
 35.1090 +    return r;
 35.1091 +}
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/xen/arch/powerpc/of-devtree.h	Fri Jul 14 10:47:50 2006 +0100
    36.3 @@ -0,0 +1,139 @@
    36.4 +/*
    36.5 + * This program is free software; you can redistribute it and/or modify
    36.6 + * it under the terms of the GNU General Public License as published by
    36.7 + * the Free Software Foundation; either version 2 of the License, or
    36.8 + * (at your option) any later version.
    36.9 + *
   36.10 + * This program is distributed in the hope that it will be useful,
   36.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   36.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   36.13 + * GNU General Public License for more details.
   36.14 + *
   36.15 + * You should have received a copy of the GNU General Public License
   36.16 + * along with this program; if not, write to the Free Software
   36.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   36.18 + *
   36.19 + * Copyright (C) IBM Corp. 2005
   36.20 + *
   36.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   36.22 + */
   36.23 +
   36.24 +#ifndef _OF_DEVTREE_H
   36.25 +#define _OF_DEVTREE_H
   36.26 +
   36.27 +#include <xen/types.h>
   36.28 +#include <public/xen.h>
   36.29 +
   36.30 +enum {
   36.31 +    OF_FAILURE = -1,
   36.32 +    OF_SUCCESS = 0,
   36.33 +};
   36.34 +
   36.35 +union of_pci_hi {
   36.36 +    u32 word;
   36.37 +    struct {
   36.38 +        u32	opa_n: 1; /* relocatable */
   36.39 +        u32	opa_p: 1; /* prefetchable */
   36.40 +        u32	opa_t: 1; /* aliased */
   36.41 +        u32 _opa_res: 3;
   36.42 +        u32	opa: 2; /* space code */
   36.43 +        u32  opa_b: 8; /* bus number */
   36.44 +        u32	opa_d: 5; /* device number */
   36.45 +        u32	opa_f: 3; /* function number */
   36.46 +        u32	opa_r: 8; /* register number */
   36.47 +    } bits;
   36.48 +};
   36.49 +
   36.50 +struct of_pci_addr {
   36.51 +    union of_pci_hi opa_hi;
   36.52 +    u32 opa_mid;
   36.53 +    u32 opa_lo;
   36.54 +};
   36.55 +
   36.56 +struct of_pci_range32 {
   36.57 +    struct of_pci_addr opr_addr;
   36.58 +    u32 opr_phys;
   36.59 +    u32 opr_size;
   36.60 +};
   36.61 +
   36.62 +struct of_pci_range64 {
   36.63 +    struct of_pci_addr opr_addr;
   36.64 +    u32 opr_phys_hi;
   36.65 +    u32 opr_phys_lo;
   36.66 +    u32 opr_size_hi;
   36.67 +    u32 opr_size_lo;
   36.68 +};
   36.69 +
   36.70 +struct of_pci_addr_range64 {
   36.71 +    struct of_pci_addr opr_addr;
   36.72 +    u32 opr_size_hi;
   36.73 +    u32 opr_size_lo;
   36.74 +};
   36.75 +
   36.76 +struct reg_property32 {
   36.77 +    u32 address;
   36.78 +    u32 size;
   36.79 +};
   36.80 +
   36.81 +typedef s32 ofdn_t;
   36.82 +
   36.83 +#define OFD_ROOT 1
   36.84 +#define OFD_DUMP_NAMES	0x1
   36.85 +#define OFD_DUMP_VALUES	0x2
   36.86 +#define OFD_DUMP_ALL	(OFD_DUMP_VALUES|OFD_DUMP_NAMES)
   36.87 +
   36.88 +extern void *ofd_create(void *mem, size_t sz);
   36.89 +extern ofdn_t ofd_node_parent(void *mem, ofdn_t n);
   36.90 +extern ofdn_t ofd_node_peer(void *mem, ofdn_t n);
   36.91 +extern ofdn_t ofd_node_child(void *mem, ofdn_t p);
   36.92 +extern const char *ofd_node_path(void *mem, ofdn_t p);
   36.93 +extern int ofd_node_to_path(void *mem, ofdn_t p, void *buf, size_t sz);
   36.94 +extern ofdn_t ofd_node_child_create(void *mem, ofdn_t parent,
   36.95 +				    const char *path, size_t pathlen);
   36.96 +extern ofdn_t ofd_node_peer_create(void *mem, ofdn_t sibling,
   36.97 +				   const char *path, size_t pathlen);
   36.98 +extern ofdn_t ofd_node_find(void *mem, const char *devspec);
   36.99 +extern ofdn_t ofd_node_add(void *m, ofdn_t n, const char *path, size_t sz);
  36.100 +extern int ofd_node_prune(void *m, ofdn_t n);
  36.101 +extern int ofd_prune_path(void *m, const char *path);
  36.102 +extern ofdn_t ofd_node_io(void *mem, ofdn_t n);
  36.103 +
  36.104 +extern ofdn_t ofd_nextprop(void *mem, ofdn_t n, const char *prev, char *name);
  36.105 +extern ofdn_t ofd_prop_find(void *mem, ofdn_t n, const char *name);
  36.106 +extern int ofd_getprop(void *mem, ofdn_t n, const char *name,
  36.107 +			void *buf, size_t sz);
  36.108 +extern int ofd_getproplen(void *mem, ofdn_t n, const char *name);
  36.109 +
  36.110 +extern int ofd_setprop(void *mem, ofdn_t n, const char *name,
  36.111 +			const void *buf, size_t sz);
  36.112 +extern void ofd_prop_remove(void *mem, ofdn_t node, ofdn_t prop);
  36.113 +extern ofdn_t ofd_prop_add(void *mem, ofdn_t n, const char *name,
  36.114 +			   const void *buf, size_t sz);
  36.115 +extern ofdn_t ofd_io_create(void *m, ofdn_t node, u64 open);
  36.116 +extern u32 ofd_io_open(void *mem, ofdn_t n);
  36.117 +extern void ofd_io_close(void *mem, ofdn_t n);
  36.118 +
  36.119 +
  36.120 +typedef void (*walk_fn)(void *m, ofdn_t p, int arg);
  36.121 +extern void ofd_dump_props(void *m, ofdn_t p, int dump);
  36.122 +
  36.123 +extern void ofd_walk(void *m, ofdn_t p, walk_fn fn, int arg);
  36.124 +
  36.125 +
  36.126 +/* Recursively look up #address_cells and #size_cells properties */
  36.127 +extern int ofd_getcells(void *mem, ofdn_t n,
  36.128 +                        u32 *addr_cells, u32 *size_cells);
  36.129 +
  36.130 +extern size_t ofd_size(void *mem);
  36.131 +extern size_t ofd_space(void *mem);
  36.132 +
  36.133 +extern void ofd_prop_print(const char *head, const char *path,
  36.134 +			   const char *name, const char *prop, size_t sz);
  36.135 +
  36.136 +extern ofdn_t ofd_node_find_by_prop(void *mem, ofdn_t n, const char *name,
  36.137 +				    const void *val, size_t sz);
  36.138 +extern ofdn_t ofd_node_find_next(void *mem, ofdn_t n);
  36.139 +extern ofdn_t ofd_node_find_prev(void *mem, ofdn_t n);
  36.140 +extern void ofd_init(int (*write)(const char *, size_t len));
  36.141 +
  36.142 +#endif /* _OF_DEVTREE_H */
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/xen/arch/powerpc/of-devwalk.c	Fri Jul 14 10:47:50 2006 +0100
    37.3 @@ -0,0 +1,135 @@
    37.4 +/*
    37.5 + * This program is free software; you can redistribute it and/or modify
    37.6 + * it under the terms of the GNU General Public License as published by
    37.7 + * the Free Software Foundation; either version 2 of the License, or
    37.8 + * (at your option) any later version.
    37.9 + *
   37.10 + * This program is distributed in the hope that it will be useful,
   37.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   37.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   37.13 + * GNU General Public License for more details.
   37.14 + *
   37.15 + * You should have received a copy of the GNU General Public License
   37.16 + * along with this program; if not, write to the Free Software
   37.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   37.18 + *
   37.19 + * Copyright (C) IBM Corp. 2005
   37.20 + *
   37.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   37.22 + */
   37.23 +
   37.24 +#include <xen/config.h>
   37.25 +#include <xen/init.h>
   37.26 +#include <xen/lib.h>
   37.27 +#include <xen/ctype.h>
   37.28 +#include <xen/kernel.h>
   37.29 +#include "of-devtree.h"
   37.30 +
   37.31 +void ofd_prop_print(
   37.32 +    const char *head,
   37.33 +    const char *path,
   37.34 +    const char *name,
   37.35 +    const char *prop,
   37.36 +    size_t sz)
   37.37 +{
   37.38 +    if ( path[0] == '/' && path[1] == '\0' ) {
   37.39 +        path = "";
   37.40 +    }
   37.41 +    printf("%s: %s/%s: 0x%lx\n", head, path,  name, sz);
   37.42 +
   37.43 +#define DEBUG_PROP
   37.44 +#ifdef DEBUG_PROP
   37.45 +    int i;
   37.46 +    int isstr = sz;
   37.47 +    const char *b = prop;
   37.48 +
   37.49 +    for ( i = 0; i < sz; i++ ) {
   37.50 +        /* see if there is any non printable characters */
   37.51 +        if ( !isprint(b[i]) ) {
   37.52 +            /* not printable */
   37.53 +            if (b[i] != '\0' || (i + 1) != sz) {
   37.54 +                /* not the end of string */
   37.55 +                isstr = 0;
   37.56 +                break;
   37.57 +            }
   37.58 +        }
   37.59 +    }
   37.60 +
   37.61 +    if ( isstr > 0 ) {
   37.62 +        printf("%s: \t%s\n", head, b);
   37.63 +    } else if ( sz != 0 ) {
   37.64 +        printf("%s: \t0x", head);
   37.65 +
   37.66 +        for ( i = 0; i < sz; i++ ) {
   37.67 +            if ( (i % 4) == 0 && i != 0 ) {
   37.68 +                if ( (i % 16) == 0 && i != 0 ) {
   37.69 +                    printf("\n%s: \t0x", head);
   37.70 +                } else {
   37.71 +                    printf(" 0x");
   37.72 +                }
   37.73 +            }
   37.74 +            if (b[i] < 0x10) {
   37.75 +                printf("0");
   37.76 +            }
   37.77 +            printf("%x", b[i]);
   37.78 +        }
   37.79 +        printf("\n");
   37.80 +    }
   37.81 +#else
   37.82 +    (void)prop;
   37.83 +#endif
   37.84 +}
   37.85 +
   37.86 +void ofd_dump_props(void *mem, ofdn_t n, int dump)
   37.87 +{
   37.88 +    ofdn_t p;
   37.89 +    char name[128];
   37.90 +    char prop[256] __attribute__ ((aligned (__alignof__ (u64))));
   37.91 +    int sz;
   37.92 +    const char *path;
   37.93 +
   37.94 +    if ( n == OFD_ROOT ) {
   37.95 +        path = "";
   37.96 +    } else {
   37.97 +        path = ofd_node_path(mem, n);
   37.98 +    }
   37.99 +
  37.100 +    if (dump & OFD_DUMP_NAMES) {
  37.101 +        printf("of_walk: %s: phandle 0x%x\n", path, n);
  37.102 +    }
  37.103 +
  37.104 +    p = ofd_nextprop(mem, n, NULL, name);
  37.105 +    while ( p > 0 ) {
  37.106 +        sz = ofd_getprop(mem, n, name, prop, sizeof (prop));
  37.107 +        if ( sz > 0 && sz > sizeof (prop) ) {
  37.108 +            sz = sizeof (prop);
  37.109 +        }
  37.110 +
  37.111 +        if ( dump & OFD_DUMP_VALUES ) {
  37.112 +            ofd_prop_print("of_walk", path, name, prop, sz);
  37.113 +        }
  37.114 +
  37.115 +        p = ofd_nextprop(mem, n, name, name);
  37.116 +    }
  37.117 +}
  37.118 +
  37.119 +void ofd_walk(void *m, ofdn_t p, walk_fn fn, int arg)
  37.120 +{
  37.121 +    ofdn_t n;
  37.122 +
  37.123 +    if ( fn != NULL ) {
  37.124 +        (*fn)(m, p, arg);
  37.125 +    }
  37.126 +
  37.127 +    /* child */
  37.128 +    n = ofd_node_child(m, p);
  37.129 +    if ( n != 0 ) {
  37.130 +        ofd_walk(m, n, fn, arg);
  37.131 +    }
  37.132 +
  37.133 +    /* peer */
  37.134 +    n = ofd_node_peer(m, p);
  37.135 +    if ( n != 0 ) {
  37.136 +        ofd_walk(m, n, fn, arg);
  37.137 +    }
  37.138 +}
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/xen/arch/powerpc/of_handler/Makefile	Fri Jul 14 10:47:50 2006 +0100
    38.3 @@ -0,0 +1,31 @@
    38.4 +#
    38.5 +# Build the Open Firmware handler
    38.6 +#
    38.7 +
    38.8 +CFLAGS += -I..
    38.9 +
   38.10 +# head.o must be first
   38.11 +obj-y = head.o
   38.12 +obj-y += console.o
   38.13 +obj-y += control.o
   38.14 +obj-y += cpu.o
   38.15 +obj-y += devtree.o
   38.16 +obj-y += head.o
   38.17 +obj-y += io.o
   38.18 +obj-y += leap.o
   38.19 +obj-y += memory.o
   38.20 +obj-y += ofh.o
   38.21 +obj-y += papr.o
   38.22 +obj-y += services.o
   38.23 +obj-y += vdevice.o
   38.24 +obj-y += xencomm.o
   38.25 +obj-y += xen_hvcall.o
   38.26 +
   38.27 +obj-y += memcmp.o
   38.28 +obj-y += memset.o
   38.29 +obj-y += snprintf.o
   38.30 +obj-y += strcmp.o
   38.31 +obj-y += strlen.o
   38.32 +obj-y += strncmp.o
   38.33 +obj-y += strncpy.o
   38.34 +obj-y += strnlen.o
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/xen/arch/powerpc/of_handler/console.c	Fri Jul 14 10:47:50 2006 +0100
    39.3 @@ -0,0 +1,233 @@
    39.4 +/*
    39.5 + * This program is free software; you can redistribute it and/or modify
    39.6 + * it under the terms of the GNU General Public License as published by
    39.7 + * the Free Software Foundation; either version 2 of the License, or
    39.8 + * (at your option) any later version.
    39.9 + *
   39.10 + * This program is distributed in the hope that it will be useful,
   39.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   39.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   39.13 + * GNU General Public License for more details.
   39.14 + *
   39.15 + * You should have received a copy of the GNU General Public License
   39.16 + * along with this program; if not, write to the Free Software
   39.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   39.18 + *
   39.19 + * Copyright (C) IBM Corp. 2005
   39.20 + *
   39.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   39.22 + */
   39.23 +
   39.24 +#include "ofh.h"
   39.25 +#include "papr.h"
   39.26 +#include <xen/string.h>
   39.27 +#include <asm/system.h>
   39.28 +
   39.29 +union chpack {
   39.30 +    u64 oct[2];
   39.31 +    u32 quad[4];
   39.32 +    char c[16];
   39.33 +};
   39.34 +
   39.35 +/* used for internal printing */
   39.36 +static struct ofh_ihandle *ofh_ihp;
   39.37 +
   39.38 +static s32 ofh_papr_read(s32 chan, void *buf, u32 count, s32 *actual, ulong b)
   39.39 +{
   39.40 +    s32 rc;
   39.41 +    ulong ret[5];
   39.42 +    ulong sz = 0;
   39.43 +
   39.44 +    rc = papr_get_term_char(ret, chan);
   39.45 +    if (rc == H_Success && ret[0] > 0) {
   39.46 +        sz = MIN(count, ret[0]);
   39.47 +        memcpy(buf, &ret[1], sz);
   39.48 +    }
   39.49 +    *actual = sz;
   39.50 +    return OF_SUCCESS;
   39.51 +}
   39.52 +
   39.53 +static s32 ofh_papr_write(s32 chan, const void *buf, u32 count, s32 *actual,
   39.54 +                          ulong b)
   39.55 +{
   39.56 +    const char *str = (const char *)buf;
   39.57 +    u32 i;
   39.58 +    union chpack ch;
   39.59 +    s32 ret;
   39.60 +
   39.61 +    for (i = 0; i < count; i++) {
   39.62 +        int m = i % sizeof(ch);
   39.63 +        ch.c[m] = str[i];
   39.64 +        if (m == sizeof(ch) - 1 || i == count - 1) {
   39.65 +            for (;;) {
   39.66 +                if (sizeof (ulong) == sizeof (u64)) {
   39.67 +                    ret = papr_put_term_char(NULL,
   39.68 +                                             chan,
   39.69 +                                             m + 1,
   39.70 +                                             ch.oct[0],
   39.71 +                                             ch.oct[1]);
   39.72 +                } else {
   39.73 +                    ret = papr_put_term_char(NULL,
   39.74 +                                             chan,
   39.75 +                                             m + 1,
   39.76 +                                             ch.quad[0],
   39.77 +                                             ch.quad[1],
   39.78 +                                             ch.quad[2],
   39.79 +                                             ch.quad[3]);
   39.80 +                }
   39.81 +                if (ret != H_Busy) {
   39.82 +                    break;
   39.83 +                }
   39.84 +                /* yielding here would be nice */
   39.85 +            }
   39.86 +            if (ret != H_Success) {
   39.87 +                return -1;
   39.88 +            }
   39.89 +        }
   39.90 +    }
   39.91 +    *actual = count;
   39.92 +    if (*actual == -1) {
   39.93 +        return OF_FAILURE;
   39.94 +    }
   39.95 +    return OF_SUCCESS;
   39.96 +}
   39.97 +
   39.98 +#define __HYPERVISOR_console_io 18
   39.99 +#define CONSOLEIO_write         0
  39.100 +#define CONSOLEIO_read          1
  39.101 +#define XEN_MARK(a) ((a) | (~0UL << 16))
  39.102 +extern long xen_hvcall(ulong code, ...);
  39.103 +
  39.104 +#define XENCOMM_MINI_AREA (sizeof(struct xencomm_mini) * 2)
  39.105 +static s32 ofh_xen_dom0_read(s32 chan, void *buf, u32 count, s32 *actual,
  39.106 +                             ulong b)
  39.107 +{
  39.108 +    char __storage[XENCOMM_MINI_AREA];
  39.109 +    struct xencomm_desc *desc;
  39.110 +    s32 rc;
  39.111 +    char *s = buf;
  39.112 +    s32 ret = 0;
  39.113 +
  39.114 +    while (count > 0) {
  39.115 +        if (xencomm_create_mini(__storage, XENCOMM_MINI_AREA, s, count, &desc))
  39.116 +            return ret;
  39.117 +
  39.118 +        rc = xen_hvcall(XEN_MARK(__HYPERVISOR_console_io), CONSOLEIO_read,
  39.119 +                count, desc);
  39.120 +        if (rc <= 0) {
  39.121 +            return ret;
  39.122 +        }
  39.123 +        count -= rc;
  39.124 +        s += rc;
  39.125 +        ret += rc;
  39.126 +    }
  39.127 +    *actual = ret;
  39.128 +    return OF_SUCCESS;
  39.129 +}
  39.130 +
  39.131 +static s32 ofh_xen_dom0_write(s32 chan, const void *buf, u32 count,
  39.132 +                              s32 *actual, ulong b)
  39.133 +{
  39.134 +    char __storage[XENCOMM_MINI_AREA];
  39.135 +    struct xencomm_desc *desc;
  39.136 +    s32 rc;
  39.137 +    char *s = (char *)buf;
  39.138 +    s32 ret = 0;
  39.139 +
  39.140 +    while (count > 0) {
  39.141 +        if (xencomm_create_mini(__storage, XENCOMM_MINI_AREA, s, count, &desc))
  39.142 +            return ret;
  39.143 +
  39.144 +        rc = xen_hvcall(XEN_MARK(__HYPERVISOR_console_io), CONSOLEIO_write,
  39.145 +                count, desc);
  39.146 +        if (rc <= 0) {
  39.147 +            return ret;
  39.148 +        }
  39.149 +        count -= rc;
  39.150 +        s += rc;
  39.151 +        ret += rc;
  39.152 +    }
  39.153 +    *actual = ret;
  39.154 +    if (*actual == -1) {
  39.155 +        return OF_FAILURE;
  39.156 +    }
  39.157 +    return OF_SUCCESS;
  39.158 +}
  39.159 +
  39.160 +static s32 ofh_xen_domu_read(s32 chan, void *buf, u32 count, s32 *actual,
  39.161 +                             ulong b)
  39.162 +{
  39.163 +	struct xencons_interface *intf;
  39.164 +	XENCONS_RING_IDX cons, prod;
  39.165 +    s32 ret;
  39.166 +
  39.167 +    intf = DRELA(ofh_ihp, b)->ofi_intf;
  39.168 +    cons = intf->in_cons;
  39.169 +    prod = intf->in_prod;
  39.170 +    mb();
  39.171 +
  39.172 +    ret = prod - cons;
  39.173 +
  39.174 +    if (ret > 0) {
  39.175 +        ret = (ret < count) ? ret : count;
  39.176 +        memcpy(buf, intf->in+MASK_XENCONS_IDX(cons,intf->in), ret);
  39.177 +    }
  39.178 +
  39.179 +    *actual = (ret < 0) ? 0 : ret;
  39.180 +    return OF_SUCCESS;
  39.181 +}
  39.182 +
  39.183 +static s32 ofh_xen_domu_write(s32 chan, const void *buf, u32 count,
  39.184 +                              s32 *actual, ulong b)
  39.185 +{
  39.186 +	struct xencons_interface *intf;
  39.187 +	XENCONS_RING_IDX cons, prod;
  39.188 +    s32 ret;
  39.189 +
  39.190 +    intf = DRELA(ofh_ihp, b)->ofi_intf;
  39.191 +    cons = intf->in_cons;
  39.192 +    prod = intf->in_prod;
  39.193 +    mb();
  39.194 +
  39.195 +    ret = prod - cons;
  39.196 +    /* FIXME: Do we have to write the whole thing or are partial writes ok? */
  39.197 +    if (ret > 0) {
  39.198 +        ret = (ret < count) ? ret : count;
  39.199 +        memcpy(intf->in+MASK_XENCONS_IDX(cons,intf->in), buf, ret);
  39.200 +    }
  39.201 +
  39.202 +    *actual = (ret < 0) ? 0 : ret;
  39.203 +    return OF_SUCCESS;
  39.204 +}
  39.205 +
  39.206 +/* for emergency printing in the OFH */
  39.207 +s32 ofh_cons_write(const void *buf, u32 count, s32 *actual)
  39.208 +{
  39.209 +    ulong b = get_base();
  39.210 +    struct ofh_ihandle *ihp = DRELA(ofh_ihp, b);
  39.211 +
  39.212 +    return ihp->ofi_write(ihp->ofi_chan, buf, count, actual, b);
  39.213 +}
  39.214 +
  39.215 +s32 ofh_cons_close(void)
  39.216 +{
  39.217 +    return OF_SUCCESS;
  39.218 +}
  39.219 +
  39.220 +void
  39.221 +ofh_cons_init(struct ofh_ihandle *ihp, ulong b)
  39.222 +{
  39.223 +    if (ihp->ofi_chan == OFH_CONS_XEN) {
  39.224 +        if (ihp->ofi_intf == NULL) {
  39.225 +            ihp->ofi_write = ofh_xen_dom0_write;
  39.226 +            ihp->ofi_read = ofh_xen_dom0_read;
  39.227 +        } else {
  39.228 +            ihp->ofi_write = ofh_xen_domu_write;
  39.229 +            ihp->ofi_read = ofh_xen_domu_read;
  39.230 +        }
  39.231 +    } else {
  39.232 +        ihp->ofi_write = ofh_papr_write;
  39.233 +        ihp->ofi_read = ofh_papr_read;
  39.234 +    }
  39.235 +    *DRELA(&ofh_ihp, b) = ihp;
  39.236 +}
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/xen/arch/powerpc/of_handler/control.c	Fri Jul 14 10:47:50 2006 +0100
    40.3 @@ -0,0 +1,90 @@
    40.4 +/*
    40.5 + * This program is free software; you can redistribute it and/or modify
    40.6 + * it under the terms of the GNU General Public License as published by
    40.7 + * the Free Software Foundation; either version 2 of the License, or
    40.8 + * (at your option) any later version.
    40.9 + *
   40.10 + * This program is distributed in the hope that it will be useful,
   40.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   40.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   40.13 + * GNU General Public License for more details.
   40.14 + *
   40.15 + * You should have received a copy of the GNU General Public License
   40.16 + * along with this program; if not, write to the Free Software
   40.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   40.18 + *
   40.19 + * Copyright (C) IBM Corp. 2005
   40.20 + *
   40.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   40.22 + */
   40.23 +
   40.24 +#include "ofh.h"
   40.25 +
   40.26 +s32
   40.27 +ofh_boot(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
   40.28 +{
   40.29 +    b=b;
   40.30 +    nargs = nargs;
   40.31 +    nrets = nrets;
   40.32 +    argp = argp;
   40.33 +    retp = retp;
   40.34 +    return OF_FAILURE;
   40.35 +}
   40.36 +
   40.37 +s32
   40.38 +ofh_enter(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
   40.39 +{
   40.40 +    b=b;
   40.41 +    nargs = nargs;
   40.42 +    nrets = nrets;
   40.43 +    argp = argp;
   40.44 +    retp = retp;
   40.45 +    return OF_FAILURE;
   40.46 +}
   40.47 +
   40.48 +s32
   40.49 +ofh_exit(u32 nargs __attribute__ ((unused)),
   40.50 +        u32 nrets  __attribute__ ((unused)),
   40.51 +        s32 argp[]  __attribute__ ((unused)),
   40.52 +        s32 retp[] __attribute__ ((unused)),
   40.53 +        ulong b)
   40.54 +{
   40.55 +    static const char msg[] = "OFH: exit method called\n";
   40.56 +    s32 dummy;
   40.57 +
   40.58 +    ofh_cons_write(DRELA(&msg[0], b), sizeof (msg), &dummy);
   40.59 +
   40.60 +    for (;;) {
   40.61 +        /* kill domain here */
   40.62 +    }
   40.63 +    return OF_FAILURE;
   40.64 +}
   40.65 +
   40.66 +s32
   40.67 +ofh_chain(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
   40.68 +{
   40.69 +    b=b;
   40.70 +    nargs = nargs;
   40.71 +    nrets = nrets;
   40.72 +    argp = argp;
   40.73 +    retp = retp;
   40.74 +    return OF_FAILURE;
   40.75 +}
   40.76 +
   40.77 +s32
   40.78 +ofh_quiesce(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
   40.79 +{
   40.80 +    if (nargs == 0) {
   40.81 +        if (nrets == 0) {
   40.82 +            void *mem = ofd_mem(b);
   40.83 +            (void)nargs;
   40.84 +            (void)nrets;
   40.85 +            (void)argp;
   40.86 +            (void)retp;
   40.87 +            (void)mem;
   40.88 +
   40.89 +            return OF_SUCCESS;
   40.90 +        }
   40.91 +    }
   40.92 +    return OF_FAILURE;
   40.93 +}
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/xen/arch/powerpc/of_handler/cpu.c	Fri Jul 14 10:47:50 2006 +0100
    41.3 @@ -0,0 +1,82 @@
    41.4 +/*
    41.5 + * This program is free software; you can redistribute it and/or modify
    41.6 + * it under the terms of the GNU General Public License as published by
    41.7 + * the Free Software Foundation; either version 2 of the License, or
    41.8 + * (at your option) any later version.
    41.9 + *
   41.10 + * This program is distributed in the hope that it will be useful,
   41.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   41.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   41.13 + * GNU General Public License for more details.
   41.14 + *
   41.15 + * You should have received a copy of the GNU General Public License
   41.16 + * along with this program; if not, write to the Free Software
   41.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   41.18 + *
   41.19 + * Copyright (C) IBM Corp. 2005
   41.20 + *
   41.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   41.22 + */
   41.23 +
   41.24 +#include "ofh.h"
   41.25 +
   41.26 +s32
   41.27 +ofh_start_cpu(u32 nargs, u32 nrets, s32 argp[],
   41.28 +        s32 retp[] __attribute__ ((unused)),
   41.29 +        ulong b __attribute__ ((unused)))
   41.30 +{
   41.31 +    if (nargs == 3) {
   41.32 +        if (nrets == 0) {
   41.33 +            ofdn_t ph = argp[0];
   41.34 +            u32 pc = argp[1];
   41.35 +            u32 arg = argp[2];
   41.36 +
   41.37 +            (void)ph; (void)pc; (void)arg;
   41.38 +            return OF_FAILURE;
   41.39 +        }
   41.40 +    }
   41.41 +    return OF_FAILURE;
   41.42 +}
   41.43 +
   41.44 +s32
   41.45 +ofh_stop_self(u32 nargs, u32 nrets,
   41.46 +        s32 argp[] __attribute__ ((unused)),
   41.47 +        s32 retp[] __attribute__ ((unused)),
   41.48 +        ulong b __attribute__ ((unused)))
   41.49 +{
   41.50 +    if (nargs == 0) {
   41.51 +        if (nrets == 0) {
   41.52 +            return OF_FAILURE;
   41.53 +        }
   41.54 +    }
   41.55 +    return OF_FAILURE;
   41.56 +}
   41.57 +
   41.58 +s32
   41.59 +ofh_idle_self(u32 nargs, u32 nrets,
   41.60 +        s32 argp[] __attribute__ ((unused)),
   41.61 +        s32 retp[] __attribute__ ((unused)),
   41.62 +        ulong b __attribute__ ((unused)))
   41.63 +{
   41.64 +    if (nargs == 0) {
   41.65 +        if (nrets == 0) {
   41.66 +            return OF_FAILURE;
   41.67 +        }
   41.68 +    }
   41.69 +    return OF_FAILURE;
   41.70 +}
   41.71 +s32
   41.72 +ofh_resume_cpu(u32 nargs, u32 nrets, s32 argp[],
   41.73 +        s32 retp[] __attribute__ ((unused)),
   41.74 +        ulong b __attribute__ ((unused)))
   41.75 +{
   41.76 +    if (nargs == 1) {
   41.77 +        if (nrets == 0) {
   41.78 +            ofdn_t ph = argp[0];
   41.79 +
   41.80 +            (void)ph;
   41.81 +            return OF_FAILURE;
   41.82 +        }
   41.83 +    }
   41.84 +    return OF_FAILURE;
   41.85 +}
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/xen/arch/powerpc/of_handler/devtree.c	Fri Jul 14 10:47:50 2006 +0100
    42.3 @@ -0,0 +1,266 @@
    42.4 +/*
    42.5 + * This program is free software; you can redistribute it and/or modify
    42.6 + * it under the terms of the GNU General Public License as published by
    42.7 + * the Free Software Foundation; either version 2 of the License, or
    42.8 + * (at your option) any later version.
    42.9 + *
   42.10 + * This program is distributed in the hope that it will be useful,
   42.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   42.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   42.13 + * GNU General Public License for more details.
   42.14 + *
   42.15 + * You should have received a copy of the GNU General Public License
   42.16 + * along with this program; if not, write to the Free Software
   42.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   42.18 + *
   42.19 + * Copyright (C) IBM Corp. 2005
   42.20 + *
   42.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   42.22 + */
   42.23 +
   42.24 +#include "ofh.h"
   42.25 +#include <of-devtree.h> 
   42.26 +
   42.27 +s32
   42.28 +ofh_peer(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
   42.29 +{
   42.30 +    if (nargs == 1) {
   42.31 +        if (nrets == 1) {
   42.32 +            ofdn_t ph = argp[0];
   42.33 +            s32 *sib_ph = &retp[0];
   42.34 +            void *mem = ofd_mem(b);
   42.35 +
   42.36 +            *sib_ph = ofd_node_peer(mem, ph);
   42.37 +            return OF_SUCCESS;
   42.38 +        }
   42.39 +    }
   42.40 +    return OF_FAILURE;
   42.41 +}
   42.42 +
   42.43 +s32
   42.44 +ofh_child(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
   42.45 +{
   42.46 +    if (nargs == 1) {
   42.47 +        if (nrets == 1) {
   42.48 +            ofdn_t ph = argp[0];
   42.49 +            s32 *ch_ph = &retp[0];
   42.50 +            void *mem = ofd_mem(b);
   42.51 +
   42.52 +            *ch_ph = ofd_node_child(mem, ph);
   42.53 +            return OF_SUCCESS;
   42.54 +        }
   42.55 +    }
   42.56 +    return OF_FAILURE;
   42.57 +}
   42.58 +
   42.59 +s32
   42.60 +ofh_parent(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
   42.61 +{
   42.62 +    if (nargs == 1) {
   42.63 +        if (nrets == 1) {
   42.64 +            ofdn_t ph = argp[0];
   42.65 +            s32 *parent_ph = &retp[0];
   42.66 +            void *mem = ofd_mem(b);
   42.67 +
   42.68 +            *parent_ph = ofd_node_parent(mem, ph);
   42.69 +            return OF_SUCCESS;
   42.70 +        }
   42.71 +    }
   42.72 +    return OF_FAILURE;
   42.73 +}
   42.74 +
   42.75 +s32
   42.76 +ofh_instance_to_package(u32 nargs, u32 nrets, s32 argp[], s32 retp[],
   42.77 +        ulong b __attribute__ ((unused)))
   42.78 +{
   42.79 +    if (nargs == 1) {
   42.80 +        if (nrets == 1) {
   42.81 +            struct ofh_ihandle *ih =
   42.82 +                (struct ofh_ihandle *)(ulong)argp[0];
   42.83 +            s32 *p = &retp[0];
   42.84 +
   42.85 +            *p = (s32)ih->ofi_node;
   42.86 +            return OF_SUCCESS;
   42.87 +        }
   42.88 +    }
   42.89 +    return OF_FAILURE;
   42.90 +}
   42.91 +
   42.92 +s32
   42.93 +ofh_getproplen(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
   42.94 +{
   42.95 +    if (nargs == 2) {
   42.96 +        if (nrets == 1) {
   42.97 +            ofdn_t ph = argp[0];
   42.98 +            const char *name = (const char *)(ulong)argp[1];
   42.99 +            s32 *size = &retp[0];
  42.100 +            void *mem = ofd_mem(b);
  42.101 +
  42.102 +            *size = ofd_getproplen(mem, ph, name);
  42.103 +            if (*size >= 0) {
  42.104 +                return OF_SUCCESS;
  42.105 +            }
  42.106 +        }
  42.107 +    }
  42.108 +    return OF_FAILURE;
  42.109 +}
  42.110 +
  42.111 +s32
  42.112 +ofh_getprop(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
  42.113 +{
  42.114 +    if (nargs == 4) {
  42.115 +        if (nrets == 1) {
  42.116 +            ofdn_t ph = argp[0];
  42.117 +            const char *name = (const char *)(ulong)argp[1];
  42.118 +            void *buf = (void *)(ulong)argp[2];
  42.119 +            ulong buflen = argp[3];
  42.120 +            s32 *size = &retp[0];
  42.121 +            void *mem = ofd_mem(b);
  42.122 +
  42.123 +            *size = ofd_getprop(mem, ph, name, buf, buflen);
  42.124 +            if (*size > 0) {
  42.125 +                return OF_SUCCESS;
  42.126 +            }
  42.127 +        }
  42.128 +    }
  42.129 +    return OF_FAILURE;
  42.130 +}
  42.131 +
  42.132 +s32
  42.133 +ofh_nextprop(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
  42.134 +{
  42.135 +    if (nargs == 3) {
  42.136 +        if (nrets == 1) {
  42.137 +            ofdn_t ph = argp[0];
  42.138 +            const char *prev = (const char *)(ulong)argp[1];
  42.139 +            char *name = (char *)(ulong)argp[2];
  42.140 +            s32 *flag = &retp[0];
  42.141 +            void *mem = ofd_mem(b);
  42.142 +
  42.143 +            *flag = ofd_nextprop(mem, ph, prev, name);
  42.144 +            if (*flag > 0) {
  42.145 +                *flag = 1;
  42.146 +            }
  42.147 +            return OF_SUCCESS;
  42.148 +        }
  42.149 +    }
  42.150 +    return OF_FAILURE;
  42.151 +}
  42.152 +
  42.153 +s32
  42.154 +ofh_setprop(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
  42.155 +{
  42.156 +    if (nargs == 4) {
  42.157 +        if (nrets == 1) {
  42.158 +            ofdn_t ph = argp[0];
  42.159 +            const char *name = (const char *)(ulong)argp[1];
  42.160 +            const void *buf = (void *)(ulong)argp[2];
  42.161 +            ulong buflen = argp[3];
  42.162 +            s32 *size = &retp[0];
  42.163 +            void *mem = ofd_mem(b);
  42.164 +
  42.165 +            *size = ofd_setprop(mem, ph, name, buf, buflen);
  42.166 +            return OF_SUCCESS;
  42.167 +        }
  42.168 +    }
  42.169 +    return OF_FAILURE;
  42.170 +}
  42.171 +
  42.172 +s32
  42.173 +ofh_canon(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
  42.174 +{
  42.175 +    if (nargs == 3) {
  42.176 +        if (nrets == 1) {
  42.177 +            const char *dev_spec = (const char *)(ulong)argp[0];
  42.178 +            char *buf = (char *)(ulong)argp[1];
  42.179 +            u32 sz = argp[2];
  42.180 +            s32 *len = &retp[0];
  42.181 +            void *mem = ofd_mem(b);
  42.182 +            ofdn_t ph;
  42.183 +
  42.184 +            ph = ofd_node_find(mem, dev_spec);
  42.185 +            if (ph > 0) {
  42.186 +                *len = ofd_node_to_path(mem, ph, buf, sz);
  42.187 +                return OF_SUCCESS;
  42.188 +            }
  42.189 +        }
  42.190 +    }
  42.191 +    return OF_FAILURE;
  42.192 +}
  42.193 +
  42.194 +s32 ofh_active_package = -1;
  42.195 +
  42.196 +s32
  42.197 +ofh_finddevice(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
  42.198 +{
  42.199 +    if (nargs == 1) {
  42.200 +        if (nrets == 1) {
  42.201 +            s32 *ap = DRELA(&ofh_active_package, b);
  42.202 +            const char *devspec = (const char *)(ulong)argp[0];
  42.203 +            s32 *ph = &retp[0];
  42.204 +            void *mem = ofd_mem(b);
  42.205 +
  42.206 +            /* good enuff */
  42.207 +            if (devspec[0] == '\0') {
  42.208 +                if (*ap == -1) {
  42.209 +                    return OF_FAILURE;
  42.210 +                }
  42.211 +                *ph = *ap;
  42.212 +            } else {
  42.213 +                *ph = ofd_node_find(mem, devspec);
  42.214 +                if (*ph <= 0) {
  42.215 +                    return OF_FAILURE;
  42.216 +                }
  42.217 +            }
  42.218 +            *ap = *ph;
  42.219 +            return OF_SUCCESS;
  42.220 +        }
  42.221 +    }
  42.222 +    return OF_FAILURE;
  42.223 +}
  42.224 +
  42.225 +s32
  42.226 +ofh_instance_to_path(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
  42.227 +{
  42.228 +    if (nargs == 3) {
  42.229 +        if (nrets == 1) {
  42.230 +            struct ofh_ihandle *ih =
  42.231 +                (struct ofh_ihandle *)((ulong)argp[0]);
  42.232 +            char *buf = (char *)(ulong)argp[1];
  42.233 +            u32 sz = argp[2];
  42.234 +            s32 *len = &retp[0];
  42.235 +            ofdn_t ph;
  42.236 +            void *mem = ofd_mem(b);
  42.237 +
  42.238 +            ph = ih->ofi_node;
  42.239 +            if (ph > 0) {
  42.240 +                *len = ofd_node_to_path(mem, ph, buf, sz);
  42.241 +                return OF_SUCCESS;
  42.242 +            }
  42.243 +        }
  42.244 +    }
  42.245 +    return OF_FAILURE;
  42.246 +}
  42.247 +
  42.248 +s32
  42.249 +ofh_package_to_path(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
  42.250 +{
  42.251 +    if (nargs == 3) {
  42.252 +        if (nrets == 1) {
  42.253 +            ofdn_t ph = argp[0];
  42.254 +            char *buf = (char *)(ulong)argp[1];
  42.255 +            u32 sz = argp[2];
  42.256 +            s32 *len = &retp[0];
  42.257 +            void *mem = ofd_mem(b);
  42.258 +
  42.259 +            if (ph > 0) {
  42.260 +                *len = ofd_node_to_path(mem, ph, buf, sz);
  42.261 +                return OF_SUCCESS;
  42.262 +            }
  42.263 +        }
  42.264 +    }
  42.265 +    return OF_FAILURE;
  42.266 +}
  42.267 +
  42.268 +
  42.269 +
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/xen/arch/powerpc/of_handler/head.S	Fri Jul 14 10:47:50 2006 +0100
    43.3 @@ -0,0 +1,152 @@
    43.4 +/*
    43.5 + * Copyright (C) 2005 Jimi Xenidis <jimix@watson.ibm.com>, IBM Corporation
    43.6 + *
    43.7 + * This program is free software; you can redistribute it and/or modify
    43.8 + * it under the terms of the GNU General Public License as published by
    43.9 + * the Free Software Foundation; either version 2 of the License, or
   43.10 + * (at your option) any later version.
   43.11 + * 
   43.12 + * This program is distributed in the hope that it will be useful,
   43.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   43.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   43.15 + * GNU General Public License for more details.
   43.16 + * 
   43.17 + * You should have received a copy of the GNU General Public License
   43.18 + * along with this program; if not, write to the Free Software
   43.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   43.20 + */
   43.21 +/*
   43.22 + * Glue code for open-firmware client interface implementation.
   43.23 + */
   43.24 +
   43.25 +#define OF_STACK_SIZE (32*1024)
   43.26 +
   43.27 +#include <asm/config.h>
   43.28 +#include <asm/processor.h>
   43.29 +
   43.30 +#define SAVE_STACK	0
   43.31 +#define SAVE_SRR0	1
   43.32 +#define SAVE_SRR1	2
   43.33 +#define SAVE_MSR	3
   43.34 +#define SAVE_LR		4
   43.35 +#define SAVE_TOC	5
   43.36 +#define SAVE_BASE	6
   43.37 +#define SAVE_BCHAIN	7  /* MUST be last */
   43.38 +
   43.39 +/* This code is NOT MP safe and does not need to be */
   43.40 +	.p2align 3
   43.41 +	. = 0x0
   43.42 +_GLOBAL(ofh_start)		# make the linker happy
   43.43 +_ofh_cih:
   43.44 +	## r3 holds the parameter.  All other volatiles are available.
   43.45 +	mflr	r0
   43.46 +	# Obtain address of _ofh_work_space via a branch-and-link
   43.47 +	bl	_ofh_cih_continue
   43.48 +_ofh_work_space:
   43.49 +	nop
   43.50 +
   43.51 +	. = 0x10
   43.52 +	.global _ofh_tree
   43.53 +_ofh_tree:
   43.54 +	.long 0xdeadbeef
   43.55 +	.long 0x0
   43.56 +
   43.57 +	. = 0x18
   43.58 +	.global _ofh_inited
   43.59 +_ofh_inited:
   43.60 +	.long 0x0	
   43.61 +
   43.62 +	. = 0x20
   43.63 +	.global _ofh_lastarg
   43.64 +_ofh_lastarg:
   43.65 +	.long 0x0	
   43.66 +	.long 0x0	
   43.67 +	
   43.68 +	. = 0x30
   43.69 +_ofh_cih_stack_end:
   43.70 +	.space	OF_STACK_SIZE
   43.71 +_ofh_cih_stack:
   43.72 +   
   43.73 +_ofh_cih_continue:
   43.74 +	mflr	r12				# r12 = &_ofh_work_space
   43.75 +	mr	r11, r1				# r11 = orig stk ptr
   43.76 +
   43.77 +	/* load base address in r4 */
   43.78 +	LOADADDR(r4, _ofh_work_space)
   43.79 +	sub	r4, r12, r4
   43.80 +	
   43.81 +
   43.82 +	# save srr0/1
   43.83 +	mfsrr0	r9
   43.84 +	mfsrr1	r8
   43.85 +	mfmsr	r7
   43.86 +	LOADADDR(r5, _ofh_cih_64bit)
   43.87 +	add	r5, r5, r4	# offset base
   43.88 +	mtsrr0	r5
   43.89 +	# r5 = MSR_SF
   43.90 +	li	r5,-1
   43.91 +	rldicr	r5,r5,0,0
   43.92 +	or	r5,r5,r7
   43.93 +	mtsrr1	r5
   43.94 +	rfid
   43.95 +	trap
   43.96 +
   43.97 +_ofh_cih_64bit:		
   43.98 +	# move to local stack
   43.99 +	lis	r1, (_ofh_cih_stack - _ofh_cih_stack_end) >> 16
  43.100 +	ori	r1, r1, (_ofh_cih_stack - _ofh_cih_stack_end) & 0xffff
  43.101 +	add	r1, r12, r1
  43.102 +	# create an initial chain
  43.103 +	li	r10, 0
  43.104 +	# frame with 3 slots
  43.105 +	stdu	r10, -(STACK_FRAME_OVERHEAD + (SAVE_BCHAIN * 8))(r1)
  43.106 +	# preserve base
  43.107 +	std	r4, (STACK_FRAME_OVERHEAD + (SAVE_BASE * 8))(r1)
  43.108 +	# preserve orig stk ptr
  43.109 +	std	r11, (STACK_FRAME_OVERHEAD + (SAVE_STACK * 8))(r1)
  43.110 +	# preserve orig srr0
  43.111 +	std	r9, (STACK_FRAME_OVERHEAD + (SAVE_SRR0 * 8))(r1)
  43.112 +	# preserve orig srr1
  43.113 +	std	r8, (STACK_FRAME_OVERHEAD + (SAVE_SRR1 * 8))(r1)
  43.114 +	# preserve orig msr
  43.115 +	std	r7, (STACK_FRAME_OVERHEAD + (SAVE_MSR * 8))(r1)
  43.116 +	# preserve orig lr
  43.117 +	std	r0,  (STACK_FRAME_OVERHEAD + (SAVE_LR * 8))(r1)
  43.118 +	# preserve orig toc
  43.119 +	std	r2,  (STACK_FRAME_OVERHEAD + (SAVE_TOC * 8))(r1)
  43.120 +
  43.121 +	LOADADDR(r2, ofh_start)	# get the address of any function
  43.122 +	add	r2, r2, r4	# add the base
  43.123 +	ld	r2, 8(r2)	# get the TOC for that funtion
  43.124 +	add	r2, r2, r4	# add the base
  43.125 +
  43.126 +	bl	_ENTRY(ofh_handler)			# call handler
  43.127 +
  43.128 +	ld	r4, (STACK_FRAME_OVERHEAD + (SAVE_BASE * 8))(r1)
  43.129 +	ld	r9, (STACK_FRAME_OVERHEAD + (SAVE_SRR0 * 8))(r1)
  43.130 +	ld	r8, (STACK_FRAME_OVERHEAD + (SAVE_SRR1 * 8))(r1)
  43.131 +	ld	r7, (STACK_FRAME_OVERHEAD + (SAVE_MSR * 8))(r1)
  43.132 +	ld	r2, (STACK_FRAME_OVERHEAD + (SAVE_TOC * 8))(r1)
  43.133 +	ld	r0, (STACK_FRAME_OVERHEAD + (SAVE_LR * 8))(r1)
  43.134 +	ld	r1, (STACK_FRAME_OVERHEAD + (SAVE_STACK * 8))(r1)
  43.135 +
  43.136 +	LOADADDR(r5, _ofh_cih_orig_msr)
  43.137 +	add	r5, r5, r4
  43.138 +	mtsrr0 r5
  43.139 +	mtsrr1 r7
  43.140 +	rfid
  43.141 +	
  43.142 +_ofh_cih_orig_msr:
  43.143 +	mtsrr0	r9
  43.144 +	mtsrr1	r8
  43.145 +	mtlr	r0
  43.146 +	blr
  43.147 +
  43.148 +_GLOBAL(get_base)
  43.149 +	mflr	r0
  43.150 +	bl	1f
  43.151 +1:	mflr	r5
  43.152 +	LOADADDR(r4,1b)
  43.153 +	subf	r3,r4,r5
  43.154 +	mtlr	r0
  43.155 +	blr
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/xen/arch/powerpc/of_handler/io.c	Fri Jul 14 10:47:50 2006 +0100
    44.3 @@ -0,0 +1,160 @@
    44.4 +/*
    44.5 + * This program is free software; you can redistribute it and/or modify
    44.6 + * it under the terms of the GNU General Public License as published by
    44.7 + * the Free Software Foundation; either version 2 of the License, or
    44.8 + * (at your option) any later version.
    44.9 + *
   44.10 + * This program is distributed in the hope that it will be useful,
   44.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   44.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   44.13 + * GNU General Public License for more details.
   44.14 + *
   44.15 + * You should have received a copy of the GNU General Public License
   44.16 + * along with this program; if not, write to the Free Software
   44.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   44.18 + *
   44.19 + * Copyright (C) IBM Corp. 2005
   44.20 + *
   44.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   44.22 + */
   44.23 +
   44.24 +#include "ofh.h"
   44.25 +#include "xen/lib.h"
   44.26 +
   44.27 +s32
   44.28 +ofh_open(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
   44.29 +{
   44.30 +    if (nargs == 1) {
   44.31 +        if (nrets == 1) {
   44.32 +            const char *devspec = (const char *)(ulong)argp[0];
   44.33 +            s32 *ih = &retp[0];
   44.34 +            ofdn_t p;
   44.35 +            void *mem = ofd_mem(b);
   44.36 +
   44.37 +            p = ofd_node_find(mem, devspec);
   44.38 +            if (p > 0) {
   44.39 +                ofdn_t io;
   44.40 +                io = ofd_node_io(mem, p);
   44.41 +                if (io > 0) {
   44.42 +                    void *f = (void *)(ulong)ofd_io_open(mem, io);
   44.43 +                    if (f != 0) {
   44.44 +                        *ih = leap(b, 0, NULL, NULL,
   44.45 +                                   b, f);
   44.46 +                        return OF_SUCCESS;
   44.47 +                    }
   44.48 +                }
   44.49 +            }
   44.50 +            *ih = 0;
   44.51 +        }
   44.52 +    }
   44.53 +    return OF_FAILURE;
   44.54 +}
   44.55 +
   44.56 +s32
   44.57 +ofh_close(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
   44.58 +{
   44.59 +    if (nargs == 1) {
   44.60 +        if (nrets == 0) {
   44.61 +            argp = argp;
   44.62 +            retp = retp;
   44.63 +            b = b;
   44.64 +            return  OF_FAILURE;
   44.65 +        }
   44.66 +    }
   44.67 +    return OF_FAILURE;
   44.68 +}
   44.69 +s32
   44.70 +ofh_read(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
   44.71 +{
   44.72 +    if (nargs == 3) {
   44.73 +        if (nrets == 1) {
   44.74 +            struct ofh_ihandle *ih =
   44.75 +                (struct ofh_ihandle *)(ulong)argp[0];
   44.76 +
   44.77 +            if (ih->ofi_read != NULL) {
   44.78 +                void *addr = (void *)(ulong)argp[1];
   44.79 +                u32 sz = argp[2];
   44.80 +                s32 *actual = &retp[0];
   44.81 +                void *f = ih->ofi_read;
   44.82 +
   44.83 +                if (f != 0) {
   44.84 +                    return io_leap(ih->ofi_chan, addr, sz, actual,
   44.85 +                                b, f);
   44.86 +                }
   44.87 +            }
   44.88 +        }
   44.89 +    }
   44.90 +    return OF_FAILURE;
   44.91 +}
   44.92 +
   44.93 +s32
   44.94 +ofh_write(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
   44.95 +{
   44.96 +    if (nargs == 3) {
   44.97 +        if (nrets == 1) {
   44.98 +            struct ofh_ihandle *ih =
   44.99 +                (struct ofh_ihandle *)(ulong)argp[0];
  44.100 +
  44.101 +            if (ih->ofi_write != NULL) {
  44.102 +                void *addr = (void *)(ulong)argp[1];
  44.103 +                u32 sz = argp[2];
  44.104 +                s32 *actual = &retp[0];
  44.105 +                void *f = ih->ofi_write;
  44.106 +
  44.107 +                if (f != 0) {
  44.108 +                    return io_leap(ih->ofi_chan, addr, sz, actual,
  44.109 +                                b, f);
  44.110 +                }
  44.111 +            }
  44.112 +        }
  44.113 +    }
  44.114 +    return OF_FAILURE;
  44.115 +}
  44.116 +
  44.117 +s32
  44.118 +ofh_seek(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
  44.119 +{
  44.120 +    b=b;
  44.121 +    nargs = nargs;
  44.122 +    nrets = nrets;
  44.123 +    argp = argp;
  44.124 +    retp = retp;
  44.125 +    return OF_FAILURE;
  44.126 +}
  44.127 +
  44.128 +static ofh_func_t *
  44.129 +method_lookup(struct ofh_ihandle *ih, const char *name, ulong b)
  44.130 +{
  44.131 +    struct ofh_methods *m = DRELA(ih->ofi_methods, b);
  44.132 +
  44.133 +    while (m != NULL && m->ofm_name != NULL ) {
  44.134 +        if (strcmp(name, DRELA(m->ofm_name, b)) == 0) {
  44.135 +            return m->ofm_method;
  44.136 +        }
  44.137 +    }
  44.138 +    return NULL;
  44.139 +}
  44.140 +
  44.141 +
  44.142 +s32
  44.143 +ofh_call_method(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
  44.144 +{
  44.145 +    if (nargs > 2) {
  44.146 +        if (nrets > 1) {
  44.147 +            const char *method = (const char *)(ulong)argp[0];
  44.148 +            struct ofh_ihandle *ih =
  44.149 +                (struct ofh_ihandle *)(ulong)argp[1];
  44.150 +            ofh_func_t *f;
  44.151 +
  44.152 +            f = method_lookup(ih, method, b);
  44.153 +            if (f != NULL) {
  44.154 +                /* set catch methods return 0 on success */
  44.155 +                retp[0] = leap(nargs - 2, nrets - 1,
  44.156 +                               &argp[2], &retp[1], b, f);
  44.157 +                return OF_SUCCESS;
  44.158 +            }
  44.159 +        }
  44.160 +    }
  44.161 +    return OF_FAILURE;
  44.162 +}
  44.163 +
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/xen/arch/powerpc/of_handler/leap.S	Fri Jul 14 10:47:50 2006 +0100
    45.3 @@ -0,0 +1,38 @@
    45.4 +/*
    45.5 + * Copyright (C) 2005 Jimi Xenidis <jimix@watson.ibm.com>, IBM Corporation
    45.6 + *
    45.7 + * This program is free software; you can redistribute it and/or modify
    45.8 + * it under the terms of the GNU General Public License as published by
    45.9 + * the Free Software Foundation; either version 2 of the License, or
   45.10 + * (at your option) any later version.
   45.11 + * 
   45.12 + * This program is distributed in the hope that it will be useful,
   45.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   45.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   45.15 + * GNU General Public License for more details.
   45.16 + * 
   45.17 + * You should have received a copy of the GNU General Public License
   45.18 + * along with this program; if not, write to the Free Software
   45.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   45.20 + */
   45.21 +#include <asm/config.h>
   45.22 +#include <asm/processor.h>
   45.23 +
   45.24 +/* 
   45.25 + * sval
   45.26 + * rh_leap(uval nargs, uval nrets, uval args[], uval rets[], uval ba,
   45.27 + *		 rh_func_t f)
   45.28 + *    We need to deal with f actually bein a function descriptor, we can
   45.29 + *    assume that TOC is correct.
   45.30 + */	
   45.31 +
   45.32 +	
   45.33 +_GLOBAL(io_leap)	
   45.34 +_GLOBAL(leap)
   45.35 +	## r8 contains the base address for everyone
   45.36 +	add	r8,r8,r7 	# add
   45.37 +	ld	r8, 0(r8)	# get the entry point
   45.38 +	add	r8,r8,r7 	# add
   45.39 +	mtctr	r8		#     and
   45.40 +	bctr			#         leap
   45.41 +	/* never get here */
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/xen/arch/powerpc/of_handler/memcmp.c	Fri Jul 14 10:47:50 2006 +0100
    46.3 @@ -0,0 +1,39 @@
    46.4 +/*
    46.5 + * This program is free software; you can redistribute it and/or modify
    46.6 + * it under the terms of the GNU General Public License as published by
    46.7 + * the Free Software Foundation; either version 2 of the License, or
    46.8 + * (at your option) any later version.
    46.9 + *
   46.10 + * This program is distributed in the hope that it will be useful,
   46.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   46.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   46.13 + * GNU General Public License for more details.
   46.14 + *
   46.15 + * You should have received a copy of the GNU General Public License
   46.16 + * along with this program; if not, write to the Free Software
   46.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   46.18 + *
   46.19 + * Copyright (C) IBM Corp. 2005
   46.20 + *
   46.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   46.22 + */
   46.23 +
   46.24 +#include <xen/string.h>
   46.25 +
   46.26 +int
   46.27 +memcmp(const void *v1, const void *v2, size_t n)
   46.28 +{
   46.29 +    const char *s1 = (const char *)v1;
   46.30 +    const char *s2 = (const char *)v2;
   46.31 +
   46.32 +    while (n > 0) {
   46.33 +        if (*s1 != *s2) {
   46.34 +            return (*s1 - *s2);
   46.35 +        }
   46.36 +        /* advance pointers to next character */
   46.37 +        ++s1;
   46.38 +        ++s2;
   46.39 +        --n;
   46.40 +    }
   46.41 +    return 0;
   46.42 +}
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/xen/arch/powerpc/of_handler/memory.c	Fri Jul 14 10:47:50 2006 +0100
    47.3 @@ -0,0 +1,129 @@
    47.4 +/*
    47.5 + * This program is free software; you can redistribute it and/or modify
    47.6 + * it under the terms of the GNU General Public License as published by
    47.7 + * the Free Software Foundation; either version 2 of the License, or
    47.8 + * (at your option) any later version.
    47.9 + *
   47.10 + * This program is distributed in the hope that it will be useful,
   47.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   47.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   47.13 + * GNU General Public License for more details.
   47.14 + *
   47.15 + * You should have received a copy of the GNU General Public License
   47.16 + * along with this program; if not, write to the Free Software
   47.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   47.18 + *
   47.19 + * Copyright (C) IBM Corp. 2005
   47.20 + *
   47.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   47.22 + */
   47.23 +
   47.24 +#include "ofh.h"
   47.25 +
   47.26 +struct of_malloc_s {
   47.27 +    u32 ofm_start;
   47.28 +    u32 ofm_end;
   47.29 +};
   47.30 +static struct of_malloc_s claimed[64];
   47.31 +
   47.32 +static s32
   47.33 +claim(ulong b, u32 virt, u32 size, u32 align, s32 *baseaddr)
   47.34 +{
   47.35 +    struct of_malloc_s *cp;
   47.36 +    u32 i;
   47.37 +    s32 e;
   47.38 +    u32 end;
   47.39 +
   47.40 +    if (align != 0) {
   47.41 +        /* we don't do this now */
   47.42 +        return OF_FAILURE;
   47.43 +    }
   47.44 +
   47.45 +    end = virt + size;
   47.46 +
   47.47 +    /* you cannot claim OF's own space */
   47.48 +    if (virt >= (u32)ofh_start && end < (u32)_end) {
   47.49 +        return OF_FAILURE;
   47.50 +    }
   47.51 +
   47.52 +    cp = DRELA(&claimed[0], b);
   47.53 +    /* don't care about speed at the moment */
   47.54 +    e = -1;
   47.55 +    for (i = 0; i < sizeof (claimed)/sizeof (claimed[0]); i++) {
   47.56 +        if (cp[i].ofm_end == 0) {
   47.57 +            if (e == -1) {
   47.58 +                e = i;
   47.59 +            }
   47.60 +            continue;
   47.61 +        }
   47.62 +        if (virt >= cp[i].ofm_start && virt < cp[i].ofm_end) {
   47.63 +            return OF_FAILURE;
   47.64 +        }
   47.65 +        if (end >= cp[i].ofm_start && end < cp[i].ofm_end) {
   47.66 +            return OF_FAILURE;
   47.67 +        }
   47.68 +    }
   47.69 +    /* e points to the first empty */
   47.70 +    cp[e].ofm_start = virt;
   47.71 +    cp[e].ofm_end = end;
   47.72 +    *baseaddr = virt;
   47.73 +    return OF_SUCCESS;
   47.74 +}
   47.75 +
   47.76 +s32
   47.77 +ofh_claim(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
   47.78 +{
   47.79 +    if (nargs == 3) {
   47.80 +        if (nrets == 1) {
   47.81 +            u32 virt = argp[0];
   47.82 +            u32 size = argp[1];
   47.83 +            u32 align = argp[2];
   47.84 +            s32 *baseaddr = &retp[0];
   47.85 +
   47.86 +            return claim(b, virt, size, align, baseaddr);
   47.87 +        }
   47.88 +    }
   47.89 +    return OF_FAILURE;
   47.90 +}
   47.91 +
   47.92 +static s32
   47.93 +release(ulong b, u32 virt, u32 size)
   47.94 +{
   47.95 +    struct of_malloc_s *cp;
   47.96 +    u32 i;
   47.97 +    u32 end;
   47.98 +
   47.99 +    end = virt + size;
  47.100 +
  47.101 +    /* you cannot release OF's own space */
  47.102 +    if (virt >= (u32)ofh_start && end < (u32)_end) {
  47.103 +        return OF_FAILURE;
  47.104 +    }
  47.105 +
  47.106 +    cp = DRELA(&claimed[0], b);
  47.107 +    /* don't care about speed at the moment */
  47.108 +    for (i = 0; i < sizeof (claimed)/sizeof (claimed[0]); i++) {
  47.109 +        if (virt == cp[i].ofm_start && end == cp[i].ofm_end) {
  47.110 +            cp[i].ofm_start = 0;
  47.111 +            cp[i].ofm_end = 0;
  47.112 +            return OF_SUCCESS;
  47.113 +        }
  47.114 +    }
  47.115 +    return OF_FAILURE;
  47.116 +}
  47.117 +
  47.118 +s32
  47.119 +ofh_release(u32 nargs, u32 nrets, s32 argp[],
  47.120 +        s32 retp[] __attribute__ ((unused)),
  47.121 +        ulong b)
  47.122 +{
  47.123 +    if (nargs == 2) {
  47.124 +        if (nrets == 0) {
  47.125 +            u32 virt = argp[0];
  47.126 +            u32 size = argp[1];
  47.127 +
  47.128 +            return release(b, virt, size);
  47.129 +        }
  47.130 +    }
  47.131 +    return OF_FAILURE;
  47.132 +}
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/xen/arch/powerpc/of_handler/memset.c	Fri Jul 14 10:47:50 2006 +0100
    48.3 @@ -0,0 +1,67 @@
    48.4 +/*
    48.5 + * This program is free software; you can redistribute it and/or modify
    48.6 + * it under the terms of the GNU General Public License as published by
    48.7 + * the Free Software Foundation; either version 2 of the License, or
    48.8 + * (at your option) any later version.
    48.9 + *
   48.10 + * This program is distributed in the hope that it will be useful,
   48.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   48.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   48.13 + * GNU General Public License for more details.
   48.14 + *
   48.15 + * You should have received a copy of the GNU General Public License
   48.16 + * along with this program; if not, write to the Free Software
   48.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   48.18 + *
   48.19 + * Copyright (C) IBM Corp. 2005
   48.20 + *
   48.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   48.22 + */
   48.23 +
   48.24 +#include <xen/string.h>
   48.25 +
   48.26 +void *
   48.27 +memset(void *s, int c, size_t n)
   48.28 +{
   48.29 +    uint8_t *ss = (uint8_t *)s;
   48.30 +
   48.31 +    if (n == 0) {
   48.32 +        return s;
   48.33 +    }
   48.34 +
   48.35 +    /* yes, I pulled the 2 out of this air */
   48.36 +    if (n >= (2 * sizeof (ulong))) {
   48.37 +        ulong val = 0;
   48.38 +        ulong i;
   48.39 +
   48.40 +        /* construct val assignment from c */
   48.41 +        if (c != 0) {
   48.42 +            for (i = 0; i < sizeof (ulong); i++) {
   48.43 +                val = (val << 8) | c;
   48.44 +            }
   48.45 +        }
   48.46 +
   48.47 +        /* do by character until aligned */
   48.48 +        while (((ulong)ss & (sizeof (ulong) - 1)) > 0) {
   48.49 +            *ss = c;
   48.50 +            ++ss;
   48.51 +            --n;
   48.52 +        }
   48.53 +
   48.54 +        /* now do the aligned stores */
   48.55 +        while (n >= sizeof (ulong)) {
   48.56 +            *(ulong *)ss = val;
   48.57 +            ss += sizeof (ulong);
   48.58 +            n -= sizeof (ulong);
   48.59 +        }
   48.60 +    }
   48.61 +    /* do that last unaligned bit */
   48.62 +    while (n > 0) {
   48.63 +        *ss = c;
   48.64 +        ++ss;
   48.65 +        --n;
   48.66 +
   48.67 +    }          
   48.68 +
   48.69 +    return s;
   48.70 +}
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/xen/arch/powerpc/of_handler/ofh.c	Fri Jul 14 10:47:50 2006 +0100
    49.3 @@ -0,0 +1,454 @@
    49.4 +/*
    49.5 + * This program is free software; you can redistribute it and/or modify
    49.6 + * it under the terms of the GNU General Public License as published by
    49.7 + * the Free Software Foundation; either version 2 of the License, or
    49.8 + * (at your option) any later version.
    49.9 + *
   49.10 + * This program is distributed in the hope that it will be useful,
   49.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   49.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   49.13 + * GNU General Public License for more details.
   49.14 + *
   49.15 + * You should have received a copy of the GNU General Public License
   49.16 + * along with this program; if not, write to the Free Software
   49.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   49.18 + *
   49.19 + * Copyright (C) IBM Corp. 2005
   49.20 + *
   49.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   49.22 + */
   49.23 +
   49.24 +#include "ofh.h"
   49.25 +#include <stdarg.h>
   49.26 +#include <xen/lib.h>
   49.27 +
   49.28 +/*
   49.29 + * 6.3.1 Access to the client interface functions
   49.30 + * This is the spec'd maximum
   49.31 + */
   49.32 +#define PFW_MAXSRVCLEN 31
   49.33 +
   49.34 +static u32 ofh_maxsrvclen;
   49.35 +
   49.36 +extern s32 debug(const char *fmt, ...);
   49.37 +
   49.38 +s32 debug(const char *fmt, ...)
   49.39 +{
   49.40 +    s32 sz;
   49.41 +    va_list ap;
   49.42 +    char buf[512];
   49.43 +    va_start(ap, fmt);
   49.44 +    sz = vsnprintf(buf, 512, fmt, ap);
   49.45 +    va_end(ap);
   49.46 +    ofh_cons_write(buf, sz, &sz);
   49.47 +
   49.48 +    return sz;
   49.49 +}
   49.50 +
   49.51 +
   49.52 +
   49.53 +void
   49.54 +assprint(const char *expr, const char *file, int line, const char *fmt, ...)
   49.55 +{
   49.56 +    char a[15];
   49.57 +
   49.58 +    a[0]  = '\n';
   49.59 +    a[1]  = '\n';
   49.60 +    a[2]  = 'O';
   49.61 +    a[3]  = 'F';
   49.62 +    a[4]  = 'H';
   49.63 +    a[5]  = ':';
   49.64 +    a[6]  = 'A';
   49.65 +    a[7]  = 'S';
   49.66 +    a[8]  = 'S';
   49.67 +    a[9]  = 'E';
   49.68 +    a[10] = 'R';
   49.69 +    a[11] = 'T';
   49.70 +    a[12] = '!';
   49.71 +    a[13] = '\n';
   49.72 +    a[14] = '\n';
   49.73 +
   49.74 +    s32 actual;
   49.75 +    u32 t = 1;
   49.76 +    volatile u32 *tp = &t;
   49.77 +
   49.78 +    (void)expr; (void)file; (void)line; (void)fmt;
   49.79 +
   49.80 +    ofh_cons_write(a, sizeof (a), &actual);
   49.81 +
   49.82 +    /* maybe I can break out of this loop manually (like with a
   49.83 +     * debugger) */
   49.84 +    while (*tp) {
   49.85 +        continue;
   49.86 +    }
   49.87 +}
   49.88 +
   49.89 +/*
   49.90 + * we use elf hash since it is pretty standard
   49.91 + */
   49.92 +static u32
   49.93 +of_hash(const char *s)
   49.94 +{
   49.95 +    u32 hash = 0;
   49.96 +    u32 hnib;
   49.97 +
   49.98 +    if (s != NULL) {
   49.99 +        while (*s != '\0') {
  49.100 +            hash = (hash << 4) + *s++;
  49.101 +            hnib = hash & 0xf0000000UL;
  49.102 +            if (hnib != 0) {
  49.103 +                hash ^= hnib >> 24;
  49.104 +            }
  49.105 +            hash &= ~hnib;
  49.106 +        }
  49.107 +    }
  49.108 +    return hash;
  49.109 +}
  49.110 +
  49.111 +static void
  49.112 +ofh_service_init(ulong b)
  49.113 +{
  49.114 +    ulong sz;
  49.115 +    int i;
  49.116 +    int j = 0;
  49.117 +    struct ofh_srvc *o;
  49.118 +    struct ofh_srvc *ofs[] = {
  49.119 +        DRELA(&ofh_srvc[0], b),
  49.120 +        DRELA(&ofh_isa_srvc[0], b),
  49.121 +        NULL
  49.122 +    };
  49.123 +
  49.124 +    j = 0;
  49.125 +    while (ofs[j] != NULL) {
  49.126 +        /* find the maximum string length for services */
  49.127 +        o = &ofs[j][0];
  49.128 +        while (o->ofs_name != NULL) {
  49.129 +            const char *n;
  49.130 +
  49.131 +            n = DRELA(&o->ofs_name[0], b);
  49.132 +            /* fix it up so we don't have to fix it anymore */
  49.133 +            o->ofs_name = n;
  49.134 +
  49.135 +            sz = strlen(n);
  49.136 +            if (sz > *DRELA(&ofh_maxsrvclen, b)) {
  49.137 +                *DRELA(&ofh_maxsrvclen, b) = sz;
  49.138 +            }
  49.139 +            o->ofs_hash =
  49.140 +                of_hash(n);
  49.141 +            ++i;
  49.142 +            ++o;
  49.143 +        }
  49.144 +        ++j;
  49.145 +    }
  49.146 +}
  49.147 +
  49.148 +
  49.149 +static void
  49.150 +ofh_cpu_init(ofdn_t chosen, ulong b)
  49.151 +{
  49.152 +    static struct ofh_ihandle _ih_cpu_0;
  49.153 +    void *mem = ofd_mem(b);
  49.154 +    u32 ih = DRELA((ulong)&_ih_cpu_0, b);
  49.155 +    struct ofh_ihandle *ihp = (struct ofh_ihandle *)((ulong)ih);
  49.156 +    const char *cpu_type = DRELA((const char*)"cpu",b);
  49.157 +
  49.158 +    ofdn_t cpu = ofd_node_find_by_prop(mem, OFD_ROOT,
  49.159 +                                       DRELA((const char*)"device_type",b),
  49.160 +                                       cpu_type, 4);
  49.161 +    ihp->ofi_node = cpu;
  49.162 +    ofd_prop_add(mem, chosen, DRELA((const char *)"cpu", b),
  49.163 +                 &ih, sizeof (ih));
  49.164 +}
  49.165 +static s32
  49.166 +mmu_translate(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
  49.167 +{
  49.168 +    /* FIXME: need a little more here */
  49.169 +    nargs = nargs;
  49.170 +    nrets = nrets;
  49.171 +    argp = argp;
  49.172 +    retp = retp;
  49.173 +    b = b;
  49.174 +    return OF_SUCCESS;
  49.175 +}
  49.176 +
  49.177 +static void
  49.178 +ofh_mmu_init(ofdn_t chosen, ulong b)
  49.179 +{
  49.180 +    static struct ofh_methods _mmu_methods[] = {
  49.181 +        { "translate", mmu_translate },
  49.182 +        { NULL, NULL},
  49.183 +    };
  49.184 +    static struct ofh_ihandle _ih_mmu = {
  49.185 +        .ofi_methods = _mmu_methods,
  49.186 +    };
  49.187 +    void *mem = ofd_mem(b);
  49.188 +    u32 ih = DRELA((ulong)&_ih_mmu, b);
  49.189 +
  49.190 +    ofd_prop_add(mem, chosen, DRELA((const char *)"mmu", b),
  49.191 +                 &ih, sizeof (ih));
  49.192 +}
  49.193 +
  49.194 +static void
  49.195 +ofh_chosen_init(ulong b)
  49.196 +{
  49.197 +    ofdn_t ph;
  49.198 +    void *mem = ofd_mem(b);
  49.199 +
  49.200 +    ph = ofd_node_find(mem, DRELA((const char *)"/chosen", b));
  49.201 +
  49.202 +    ofh_vty_init(ph, b);
  49.203 +    ofh_cpu_init(ph, b);
  49.204 +    ofh_mmu_init(ph, b);
  49.205 +}
  49.206 +
  49.207 +static void
  49.208 +ofh_options_init(ulong b)
  49.209 +{
  49.210 +    void *mem = ofd_mem(b);
  49.211 +    ofdn_t options;
  49.212 +    u32 size = 1 << 20;
  49.213 +    u32 base = b;
  49.214 +    char buf[20];
  49.215 +    int i;
  49.216 +
  49.217 +
  49.218 +    /* fixup the ihandle */
  49.219 +    options = ofd_node_find(mem,
  49.220 +                            DRELA((const char *)"options", b));
  49.221 +
  49.222 +    i = snprintf(buf, sizeof (buf), "0x%x", base);
  49.223 +    ofd_prop_add(mem, options, DRELA((const char *)"real-base", b),
  49.224 +                 buf, i);
  49.225 +
  49.226 +    i = snprintf(buf,sizeof (buf), "0x%x", size);
  49.227 +    ofd_prop_add(mem, options, DRELA((const char *)"real-size", b),
  49.228 +                 buf, i);
  49.229 +}
  49.230 +
  49.231 +static void
  49.232 +ofh_init(ulong b)
  49.233 +{
  49.234 +    ulong sz = (ulong)_end - (ulong)__bss_start;
  49.235 +    /* clear bss */
  49.236 +    memset(__bss_start + b, 0, sz);
  49.237 +
  49.238 +    ofh_service_init(b);
  49.239 +    ofh_chosen_init(b);
  49.240 +    ofh_options_init(b);
  49.241 +}
  49.242 +
  49.243 +static ofh_func_t *
  49.244 +ofh_lookup(const char *service, ulong b)
  49.245 +{
  49.246 +    int j;
  49.247 +    u32 hash;
  49.248 +    struct ofh_srvc *o;
  49.249 +    struct ofh_srvc *ofs[] = {
  49.250 +        DRELA(&ofh_srvc[0], b),
  49.251 +        DRELA(&ofh_isa_srvc[0], b),
  49.252 +        NULL
  49.253 +    };
  49.254 +    u32 sz;
  49.255 +
  49.256 +    sz = *DRELA(&ofh_maxsrvclen, b);
  49.257 +
  49.258 +    if (strnlen(service, sz + 1) > sz) {
  49.259 +        return NULL;
  49.260 +    }
  49.261 +
  49.262 +    hash = of_hash(service);
  49.263 +
  49.264 +    j = 0;
  49.265 +    while (ofs[j] != NULL) {
  49.266 +        /* yes this could be quicker */
  49.267 +        o = &ofs[j][0];
  49.268 +        while (o->ofs_name != NULL) {
  49.269 +            if (o->ofs_hash == hash) {
  49.270 +                const char *n = o->ofs_name;
  49.271 +                if (strcmp(service, n) == 0) {
  49.272 +                    return o->ofs_func;
  49.273 +                }
  49.274 +            }
  49.275 +            ++o;
  49.276 +        }
  49.277 +        ++j;
  49.278 +    }
  49.279 +    return NULL;
  49.280 +}
  49.281 +
  49.282 +s32
  49.283 +ofh_nosup(u32 nargs __attribute__ ((unused)),
  49.284 +        u32 nrets __attribute__ ((unused)),
  49.285 +        s32 argp[] __attribute__ ((unused)),
  49.286 +        s32 retp[] __attribute__ ((unused)),
  49.287 +        ulong b __attribute__ ((unused)))
  49.288 +{
  49.289 +    return OF_FAILURE;
  49.290 +}
  49.291 +
  49.292 +s32
  49.293 +ofh_test_method(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
  49.294 +{
  49.295 +    if (nargs == 2) {
  49.296 +        if (nrets == 1) {
  49.297 +            s32 *ap = DRELA(&ofh_active_package, b);
  49.298 +            u32 service = (s32)argp[0];
  49.299 +            const char *method = (const char *)(ulong)argp[1];
  49.300 +            s32 *stat = &retp[0];
  49.301 +
  49.302 +            (void)ap; (void)service; (void)method;
  49.303 +
  49.304 +            *stat = 0;
  49.305 +            /* we do not do this yet */
  49.306 +            return OF_FAILURE;
  49.307 +        }
  49.308 +    }
  49.309 +    return OF_FAILURE;
  49.310 +}
  49.311 +extern u32 _ofh_inited[0];
  49.312 +extern u32 _ofh_lastarg[0];
  49.313 +
  49.314 +s32
  49.315 +ofh_handler(struct ofh_args *args, ulong b)
  49.316 +{
  49.317 +    u32 *inited = (u32 *)DRELA(&_ofh_inited[0],b);
  49.318 +    u32 *lastarg = (u32 *)DRELA(&_ofh_lastarg[0],b);
  49.319 +    ofh_func_t *f;
  49.320 +
  49.321 +    if (*inited == 0) {
  49.322 +        ofh_init(b);
  49.323 +
  49.324 +        if ((ulong)ofd_mem(b) < (ulong)_end + b) {
  49.325 +            static const char msg[] = "PANIC: OFD and BSS collide\n";
  49.326 +            s32 dummy;
  49.327 +
  49.328 +            ofh_cons_write(DRELA(&msg[0], b), sizeof (msg), &dummy);
  49.329 +            for (;;);
  49.330 +        }
  49.331 +
  49.332 +        *inited = 1;
  49.333 +    }
  49.334 +
  49.335 +    *lastarg = (ulong)args;
  49.336 +
  49.337 +    f = ofh_lookup((char *)((ulong)args->ofa_service), b);
  49.338 +
  49.339 +    if (f == ((ofh_func_t *)~0UL)) {
  49.340 +        /* do test */
  49.341 +        if (args->ofa_nargs == 1) {
  49.342 +            if (args->ofa_nreturns == 1) {
  49.343 +                char *name = (char *)(ulong)args->ofa_args[0];
  49.344 +                if (ofh_lookup(name, b) != NULL) {
  49.345 +                    args->ofa_args[args->ofa_nargs] =
  49.346 +                        OF_SUCCESS;
  49.347 +                    return OF_SUCCESS;
  49.348 +                }
  49.349 +            }
  49.350 +        }
  49.351 +        return OF_FAILURE;
  49.352 +
  49.353 +    } else if (f != NULL) {
  49.354 +        return leap(args->ofa_nargs,
  49.355 +                    args->ofa_nreturns,
  49.356 +                    args->ofa_args,
  49.357 +                    &args->ofa_args[args->ofa_nargs],
  49.358 +                    b, f);
  49.359 +    }
  49.360 +    return OF_FAILURE;
  49.361 +}
  49.362 +
  49.363 +/*
  49.364 + * The following code exists solely to run the handler code standalone
  49.365 + */
  49.366 +void
  49.367 +__ofh_start(void)
  49.368 +{
  49.369 +    s32 ret;
  49.370 +    u32 of_stdout;
  49.371 +    u32 ihandle;
  49.372 +    char buf[1024];
  49.373 +    u32 args_buf[sizeof (struct ofh_args) + (sizeof (u32) * 10)];
  49.374 +    struct ofh_args *args;
  49.375 +
  49.376 +    args = (struct ofh_args *)args_buf;
  49.377 +
  49.378 +    args->ofa_service = (u32)"finddevice";
  49.379 +    args->ofa_nargs     = 1;
  49.380 +    args->ofa_nreturns  = 1;
  49.381 +    args->ofa_args[0]   = (u32)"/";
  49.382 +    args->ofa_args[1]   = -1;
  49.383 +    ret = ofh_start(args);
  49.384 +
  49.385 +    if (ret == OF_SUCCESS) {
  49.386 +        args->ofa_service   = (u32)"finddevice";
  49.387 +        args->ofa_nargs     = 1;
  49.388 +        args->ofa_nreturns  = 1;
  49.389 +        args->ofa_args[0]   = (u32)"/chosen";
  49.390 +        args->ofa_args[1]   = -1;
  49.391 +        ret = ofh_start(args);
  49.392 +    }
  49.393 +
  49.394 +    if (ret == OF_SUCCESS) {
  49.395 +        u32 phandle = args->ofa_args[1];
  49.396 +
  49.397 +        args->ofa_service   = (u32)"getprop";
  49.398 +        args->ofa_nargs     = 4;
  49.399 +        args->ofa_nreturns  = 1;
  49.400 +        args->ofa_args[0]   = phandle;
  49.401 +        args->ofa_args[1]   = (ulong)"stdout";
  49.402 +        args->ofa_args[2]   = (ulong)&of_stdout;
  49.403 +        args->ofa_args[3]   = sizeof(of_stdout);
  49.404 +        args->ofa_args[4]   = -1;
  49.405 +        ret = ofh_start(args);
  49.406 +    }
  49.407 +
  49.408 +    ihandle = *(u32 *)((ulong)args->ofa_args[2]);
  49.409 +
  49.410 +    if (ret == OF_SUCCESS) {
  49.411 +        /* instance to path */
  49.412 +        args->ofa_service   = (u32)"instance-to-path";
  49.413 +        args->ofa_nargs     = 3;
  49.414 +        args->ofa_nreturns  = 1;
  49.415 +        args->ofa_args[0]   = ihandle;
  49.416 +        args->ofa_args[1]   = (ulong)buf;
  49.417 +        args->ofa_args[2]   = sizeof (buf);
  49.418 +        args->ofa_args[3]   = -1;
  49.419 +        ret = ofh_start(args);
  49.420 +
  49.421 +    }
  49.422 +
  49.423 +    if (ret == OF_SUCCESS) {
  49.424 +        /* open rtas */
  49.425 +        args->ofa_service   = (u32)"open";
  49.426 +        args->ofa_nargs     = 1;
  49.427 +        args->ofa_nreturns  = 1;
  49.428 +        args->ofa_args[0]   = (u32)"/rtas";
  49.429 +        ret = ofh_start(args);
  49.430 +        if (ret == OF_SUCCESS) {
  49.431 +            u32 ir = args->ofa_args[1];
  49.432 +            args->ofa_service   = (u32)"call-method";
  49.433 +            args->ofa_nargs     = 3;
  49.434 +            args->ofa_nreturns  = 2;
  49.435 +            args->ofa_args[0]   = (ulong)"instantiate-rtas";
  49.436 +            args->ofa_args[1]   = ir;
  49.437 +            args->ofa_args[2]   = (ulong)buf;
  49.438 +
  49.439 +            ret = ofh_start(args);
  49.440 +        }
  49.441 +    }
  49.442 +
  49.443 +    if (ret == OF_SUCCESS) {
  49.444 +        const char msg[] = "This is a test";
  49.445 +        u32 msgsz = sizeof(msg) - 1; /* Includes \0 */
  49.446 +
  49.447 +        args->ofa_service   = (u32)"write";
  49.448 +        args->ofa_nargs     = 3;
  49.449 +        args->ofa_nreturns  = 1;
  49.450 +        args->ofa_args[0]   = ihandle;
  49.451 +        args->ofa_args[1]   = (ulong)msg;
  49.452 +        args->ofa_args[2]   = msgsz;
  49.453 +        args->ofa_args[3]   = -1;
  49.454 +        ret = ofh_start(args);
  49.455 +    }
  49.456 +
  49.457 +}
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/xen/arch/powerpc/of_handler/ofh.h	Fri Jul 14 10:47:50 2006 +0100
    50.3 @@ -0,0 +1,164 @@
    50.4 +/*
    50.5 + * This program is free software; you can redistribute it and/or modify
    50.6 + * it under the terms of the GNU General Public License as published by
    50.7 + * the Free Software Foundation; either version 2 of the License, or
    50.8 + * (at your option) any later version.
    50.9 + *
   50.10 + * This program is distributed in the hope that it will be useful,
   50.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   50.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   50.13 + * GNU General Public License for more details.
   50.14 + *
   50.15 + * You should have received a copy of the GNU General Public License
   50.16 + * along with this program; if not, write to the Free Software
   50.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   50.18 + *
   50.19 + * Copyright (C) IBM Corp. 2005
   50.20 + *
   50.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   50.22 + */
   50.23 +
   50.24 +#ifndef _PFW_H
   50.25 +#define _PFW_H
   50.26 +
   50.27 +#include <xen/types.h>
   50.28 +#include <public/xencomm.h>
   50.29 +#include <public/io/console.h>
   50.30 +#include <of-devtree.h>
   50.31 +
   50.32 +#define MIN(x,y) (((x)<(y))?(x):(y))
   50.33 +
   50.34 +#define PAGE_SHIFT 12
   50.35 +#define PAGE_SIZE (1UL<<PAGE_SHIFT)
   50.36 +
   50.37 +struct ofh_args {
   50.38 +    u32 ofa_service;
   50.39 +    u32 ofa_nargs;
   50.40 +    u32 ofa_nreturns;
   50.41 +    s32 ofa_args[0];
   50.42 +};
   50.43 +
   50.44 +typedef s32 (ofh_func_t)(u32, u32, s32 [], s32 [], ulong b);
   50.45 +
   50.46 +struct ofh_srvc {
   50.47 +    const char *ofs_name;
   50.48 +    ofh_func_t *ofs_func;
   50.49 +    u32 ofs_hash;
   50.50 +};
   50.51 +
   50.52 +extern ofh_func_t ofh_test_method;
   50.53 +extern ofh_func_t ofh_nosup;
   50.54 +
   50.55 +/* device tree */
   50.56 +extern ofh_func_t ofh_peer;
   50.57 +extern ofh_func_t ofh_child;
   50.58 +extern ofh_func_t ofh_parent;
   50.59 +extern ofh_func_t ofh_instance_to_package;
   50.60 +extern ofh_func_t ofh_getproplen;
   50.61 +extern ofh_func_t ofh_getprop;
   50.62 +extern ofh_func_t ofh_nextprop;
   50.63 +extern ofh_func_t ofh_setprop;
   50.64 +extern ofh_func_t ofh_canon;
   50.65 +extern ofh_func_t ofh_finddevice;
   50.66 +extern ofh_func_t ofh_instance_to_path;
   50.67 +extern ofh_func_t ofh_package_to_path;
   50.68 +extern ofh_func_t ofh_call_method;
   50.69 +
   50.70 +/* IO */
   50.71 +extern ofh_func_t ofh_open;
   50.72 +extern ofh_func_t ofh_close;
   50.73 +extern ofh_func_t ofh_read;
   50.74 +extern ofh_func_t ofh_write;
   50.75 +extern ofh_func_t ofh_seek;
   50.76 +
   50.77 +/* memory */
   50.78 +extern ofh_func_t ofh_claim;
   50.79 +extern ofh_func_t ofh_release;
   50.80 +
   50.81 +/* control */
   50.82 +extern ofh_func_t ofh_boot;
   50.83 +extern ofh_func_t ofh_enter;
   50.84 +extern ofh_func_t ofh_exit; /* __attribute__ ((noreturn)); */
   50.85 +extern ofh_func_t ofh_chain;
   50.86 +extern ofh_func_t ofh_quiesce;
   50.87 +
   50.88 +extern struct ofh_srvc ofh_srvc[];
   50.89 +extern struct ofh_srvc ofh_isa_srvc[];
   50.90 +extern s32 ofh_active_package;
   50.91 +
   50.92 +struct ofh_methods {
   50.93 +    const char *ofm_name;
   50.94 +    ofh_func_t *ofm_method;
   50.95 +};
   50.96 +
   50.97 +struct ofh_ihandle {
   50.98 +    s32 (*ofi_close)(void);
   50.99 +    s32 (*ofi_read)(s32 chan, void *buf, u32 count, s32 *actual, ulong b);
  50.100 +    s32 (*ofi_write)(s32 chan, const void *buf, u32 count, s32 *actual,
  50.101 +                     ulong b);
  50.102 +    s32 (*ofi_seek)(u32 pos_hi, u32 pos_lo, u32 *status);
  50.103 +    struct ofh_methods *ofi_methods;
  50.104 +    struct xencons_interface *ofi_intf;
  50.105 +    s32 ofi_node;
  50.106 +    s32 ofi_chan;
  50.107 +};
  50.108 +
  50.109 +struct ofh_imem {
  50.110 +    s32 (*ofi_xlate)(void *addr, u32 ret[4]);
  50.111 +};
  50.112 +
  50.113 +
  50.114 +enum prop_type {
  50.115 +    pt_byte_array,
  50.116 +    pt_value,
  50.117 +    pt_string,
  50.118 +    pt_composite,
  50.119 +    /* these are for our own use */
  50.120 +    pt_func,
  50.121 +};
  50.122 +
  50.123 +extern s32 ofh_start(struct ofh_args *);
  50.124 +
  50.125 +#define OFH_CONS_XEN -1
  50.126 +extern void ofh_cons_init(struct ofh_ihandle *ihp, ulong b);
  50.127 +extern s32 ofh_cons_read(s32 chan, void *buf, u32 count, s32 *actual);
  50.128 +extern s32 ofh_cons_write(const void *buf, u32 count, s32 *actual);
  50.129 +extern s32 ofh_cons_close(void);
  50.130 +extern s32 ofh_handler(struct ofh_args *args, ulong ifh_base);
  50.131 +extern s32 leap(u32 nargs, u32 nrets, s32 args[], s32 rets[],
  50.132 +                ulong ba, void *f);
  50.133 +
  50.134 +extern s32 io_leap(s32 chan, void *buf, u32 sz, s32 *actual,
  50.135 +                ulong ba, void *f);
  50.136 +
  50.137 +extern void ofh_vty_init(ofdn_t chosen, ulong b);
  50.138 +extern void ofh_rtas_init(ulong b);
  50.139 +
  50.140 +extern void *_ofh_tree;
  50.141 +
  50.142 +#if 1
  50.143 +#define DRELA(p,b) ((__typeof__ (p))((((ulong)(p)) + (b))))
  50.144 +#else
  50.145 +#define DRELA(p,b) (b == b ? p : 0)
  50.146 +#endif
  50.147 +extern ulong get_base(void);
  50.148 +
  50.149 +static inline void *ofd_mem(ulong base) { return *DRELA(&_ofh_tree, base); }
  50.150 +
  50.151 +extern ofh_func_t ofh_start_cpu;
  50.152 +extern ofh_func_t ofh_stop_self;
  50.153 +extern ofh_func_t ofh_idle_self;
  50.154 +extern ofh_func_t ofh_resume_cpu;
  50.155 +
  50.156 +/* In Open Firmware, we only use xencomm for reading/writing console data.
  50.157 + * Since that's always small, we can use this fixed-size structure. */
  50.158 +#define XENCOMM_MINI_ADDRS 3
  50.159 +struct xencomm_mini {
  50.160 +    struct xencomm_desc _desc;
  50.161 +    u64 address[XENCOMM_MINI_ADDRS];
  50.162 +};
  50.163 +
  50.164 +extern int xencomm_create_mini(void *area, int arealen, void *buffer,
  50.165 +            unsigned long bytes, struct xencomm_desc **ret);
  50.166 +
  50.167 +#endif
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/xen/arch/powerpc/of_handler/papr.S	Fri Jul 14 10:47:50 2006 +0100
    51.3 @@ -0,0 +1,97 @@
    51.4 +/*
    51.5 + * Copyright (C) 2005 Jimi Xenidis <jimix@watson.ibm.com>, IBM Corporation
    51.6 + *
    51.7 + * This program is free software; you can redistribute it and/or modify
    51.8 + * it under the terms of the GNU General Public License as published by
    51.9 + * the Free Software Foundation; either version 2 of the License, or
   51.10 + * (at your option) any later version.
   51.11 + * 
   51.12 + * This program is distributed in the hope that it will be useful,
   51.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   51.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   51.15 + * GNU General Public License for more details.
   51.16 + * 
   51.17 + * You should have received a copy of the GNU General Public License
   51.18 + * along with this program; if not, write to the Free Software
   51.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   51.20 + */
   51.21 +
   51.22 +#include <asm/config.h>
   51.23 +#include <asm/processor.h>
   51.24 +#include <asm/papr.h>
   51.25 +#include <asm/asm-offsets.h>
   51.26 +
   51.27 +#define HSC	.long 0x44000022
   51.28 +
   51.29 +	
   51.30 +/* in is unsused */
   51.31 +#define PAPR(in, out, name, func_code)	\
   51.32 +	_GLOBAL(name);	 		\
   51.33 +	std r3,-GPR_WIDTH(r1); 		\
   51.34 +	li r3,func_code; 		\
   51.35 +	HSC;				\
   51.36 +	ld r12,-GPR_WIDTH(r1);		\
   51.37 +	cmpi 0,r12,0;			\
   51.38 +        bne ret	## out;	/* only store regs if r12 != NULL */ \
   51.39 +	b ret0
   51.40 +
   51.41 +ret8:	std r11, 7 * GPR_WIDTH(r12)
   51.42 +ret7:	std r10, 6 * GPR_WIDTH(r12)
   51.43 +ret6:	std r9, 5 * GPR_WIDTH(r12)
   51.44 +ret5:	std r8, 4 * GPR_WIDTH(r12)
   51.45 +ret4:	std r7, 3 * GPR_WIDTH(r12)
   51.46 +ret3:	std r6, 2 * GPR_WIDTH(r12)
   51.47 +ret2:	std r5, 1 * GPR_WIDTH(r12)
   51.48 +ret1:	std r4, 0 * GPR_WIDTH(r12)
   51.49 +	nop
   51.50 +ret0:	blr
   51.51 +	
   51.52 +PAPR(5, 2,papr_remove, H_REMOVE)
   51.53 +PAPR(5, 1,papr_clear_mod, H_CLEAR_MOD)
   51.54 +PAPR(5, 1,papr_clear_ref, H_CLEAR_REF)
   51.55 +PAPR(5, 0,papr_protect, H_PROTECT)
   51.56 +PAPR(1, 0,papr_eoi, H_EOI)
   51.57 +PAPR(5, 1,papr_cppr, H_CPPR)
   51.58 +PAPR(5, 2,papr_ipi, H_IPI)
   51.59 +PAPR(5, 1,papr_ipoll, H_IPOLL)
   51.60 +PAPR(5, 1,papr_xirr, H_XIRR)
   51.61 +PAPR(2, 0,papr_interrupt, H_INTERRUPT)
   51.62 +PAPR(5, 1,papr_logical_ci_load_64, H_LOGICAL_CI_LOAD)
   51.63 +PAPR(5, 0,papr_logical_ci_store_64, H_LOGICAL_CI_STORE)
   51.64 +PAPR(5, 1,papr_logical_cache_load_64, H_LOGICAL_CACHE_LOAD)
   51.65 +PAPR(5, 0,papr_logical_cache_store_64, H_LOGICAL_CACHE_STORE)
   51.66 +PAPR(5, 0,papr_logical_icbi, H_LOGICAL_ICBI)
   51.67 +PAPR(5, 0,papr_logical_dcbf, H_LOGICAL_DCBF)
   51.68 +PAPR(5, 1,papr_set_dabr, H_SET_DABR)
   51.69 +PAPR(5, 1,papr_real_to_logical, H_REAL_TO_LOGICAL)
   51.70 +PAPR(5, 1,papr_pci_config_read, H_PCI_CONFIG_READ)
   51.71 +PAPR(5, 0,papr_pci_config_write, H_PCI_CONFIG_WRITE)
   51.72 +
   51.73 +	PAPR(5, 1,papr_grant_logical, H_GRANT_LOGICAL)
   51.74 +PAPR(1, 1,papr_accept_logical, H_ACCEPT_LOGICAL)
   51.75 +PAPR(0, 2,papr_rescind_logical, H_RESCIND_LOGICAL)
   51.76 +PAPR(3, 0,papr_register_vterm, H_REGISTER_VTERM)
   51.77 +PAPR(4, 0,papr_vterm_partner_info, H_VTERM_PARTNER_INFO)
   51.78 +PAPR(1, 0,papr_free_vterm, H_FREE_VTERM)
   51.79 +
   51.80 +/* Definitions for hypervisor functions. Note that we do not use the
   51.81 + * first macro arg */
   51.82 +
   51.83 +PAPR(x, 1,papr_enter, H_ENTER)
   51.84 +PAPR(x, 8,papr_read, H_READ)
   51.85 +PAPR(x, 1,papr_thread_control, H_THREAD_CONTROL)
   51.86 +PAPR(x, 0,papr_cede, H_CEDE)
   51.87 +
   51.88 +PAPR(x, 0,papr_page_init, H_PAGE_INIT)
   51.89 +PAPR(x, 1,papr_set_asr, H_SET_ASR)  /* ISTAR only. */
   51.90 +PAPR(x, 0,papr_asr_on, H_ASR_ON)  /* ISTAR only. */
   51.91 +PAPR(x, 0,papr_asr_off, H_ASR_OFF)  /* ISTAR only. */
   51.92 +
   51.93 +PAPR(x, 8,papr_hypervisor_data, H_HYPERVISOR_DATA)
   51.94 +
   51.95 +PAPR(x, 2,papr_get_xive, H_GET_XIVE)
   51.96 +PAPR(x, 0,papr_set_xive, H_SET_XIVE)
   51.97 +
   51.98 +
   51.99 +PAPR(x, 0,papr_put_term_char, H_PUT_TERM_CHAR)
  51.100 +PAPR(x, 3,papr_get_term_char, H_GET_TERM_CHAR)
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/xen/arch/powerpc/of_handler/papr.h	Fri Jul 14 10:47:50 2006 +0100
    52.3 @@ -0,0 +1,69 @@
    52.4 +/*
    52.5 + * This program is free software; you can redistribute it and/or modify
    52.6 + * it under the terms of the GNU General Public License as published by
    52.7 + * the Free Software Foundation; either version 2 of the License, or
    52.8 + * (at your option) any later version.
    52.9 + *
   52.10 + * This program is distributed in the hope that it will be useful,
   52.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   52.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   52.13 + * GNU General Public License for more details.
   52.14 + *
   52.15 + * You should have received a copy of the GNU General Public License
   52.16 + * along with this program; if not, write to the Free Software
   52.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   52.18 + *
   52.19 + * Copyright (C) IBM Corp. 2005
   52.20 + *
   52.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   52.22 + */
   52.23 +
   52.24 +#ifndef _OFH_PAPR_H
   52.25 +#define _OFH_PAPR_H
   52.26 +
   52.27 +#include <asm/papr.h>
   52.28 +
   52.29 +#ifndef __ASSEMBLY__
   52.30 +
   52.31 +extern long papr_enter(ulong *retvals, ulong flags, ulong idx, ...);
   52.32 +extern long papr_read(ulong *retvals, ulong flags, ulong idx);
   52.33 +extern long papr_remove(ulong *retvals, ulong flags, ulong pte_index,
   52.34 +        ulong avpn);
   52.35 +extern long papr_clear_mod(ulong *retvals, ulong flags, ulong pte_index);
   52.36 +extern long papr_clear_ref(ulong *retvals, ulong flags, ulong pte_index);
   52.37 +extern long papr_protect(ulong *retvals, ulong flags, ulong pte_index,
   52.38 +        ulong avpn);
   52.39 +extern long papr_get_term_char(ulong *retvals, ulong idx);
   52.40 +extern long papr_put_term_char(ulong *retvals, ulong idx, ulong count, ...);
   52.41 +extern long papr_register_vterm(ulong *retvals, ulong ua, ulong plpid, ulong pua);
   52.42 +extern long papr_vterm_partner_info(ulong *retvals, ulong ua, ulong plpid,
   52.43 +        ulong pua, ulong lpage);
   52.44 +extern long papr_free_vterm(ulong *retvals, ulong uaddr);
   52.45 +
   52.46 +extern long papr_cede(ulong *retvals);
   52.47 +extern long papr_page_init(ulong *retvals, ulong flags,
   52.48 +        ulong destination, ulong source);
   52.49 +extern long papr_set_asr(ulong *retvals, ulong value); /* ISTAR only. */
   52.50 +extern long papr_asr_on(ulong *retvals); /* ISTAR only. */
   52.51 +extern long papr_asr_off(ulong *retvals); /* ISTAR only. */
   52.52 +extern long papr_eoi(ulong *retvals, ulong xirr);
   52.53 +extern long papr_cppr(ulong *retvals, ulong cppr);
   52.54 +extern long papr_ipi(ulong *retvals, ulong sn, ulong mfrr);
   52.55 +extern long papr_ipoll(ulong *retvals, ulong sn);
   52.56 +extern long papr_xirr(ulong *retvals);
   52.57 +extern long papr_logical_ci_load_64(ulong *retvals, ulong size,
   52.58 +        ulong addrAndVal);
   52.59 +extern long papr_logical_ci_store_64(ulong *retvals, ulong size,
   52.60 +        ulong addr, ulong value);
   52.61 +extern long papr_logical_cache_load_64(ulong *retvals, ulong size,
   52.62 +        ulong addrAndVal);
   52.63 +extern long papr_logical_cache_store_64(ulong *retvals, ulong size,
   52.64 +        ulong addr, ulong value);
   52.65 +extern long papr_logical_icbi(ulong *retvals, ulong addr);
   52.66 +extern long papr_logical_dcbf(ulong *retvals, ulong addr);
   52.67 +extern long papr_set_dabr(ulong *retvals, ulong dabr);
   52.68 +extern long papr_hypervisor_data(ulong *retvals, u64 control);
   52.69 +extern long papr_real_to_logical(ulong *retvals, ulong raddr);
   52.70 +
   52.71 +#endif /* ! __ASSEMBLY__ */
   52.72 +#endif /* ! _OFH_PAPR_H */
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/xen/arch/powerpc/of_handler/services.c	Fri Jul 14 10:47:50 2006 +0100
    53.3 @@ -0,0 +1,96 @@
    53.4 +/*
    53.5 + * This program is free software; you can redistribute it and/or modify
    53.6 + * it under the terms of the GNU General Public License as published by
    53.7 + * the Free Software Foundation; either version 2 of the License, or
    53.8 + * (at your option) any later version.
    53.9 + *
   53.10 + * This program is distributed in the hope that it will be useful,
   53.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   53.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   53.13 + * GNU General Public License for more details.
   53.14 + *
   53.15 + * You should have received a copy of the GNU General Public License
   53.16 + * along with this program; if not, write to the Free Software
   53.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   53.18 + *
   53.19 + * Copyright (C) IBM Corp. 2005
   53.20 + *
   53.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   53.22 + */
   53.23 +
   53.24 +#include "ofh.h"
   53.25 +
   53.26 +/*
   53.27 + * These are ISA independent OF services
   53.28 + */
   53.29 +
   53.30 +struct ofh_srvc ofh_srvc[] = {
   53.31 +    /* Document Section 6.3.2.1 Client Interface */
   53.32 +    { .ofs_name = "test", .ofs_func = ((ofh_func_t *)~0UL) },
   53.33 +    { .ofs_name = "test-method", .ofs_func = ofh_test_method },
   53.34 +
   53.35 +    /* Document Section 6.3.2.2 Device Tree */
   53.36 +    { .ofs_name = "peer", .ofs_func = ofh_peer },
   53.37 +    { .ofs_name = "child", .ofs_func = ofh_child },
   53.38 +    { .ofs_name = "parent", .ofs_func = ofh_parent },
   53.39 +    { .ofs_name = "instance-to-package",
   53.40 +      .ofs_func = ofh_instance_to_package },
   53.41 +    { .ofs_name = "getproplen", .ofs_func = ofh_getproplen },
   53.42 +    { .ofs_name = "getprop", .ofs_func = ofh_getprop },
   53.43 +    { .ofs_name = "nextprop", .ofs_func = ofh_nextprop },
   53.44 +    { .ofs_name = "setprop", .ofs_func = ofh_setprop },
   53.45 +    { .ofs_name = "canon", .ofs_func = ofh_canon },
   53.46 +    { .ofs_name = "finddevice", .ofs_func = ofh_finddevice },
   53.47 +    { .ofs_name = "instance-to-path", .ofs_func = ofh_instance_to_path },
   53.48 +    { .ofs_name = "package-to-path", .ofs_func = ofh_package_to_path },
   53.49 +    { .ofs_name = "call-method", .ofs_func = ofh_call_method },
   53.50 +
   53.51 +    /* Document Section 6.3.2.3 Device I/O */
   53.52 +    { .ofs_name = "open", .ofs_func = ofh_open },
   53.53 +    { .ofs_name = "close", .ofs_func = ofh_close },
   53.54 +    { .ofs_name = "read", .ofs_func = ofh_read },
   53.55 +    { .ofs_name = "write", .ofs_func = ofh_write },
   53.56 +    { .ofs_name = "seek", .ofs_func = ofh_seek },
   53.57 +
   53.58 +    /* Document Section 6.3.2.4 Memory */
   53.59 +    { .ofs_name = "claim", .ofs_func = ofh_claim },
   53.60 +    { .ofs_name = "release", .ofs_func = ofh_release },
   53.61 +
   53.62 +    /* Document Section 6.3.2.5 Control Transfer */
   53.63 +    { .ofs_name = "boot", .ofs_func = ofh_boot },
   53.64 +    { .ofs_name = "enter", .ofs_func = ofh_enter },
   53.65 +    { .ofs_name = "exit", .ofs_func = ofh_exit },
   53.66 +    { .ofs_name = "chain", .ofs_func = ofh_chain },
   53.67 +    { .ofs_name = "quiesce", .ofs_func = ofh_quiesce },
   53.68 +
   53.69 +    /* Document Section 6.3.2.6 User Interface */
   53.70 +    { .ofs_name = "interpret", .ofs_func = ofh_nosup },
   53.71 +    { .ofs_name = "set-callback", .ofs_func = ofh_nosup },
   53.72 +    { .ofs_name = "set-symbol-lookup", .ofs_func = ofh_nosup },
   53.73 +
   53.74 +    /* Document Section 6.3.2.7 Time */
   53.75 +    { .ofs_name = "milliseconds", .ofs_func = ofh_nosup },
   53.76 +    { .ofs_name = NULL, .ofs_func = NULL}
   53.77 +};
   53.78 +
   53.79 +/*
   53.80 + * These are services particular to poweprc 32/64
   53.81 + */
   53.82 +
   53.83 +struct ofh_srvc ofh_isa_srvc[] = {
   53.84 +    /* Document Section 8.5.1 Real-Mode physical memory ... */
   53.85 +    { .ofs_name = "alloc-real_mem", .ofs_func = ofh_nosup },
   53.86 +
   53.87 +    /* Document Section 8.5.2 Virtual address translation ... */
   53.88 +    { .ofs_name = "map", .ofs_func = ofh_nosup },
   53.89 +    { .ofs_name = "unmap", .ofs_func = ofh_nosup },
   53.90 +    { .ofs_name = "translate", .ofs_func = ofh_nosup },
   53.91 +
   53.92 +    /* Document Section 11.3 Client Interface Services */
   53.93 +    { .ofs_name = "start-cpu", .ofs_func = ofh_start_cpu },
   53.94 +    { .ofs_name = "stop-self", .ofs_func = ofh_stop_self },
   53.95 +    { .ofs_name = "idle-self", .ofs_func = ofh_idle_self },
   53.96 +    { .ofs_name = "resume-cpu", .ofs_func = ofh_resume_cpu },
   53.97 +    { .ofs_name = NULL, .ofs_func = NULL}
   53.98 +};
   53.99 +
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/xen/arch/powerpc/of_handler/snprintf.c	Fri Jul 14 10:47:50 2006 +0100
    54.3 @@ -0,0 +1,332 @@
    54.4 +/*
    54.5 + * This program is free software; you can redistribute it and/or modify
    54.6 + * it under the terms of the GNU General Public License as published by
    54.7 + * the Free Software Foundation; either version 2 of the License, or
    54.8 + * (at your option) any later version.
    54.9 + *
   54.10 + * This program is distributed in the hope that it will be useful,
   54.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   54.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   54.13 + * GNU General Public License for more details.
   54.14 + *
   54.15 + * You should have received a copy of the GNU General Public License
   54.16 + * along with this program; if not, write to the Free Software
   54.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   54.18 + *
   54.19 + * Copyright (C) IBM Corp. 2005
   54.20 + *
   54.21 + * Authors: Jimi Xenidis <jimix@watson.ibm.com>
   54.22 + */
   54.23 +
   54.24 +#include <xen/types.h>
   54.25 +#include <stdarg.h>
   54.26 +
   54.27 +#define UPPER   0x00001
   54.28 +#define SIGNED  0x00010
   54.29 +#define ZERO    0x00100
   54.30 +#define PTR 0x01000
   54.31 +
   54.32 +#define NUMBUFSZ 24     /* fits a 64bit value formatted in octal */
   54.33 +
   54.34 +/* do we need to handle 128 bits? */
   54.35 +static ulong
   54.36 +digits(char *buf, uint64_t val, ulong radix, ulong width, ulong flgs)
   54.37 +{
   54.38 +    const char hex[] = "0123456789abcdefx";
   54.39 +    const char Hex[] = "0123456789ABCDEFX";
   54.40 +    const char *dig;
   54.41 +    char *b = buf;
   54.42 +    char num[NUMBUFSZ];
   54.43 +    ulong i;
   54.44 +
   54.45 +    if (radix == 0 || radix > 16) {
   54.46 +        radix = 16;
   54.47 +    }
   54.48 +    
   54.49 +    if (flgs & UPPER) {
   54.50 +        dig = Hex;
   54.51 +    } else {
   54.52 +        dig = hex;
   54.53 +    }
   54.54 +    
   54.55 +    /* sign */
   54.56 +    if (flgs & SIGNED && radix == 10) {
   54.57 +        /* there are corner cases here, for sure */
   54.58 +        if ((int64_t)val < 0) {
   54.59 +            *b++ = '-';
   54.60 +            val *= -1;
   54.61 +        }
   54.62 +    }
   54.63 +
   54.64 +    /* ptr */
   54.65 +    if (flgs & PTR && radix == 16) {
   54.66 +        *b++ = '0';
   54.67 +        *b++ = dig[16];
   54.68 +    }
   54.69 +
   54.70 +    /* put it in t backwards */
   54.71 +    i = 0;
   54.72 +    if (val == 0) {
   54.73 +        num[i++] = '0';
   54.74 +    } else {
   54.75 +        while (val > 0) {
   54.76 +            num[i++] = dig[val % radix];
   54.77 +            val /= radix;
   54.78 +        }
   54.79 +    }
   54.80 +
   54.81 +    /* pad */
   54.82 +    if (flgs & ZERO && width > i) {
   54.83 +        while (width-- > i) {
   54.84 +            *b++ = '0';
   54.85 +        }
   54.86 +    }
   54.87 +
   54.88 +    /* number */
   54.89 +    while (i-- > 0) {
   54.90 +        *b++ = num[i];
   54.91 +    }
   54.92 +
   54.93 +    return (b - buf);
   54.94 +}
   54.95 +
   54.96 +/*
   54.97 + * yeah, I dislike goto's too, but ...
   54.98 + */
   54.99 +int
  54.100 +vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
  54.101 +{
  54.102 +    int c;
  54.103 +    int nullify;
  54.104 +    ulong used = 0;
  54.105 +    ulong sz;
  54.106 +    unsigned ells;
  54.107 +    ulong flgs;
  54.108 +    const char *str;
  54.109 +    uint64_t val = 0;
  54.110 +    ulong radix;
  54.111 +    ulong width;
  54.112 +    char num[NUMBUFSZ];
  54.113 +
  54.114 +    /* there must always be a trailing null */
  54.115 +    if (size == 0) {
  54.116 +        /* but don't write anything is size is zero */
  54.117 +        nullify = 0;
  54.118 +    } else {
  54.119 +        --size;
  54.120 +        nullify = 1;
  54.121 +    }
  54.122 +
  54.123 +    while ((c = *fmt++) != '\0') {
  54.124 +        if (c != '%') {
  54.125 +            if (used++ < size) {
  54.126 +                *buf++ = c;
  54.127 +            }
  54.128 +            continue;
  54.129 +        }
  54.130 +        /* deal with format */
  54.131 +        ells = 0;
  54.132 +        flgs = 0;
  54.133 +
  54.134 +        /* check for a given width */
  54.135 +        width = 0;
  54.136 +        
  54.137 +        c = *fmt;
  54.138 +        if (c >= '0' && c <= '9') {
  54.139 +            flgs |= ZERO;
  54.140 +            ++fmt;
  54.141 +            while (c >= '0' && c <= '9') {
  54.142 +                width = (width * 10) + (c - '0');
  54.143 +                c = *fmt++;
  54.144 +            }
  54.145 +            --fmt;
  54.146 +        }
  54.147 +        
  54.148 +loop:
  54.149 +        c = *fmt++;
  54.150 +        switch (c) {
  54.151 +        case 'l':
  54.152 +            ++ells;
  54.153 +            goto loop;
  54.154 +            /*NOTREACHED*/
  54.155 +            break;
  54.156 +
  54.157 +        case 'h':   /* support linux kernel 'h'  for short */
  54.158 +            ells = 0;
  54.159 +            goto loop;
  54.160 +            /*NOTREACHED*/
  54.161 +            break;
  54.162 +
  54.163 +        case 'L':   /* support linux kernel 'L'  for long long */
  54.164 +            ells = 2;
  54.165 +            goto loop;
  54.166 +            /*NOTREACHED*/
  54.167</