]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/powerpc/ofw/ofwcall64.S
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.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 /*
56  * Open Firmware Real-mode Entry Point. This is a huge pain.
57  */
58
59 ASENTRY_NOPROF(ofwcall)
60         mflr    %r0
61         std     %r0,16(%r1)
62         stdu    %r1,-208(%r1)
63
64         /*
65          * We need to save the following, because OF's register save/
66          * restore code assumes that the contents of registers are
67          * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
68          * get placed in that order in the stack.
69          */
70
71         mfcr    %r4
72         std     %r4,48(%r1)
73         std     %r13,56(%r1)
74         std     %r14,64(%r1)
75         std     %r15,72(%r1)
76         std     %r16,80(%r1)
77         std     %r17,88(%r1)
78         std     %r18,96(%r1)
79         std     %r19,104(%r1)
80         std     %r20,112(%r1)
81         std     %r21,120(%r1)
82         std     %r22,128(%r1)
83         std     %r23,136(%r1)
84         std     %r24,144(%r1)
85         std     %r25,152(%r1)
86         std     %r26,160(%r1)
87         std     %r27,168(%r1)
88         std     %r28,176(%r1)
89         std     %r29,184(%r1)
90         std     %r30,192(%r1)
91         std     %r31,200(%r1)
92
93         /* Record the old MSR */
94         mfmsr   %r6
95
96         /* read client interface handler */
97         lis     %r4,openfirmware_entry@ha
98         ld      %r4,openfirmware_entry@l(%r4)
99
100         /*
101          * Set the MSR to the OF value. This has the side effect of disabling
102          * exceptions, which is important for the next few steps.
103          */
104
105         lis     %r5,ofmsr@ha
106         ld      %r5,ofmsr@l(%r5)
107         mtmsrd  %r5
108         isync
109
110         /*
111          * Set up OF stack. This needs to be accessible in real mode and
112          * use the 32-bit ABI stack frame format. The pointer to the current
113          * kernel stack is placed at the very top of the stack along with
114          * the old MSR so we can get them back later.
115          */
116         mr      %r5,%r1
117         lis     %r1,(ofwstk+OFWSTKSZ-32)@ha
118         addi    %r1,%r1,(ofwstk+OFWSTKSZ-32)@l
119         std     %r5,8(%r1)      /* Save real stack pointer */
120         std     %r2,16(%r1)     /* Save old TOC */
121         std     %r6,24(%r1)     /* Save old MSR */
122         li      %r5,0
123         stw     %r5,4(%r1)
124         stw     %r5,0(%r1)
125
126         /* Finally, branch to OF */
127         mtctr   %r4
128         bctrl
129
130         /* Reload stack pointer and MSR from the OFW stack */
131         ld      %r6,24(%r1)
132         ld      %r2,16(%r1)
133         ld      %r1,8(%r1)
134
135         /* Now set the real MSR */
136         mtmsrd  %r6
137         isync
138
139         /* Sign-extend the return value from OF */
140         extsw   %r3,%r3
141
142         /* Restore all the non-volatile registers */
143         ld      %r5,48(%r1)
144         mtcr    %r5
145         ld      %r13,56(%r1)
146         ld      %r14,64(%r1)
147         ld      %r15,72(%r1)
148         ld      %r16,80(%r1)
149         ld      %r17,88(%r1)
150         ld      %r18,96(%r1)
151         ld      %r19,104(%r1)
152         ld      %r20,112(%r1)
153         ld      %r21,120(%r1)
154         ld      %r22,128(%r1)
155         ld      %r23,136(%r1)
156         ld      %r24,144(%r1)
157         ld      %r25,152(%r1)
158         ld      %r26,160(%r1)
159         ld      %r27,168(%r1)
160         ld      %r28,176(%r1)
161         ld      %r29,184(%r1)
162         ld      %r30,192(%r1)
163         ld      %r31,200(%r1)
164
165         /* Restore the stack and link register */
166         ld      %r1,0(%r1)
167         ld      %r0,16(%r1)
168         mtlr    %r0
169         blr
170
171 /*
172  * RTAS 32-bit Entry Point. Similar to the OF one, but simpler (no separate
173  * stack)
174  *
175  * C prototype: int rtascall(void *callbuffer, void *rtas_privdat);
176  */
177
178 ASENTRY_NOPROF(rtascall)
179         mflr    %r0
180         std     %r0,16(%r1)
181         stdu    %r1,-208(%r1)
182
183         /*
184          * We need to save the following, because RTAS's register save/
185          * restore code assumes that the contents of registers are
186          * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
187          * get placed in that order in the stack.
188          */
189
190         mfcr    %r5
191         std     %r5,48(%r1)
192         std     %r13,56(%r1)
193         std     %r14,64(%r1)
194         std     %r15,72(%r1)
195         std     %r16,80(%r1)
196         std     %r17,88(%r1)
197         std     %r18,96(%r1)
198         std     %r19,104(%r1)
199         std     %r20,112(%r1)
200         std     %r21,120(%r1)
201         std     %r22,128(%r1)
202         std     %r23,136(%r1)
203         std     %r24,144(%r1)
204         std     %r25,152(%r1)
205         std     %r26,160(%r1)
206         std     %r27,168(%r1)
207         std     %r28,176(%r1)
208         std     %r29,184(%r1)
209         std     %r30,192(%r1)
210         std     %r31,200(%r1)
211
212         /* Record the old MSR */
213         mfmsr   %r6
214
215         /* read client interface handler */
216         lis     %r5,rtas_entry@ha
217         ld      %r5,rtas_entry@l(%r5)
218
219         /*
220          * Set the MSR to the RTAS value. This has the side effect of disabling
221          * exceptions, which is important for the next few steps.
222          */
223
224         lis     %r7,rtasmsr@ha
225         ld      %r7,rtasmsr@l(%r7)
226         mtmsrd  %r7
227         isync
228
229         /*
230          * Set up RTAS register save area, so that we can get back all of
231          * our 64-bit pointers. Save our stack pointer, the TOC, and the MSR.
232          * Put this in r1, since RTAS is obliged to save it. Kernel globals
233          * are below 4 GB, so this is safe.
234          */
235         mr      %r7,%r1
236         lis     %r1,rtas_regsave@ha
237         addi    %r1,%r1,rtas_regsave@l
238         std     %r7,0(%r1)      /* Save 64-bit stack pointer */
239         std     %r2,8(%r1)      /* Save TOC */
240         std     %r6,16(%r1)     /* Save MSR */
241
242         /* Finally, branch to RTAS */
243         mtctr   %r5
244         bctrl
245
246         /* 
247          * Reload stack pointer and MSR from the reg save area in r1. We are
248          * running in 32-bit mode at this point, so it doesn't matter if r1
249          * has become sign-extended.
250          */
251         ld      %r6,16(%r1)
252         ld      %r2,8(%r1)
253         ld      %r1,0(%r1)
254
255         /* Now set the real MSR */
256         mtmsrd  %r6
257         isync
258
259         /* Sign-extend the return value from RTAS */
260         extsw   %r3,%r3
261
262         /* Restore all the non-volatile registers */
263         ld      %r5,48(%r1)
264         mtcr    %r5
265         ld      %r13,56(%r1)
266         ld      %r14,64(%r1)
267         ld      %r15,72(%r1)
268         ld      %r16,80(%r1)
269         ld      %r17,88(%r1)
270         ld      %r18,96(%r1)
271         ld      %r19,104(%r1)
272         ld      %r20,112(%r1)
273         ld      %r21,120(%r1)
274         ld      %r22,128(%r1)
275         ld      %r23,136(%r1)
276         ld      %r24,144(%r1)
277         ld      %r25,152(%r1)
278         ld      %r26,160(%r1)
279         ld      %r27,168(%r1)
280         ld      %r28,176(%r1)
281         ld      %r29,184(%r1)
282         ld      %r30,192(%r1)
283         ld      %r31,200(%r1)
284
285         /* Restore the stack and link register */
286         ld      %r1,0(%r1)
287         ld      %r0,16(%r1)
288         mtlr    %r0
289         blr
290