]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/powerpc/ofw/ofwcall64.S
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / sys / powerpc / ofw / ofwcall64.S
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 #define OFWSTKSZ        4096            /* 4K Open Firmware stack */
36
37 /*
38  * Globals
39  */
40         .data
41         .align  4
42 ofwstk:
43         .space  OFWSTKSZ
44 rtas_regsave:
45         .space  32 /* 4 * sizeof(register_t) */
46 GLOBAL(ofmsr)
47         .llong  0, 0, 0, 0, 0           /* msr/sprg0-3 used in Open Firmware */
48 GLOBAL(rtasmsr)
49         .llong  0
50 GLOBAL(openfirmware_entry)
51         .llong  0                       /* Open Firmware entry point */
52 GLOBAL(rtas_entry)
53         .llong  0                       /* RTAS entry point */
54
55 TOC_ENTRY(ofmsr)
56 TOC_ENTRY(ofwstk)
57 TOC_ENTRY(rtasmsr)
58 TOC_ENTRY(openfirmware_entry)
59 TOC_ENTRY(rtas_entry)
60 TOC_ENTRY(rtas_regsave)
61
62 /*
63  * Open Firmware Real-mode Entry Point. This is a huge pain.
64  */
65
66 ASENTRY_NOPROF(ofwcall)
67         mflr    %r8
68         std     %r8,16(%r1)
69         stdu    %r1,-208(%r1)
70
71         /*
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.
76          */
77
78         mfcr    %r4
79         std     %r4,48(%r1)
80         std     %r13,56(%r1)
81         std     %r14,64(%r1)
82         std     %r15,72(%r1)
83         std     %r16,80(%r1)
84         std     %r17,88(%r1)
85         std     %r18,96(%r1)
86         std     %r19,104(%r1)
87         std     %r20,112(%r1)
88         std     %r21,120(%r1)
89         std     %r22,128(%r1)
90         std     %r23,136(%r1)
91         std     %r24,144(%r1)
92         std     %r25,152(%r1)
93         std     %r26,160(%r1)
94         std     %r27,168(%r1)
95         std     %r28,176(%r1)
96         std     %r29,184(%r1)
97         std     %r30,192(%r1)
98         std     %r31,200(%r1)
99
100         /* Record the old MSR */
101         mfmsr   %r6
102
103         /* read client interface handler */
104         addis   %r4,%r2,TOC_REF(openfirmware_entry)@ha
105         ld      %r4,TOC_REF(openfirmware_entry)@l(%r4)
106         ld      %r4,0(%r4)
107
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
112
113         /*
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.
116          */
117
118         addis   %r5,%r2,TOC_REF(ofmsr)@ha
119         ld      %r5,TOC_REF(ofmsr)@l(%r5)
120         ld      %r5,0(%r5)
121         mtmsrd  %r5
122         isync
123
124         /*
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.
129          */
130         mr      %r5,%r1
131         mr      %r1,%r7
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 */
136
137         li      %r5,0
138         stw     %r5,4(%r1)
139         stw     %r5,0(%r1)
140
141         /* Finally, branch to OF */
142         mtctr   %r4
143         bctrl
144
145         /* Reload stack pointer, MSR, and reference PC from the OFW stack */
146         ld      %r7,32(%r1)
147         ld      %r6,24(%r1)
148         ld      %r2,16(%r1)
149         ld      %r1,8(%r1)
150
151         /* Get back to the MSR/PC we want, using the cached high bits of PC */
152         mtsrr1  %r6
153         clrrdi  %r7,%r7,32
154         bl      1f
155 1:      mflr    %r8
156         or      %r8,%r8,%r7
157         addi    %r8,%r8,2f-1b
158         mtsrr0  %r8
159         rfid                    /* Turn on MMU, exceptions, and 64-bit mode */
160
161 2:
162         /* Sign-extend the return value from OF */
163         extsw   %r3,%r3
164
165         /* Restore all the non-volatile registers */
166         ld      %r5,48(%r1)
167         mtcr    %r5
168         ld      %r13,56(%r1)
169         ld      %r14,64(%r1)
170         ld      %r15,72(%r1)
171         ld      %r16,80(%r1)
172         ld      %r17,88(%r1)
173         ld      %r18,96(%r1)
174         ld      %r19,104(%r1)
175         ld      %r20,112(%r1)
176         ld      %r21,120(%r1)
177         ld      %r22,128(%r1)
178         ld      %r23,136(%r1)
179         ld      %r24,144(%r1)
180         ld      %r25,152(%r1)
181         ld      %r26,160(%r1)
182         ld      %r27,168(%r1)
183         ld      %r28,176(%r1)
184         ld      %r29,184(%r1)
185         ld      %r30,192(%r1)
186         ld      %r31,200(%r1)
187
188         /* Restore the stack and link register */
189         ld      %r1,0(%r1)
190         ld      %r0,16(%r1)
191         mtlr    %r0
192         blr
193
194 /*
195  * RTAS 32-bit Entry Point. Similar to the OF one, but simpler (no separate
196  * stack)
197  *
198  * C prototype: int rtascall(void *callbuffer, void *rtas_privdat);
199  */
200
201 ASENTRY_NOPROF(rtascall)
202         mflr    %r9
203         std     %r9,16(%r1)
204         stdu    %r1,-208(%r1)
205
206         /*
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.
211          */
212
213         mfcr    %r5
214         std     %r5,48(%r1)
215         std     %r13,56(%r1)
216         std     %r14,64(%r1)
217         std     %r15,72(%r1)
218         std     %r16,80(%r1)
219         std     %r17,88(%r1)
220         std     %r18,96(%r1)
221         std     %r19,104(%r1)
222         std     %r20,112(%r1)
223         std     %r21,120(%r1)
224         std     %r22,128(%r1)
225         std     %r23,136(%r1)
226         std     %r24,144(%r1)
227         std     %r25,152(%r1)
228         std     %r26,160(%r1)
229         std     %r27,168(%r1)
230         std     %r28,176(%r1)
231         std     %r29,184(%r1)
232         std     %r30,192(%r1)
233         std     %r31,200(%r1)
234
235         /* Record the old MSR */
236         mfmsr   %r6
237
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)
241         ld      %r5,0(%r5)
242         addis   %r8,%r2,TOC_REF(rtas_regsave)@ha
243         ld      %r8,TOC_REF(rtas_regsave)@l(%r8)
244
245         /*
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.
248          */
249
250         addis   %r7,%r2,TOC_REF(rtasmsr)@ha
251         ld      %r7,TOC_REF(rtasmsr)@l(%r7)
252         ld      %r7,0(%r7)
253         mtmsrd  %r7
254         isync
255
256         /*
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.
261          */
262         mr      %r7,%r1
263         mr      %r1,%r8
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 */
268
269         /* Finally, branch to RTAS */
270         mtctr   %r5
271         bctrl
272
273         /* 
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.
277          */
278         ld      %r7,24(%r1)
279         ld      %r6,16(%r1)
280         ld      %r2,8(%r1)
281         ld      %r1,0(%r1)
282
283         /*
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
290          * all the MSR bits.
291          */
292         mtsrr1  %r6
293         clrrdi  %r7,%r7,32
294         bl      1f
295 1:      mflr    %r8
296         or      %r8,%r8,%r7
297         addi    %r8,%r8,2f-1b
298         mtsrr0  %r8
299         rfid                    /* Turn on MMU, exceptions, and 64-bit mode */
300
301 2:
302         /* Sign-extend the return value from RTAS */
303         extsw   %r3,%r3
304
305         /* Restore all the non-volatile registers */
306         ld      %r5,48(%r1)
307         mtcr    %r5
308         ld      %r13,56(%r1)
309         ld      %r14,64(%r1)
310         ld      %r15,72(%r1)
311         ld      %r16,80(%r1)
312         ld      %r17,88(%r1)
313         ld      %r18,96(%r1)
314         ld      %r19,104(%r1)
315         ld      %r20,112(%r1)
316         ld      %r21,120(%r1)
317         ld      %r22,128(%r1)
318         ld      %r23,136(%r1)
319         ld      %r24,144(%r1)
320         ld      %r25,152(%r1)
321         ld      %r26,160(%r1)
322         ld      %r27,168(%r1)
323         ld      %r28,176(%r1)
324         ld      %r29,184(%r1)
325         ld      %r30,192(%r1)
326         ld      %r31,200(%r1)
327
328         /* Restore the stack and link register */
329         ld      %r1,0(%r1)
330         ld      %r0,16(%r1)
331         mtlr    %r0
332         blr
333