2 * Copyright (C) 2009-2011 Nathan Whitehorn
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
28 #include <sys/syscall.h>
30 #include <machine/trap.h>
31 #include <machine/param.h>
32 #include <machine/spr.h>
33 #include <machine/asm.h>
35 #define OFWSTKSZ 4096 /* 4K Open Firmware stack */
45 .space 32 /* 4 * sizeof(register_t) */
47 .llong 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */
50 GLOBAL(openfirmware_entry)
51 .llong 0 /* Open Firmware entry point */
53 .llong 0 /* RTAS entry point */
58 TOC_ENTRY(openfirmware_entry)
60 TOC_ENTRY(rtas_regsave)
63 * Open Firmware Real-mode Entry Point. This is a huge pain.
66 ASENTRY_NOPROF(ofwcall)
72 * We need to save the following, because OF's register save/
73 * restore code assumes that the contents of registers are
74 * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
75 * get placed in that order in the stack.
100 /* Record the old MSR */
103 /* read client interface handler */
104 addis %r4,%r2,TOC_REF(openfirmware_entry)@ha
105 ld %r4,TOC_REF(openfirmware_entry)@l(%r4)
108 /* Get OF stack pointer */
109 addis %r7,%r2,TOC_REF(ofwstk)@ha
110 ld %r7,TOC_REF(ofwstk)@l(%r7)
111 addi %r7,%r7,OFWSTKSZ-40
114 * Set the MSR to the OF value. This has the side effect of disabling
115 * exceptions, which is important for the next few steps.
118 addis %r5,%r2,TOC_REF(ofmsr)@ha
119 ld %r5,TOC_REF(ofmsr)@l(%r5)
125 * Set up OF stack. This needs to be accessible in real mode and
126 * use the 32-bit ABI stack frame format. The pointer to the current
127 * kernel stack is placed at the very top of the stack along with
128 * the old MSR so we can get them back later.
132 std %r5,8(%r1) /* Save real stack pointer */
133 std %r2,16(%r1) /* Save old TOC */
134 std %r6,24(%r1) /* Save old MSR */
135 std %r8,32(%r1) /* Save high 32-bits of the kernel's PC */
141 /* Finally, branch to OF */
145 /* Reload stack pointer, MSR, and reference PC from the OFW stack */
151 /* Get back to the MSR/PC we want, using the cached high bits of PC */
159 rfid /* Turn on MMU, exceptions, and 64-bit mode */
162 /* Sign-extend the return value from OF */
165 /* Restore all the non-volatile registers */
188 /* Restore the stack and link register */
195 * RTAS 32-bit Entry Point. Similar to the OF one, but simpler (no separate
198 * C prototype: int rtascall(void *callbuffer, void *rtas_privdat);
201 ASENTRY_NOPROF(rtascall)
207 * We need to save the following, because RTAS's register save/
208 * restore code assumes that the contents of registers are
209 * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
210 * get placed in that order in the stack.
235 /* Record the old MSR */
238 /* Read RTAS entry and reg save area pointers */
239 addis %r5,%r2,TOC_REF(rtas_entry)@ha
240 ld %r5,TOC_REF(rtas_entry)@l(%r5)
242 addis %r8,%r2,TOC_REF(rtas_regsave)@ha
243 ld %r8,TOC_REF(rtas_regsave)@l(%r8)
246 * Set the MSR to the RTAS value. This has the side effect of disabling
247 * exceptions, which is important for the next few steps.
250 addis %r7,%r2,TOC_REF(rtasmsr)@ha
251 ld %r7,TOC_REF(rtasmsr)@l(%r7)
257 * Set up RTAS register save area, so that we can get back all of
258 * our 64-bit pointers. Save our stack pointer, the TOC, and the MSR.
259 * Put this in r1, since RTAS is obliged to save it. Kernel globals
260 * are below 4 GB, so this is safe.
264 std %r7,0(%r1) /* Save 64-bit stack pointer */
265 std %r2,8(%r1) /* Save TOC */
266 std %r6,16(%r1) /* Save MSR */
267 std %r9,24(%r1) /* Save reference PC for high 32 bits */
269 /* Finally, branch to RTAS */
274 * Reload stack pointer, MSR, reg PC from the reg save area in r1. We
275 * are running in 32-bit mode at this point, so it doesn't matter if r1
276 * has become sign-extended.
284 * Get back to the right PC. We need to atomically re-enable
285 * exceptions, 64-bit mode, and the MMU. One thing that has likely
286 * happened is that, if we were running in the high-memory direct
287 * map, we no longer are as a result of LR truncation in RTAS.
288 * Fix this by copying the high-order bits of the LR at function
289 * entry onto the current PC and then jumping there while flipping
299 rfid /* Turn on MMU, exceptions, and 64-bit mode */
302 /* Sign-extend the return value from RTAS */
305 /* Restore all the non-volatile registers */
328 /* Restore the stack and link register */