]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/powerpc/ofw/ofwcall64.S
Add ELF Tool Chain's ar(1) and elfdump(1) to contrib
[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  24 /* 3 * 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    %r0
68         std     %r0,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-32
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         li      %r5,0
133         stw     %r5,4(%r1)
134         stw     %r5,0(%r1)
135
136         /* Finally, branch to OF */
137         mtctr   %r4
138         bctrl
139
140         /* Reload stack pointer and MSR from the OFW stack */
141         ld      %r6,24(%r1)
142         ld      %r2,16(%r1)
143         ld      %r1,8(%r1)
144
145         /* Now set the real MSR */
146         mtmsrd  %r6
147         isync
148
149         /* Sign-extend the return value from OF */
150         extsw   %r3,%r3
151
152         /* Restore all the non-volatile registers */
153         ld      %r5,48(%r1)
154         mtcr    %r5
155         ld      %r13,56(%r1)
156         ld      %r14,64(%r1)
157         ld      %r15,72(%r1)
158         ld      %r16,80(%r1)
159         ld      %r17,88(%r1)
160         ld      %r18,96(%r1)
161         ld      %r19,104(%r1)
162         ld      %r20,112(%r1)
163         ld      %r21,120(%r1)
164         ld      %r22,128(%r1)
165         ld      %r23,136(%r1)
166         ld      %r24,144(%r1)
167         ld      %r25,152(%r1)
168         ld      %r26,160(%r1)
169         ld      %r27,168(%r1)
170         ld      %r28,176(%r1)
171         ld      %r29,184(%r1)
172         ld      %r30,192(%r1)
173         ld      %r31,200(%r1)
174
175         /* Restore the stack and link register */
176         ld      %r1,0(%r1)
177         ld      %r0,16(%r1)
178         mtlr    %r0
179         blr
180
181 /*
182  * RTAS 32-bit Entry Point. Similar to the OF one, but simpler (no separate
183  * stack)
184  *
185  * C prototype: int rtascall(void *callbuffer, void *rtas_privdat);
186  */
187
188 ASENTRY_NOPROF(rtascall)
189         mflr    %r0
190         std     %r0,16(%r1)
191         stdu    %r1,-208(%r1)
192
193         /*
194          * We need to save the following, because RTAS's register save/
195          * restore code assumes that the contents of registers are
196          * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
197          * get placed in that order in the stack.
198          */
199
200         mfcr    %r5
201         std     %r5,48(%r1)
202         std     %r13,56(%r1)
203         std     %r14,64(%r1)
204         std     %r15,72(%r1)
205         std     %r16,80(%r1)
206         std     %r17,88(%r1)
207         std     %r18,96(%r1)
208         std     %r19,104(%r1)
209         std     %r20,112(%r1)
210         std     %r21,120(%r1)
211         std     %r22,128(%r1)
212         std     %r23,136(%r1)
213         std     %r24,144(%r1)
214         std     %r25,152(%r1)
215         std     %r26,160(%r1)
216         std     %r27,168(%r1)
217         std     %r28,176(%r1)
218         std     %r29,184(%r1)
219         std     %r30,192(%r1)
220         std     %r31,200(%r1)
221
222         /* Record the old MSR */
223         mfmsr   %r6
224
225         /* Read RTAS entry and reg save area pointers */
226         ld      %r5,TOC_REF(rtas_entry)(%r2)
227         ld      %r5,0(%r5)
228         ld      %r8,TOC_REF(rtas_regsave)(%r2)
229
230         /*
231          * Set the MSR to the RTAS value. This has the side effect of disabling
232          * exceptions, which is important for the next few steps.
233          */
234
235         ld      %r7,TOC_REF(rtasmsr)(%r2)
236         ld      %r7,0(%r7)
237         mtmsrd  %r7
238         isync
239
240         /*
241          * Set up RTAS register save area, so that we can get back all of
242          * our 64-bit pointers. Save our stack pointer, the TOC, and the MSR.
243          * Put this in r1, since RTAS is obliged to save it. Kernel globals
244          * are below 4 GB, so this is safe.
245          */
246         mr      %r7,%r1
247         mr      %r1,%r8
248         std     %r7,0(%r1)      /* Save 64-bit stack pointer */
249         std     %r2,8(%r1)      /* Save TOC */
250         std     %r6,16(%r1)     /* Save MSR */
251
252         /* Finally, branch to RTAS */
253         mtctr   %r5
254         bctrl
255
256         /* 
257          * Reload stack pointer and MSR from the reg save area in r1. We are
258          * running in 32-bit mode at this point, so it doesn't matter if r1
259          * has become sign-extended.
260          */
261         ld      %r6,16(%r1)
262         ld      %r2,8(%r1)
263         ld      %r1,0(%r1)
264
265         /* Now set the real MSR */
266         mtmsrd  %r6
267         isync
268
269         /* Sign-extend the return value from RTAS */
270         extsw   %r3,%r3
271
272         /* Restore all the non-volatile registers */
273         ld      %r5,48(%r1)
274         mtcr    %r5
275         ld      %r13,56(%r1)
276         ld      %r14,64(%r1)
277         ld      %r15,72(%r1)
278         ld      %r16,80(%r1)
279         ld      %r17,88(%r1)
280         ld      %r18,96(%r1)
281         ld      %r19,104(%r1)
282         ld      %r20,112(%r1)
283         ld      %r21,120(%r1)
284         ld      %r22,128(%r1)
285         ld      %r23,136(%r1)
286         ld      %r24,144(%r1)
287         ld      %r25,152(%r1)
288         ld      %r26,160(%r1)
289         ld      %r27,168(%r1)
290         ld      %r28,176(%r1)
291         ld      %r29,184(%r1)
292         ld      %r30,192(%r1)
293         ld      %r31,200(%r1)
294
295         /* Restore the stack and link register */
296         ld      %r1,0(%r1)
297         ld      %r0,16(%r1)
298         mtlr    %r0
299         blr
300