The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/powerpc/ofw/ofwcall64.S

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (C) 2009-2011 Nathan Whitehorn
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   17  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   18  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   21  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   23  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   24  *
   25  * $FreeBSD$
   26  */
   27 
   28 #include <sys/syscall.h>
   29 
   30 #include <machine/trap.h>
   31 #include <machine/param.h>
   32 #include <machine/spr.h>
   33 #include <machine/asm.h>
   34 
   35 #include "opt_platform.h"
   36 
   37 #define OFWSTKSZ        4096            /* 4K Open Firmware stack */
   38 
   39 /*
   40  * Globals
   41  */
   42         .data
   43         .align  4
   44 ofwstk:
   45         .space  OFWSTKSZ
   46 rtas_regsave:
   47         .space  32 /* 4 * sizeof(register_t) */
   48 GLOBAL(ofmsr)
   49         .llong  0, 0, 0, 0, 0           /* msr/sprg0-3 used in Open Firmware */
   50 GLOBAL(rtasmsr)
   51         .llong  0
   52 GLOBAL(openfirmware_entry)
   53         .llong  0                       /* Open Firmware entry point */
   54 GLOBAL(rtas_entry)
   55         .llong  0                       /* RTAS entry point */
   56 
   57 TOC_ENTRY(ofmsr)
   58 TOC_ENTRY(ofwstk)
   59 TOC_ENTRY(rtasmsr)
   60 TOC_ENTRY(openfirmware_entry)
   61 TOC_ENTRY(rtas_entry)
   62 TOC_ENTRY(rtas_regsave)
   63 
   64 /*
   65  * Open Firmware Real-mode Entry Point. This is a huge pain.
   66  */
   67 
   68 ASENTRY_NOPROF(ofwcall)
   69         mflr    %r8
   70         std     %r8,16(%r1)
   71         stdu    %r1,-208(%r1)
   72 
   73         /*
   74          * We need to save the following, because OF's register save/
   75          * restore code assumes that the contents of registers are
   76          * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
   77          * get placed in that order in the stack.
   78          */
   79 
   80         mfcr    %r4
   81         std     %r4,48(%r1)
   82         std     %r13,56(%r1)
   83         std     %r14,64(%r1)
   84         std     %r15,72(%r1)
   85         std     %r16,80(%r1)
   86         std     %r17,88(%r1)
   87         std     %r18,96(%r1)
   88         std     %r19,104(%r1)
   89         std     %r20,112(%r1)
   90         std     %r21,120(%r1)
   91         std     %r22,128(%r1)
   92         std     %r23,136(%r1)
   93         std     %r24,144(%r1)
   94         std     %r25,152(%r1)
   95         std     %r26,160(%r1)
   96         std     %r27,168(%r1)
   97         std     %r28,176(%r1)
   98         std     %r29,184(%r1)
   99         std     %r30,192(%r1)
  100         std     %r31,200(%r1)
  101 
  102         /* Record the old MSR */
  103         mfmsr   %r6
  104 
  105         /* read client interface handler */
  106         addis   %r4,%r2,TOC_REF(openfirmware_entry)@ha
  107         ld      %r4,TOC_REF(openfirmware_entry)@l(%r4)
  108         ld      %r4,0(%r4)
  109 
  110         /* Get OF stack pointer */
  111         addis   %r7,%r2,TOC_REF(ofwstk)@ha
  112         ld      %r7,TOC_REF(ofwstk)@l(%r7)
  113         addi    %r7,%r7,OFWSTKSZ-40
  114 
  115         /*
  116          * Set the MSR to the OF value. This has the side effect of disabling
  117          * exceptions, which is important for the next few steps.
  118          * This does NOT, however, cause us to switch endianness.
  119          */
  120 
  121         addis   %r5,%r2,TOC_REF(ofmsr)@ha
  122         ld      %r5,TOC_REF(ofmsr)@l(%r5)
  123         ld      %r5,0(%r5)
  124 #if defined(__LITTLE_ENDIAN__) && defined(QEMU)
  125         /* QEMU hack: qemu does not emulate mtmsrd correctly! */
  126         ori     %r5,%r5,1       /* Leave PSR_LE set */
  127 #endif
  128         mtmsrd  %r5
  129         isync
  130 
  131         /*
  132          * Set up OF stack. This needs to be accessible in real mode and
  133          * use the 32-bit ABI stack frame format. The pointer to the current
  134          * kernel stack is placed at the very top of the stack along with
  135          * the old MSR so we can get them back later.
  136          */
  137         mr      %r5,%r1
  138         mr      %r1,%r7
  139         std     %r5,8(%r1)      /* Save real stack pointer */
  140         std     %r2,16(%r1)     /* Save old TOC */
  141         std     %r6,24(%r1)     /* Save old MSR */
  142         std     %r8,32(%r1)     /* Save high 32-bits of the kernel's PC */
  143 
  144         li      %r5,0
  145         stw     %r5,4(%r1)
  146         stw     %r5,0(%r1)
  147 
  148 #ifdef __LITTLE_ENDIAN__
  149         /* Atomic context switch w/ endian change */
  150         mtmsrd  %r5, 1  /* Clear PSL_EE|PSL_RI */
  151         addis   %r5,%r2,TOC_REF(ofmsr)@ha
  152         ld      %r5,TOC_REF(ofmsr)@l(%r5)
  153         ld      %r5,0(%r5)
  154         mtsrr0  %r4
  155         mtsrr1  %r5
  156         LOAD_LR_NIA
  157 1:
  158         mflr    %r5
  159         addi    %r5, %r5, (2f-1b)
  160         mtlr    %r5
  161         li      %r5, 0
  162         rfid
  163 2:
  164         RETURN_TO_NATIVE_ENDIAN
  165 #else
  166         /* Finally, branch to OF */
  167         mtctr   %r4
  168         bctrl
  169 #endif
  170 
  171         /* Reload stack pointer, MSR, and reference PC from the OFW stack */
  172         ld      %r7,32(%r1)
  173         ld      %r6,24(%r1)
  174         ld      %r2,16(%r1)
  175         ld      %r1,8(%r1)
  176 
  177         /* Get back to the MSR/PC we want, using the cached high bits of PC */
  178         mtsrr1  %r6
  179         clrrdi  %r7,%r7,32
  180         bl      1f
  181 1:      mflr    %r8
  182         or      %r8,%r8,%r7
  183         addi    %r8,%r8,2f-1b
  184         mtsrr0  %r8
  185         rfid                    /* Turn on MMU, exceptions, and 64-bit mode */
  186 
  187 2:
  188         /* Sign-extend the return value from OF */
  189         extsw   %r3,%r3
  190 
  191         /* Restore all the non-volatile registers */
  192         ld      %r5,48(%r1)
  193         mtcr    %r5
  194         ld      %r13,56(%r1)
  195         ld      %r14,64(%r1)
  196         ld      %r15,72(%r1)
  197         ld      %r16,80(%r1)
  198         ld      %r17,88(%r1)
  199         ld      %r18,96(%r1)
  200         ld      %r19,104(%r1)
  201         ld      %r20,112(%r1)
  202         ld      %r21,120(%r1)
  203         ld      %r22,128(%r1)
  204         ld      %r23,136(%r1)
  205         ld      %r24,144(%r1)
  206         ld      %r25,152(%r1)
  207         ld      %r26,160(%r1)
  208         ld      %r27,168(%r1)
  209         ld      %r28,176(%r1)
  210         ld      %r29,184(%r1)
  211         ld      %r30,192(%r1)
  212         ld      %r31,200(%r1)
  213 
  214         /* Restore the stack and link register */
  215         ld      %r1,0(%r1)
  216         ld      %r0,16(%r1)
  217         mtlr    %r0
  218         blr
  219 ASEND(ofwcall)
  220 
  221 /*
  222  * RTAS 32-bit Entry Point. Similar to the OF one, but simpler (no separate
  223  * stack)
  224  *
  225  * C prototype: int rtascall(void *callbuffer, void *rtas_privdat);
  226  */
  227 
  228 ASENTRY_NOPROF(rtascall)
  229         mflr    %r9
  230         std     %r9,16(%r1)
  231         stdu    %r1,-208(%r1)
  232 
  233         /*
  234          * We need to save the following, because RTAS's register save/
  235          * restore code assumes that the contents of registers are
  236          * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
  237          * get placed in that order in the stack.
  238          */
  239 
  240         mfcr    %r5
  241         std     %r5,48(%r1)
  242         std     %r13,56(%r1)
  243         std     %r14,64(%r1)
  244         std     %r15,72(%r1)
  245         std     %r16,80(%r1)
  246         std     %r17,88(%r1)
  247         std     %r18,96(%r1)
  248         std     %r19,104(%r1)
  249         std     %r20,112(%r1)
  250         std     %r21,120(%r1)
  251         std     %r22,128(%r1)
  252         std     %r23,136(%r1)
  253         std     %r24,144(%r1)
  254         std     %r25,152(%r1)
  255         std     %r26,160(%r1)
  256         std     %r27,168(%r1)
  257         std     %r28,176(%r1)
  258         std     %r29,184(%r1)
  259         std     %r30,192(%r1)
  260         std     %r31,200(%r1)
  261 
  262         /* Record the old MSR */
  263         mfmsr   %r6
  264 
  265         /* Read RTAS entry and reg save area pointers */
  266         addis   %r5,%r2,TOC_REF(rtas_entry)@ha
  267         ld      %r5,TOC_REF(rtas_entry)@l(%r5)
  268         ld      %r5,0(%r5)
  269         addis   %r8,%r2,TOC_REF(rtas_regsave)@ha
  270         ld      %r8,TOC_REF(rtas_regsave)@l(%r8)
  271 
  272         /*
  273          * Set the MSR to the RTAS value. This has the side effect of disabling
  274          * exceptions, which is important for the next few steps.
  275          */
  276 
  277         addis   %r7,%r2,TOC_REF(rtasmsr)@ha
  278         ld      %r7,TOC_REF(rtasmsr)@l(%r7)
  279         ld      %r7,0(%r7)
  280 #ifdef  __LITTLE_ENDIAN__
  281         /* QEMU hack: qemu does not emulate mtmsrd correctly! */
  282         ori     %r7,%r7,1       /* Leave PSR_LE set */
  283 #endif
  284         mtmsrd  %r7
  285         isync
  286 
  287         /*
  288          * Set up RTAS register save area, so that we can get back all of
  289          * our 64-bit pointers. Save our stack pointer, the TOC, and the MSR.
  290          * Put this in r1, since RTAS is obliged to save it. Kernel globals
  291          * are below 4 GB, so this is safe.
  292          */
  293         mr      %r7,%r1
  294         mr      %r1,%r8
  295         std     %r7,0(%r1)      /* Save 64-bit stack pointer */
  296         std     %r2,8(%r1)      /* Save TOC */
  297         std     %r6,16(%r1)     /* Save MSR */
  298         std     %r9,24(%r1)     /* Save reference PC for high 32 bits */
  299 
  300 #ifdef __LITTLE_ENDIAN__
  301         /* Atomic context switch w/ endian change */
  302         li      %r7, 0
  303         mtmsrd  %r7, 1  /* Clear PSL_EE|PSL_RI */
  304         addis   %r7,%r2,TOC_REF(rtasmsr)@ha
  305         ld      %r7,TOC_REF(rtasmsr)@l(%r7)
  306         ld      %r7,0(%r7)
  307         mtsrr0  %r5
  308         mtsrr1  %r7
  309         LOAD_LR_NIA
  310 1:
  311         mflr    %r5
  312         addi    %r5, %r5, (2f-1b)
  313         mtlr    %r5
  314         li      %r5, 0
  315         rfid
  316 2:
  317         RETURN_TO_NATIVE_ENDIAN
  318 #else
  319         /* Finally, branch to RTAS */
  320         mtctr   %r5
  321         bctrl
  322 #endif
  323 
  324         /* 
  325          * Reload stack pointer, MSR, reg PC from the reg save area in r1. We
  326          * are running in 32-bit mode at this point, so it doesn't matter if r1
  327          * has become sign-extended.
  328          */
  329         ld      %r7,24(%r1)
  330         ld      %r6,16(%r1)
  331         ld      %r2,8(%r1)
  332         ld      %r1,0(%r1)
  333 
  334         /*
  335          * Get back to the right PC. We need to atomically re-enable
  336          * exceptions, 64-bit mode, and the MMU. One thing that has likely
  337          * happened is that, if we were running in the high-memory direct
  338          * map, we no longer are as a result of LR truncation in RTAS.
  339          * Fix this by copying the high-order bits of the LR at function
  340          * entry onto the current PC and then jumping there while flipping
  341          * all the MSR bits.
  342          */
  343         mtsrr1  %r6
  344         clrrdi  %r7,%r7,32
  345         bl      1f
  346 1:      mflr    %r8
  347         or      %r8,%r8,%r7
  348         addi    %r8,%r8,2f-1b
  349         mtsrr0  %r8
  350         rfid                    /* Turn on MMU, exceptions, and 64-bit mode */
  351 
  352 2:
  353         /* Sign-extend the return value from RTAS */
  354         extsw   %r3,%r3
  355 
  356         /* Restore all the non-volatile registers */
  357         ld      %r5,48(%r1)
  358         mtcr    %r5
  359         ld      %r13,56(%r1)
  360         ld      %r14,64(%r1)
  361         ld      %r15,72(%r1)
  362         ld      %r16,80(%r1)
  363         ld      %r17,88(%r1)
  364         ld      %r18,96(%r1)
  365         ld      %r19,104(%r1)
  366         ld      %r20,112(%r1)
  367         ld      %r21,120(%r1)
  368         ld      %r22,128(%r1)
  369         ld      %r23,136(%r1)
  370         ld      %r24,144(%r1)
  371         ld      %r25,152(%r1)
  372         ld      %r26,160(%r1)
  373         ld      %r27,168(%r1)
  374         ld      %r28,176(%r1)
  375         ld      %r29,184(%r1)
  376         ld      %r30,192(%r1)
  377         ld      %r31,200(%r1)
  378 
  379         /* Restore the stack and link register */
  380         ld      %r1,0(%r1)
  381         ld      %r0,16(%r1)
  382         mtlr    %r0
  383         blr
  384 ASEND(rtascall)

Cache object: 60eb40c292e243088f43c56d19c39b7c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.