ofw_subr.S revision 1.14 1 /* $NetBSD: ofw_subr.S,v 1.14 2021/02/18 16:29:12 thorpej Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5 * Copyright (C) 1995, 1996 TooLs GmbH.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by TooLs GmbH.
19 * 4. The name of TooLs GmbH may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #ifdef _KERNEL_OPT
35 #include "opt_ppcarch.h"
36 #endif
37
38 /* Stack used to call into OpenFirmware. */
39 .lcomm firmstk,NBPG,16
40
41 /* Buffer used to pass data to/from OpenFirmware. */
42 .lcomm OF_buffer,NBPG + 36,4
43
44 /* The OpenFirmware entry point, provided by OpenFirmware. */
45 .lcomm ofentry,4,4
46
47 /* Entry trampoline used by openfirmware(). */
48 .lcomm oftramp,4,4
49
50 /* OpenFirmware SR save area */
51 .lcomm ofwsrsave,64,4
52
53 /* MSR and SPRG[0-3] used in OpenFirmware */
54 .globl ofwmsr
55 .comm ofwmsr,20,4
56
57 /*
58 * Called by start to save the initial OFW state so we can restore it
59 * when call back to OFW.
60 *
61 * We expect the registers to be as for the entry point into the kernel:
62 *
63 * %r1 Stack provided by OpenFirmware / boot loader
64 * %r5 OpenFirmware client entry point
65 *
66 * (others -- don't care)
67 */
68 ENTRY_NOPROFILE(ofwinit)
69 /* Save return address, Push a stack frame. */
70 mflr %r0
71 stw %r0,4(%r1)
72 stwu %r1,-16(%r1)
73
74 #ifdef FIRMWORKSBUGS
75 mfmsr %r0
76 andi. %r0,%r0,PSL_IR|PSL_DR
77 beq 1f
78
79 li %r8,1
80 lis %r9,ofwreal_incharge@ha
81 stw %r8,ofwreal_incharge@l(%r9)
82
83 bl _C_LABEL(ofwr_init)
84 1:
85 #endif
86
87 lis %r8,ofentry@ha
88 stw %r5,ofentry@l(%r8) /* save client interface handler */
89
90 /*
91 * Call directly into OpenFirmware until we're ready to use
92 * the trampoline.
93 */
94 lis %r8,oftramp@ha
95 stw %r5,oftramp@l(%r8)
96
97 /* Save the MSR that OpenFirmware is using. */
98 mfmsr %r0
99 lis %r9,ofwmsr@ha
100 stwu %r0,ofwmsr@l(%r9)
101
102 mfsprg0 %r0 /* save SPRGs */
103 stw %r0,4(%r9)
104 mfsprg1 %r0
105 stw %r0,8(%r9)
106 mfsprg2 %r0
107 stw %r0,12(%r9)
108 mfsprg3 %r0
109 stw %r0,16(%r9)
110
111 lis %r8,OF_buffer@ha
112 addi %r8,%r8,OF_buffer@l
113 lis %r9,_C_LABEL(OF_buf)@ha
114 stw %r8,_C_LABEL(OF_buf)@l(%r9)
115
116 /* XXX Do other stuff in C code. */
117
118 /*
119 * Jump off the trampoline for all subsequent calls
120 * into OpenFirmware.
121 */
122 lis %r5,_C_LABEL(openfirmware_trampoline)@ha
123 addi %r5,%r5,_C_LABEL(openfirmware_trampoline)@l
124 lis %r8,oftramp@ha
125 stw %r5,oftramp@l(%r8)
126
127 /* Retrieve LR, pop stack frame. */
128 addi %r1,%r1,16
129 lwz %r0,4(%r1)
130 mtlr %r0
131
132 blr
133
134 /*
135 * OpenFirmware trampoline. We are already on the OpenFirmware stack.
136 */
137 ENTRY_NOPROFILE(openfirmware_trampoline)
138 mflr %r0
139 stw %r0,4(%r1) /* save return address */
140
141 /*
142 * Push stack frame and save area:
143 *
144 * [SP+8 save area]
145 * [SP+4 slot for saved LR in callee]
146 * [SP+0 saved SP]
147 */
148 stwu %r1,-48(%r1)
149
150 lis %r4,ofentry@ha /* get firmware entry point */
151 lwz %r4,ofentry@l(%r4)
152 mtlr %r4
153
154 mfsprg0 %r5 /* save current sprg0 (curcpu) */
155 stw %r5,16(%r1)
156 mfsprg1 %r5 /* save current sprg1 */
157 stw %r5,20(%r1)
158 mfsprg2 %r5 /* save current sprg1 */
159 stw %r5,24(%r1)
160 mfsprg3 %r5 /* save current sprg3 */
161 stw %r5,28(%r1)
162
163 #ifdef FIRMWORKSBUGS
164 lis %r4,ofwreal_incharge@ha
165 lwz %r4,ofwreal_incharge@l(%r4)
166 cmpwi %r4,1
167 bne 1f
168 blrl
169 b 4f
170 1:
171 #endif
172 mfmsr %r4 /* save msr */
173 stw %r4,8(%r1)
174
175 li %r0,0 /* clear battable translations */
176 mtmsr %r0
177 #if defined (PPC_OEA) || defined (PPC_OEA64_BRIDGE)
178 mtdbatu 2,%r0
179 mtdbatu 3,%r0
180 mtibatu 2,%r0
181 mtibatu 3,%r0
182 #endif /* PPC_OEA */
183
184 lis %r4,ofwsrsave@ha /* save current SRs */
185 addi %r4,%r4,ofwsrsave@l
186 li %r5,0
187 1: mfsrin %r0,%r5
188 stw %r0,0(%r4)
189 addi %r4,%r4,4
190 addis %r5,%r5,0x10000000@h
191 cmpwi %r5,0
192 bne 1b
193
194 lis %r4,_C_LABEL(ofw_pmap)@ha /* load OFW SR */
195 addi %r4,%r4,_C_LABEL(ofw_pmap)@l
196 lwz %r0,PM_KERNELSR(%r4)
197 cmpwi %r0,0 /* pm_sr[KERNEL_SR] == 0? */
198 beq 2f /* then skip (not initialized yet) */
199 li %r5,0
200 1: lwz %r0,0(%r4)
201 mtsrin %r0,%r5
202 addi %r4,%r4,4
203 addis %r5,%r5,0x10000000@h
204 cmpwi %r5,0
205 bne 1b
206 2:
207 lis %r4,ofwmsr+16@ha /* Open Firmware msr + sprg[0-3] */
208 lwzu %r5,ofwmsr+16@l(%r4)
209 mtsprg3 %r5
210 lwz %r5,-4(%r4)
211 mtsprg2 %r5
212 lwz %r5,-8(%r4)
213 mtsprg1 %r5
214 lwz %r5,-12(%r4)
215 mtsprg0 %r5
216 lwz %r5,-16(%r4)
217 mtmsr %r5
218 isync
219
220 blrl /* call Open Firmware */
221
222 lis %r4,ofwsrsave@ha /* restore saved SRs */
223 addi %r4,%r4,ofwsrsave@l
224 li %r5,0
225 1: lwz %r0,0(%r4)
226 mtsrin %r0,%r5
227 addi %r4,%r4,4
228 addis %r5,%r5,0x10000000@h
229 cmpwi %r5,0
230 bne 1b
231
232 lwz %r4,8(%r1) /* restore msr */
233 mtmsr %r4
234 isync
235 4:
236 lwz %r5,16(%r1) /* restore saved sprgs (curcpu) */
237 mtsprg0 %r5
238 lwz %r5,20(%r1)
239 mtsprg1 %r5
240 lwz %r5,24(%r1)
241 mtsprg2 %r5
242 lwz %r5,28(%r1)
243 mtsprg3 %r5
244
245 addi %r1,%r1,48 /* pop stack frame and save area */
246 lwz %r0,4(%r1) /* return address */
247 mtlr %r0
248 blr
249
250 /*
251 * Call into OpenFirmware.
252 */
253 ENTRY_NOPROFILE(openfirmware)
254 mflr %r0
255 stw %r0,4(%r1) /* save return address */
256
257 /* Switch to OpenFirmware stack. */
258 lis %r7,firmstk+NBPG-16@ha
259 addi %r7,%r7,firmstk+NBPG-16@l
260 stw %r1,0(%r7) /* stash away prev stack pointer */
261 mr %r1,%r7
262
263 lis %r4,oftramp@ha
264 lwz %r4,oftramp@l(%r4)
265
266 mtctr %r4
267 bctrl
268
269 lwz %r1,0(%r1) /* restore previous stack pointer */
270 lwz %r0,4(%r1) /* return address */
271 mtlr %r0
272 blr
273