Author: nwhitehorn
Date: Thu Jun  2 14:12:37 2011
New Revision: 222613
URL: http://svn.freebsd.org/changeset/base/222613

Log:
  MFpseries:
  Renovate and improve the AIM Open Firmware support:
  - Add RTAS (Run-Time Abstraction Services) support, found on all IBM systems
    and some Apple ones
  - Improve support for 32-bit real mode Open Firmware systems
  - Pull some more OF bits over from the AIM directory
  - Fix memory detection on IBM LPARs and systems with more than one /memory
    node (by andreast@)

Added:
  head/sys/powerpc/include/rtas.h   (contents, props changed)
  head/sys/powerpc/ofw/ofwcall32.S   (contents, props changed)
  head/sys/powerpc/ofw/ofwcall64.S   (contents, props changed)
  head/sys/powerpc/ofw/ofwmagic.S
     - copied unchanged from r222507, head/sys/powerpc/aim/ofwmagic.S
  head/sys/powerpc/ofw/rtas.c   (contents, props changed)
Deleted:
  head/sys/powerpc/aim/ofwmagic.S
Modified:
  head/sys/powerpc/aim/locore32.S
  head/sys/powerpc/aim/locore64.S
  head/sys/powerpc/ofw/ofw_machdep.c
  head/sys/powerpc/ofw/ofw_real.c

Modified: head/sys/powerpc/aim/locore32.S
==============================================================================
--- head/sys/powerpc/aim/locore32.S     Thu Jun  2 14:09:30 2011        
(r222612)
+++ head/sys/powerpc/aim/locore32.S     Thu Jun  2 14:12:37 2011        
(r222613)
@@ -87,9 +87,6 @@ GLOBAL(tmpstk)
 GLOBAL(esym)
        .long   0                       /* end of symbol table */
 
-GLOBAL(ofmsr)
-       .long   0, 0, 0, 0, 0           /* msr/sprg0-3 used in Open Firmware */
-
 #define        INTRCNT_COUNT   256             /* 
max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */
 GLOBAL(intrnames)
        .space  INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
@@ -99,16 +96,6 @@ GLOBAL(intrcnt)
        .space  INTRCNT_COUNT * 4 * 2
 GLOBAL(eintrcnt)
 
-/*
- * File-scope for locore.S
- */
-idle_u:
-       .long   0                       /* fake uarea during idle after exit */
-openfirmware_entry:
-       .long   0                       /* Open Firmware entry point */
-srsave:
-       .long   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-
        .text
        .globl  btext
 btext:

Modified: head/sys/powerpc/aim/locore64.S
==============================================================================
--- head/sys/powerpc/aim/locore64.S     Thu Jun  2 14:09:30 2011        
(r222612)
+++ head/sys/powerpc/aim/locore64.S     Thu Jun  2 14:12:37 2011        
(r222613)
@@ -76,7 +76,6 @@
         .set    kernbase, KERNBASE
 
 #define        TMPSTKSZ        8192            /* 8K temporary stack */
-#define        OFWSTKSZ        4096            /* 4K Open Firmware stack */
 
 /*
  * Globals
@@ -85,14 +84,9 @@
        .align  4
 GLOBAL(tmpstk)
        .space  TMPSTKSZ
-GLOBAL(ofwstk)
-       .space  OFWSTKSZ
 GLOBAL(esym)
        .llong  0                       /* end of symbol table */
 
-GLOBAL(ofmsr)
-       .llong  0, 0, 0, 0, 0           /* msr/sprg0-3 used in Open Firmware */
-
 #define        INTRCNT_COUNT   256             /* 
max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */
 GLOBAL(intrnames)
        .space  INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
@@ -102,16 +96,6 @@ GLOBAL(intrcnt)
        .space  INTRCNT_COUNT * 4 * 2
 GLOBAL(eintrcnt)
 
-/*
- * File-scope for locore.S
- */
-idle_u:
-       .llong  0                       /* fake uarea during idle after exit */
-openfirmware_entry:
-       .llong  0                       /* Open Firmware entry point */
-srsave:
-       .llong  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-
        .text
        .globl  btext
 btext:
@@ -208,122 +192,6 @@ tocbase:
         .llong  .TOC.@tocbase
 
 /*
- * Open Firmware Real-mode Entry Point. This is a huge pain.
- */
-
-ASENTRY(ofw_32bit_mode_entry)
-       mflr    %r0
-       std     %r0,16(%r1)
-       stdu    %r1,-208(%r1)
-
-       /*
-        * We need to save the following, because OF's register save/
-        * restore code assumes that the contents of registers are
-        * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
-        * get placed in that order in the stack.
-        */
-
-       mfcr    %r4
-       std     %r4,48(%r1)
-       std     %r13,56(%r1)
-       std     %r14,64(%r1)
-       std     %r15,72(%r1)
-       std     %r16,80(%r1)
-       std     %r17,88(%r1)
-       std     %r18,96(%r1)
-       std     %r19,104(%r1)
-       std     %r20,112(%r1)
-       std     %r21,120(%r1)
-       std     %r22,128(%r1)
-       std     %r23,136(%r1)
-       std     %r24,144(%r1)
-       std     %r25,152(%r1)
-       std     %r26,160(%r1)
-       std     %r27,168(%r1)
-       std     %r28,176(%r1)
-       std     %r29,184(%r1)
-       std     %r30,192(%r1)
-       std     %r31,200(%r1)
-
-       /* Record the old MSR */
-       mfmsr   %r6
-
-       /* read client interface handler */
-       lis     %r4,openfirmware_entry@ha
-       ld      %r4,openfirmware_entry@l(%r4)
-
-       /*
-        * Set the MSR to the OF value. This has the side effect of disabling
-        * exceptions, which is important for the next few steps.
-        */
-
-       lis     %r5,ofmsr@ha
-       ld      %r5,ofmsr@l(%r5)
-       mtmsrd  %r5
-       isync
-
-       /*
-        * Set up OF stack. This needs to be accessible in real mode and
-        * use the 32-bit ABI stack frame format. The pointer to the current
-        * kernel stack is placed at the very top of the stack along with
-        * the old MSR so we can get them back later.
-        */
-       mr      %r5,%r1
-       lis     %r1,(ofwstk+OFWSTKSZ-32)@ha
-       addi    %r1,%r1,(ofwstk+OFWSTKSZ-32)@l
-       std     %r5,8(%r1)      /* Save real stack pointer */
-       std     %r2,16(%r1)     /* Save old TOC */
-       std     %r6,24(%r1)     /* Save old MSR */
-       li      %r5,0
-       stw     %r5,4(%r1)
-       stw     %r5,0(%r1)
-
-       /* Finally, branch to OF */
-       mtctr   %r4
-       bctrl
-
-       /* Reload stack pointer and MSR from the OFW stack */
-       ld      %r6,24(%r1)
-       ld      %r2,16(%r1)
-       ld      %r1,8(%r1)
-
-       /* Now set the real MSR */
-       mtmsrd  %r6
-       isync
-
-       /* Sign-extend the return value from OF */
-       extsw   %r3,%r3
-
-       /* Restore all the non-volatile registers */
-       ld      %r5,48(%r1)
-       mtcr    %r5
-       ld      %r13,56(%r1)
-       ld      %r14,64(%r1)
-       ld      %r15,72(%r1)
-       ld      %r16,80(%r1)
-       ld      %r17,88(%r1)
-       ld      %r18,96(%r1)
-       ld      %r19,104(%r1)
-       ld      %r20,112(%r1)
-       ld      %r21,120(%r1)
-       ld      %r22,128(%r1)
-       ld      %r23,136(%r1)
-       ld      %r24,144(%r1)
-       ld      %r25,152(%r1)
-       ld      %r26,160(%r1)
-       ld      %r27,168(%r1)
-       ld      %r28,176(%r1)
-       ld      %r29,184(%r1)
-       ld      %r30,192(%r1)
-       ld      %r31,200(%r1)
-
-       /* Restore the stack and link register */
-       ld      %r1,0(%r1)
-       ld      %r0,16(%r1)
-       mtlr    %r0
-       blr
-
-/*
  * int setfault()
  *
  * Similar to setjmp to setup for handling faults on accesses to user memory.

Added: head/sys/powerpc/include/rtas.h
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/powerpc/include/rtas.h     Thu Jun  2 14:12:37 2011        
(r222613)
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 2011 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE_RTAS_H_
+#define _MACHINE_RTAS_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <dev/ofw/openfirm.h>
+
+/*
+ * RTAS functions are defined by 32-bit integer tokens. These vary from
+ * system to system, and can be looked up from their standardized names
+ * using rtas_token_lookup(). If RTAS is not available, rtas_token_lookup()
+ * and rtas_call_method() return -1; this can be checked in advance using
+ * rtas_exists(). Otherwise, rtas_call_method() returns one of the RTAS
+ * status codes from the bottom of this file.
+ */
+
+int rtas_exists(void);
+int rtas_call_method(cell_t token, int nargs, int nreturns, ...);
+cell_t rtas_token_lookup(const char *method);
+
+/* RTAS Status Codes: see CHRP or PAPR specification */
+#define        RTAS_OK                         0
+#define        RTAS_HW_ERROR                   -1
+#define        RTAS_BUSY                       -2
+#define        RTAS_PARAM_ERROR                -3
+#define        RTAS_STATE_CHANGE               -7
+#define        RTAS_VENDOR_BEGIN               9000
+#define        RTAS_EXTENDED_DELAY             9900
+#define        RTAS_ISOLATION_ERROR            -9000
+#define        RTAS_VENDOR_ERROR_BEGIN         -9004
+
+#endif /* _MACHINE_RTAS_H_ */
+

Modified: head/sys/powerpc/ofw/ofw_machdep.c
==============================================================================
--- head/sys/powerpc/ofw/ofw_machdep.c  Thu Jun  2 14:09:30 2011        
(r222612)
+++ head/sys/powerpc/ofw/ofw_machdep.c  Thu Jun  2 14:12:37 2011        
(r222613)
@@ -60,17 +60,15 @@ __FBSDID("$FreeBSD$");
 #include <machine/platform.h>
 #include <machine/ofw_machdep.h>
 
-#define        OFMEM_REGIONS   32
-static struct mem_region OFmem[OFMEM_REGIONS + 1], OFavail[OFMEM_REGIONS + 3];
-static struct mem_region OFfree[OFMEM_REGIONS + 3];
-static int nOFmem;
+static struct mem_region OFmem[PHYS_AVAIL_SZ], OFavail[PHYS_AVAIL_SZ];
+static struct mem_region OFfree[PHYS_AVAIL_SZ];
 
 extern register_t ofmsr[5];
-static int     (*ofwcall)(void *);
+extern void    *openfirmware_entry;
 static void    *fdt;
 int            ofw_real_mode;
 
-int            ofw_32bit_mode_entry(void *);
+int            ofwcall(void *);
 static void    ofw_quiesce(void);
 static int     openfirmware(void *args);
 
@@ -134,11 +132,32 @@ memr_merge(struct mem_region *from, stru
        to->mr_size = end - to->mr_start;
 }
 
+/*
+ * Quick sort callout for comparing memory regions.
+ */
+static int     mr_cmp(const void *a, const void *b);
+
+static int
+mr_cmp(const void *a, const void *b)
+{
+       const struct    mem_region *regiona;
+       const struct    mem_region *regionb;
+
+       regiona = a;
+       regionb = b;
+       if (regiona->mr_start < regionb->mr_start)
+               return (-1);
+       else if (regiona->mr_start > regionb->mr_start)
+               return (1);
+       else
+               return (0);
+}
+
 static int
 parse_ofw_memory(phandle_t node, const char *prop, struct mem_region *output)
 {
        cell_t address_cells, size_cells;
-       cell_t OFmem[4*(OFMEM_REGIONS + 1)];
+       cell_t OFmem[4 * PHYS_AVAIL_SZ];
        int sz, i, j;
        int apple_hack_mode;
        phandle_t phandle;
@@ -175,7 +194,7 @@ parse_ofw_memory(phandle_t node, const c
         * Get memory.
         */
        if ((node == -1) || (sz = OF_getprop(node, prop,
-           OFmem, sizeof(OFmem[0]) * 4 * OFMEM_REGIONS)) <= 0)
+           OFmem, sizeof(OFmem[0]) * 4 * PHYS_AVAIL_SZ)) <= 0)
                panic("Physical memory map not found");
 
        i = 0;
@@ -225,7 +244,7 @@ parse_ofw_memory(phandle_t node, const c
        #ifdef __powerpc64__
        if (apple_hack_mode) {
                /* Add in regions above 4 GB to the available list */
-               struct mem_region himem[OFMEM_REGIONS];
+               struct mem_region himem[PHYS_AVAIL_SZ];
                int hisz;
 
                hisz = parse_ofw_memory(node, "reg", himem);
@@ -243,6 +262,81 @@ parse_ofw_memory(phandle_t node, const c
        return (sz);
 }
 
+static int
+parse_drconf_memory(int *msz, int *asz, struct mem_region *ofmem,
+                   struct mem_region *ofavail)
+{
+       phandle_t phandle;
+       vm_offset_t base;
+       int i, idx, len, lasz, lmsz, res;
+       uint32_t lmb_size[2];
+       unsigned long *dmem, flags;
+
+       lmsz = *msz;
+       lasz = *asz;
+
+       phandle = OF_finddevice("/ibm,dynamic-reconfiguration-memory");
+       if (phandle == -1)
+               /* No drconf node, return. */
+               return (0);
+
+       res = OF_getprop(phandle, "ibm,lmb-size", lmb_size, sizeof(lmb_size));
+       if (res == -1)
+               return (0);
+
+       /* Parse the /ibm,dynamic-memory.
+          The first position gives the # of entries. The next two words
+          reflect the address of the memory block. The next four words are
+          the DRC index, reserved, list index and flags.
+          (see PAPR C.6.6.2 ibm,dynamic-reconfiguration-memory)
+          
+           #el  Addr   DRC-idx  res   list-idx  flags
+          -------------------------------------------------
+          | 4 |   8   |   4   |   4   |   4   |   4   |....
+          -------------------------------------------------
+       */
+
+       len = OF_getproplen(phandle, "ibm,dynamic-memory");
+       if (len > 0) {
+
+               /* We have to use a variable length array on the stack
+                  since we have very limited stack space.
+               */
+               cell_t arr[len/sizeof(cell_t)];
+
+               res = OF_getprop(phandle, "ibm,dynamic-memory", &arr,
+                                sizeof(arr));
+               if (res == -1)
+                       return (0);
+
+               /* Number of elements */
+               idx = arr[0];
+
+               /* First address. */
+               dmem = (void*)&arr[1];
+       
+               for (i = 0; i < idx; i++) {
+                       base = *dmem;
+                       dmem += 2;
+                       flags = *dmem;
+                       /* Use region only if available and not reserved. */
+                       if ((flags & 0x8) && !(flags & 0x80)) {
+                               ofmem[lmsz].mr_start = base;
+                               ofmem[lmsz].mr_size = (vm_size_t)lmb_size[1];
+                               ofavail[lasz].mr_start = base;
+                               ofavail[lasz].mr_size = (vm_size_t)lmb_size[1];
+                               lmsz++;
+                               lasz++;
+                       }
+                       dmem++;
+               }
+       }
+
+       *msz = lmsz;
+       *asz = lasz;
+
+       return (1);
+}
 /*
  * This is called during powerpc_init, before the system is really initialized.
  * It shall provide the total and the available regions of RAM.
@@ -255,31 +349,62 @@ ofw_mem_regions(struct mem_region **memp
                struct mem_region **availp, int *availsz)
 {
        phandle_t phandle;
+       vm_offset_t maxphysaddr;
        int asz, msz, fsz;
-       int i, j;
+       int i, j, res;
        int still_merging;
+       char name[31];
 
        asz = msz = 0;
 
        /*
-        * Get memory.
+        * Get memory from all the /memory nodes.
         */
-       phandle = OF_finddevice("/memory");
-       if (phandle == -1)
-               phandle = OF_finddevice("/memory@0");
+       for (phandle = OF_child(OF_peer(0)); phandle != 0;
+           phandle = OF_peer(phandle)) {
+               if (OF_getprop(phandle, "name", name, sizeof(name)) <= 0)
+                       continue;
+               if (strncmp(name, "memory", sizeof(name)) != 0)
+                       continue;
+
+               res = parse_ofw_memory(phandle, "reg", &OFmem[msz]);
+               msz += res/sizeof(struct mem_region);
+               if (OF_getproplen(phandle, "available") >= 0)
+                       res = parse_ofw_memory(phandle, "available",
+                           &OFavail[asz]);
+               else
+                       res = parse_ofw_memory(phandle, "reg", &OFavail[asz]);
+               asz += res/sizeof(struct mem_region);
+       }
 
-       msz = parse_ofw_memory(phandle, "reg", OFmem);
-       nOFmem = msz / sizeof(struct mem_region);
-       asz = parse_ofw_memory(phandle, "available", OFavail);
+       /* Check for memory in ibm,dynamic-reconfiguration-memory */
+       parse_drconf_memory(&msz, &asz, OFmem, OFavail);
+
+       qsort(OFmem, msz, sizeof(*OFmem), mr_cmp);
+       qsort(OFavail, asz, sizeof(*OFavail), mr_cmp);
 
        *memp = OFmem;
-       *memsz = nOFmem;
-       
+       *memsz = msz;
+
+       /*
+        * On some firmwares (SLOF), some memory may be marked available that
+        * doesn't actually exist. This manifests as an extension of the last
+        * available segment past the end of physical memory, so truncate that
+        * one.
+        */
+       maxphysaddr = 0;
+       for (i = 0; i < msz; i++)
+               if (OFmem[i].mr_start + OFmem[i].mr_size > maxphysaddr)
+                       maxphysaddr = OFmem[i].mr_start + OFmem[i].mr_size;
+
+       if (OFavail[asz - 1].mr_start + OFavail[asz - 1].mr_size > maxphysaddr)
+               OFavail[asz - 1].mr_size = maxphysaddr -
+                   OFavail[asz - 1].mr_start;
+
        /*
         * OFavail may have overlapping regions - collapse these
         * and copy out remaining regions to OFfree
         */
-       asz /= sizeof(struct mem_region);
        do {
                still_merging = FALSE;
                for (i = 0; i < asz; i++) {
@@ -318,19 +443,6 @@ OF_initial_setup(void *fdt_ptr, void *ju
        else
                ofw_real_mode = 1;
 
-       ofwcall = NULL;
-
-       #ifdef __powerpc64__
-               /*
-                * For PPC64, we need to use some hand-written
-                * asm trampolines to get to OF.
-                */
-               if (openfirm != NULL)
-                       ofwcall = ofw_32bit_mode_entry;
-       #else
-               ofwcall = openfirm;
-       #endif
-
        fdt = fdt_ptr;
 
        #ifdef FDT_DTB_STATIC
@@ -345,7 +457,7 @@ OF_bootstrap()
 {
        boolean_t status = FALSE;
 
-       if (ofwcall != NULL) {
+       if (openfirmware_entry != NULL) {
                if (ofw_real_mode) {
                        status = OF_install(OFW_STD_REAL, 0);
                } else {
@@ -481,12 +593,7 @@ openfirmware(void *args)
        int result;
        #ifdef SMP
        struct ofw_rv_args rv_args;
-       #endif
-
-       if (pmap_bootstrapped && ofw_real_mode)
-               args = (void *)pmap_kextract((vm_offset_t)args);
 
-       #ifdef SMP
        rv_args.args = args;
        rv_args.in_progress = 1;
        smp_rendezvous(smp_no_rendevous_barrier, ofw_rendezvous_dispatch,

Modified: head/sys/powerpc/ofw/ofw_real.c
==============================================================================
--- head/sys/powerpc/ofw/ofw_real.c     Thu Jun  2 14:09:30 2011        
(r222612)
+++ head/sys/powerpc/ofw/ofw_real.c     Thu Jun  2 14:12:37 2011        
(r222613)
@@ -205,13 +205,14 @@ ofw_real_bounce_alloc(void *junk)
 
        /*
         * Allocate a page of contiguous, wired physical memory that can
-        * fit into a 32-bit address space.
+        * fit into a 32-bit address space and accessed from real mode.
         */
 
        mtx_lock(&of_bounce_mtx);
 
-       of_bounce_virt = contigmalloc(PAGE_SIZE, M_OFWREAL, 0,
-                            0, BUS_SPACE_MAXADDR_32BIT, PAGE_SIZE, PAGE_SIZE);
+       of_bounce_virt = contigmalloc(PAGE_SIZE, M_OFWREAL, 0, 0,
+           ulmin(platform_real_maxaddr(), BUS_SPACE_MAXADDR_32BIT), PAGE_SIZE,
+           PAGE_SIZE);
 
        of_bounce_phys = vtophys(of_bounce_virt);
        of_bounce_size = PAGE_SIZE;

Added: head/sys/powerpc/ofw/ofwcall32.S
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/powerpc/ofw/ofwcall32.S    Thu Jun  2 14:12:37 2011        
(r222613)
@@ -0,0 +1,154 @@
+/*-
+ * Copyright (C) 2009-2011 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/syscall.h>
+
+#include <machine/trap.h>
+#include <machine/param.h>
+#include <machine/spr.h>
+#include <machine/asm.h>
+
+#define        OFWSTKSZ        4096            /* 4K Open Firmware stack */
+
+/*
+ * Globals
+ */
+       .data
+GLOBAL(ofmsr)
+       .long   0, 0, 0, 0, 0           /* msr/sprg0-3 used in Open Firmware */
+GLOBAL(rtasmsr)
+       .long   0
+GLOBAL(openfirmware_entry)
+       .long   0                       /* Open Firmware entry point */
+GLOBAL(rtas_entry)
+       .long   0                       /* RTAS entry point */
+
+       .align  4
+ofwstk:
+       .space  OFWSTKSZ
+rtas_regsave:
+       .space  4
+
+/*
+ * Open Firmware Entry Point. May need to enter real mode.
+ *
+ * C prototype: int ofwcall(void *callbuffer);
+ */
+
+ASENTRY(ofwcall)
+       mflr    %r0
+       stw     %r0,4(%r1)
+
+       /* Record the old MSR */
+       mfmsr   %r6
+
+       /* read client interface handler */
+       lis     %r4,openfirmware_entry@ha
+       lwz     %r4,openfirmware_entry@l(%r4)
+
+       /*
+        * Set the MSR to the OF value. This has the side effect of disabling
+        * exceptions, which prevents preemption later.
+        */
+
+       lis     %r5,ofmsr@ha
+       lwz     %r5,ofmsr@l(%r5)
+       mtmsr   %r5
+       isync
+
+       /*
+        * Set up OF stack. This needs to be potentially accessible in real mode
+        * The pointer to the current kernel stack is placed at the very
+        * top of the stack along with the old MSR so we can get them back
+        * later.
+        */
+       mr      %r5,%r1
+       lis     %r1,(ofwstk+OFWSTKSZ-16)@ha
+       addi    %r1,%r1,(ofwstk+OFWSTKSZ-16)@l
+       stw     %r5,8(%r1)      /* Save real stack pointer */
+       stw     %r6,12(%r1)     /* Save old MSR */
+       li      %r5,0
+       stw     %r5,4(%r1)
+       stw     %r5,0(%r1)
+
+       /* Finally, branch to OF */
+       mtctr   %r4
+       bctrl
+
+       /* Reload stack pointer and MSR from the OFW stack */
+       lwz     %r6,12(%r1)
+       lwz     %r1,8(%r1)
+
+       /* Now set the real MSR */
+       mtmsr   %r6
+       isync
+
+       /* Return */
+       lwz     %r0,4(%r1)
+       mtlr    %r0
+       blr
+
+/*
+ * RTAS Entry Point. Similar to the OF one, but simpler (no separate stack)
+ *
+ * C prototype: int rtascall(void *callbuffer, void *rtas_privdat);
+ */
+
+ASENTRY(rtascall)
+       mflr    %r0
+       stw     %r0,4(%r1)
+
+       /* Record the old MSR to real-mode-accessible area */
+       mfmsr   %r0
+       lis     %r5,rtas_regsave@ha
+       stw     %r0,rtas_regsave@l(%r5)
+
+       /* read client interface handler */
+       lis     %r5,rtas_entry@ha
+       lwz     %r5,rtas_entry@l(%r5)
+
+       /* Set the MSR to the RTAS value */
+       lis     %r6,rtasmsr@ha
+       lwz     %r6,rtasmsr@l(%r6)
+       mtmsr   %r6
+       isync
+
+       /* Branch to RTAS */
+       mtctr   %r5
+       bctrl
+
+       /* Now set the MSR back */
+       lis     %r6,rtas_regsave@ha
+       lwz     %r6,rtas_regsave@l(%r6)
+       mtmsr   %r6
+       isync
+
+       /* And return */
+       lwz     %r0,4(%r1)
+       mtlr    %r0
+       blr
+

Added: head/sys/powerpc/ofw/ofwcall64.S
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/powerpc/ofw/ofwcall64.S    Thu Jun  2 14:12:37 2011        
(r222613)
@@ -0,0 +1,290 @@
+/*-
+ * Copyright (C) 2009-2011 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/syscall.h>
+
+#include <machine/trap.h>
+#include <machine/param.h>
+#include <machine/spr.h>
+#include <machine/asm.h>
+
+#define        OFWSTKSZ        4096            /* 4K Open Firmware stack */
+
+/*
+ * Globals
+ */
+       .data
+       .align  4
+ofwstk:
+       .space  OFWSTKSZ
+rtas_regsave:
+       .space  24 /* 3 * sizeof(register_t) */
+GLOBAL(ofmsr)
+       .llong  0, 0, 0, 0, 0           /* msr/sprg0-3 used in Open Firmware */
+GLOBAL(rtasmsr)
+       .llong  0
+GLOBAL(openfirmware_entry)
+       .llong  0                       /* Open Firmware entry point */
+GLOBAL(rtas_entry)
+       .llong  0                       /* RTAS entry point */
+
+/*
+ * Open Firmware Real-mode Entry Point. This is a huge pain.
+ */
+
+ASENTRY(ofwcall)
+       mflr    %r0
+       std     %r0,16(%r1)
+       stdu    %r1,-208(%r1)
+
+       /*
+        * We need to save the following, because OF's register save/
+        * restore code assumes that the contents of registers are
+        * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
+        * get placed in that order in the stack.
+        */
+
+       mfcr    %r4
+       std     %r4,48(%r1)
+       std     %r13,56(%r1)
+       std     %r14,64(%r1)
+       std     %r15,72(%r1)
+       std     %r16,80(%r1)
+       std     %r17,88(%r1)
+       std     %r18,96(%r1)
+       std     %r19,104(%r1)
+       std     %r20,112(%r1)
+       std     %r21,120(%r1)
+       std     %r22,128(%r1)
+       std     %r23,136(%r1)
+       std     %r24,144(%r1)
+       std     %r25,152(%r1)
+       std     %r26,160(%r1)
+       std     %r27,168(%r1)
+       std     %r28,176(%r1)
+       std     %r29,184(%r1)
+       std     %r30,192(%r1)
+       std     %r31,200(%r1)
+
+       /* Record the old MSR */
+       mfmsr   %r6
+
+       /* read client interface handler */
+       lis     %r4,openfirmware_entry@ha
+       ld      %r4,openfirmware_entry@l(%r4)
+
+       /*
+        * Set the MSR to the OF value. This has the side effect of disabling
+        * exceptions, which is important for the next few steps.
+        */
+
+       lis     %r5,ofmsr@ha
+       ld      %r5,ofmsr@l(%r5)
+       mtmsrd  %r5
+       isync
+
+       /*
+        * Set up OF stack. This needs to be accessible in real mode and
+        * use the 32-bit ABI stack frame format. The pointer to the current
+        * kernel stack is placed at the very top of the stack along with
+        * the old MSR so we can get them back later.
+        */
+       mr      %r5,%r1
+       lis     %r1,(ofwstk+OFWSTKSZ-32)@ha
+       addi    %r1,%r1,(ofwstk+OFWSTKSZ-32)@l
+       std     %r5,8(%r1)      /* Save real stack pointer */
+       std     %r2,16(%r1)     /* Save old TOC */
+       std     %r6,24(%r1)     /* Save old MSR */
+       li      %r5,0
+       stw     %r5,4(%r1)
+       stw     %r5,0(%r1)
+
+       /* Finally, branch to OF */
+       mtctr   %r4
+       bctrl
+
+       /* Reload stack pointer and MSR from the OFW stack */
+       ld      %r6,24(%r1)
+       ld      %r2,16(%r1)
+       ld      %r1,8(%r1)
+
+       /* Now set the real MSR */
+       mtmsrd  %r6
+       isync
+
+       /* Sign-extend the return value from OF */
+       extsw   %r3,%r3
+
+       /* Restore all the non-volatile registers */
+       ld      %r5,48(%r1)
+       mtcr    %r5
+       ld      %r13,56(%r1)
+       ld      %r14,64(%r1)
+       ld      %r15,72(%r1)
+       ld      %r16,80(%r1)
+       ld      %r17,88(%r1)
+       ld      %r18,96(%r1)
+       ld      %r19,104(%r1)
+       ld      %r20,112(%r1)
+       ld      %r21,120(%r1)
+       ld      %r22,128(%r1)
+       ld      %r23,136(%r1)
+       ld      %r24,144(%r1)
+       ld      %r25,152(%r1)
+       ld      %r26,160(%r1)
+       ld      %r27,168(%r1)
+       ld      %r28,176(%r1)
+       ld      %r29,184(%r1)
+       ld      %r30,192(%r1)
+       ld      %r31,200(%r1)
+
+       /* Restore the stack and link register */
+       ld      %r1,0(%r1)
+       ld      %r0,16(%r1)
+       mtlr    %r0
+       blr
+
+/*
+ * RTAS 32-bit Entry Point. Similar to the OF one, but simpler (no separate
+ * stack)
+ *
+ * C prototype: int rtascall(void *callbuffer, void *rtas_privdat);
+ */
+
+ASENTRY(rtascall)
+       mflr    %r0
+       std     %r0,16(%r1)
+       stdu    %r1,-208(%r1)
+
+       /*
+        * We need to save the following, because RTAS's register save/
+        * restore code assumes that the contents of registers are
+        * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
+        * get placed in that order in the stack.
+        */
+
+       mfcr    %r5
+       std     %r5,48(%r1)
+       std     %r13,56(%r1)
+       std     %r14,64(%r1)
+       std     %r15,72(%r1)
+       std     %r16,80(%r1)
+       std     %r17,88(%r1)
+       std     %r18,96(%r1)
+       std     %r19,104(%r1)
+       std     %r20,112(%r1)
+       std     %r21,120(%r1)
+       std     %r22,128(%r1)
+       std     %r23,136(%r1)
+       std     %r24,144(%r1)
+       std     %r25,152(%r1)
+       std     %r26,160(%r1)
+       std     %r27,168(%r1)
+       std     %r28,176(%r1)
+       std     %r29,184(%r1)
+       std     %r30,192(%r1)
+       std     %r31,200(%r1)
+
+       /* Record the old MSR */
+       mfmsr   %r6
+
+       /* read client interface handler */
+       lis     %r5,rtas_entry@ha
+       ld      %r5,rtas_entry@l(%r5)
+
+       /*
+        * Set the MSR to the RTAS value. This has the side effect of disabling
+        * exceptions, which is important for the next few steps.
+        */
+
+       lis     %r7,rtasmsr@ha
+       ld      %r7,rtasmsr@l(%r7)
+       mtmsrd  %r7
+       isync
+
+       /*
+        * Set up RTAS register save area, so that we can get back all of
+        * our 64-bit pointers. Save our stack pointer, the TOC, and the MSR.
+        * Put this in r1, since RTAS is obliged to save it. Kernel globals
+        * are below 4 GB, so this is safe.
+        */
+       mr      %r7,%r1
+       lis     %r1,rtas_regsave@ha
+       addi    %r1,%r1,rtas_regsave@l
+       std     %r7,0(%r1)      /* Save 64-bit stack pointer */
+       std     %r2,8(%r1)      /* Save TOC */
+       std     %r6,16(%r1)     /* Save MSR */
+
+       /* Finally, branch to RTAS */
+       mtctr   %r5
+       bctrl
+
+       /* 
+        * Reload stack pointer and MSR from the reg save area in r1. We are
+        * running in 32-bit mode at this point, so it doesn't matter if r1
+        * has become sign-extended.
+        */
+       ld      %r6,16(%r1)
+       ld      %r2,8(%r1)
+       ld      %r1,0(%r1)
+
+       /* Now set the real MSR */
+       mtmsrd  %r6
+       isync
+
+       /* Sign-extend the return value from RTAS */
+       extsw   %r3,%r3
+
+       /* Restore all the non-volatile registers */
+       ld      %r5,48(%r1)
+       mtcr    %r5
+       ld      %r13,56(%r1)
+       ld      %r14,64(%r1)
+       ld      %r15,72(%r1)
+       ld      %r16,80(%r1)
+       ld      %r17,88(%r1)
+       ld      %r18,96(%r1)
+       ld      %r19,104(%r1)
+       ld      %r20,112(%r1)
+       ld      %r21,120(%r1)
+       ld      %r22,128(%r1)
+       ld      %r23,136(%r1)
+       ld      %r24,144(%r1)
+       ld      %r25,152(%r1)
+       ld      %r26,160(%r1)
+       ld      %r27,168(%r1)
+       ld      %r28,176(%r1)
+       ld      %r29,184(%r1)
+       ld      %r30,192(%r1)
+       ld      %r31,200(%r1)
+
+       /* Restore the stack and link register */
+       ld      %r1,0(%r1)
+       ld      %r0,16(%r1)
+       mtlr    %r0

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to