]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/powerpc/ofw/ofwcall64.S
Merge OpenSSL 1.1.1a.
[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         ld      %r4,TOC_REF(openfirmware_entry)(%r2)
105         ld      %r4,0(%r4)
106
107         /* Get OF stack pointer */
108         ld      %r7,TOC_REF(ofwstk)(%r2)
109         addi    %r7,%r7,OFWSTKSZ-40
110
111         /*
112          * Set the MSR to the OF value. This has the side effect of disabling
113          * exceptions, which is important for the next few steps.
114          */
115
116         ld      %r5,TOC_REF(ofmsr)(%r2)
117         ld      %r5,0(%r5)
118         mtmsrd  %r5
119         isync
120
121         /*
122          * Set up OF stack. This needs to be accessible in real mode and
123          * use the 32-bit ABI stack frame format. The pointer to the current
124          * kernel stack is placed at the very top of the stack along with
125          * the old MSR so we can get them back later.
126          */
127         mr      %r5,%r1
128         mr      %r1,%r7
129         std     %r5,8(%r1)      /* Save real stack pointer */
130         std     %r2,16(%r1)     /* Save old TOC */
131         std     %r6,24(%r1)     /* Save old MSR */
132         std     %r8,32(%r1)     /* Save high 32-bits of the kernel's PC */
133
134         li      %r5,0
135         stw     %r5,4(%r1)
136         stw     %r5,0(%r1)
137
138         /* Finally, branch to OF */
139         mtctr   %r4
140         bctrl
141
142         /* Reload stack pointer, MSR, and reference PC from the OFW stack */
143         ld      %r7,32(%r1)
144         ld      %r6,24(%r1)
145         ld      %r2,16(%r1)
146         ld      %r1,8(%r1)
147
148         /* Get back to the MSR/PC we want, using the cached high bits of PC */
149         mtsrr1  %r6
150         clrrdi  %r7,%r7,32
151         bl      1f
152 1:      mflr    %r8
153         or      %r8,%r8,%r7
154         addi    %r8,%r8,2f-1b
155         mtsrr0  %r8
156         rfid                    /* Turn on MMU, exceptions, and 64-bit mode */
157
158 2:
159         /* Sign-extend the return value from OF */
160         extsw   %r3,%r3
161
162         /* Restore all the non-volatile registers */
163         ld      %r5,48(%r1)
164         mtcr    %r5
165         ld      %r13,56(%r1)
166         ld      %r14,64(%r1)
167         ld      %r15,72(%r1)
168         ld      %r16,80(%r1)
169         ld      %r17,88(%r1)
170         ld      %r18,96(%r1)
171         ld      %r19,104(%r1)
172         ld      %r20,112(%r1)
173         ld      %r21,120(%r1)
174         ld      %r22,128(%r1)
175         ld      %r23,136(%r1)
176         ld      %r24,144(%r1)
177         ld      %r25,152(%r1)
178         ld      %r26,160(%r1)
179         ld      %r27,168(%r1)
180         ld      %r28,176(%r1)
181         ld      %r29,184(%r1)
182         ld      %r30,192(%r1)
183         ld      %r31,200(%r1)
184
185         /* Restore the stack and link register */
186         ld      %r1,0(%r1)
187         ld      %r0,16(%r1)
188         mtlr    %r0
189         blr
190
191 /*
192  * RTAS 32-bit Entry Point. Similar to the OF one, but simpler (no separate
193  * stack)
194  *
195  * C prototype: int rtascall(void *callbuffer, void *rtas_privdat);
196  */
197
198 ASENTRY_NOPROF(rtascall)
199         mflr    %r9
200         std     %r9,16(%r1)
201         stdu    %r1,-208(%r1)
202
203         /*
204          * We need to save the following, because RTAS's register save/
205          * restore code assumes that the contents of registers are
206          * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
207          * get placed in that order in the stack.
208          */
209
210         mfcr    %r5
211         std     %r5,48(%r1)
212         std     %r13,56(%r1)
213         std     %r14,64(%r1)
214         std     %r15,72(%r1)
215         std     %r16,80(%r1)
216         std     %r17,88(%r1)
217         std     %r18,96(%r1)
218         std     %r19,104(%r1)
219         std     %r20,112(%r1)
220         std     %r21,120(%r1)
221         std     %r22,128(%r1)
222         std     %r23,136(%r1)
223         std     %r24,144(%r1)
224         std     %r25,152(%r1)
225         std     %r26,160(%r1)
226         std     %r27,168(%r1)
227         std     %r28,176(%r1)
228         std     %r29,184(%r1)
229         std     %r30,192(%r1)
230         std     %r31,200(%r1)
231
232         /* Record the old MSR */
233         mfmsr   %r6
234
235         /* Read RTAS entry and reg save area pointers */
236         ld      %r5,TOC_REF(rtas_entry)(%r2)
237         ld      %r5,0(%r5)
238         ld      %r8,TOC_REF(rtas_regsave)(%r2)
239
240         /*
241          * Set the MSR to the RTAS value. This has the side effect of disabling
242          * exceptions, which is important for the next few steps.
243          */
244
245         ld      %r7,TOC_REF(rtasmsr)(%r2)
246         ld      %r7,0(%r7)
247         mtmsrd  %r7
248         isync
249
250         /*
251          * Set up RTAS register save area, so that we can get back all of
252          * our 64-bit pointers. Save our stack pointer, the TOC, and the MSR.
253          * Put this in r1, since RTAS is obliged to save it. Kernel globals
254          * are below 4 GB, so this is safe.
255          */
256         mr      %r7,%r1
257         mr      %r1,%r8
258         std     %r7,0(%r1)      /* Save 64-bit stack pointer */
259         std     %r2,8(%r1)      /* Save TOC */
260         std     %r6,16(%r1)     /* Save MSR */
261         std     %r9,24(%r1)     /* Save reference PC for high 32 bits */
262
263         /* Finally, branch to RTAS */
264         mtctr   %r5
265         bctrl
266
267         /* 
268          * Reload stack pointer, MSR, reg PC from the reg save area in r1. We
269          * are running in 32-bit mode at this point, so it doesn't matter if r1
270          * has become sign-extended.
271          */
272         ld      %r7,24(%r1)
273         ld      %r6,16(%r1)
274         ld      %r2,8(%r1)
275         ld      %r1,0(%r1)
276
277         /*
278          * Get back to the right PC. We need to atomically re-enable
279          * exceptions, 64-bit mode, and the MMU. One thing that has likely
280          * happened is that, if we were running in the high-memory direct
281          * map, we no longer are as a result of LR truncation in RTAS.
282          * Fix this by copying the high-order bits of the LR at function
283          * entry onto the current PC and then jumping there while flipping
284          * all the MSR bits.
285          */
286         mtsrr1  %r6
287         clrrdi  %r7,%r7,32
288         bl      1f
289 1:      mflr    %r8
290         or      %r8,%r8,%r7
291         addi    %r8,%r8,2f-1b
292         mtsrr0  %r8
293         rfid                    /* Turn on MMU, exceptions, and 64-bit mode */
294
295 2:
296         /* Sign-extend the return value from RTAS */
297         extsw   %r3,%r3
298
299         /* Restore all the non-volatile registers */
300         ld      %r5,48(%r1)
301         mtcr    %r5
302         ld      %r13,56(%r1)
303         ld      %r14,64(%r1)
304         ld      %r15,72(%r1)
305         ld      %r16,80(%r1)
306         ld      %r17,88(%r1)
307         ld      %r18,96(%r1)
308         ld      %r19,104(%r1)
309         ld      %r20,112(%r1)
310         ld      %r21,120(%r1)
311         ld      %r22,128(%r1)
312         ld      %r23,136(%r1)
313         ld      %r24,144(%r1)
314         ld      %r25,152(%r1)
315         ld      %r26,160(%r1)
316         ld      %r27,168(%r1)
317         ld      %r28,176(%r1)
318         ld      %r29,184(%r1)
319         ld      %r30,192(%r1)
320         ld      %r31,200(%r1)
321
322         /* Restore the stack and link register */
323         ld      %r1,0(%r1)
324         ld      %r0,16(%r1)
325         mtlr    %r0
326         blr
327