]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/powerpc/ofw/ofwcall64.S
amd64: use register macros for gdb_cpu_getreg()
[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 #include "opt_platform.h"
36
37 #define OFWSTKSZ        4096            /* 4K Open Firmware stack */
38
39 /*
40  * Globals
41  */
42         .data
43         .align  4
44 ofwstk:
45         .space  OFWSTKSZ
46 rtas_regsave:
47         .space  32 /* 4 * sizeof(register_t) */
48 GLOBAL(ofmsr)
49         .llong  0, 0, 0, 0, 0           /* msr/sprg0-3 used in Open Firmware */
50 GLOBAL(rtasmsr)
51         .llong  0
52 GLOBAL(openfirmware_entry)
53         .llong  0                       /* Open Firmware entry point */
54 GLOBAL(rtas_entry)
55         .llong  0                       /* RTAS entry point */
56
57 TOC_ENTRY(ofmsr)
58 TOC_ENTRY(ofwstk)
59 TOC_ENTRY(rtasmsr)
60 TOC_ENTRY(openfirmware_entry)
61 TOC_ENTRY(rtas_entry)
62 TOC_ENTRY(rtas_regsave)
63
64 /*
65  * Open Firmware Real-mode Entry Point. This is a huge pain.
66  */
67
68 ASENTRY_NOPROF(ofwcall)
69         mflr    %r8
70         std     %r8,16(%r1)
71         stdu    %r1,-208(%r1)
72
73         /*
74          * We need to save the following, because OF's register save/
75          * restore code assumes that the contents of registers are
76          * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
77          * get placed in that order in the stack.
78          */
79
80         mfcr    %r4
81         std     %r4,48(%r1)
82         std     %r13,56(%r1)
83         std     %r14,64(%r1)
84         std     %r15,72(%r1)
85         std     %r16,80(%r1)
86         std     %r17,88(%r1)
87         std     %r18,96(%r1)
88         std     %r19,104(%r1)
89         std     %r20,112(%r1)
90         std     %r21,120(%r1)
91         std     %r22,128(%r1)
92         std     %r23,136(%r1)
93         std     %r24,144(%r1)
94         std     %r25,152(%r1)
95         std     %r26,160(%r1)
96         std     %r27,168(%r1)
97         std     %r28,176(%r1)
98         std     %r29,184(%r1)
99         std     %r30,192(%r1)
100         std     %r31,200(%r1)
101
102         /* Record the old MSR */
103         mfmsr   %r6
104
105         /* read client interface handler */
106         addis   %r4,%r2,TOC_REF(openfirmware_entry)@ha
107         ld      %r4,TOC_REF(openfirmware_entry)@l(%r4)
108         ld      %r4,0(%r4)
109
110         /* Get OF stack pointer */
111         addis   %r7,%r2,TOC_REF(ofwstk)@ha
112         ld      %r7,TOC_REF(ofwstk)@l(%r7)
113         addi    %r7,%r7,OFWSTKSZ-40
114
115         /*
116          * Set the MSR to the OF value. This has the side effect of disabling
117          * exceptions, which is important for the next few steps.
118          * This does NOT, however, cause us to switch endianness.
119          */
120
121         addis   %r5,%r2,TOC_REF(ofmsr)@ha
122         ld      %r5,TOC_REF(ofmsr)@l(%r5)
123         ld      %r5,0(%r5)
124 #if defined(__LITTLE_ENDIAN__) && defined(QEMU)
125         /* QEMU hack: qemu does not emulate mtmsrd correctly! */
126         ori     %r5,%r5,1       /* Leave PSR_LE set */
127 #endif
128         mtmsrd  %r5
129         isync
130
131         /*
132          * Set up OF stack. This needs to be accessible in real mode and
133          * use the 32-bit ABI stack frame format. The pointer to the current
134          * kernel stack is placed at the very top of the stack along with
135          * the old MSR so we can get them back later.
136          */
137         mr      %r5,%r1
138         mr      %r1,%r7
139         std     %r5,8(%r1)      /* Save real stack pointer */
140         std     %r2,16(%r1)     /* Save old TOC */
141         std     %r6,24(%r1)     /* Save old MSR */
142         std     %r8,32(%r1)     /* Save high 32-bits of the kernel's PC */
143
144         li      %r5,0
145         stw     %r5,4(%r1)
146         stw     %r5,0(%r1)
147
148 #ifdef __LITTLE_ENDIAN__
149         /* Atomic context switch w/ endian change */
150         mtmsrd  %r5, 1  /* Clear PSL_EE|PSL_RI */
151         addis   %r5,%r2,TOC_REF(ofmsr)@ha
152         ld      %r5,TOC_REF(ofmsr)@l(%r5)
153         ld      %r5,0(%r5)
154         mtsrr0  %r4
155         mtsrr1  %r5
156         LOAD_LR_NIA
157 1:
158         mflr    %r5
159         addi    %r5, %r5, (2f-1b)
160         mtlr    %r5
161         li      %r5, 0
162         rfid
163 2:
164         RETURN_TO_NATIVE_ENDIAN
165 #else
166         /* Finally, branch to OF */
167         mtctr   %r4
168         bctrl
169 #endif
170
171         /* Reload stack pointer, MSR, and reference PC from the OFW stack */
172         ld      %r7,32(%r1)
173         ld      %r6,24(%r1)
174         ld      %r2,16(%r1)
175         ld      %r1,8(%r1)
176
177         /* Get back to the MSR/PC we want, using the cached high bits of PC */
178         mtsrr1  %r6
179         clrrdi  %r7,%r7,32
180         bl      1f
181 1:      mflr    %r8
182         or      %r8,%r8,%r7
183         addi    %r8,%r8,2f-1b
184         mtsrr0  %r8
185         rfid                    /* Turn on MMU, exceptions, and 64-bit mode */
186
187 2:
188         /* Sign-extend the return value from OF */
189         extsw   %r3,%r3
190
191         /* Restore all the non-volatile registers */
192         ld      %r5,48(%r1)
193         mtcr    %r5
194         ld      %r13,56(%r1)
195         ld      %r14,64(%r1)
196         ld      %r15,72(%r1)
197         ld      %r16,80(%r1)
198         ld      %r17,88(%r1)
199         ld      %r18,96(%r1)
200         ld      %r19,104(%r1)
201         ld      %r20,112(%r1)
202         ld      %r21,120(%r1)
203         ld      %r22,128(%r1)
204         ld      %r23,136(%r1)
205         ld      %r24,144(%r1)
206         ld      %r25,152(%r1)
207         ld      %r26,160(%r1)
208         ld      %r27,168(%r1)
209         ld      %r28,176(%r1)
210         ld      %r29,184(%r1)
211         ld      %r30,192(%r1)
212         ld      %r31,200(%r1)
213
214         /* Restore the stack and link register */
215         ld      %r1,0(%r1)
216         ld      %r0,16(%r1)
217         mtlr    %r0
218         blr
219 ASEND(ofwcall)
220
221 /*
222  * RTAS 32-bit Entry Point. Similar to the OF one, but simpler (no separate
223  * stack)
224  *
225  * C prototype: int rtascall(void *callbuffer, void *rtas_privdat);
226  */
227
228 ASENTRY_NOPROF(rtascall)
229         mflr    %r9
230         std     %r9,16(%r1)
231         stdu    %r1,-208(%r1)
232
233         /*
234          * We need to save the following, because RTAS's register save/
235          * restore code assumes that the contents of registers are
236          * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
237          * get placed in that order in the stack.
238          */
239
240         mfcr    %r5
241         std     %r5,48(%r1)
242         std     %r13,56(%r1)
243         std     %r14,64(%r1)
244         std     %r15,72(%r1)
245         std     %r16,80(%r1)
246         std     %r17,88(%r1)
247         std     %r18,96(%r1)
248         std     %r19,104(%r1)
249         std     %r20,112(%r1)
250         std     %r21,120(%r1)
251         std     %r22,128(%r1)
252         std     %r23,136(%r1)
253         std     %r24,144(%r1)
254         std     %r25,152(%r1)
255         std     %r26,160(%r1)
256         std     %r27,168(%r1)
257         std     %r28,176(%r1)
258         std     %r29,184(%r1)
259         std     %r30,192(%r1)
260         std     %r31,200(%r1)
261
262         /* Record the old MSR */
263         mfmsr   %r6
264
265         /* Read RTAS entry and reg save area pointers */
266         addis   %r5,%r2,TOC_REF(rtas_entry)@ha
267         ld      %r5,TOC_REF(rtas_entry)@l(%r5)
268         ld      %r5,0(%r5)
269         addis   %r8,%r2,TOC_REF(rtas_regsave)@ha
270         ld      %r8,TOC_REF(rtas_regsave)@l(%r8)
271
272         /*
273          * Set the MSR to the RTAS value. This has the side effect of disabling
274          * exceptions, which is important for the next few steps.
275          */
276
277         addis   %r7,%r2,TOC_REF(rtasmsr)@ha
278         ld      %r7,TOC_REF(rtasmsr)@l(%r7)
279         ld      %r7,0(%r7)
280 #ifdef  __LITTLE_ENDIAN__
281         /* QEMU hack: qemu does not emulate mtmsrd correctly! */
282         ori     %r7,%r7,1       /* Leave PSR_LE set */
283 #endif
284         mtmsrd  %r7
285         isync
286
287         /*
288          * Set up RTAS register save area, so that we can get back all of
289          * our 64-bit pointers. Save our stack pointer, the TOC, and the MSR.
290          * Put this in r1, since RTAS is obliged to save it. Kernel globals
291          * are below 4 GB, so this is safe.
292          */
293         mr      %r7,%r1
294         mr      %r1,%r8
295         std     %r7,0(%r1)      /* Save 64-bit stack pointer */
296         std     %r2,8(%r1)      /* Save TOC */
297         std     %r6,16(%r1)     /* Save MSR */
298         std     %r9,24(%r1)     /* Save reference PC for high 32 bits */
299
300 #ifdef __LITTLE_ENDIAN__
301         /* Atomic context switch w/ endian change */
302         li      %r7, 0
303         mtmsrd  %r7, 1  /* Clear PSL_EE|PSL_RI */
304         addis   %r7,%r2,TOC_REF(rtasmsr)@ha
305         ld      %r7,TOC_REF(rtasmsr)@l(%r7)
306         ld      %r7,0(%r7)
307         mtsrr0  %r5
308         mtsrr1  %r7
309         LOAD_LR_NIA
310 1:
311         mflr    %r5
312         addi    %r5, %r5, (2f-1b)
313         mtlr    %r5
314         li      %r5, 0
315         rfid
316 2:
317         RETURN_TO_NATIVE_ENDIAN
318 #else
319         /* Finally, branch to RTAS */
320         mtctr   %r5
321         bctrl
322 #endif
323
324         /* 
325          * Reload stack pointer, MSR, reg PC from the reg save area in r1. We
326          * are running in 32-bit mode at this point, so it doesn't matter if r1
327          * has become sign-extended.
328          */
329         ld      %r7,24(%r1)
330         ld      %r6,16(%r1)
331         ld      %r2,8(%r1)
332         ld      %r1,0(%r1)
333
334         /*
335          * Get back to the right PC. We need to atomically re-enable
336          * exceptions, 64-bit mode, and the MMU. One thing that has likely
337          * happened is that, if we were running in the high-memory direct
338          * map, we no longer are as a result of LR truncation in RTAS.
339          * Fix this by copying the high-order bits of the LR at function
340          * entry onto the current PC and then jumping there while flipping
341          * all the MSR bits.
342          */
343         mtsrr1  %r6
344         clrrdi  %r7,%r7,32
345         bl      1f
346 1:      mflr    %r8
347         or      %r8,%r8,%r7
348         addi    %r8,%r8,2f-1b
349         mtsrr0  %r8
350         rfid                    /* Turn on MMU, exceptions, and 64-bit mode */
351
352 2:
353         /* Sign-extend the return value from RTAS */
354         extsw   %r3,%r3
355
356         /* Restore all the non-volatile registers */
357         ld      %r5,48(%r1)
358         mtcr    %r5
359         ld      %r13,56(%r1)
360         ld      %r14,64(%r1)
361         ld      %r15,72(%r1)
362         ld      %r16,80(%r1)
363         ld      %r17,88(%r1)
364         ld      %r18,96(%r1)
365         ld      %r19,104(%r1)
366         ld      %r20,112(%r1)
367         ld      %r21,120(%r1)
368         ld      %r22,128(%r1)
369         ld      %r23,136(%r1)
370         ld      %r24,144(%r1)
371         ld      %r25,152(%r1)
372         ld      %r26,160(%r1)
373         ld      %r27,168(%r1)
374         ld      %r28,176(%r1)
375         ld      %r29,184(%r1)
376         ld      %r30,192(%r1)
377         ld      %r31,200(%r1)
378
379         /* Restore the stack and link register */
380         ld      %r1,0(%r1)
381         ld      %r0,16(%r1)
382         mtlr    %r0
383         blr
384 ASEND(rtascall)