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: releng/11.1/sys/powerpc/ofw/ofwcall64.S 277335 2015-01-18 20:00:33Z nwhitehorn $
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
Cache object: 92da645b7ab61ba3dfe08ff26f42c662
|