ofw_subr.S revision 1.10.54.1 1 /* $NetBSD: ofw_subr.S,v 1.10.54.1 2020/04/13 08:04:04 martin 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
35 .local firmstk
36 .globl openfirmware_entry
37 .globl ofwmsr
38 .local ofwsrsave
39 .local OF_buffer
40
41 .lcomm firmstk,NBPG,16
42 .lcomm OF_buffer,NBPG + 36,4
43 .comm openfirmware_entry,4,4 /* openfirmware entry point */
44 .lcomm ofwsrsave,64,4 /* openfirmware SR savearea */
45 .comm ofwmsr,20,4 /* msr & sprg[0-3] used in OF */
46 .comm ofwreal_incharge,4,4
47
48 /*
49 * Called by start to save the initial OFW state so we can restore it
50 * when call back to OFW.
51 */
52 ENTRY_NOPROFILE(ofwinit)
53 #ifdef FIRMWORKSBUGS
54 mfmsr %r0
55 andi. %r0,%r0,PSL_IR|PSL_DR
56 beq 1f
57
58 li %r8,1
59 lis %r9,ofwreal_incharge@ha
60 stw %r8,ofwreal_incharge@l(%r9)
61
62 mflr %r30
63 bl _C_LABEL(ofwr_init)
64 mtlr %r30
65 1:
66 #endif
67 lis %r8,openfirmware_entry@ha
68 stw %r5,openfirmware_entry@l(%r8) /* save client interface handler*/
69
70 mfmsr %r0
71 /*
72 * XXX
73 * doing this here instead of later on in ofwoea_initppc() after setting
74 * up the console and such makes my PowerBook 3400c hang.
75 * Probably just another OF 2.0 weirdness
76 */
77 /*li %r8,PSL_IP*/
78 /*andc %r0,%r0,%r8*/ /* make sure PSL_IP is off */
79 lis %r9,ofwmsr@ha
80 stwu %r0,ofwmsr@l(%r9) /* save initial MSR value */
81
82 mfsprg0 %r0 /* save SPRGs */
83 stw %r0,4(%r9)
84 mfsprg1 %r0
85 stw %r0,8(%r9)
86 mfsprg2 %r0
87 stw %r0,12(%r9)
88 mfsprg3 %r0
89 stw %r0,16(%r9)
90
91 lis %r8,OF_buffer@ha
92 addi %r8,%r8,OF_buffer@l
93 lis %r9,_C_LABEL(OF_buf)@ha
94 stw %r8,_C_LABEL(OF_buf)@l(%r9)
95
96 blr
97
98 /*
99 * OpenFirmware entry point
100 */
101 .text
102 ENTRY(openfirmware)
103 mflr %r0 /* save return address */
104 stw %r0,4(%r1)
105 stwu %r1,-32(%r1) /* setup stack frame */
106
107 lis %r4,openfirmware_entry@ha /* get firmware entry point */
108 lwz %r4,openfirmware_entry@l(%r4)
109 mtlr %r4
110
111 mfsprg0 %r5 /* save current sprg0 (curcpu) */
112 stw %r5,16(%r1)
113 mfsprg1 %r5 /* save current sprg1 */
114 stw %r5,20(%r1)
115 mfsprg2 %r5 /* save current sprg1 */
116 stw %r5,24(%r1)
117 mfsprg3 %r5 /* save current sprg3 */
118 stw %r5,28(%r1)
119
120 #ifdef FIRMWORKSBUGS
121 lis %r4,ofwreal_incharge@ha
122 lwz %r4,ofwreal_incharge@l(%r4)
123 cmpwi %r4,1
124 bne 1f
125 blrl
126 b 4f
127 1:
128 #endif
129 mfmsr %r4 /* save msr */
130 stw %r4,8(%r1)
131
132 li %r0,0 /* clear battable translations */
133 mtmsr %r0
134 #if defined (PPC_OEA) || defined (PPC_OEA64_BRIDGE)
135 mtdbatu 2,%r0
136 mtdbatu 3,%r0
137 mtibatu 2,%r0
138 mtibatu 3,%r0
139 #endif /* PPC_OEA */
140
141 lis %r4,ofwsrsave@ha /* save current SRs */
142 addi %r4,%r4,ofwsrsave@l
143 li %r5,0
144 1: mfsrin %r0,%r5
145 stw %r0,0(%r4)
146 addi %r4,%r4,4
147 addis %r5,%r5,0x10000000@h
148 cmpwi %r5,0
149 bne 1b
150
151 lis %r4,_C_LABEL(ofw_pmap)@ha /* load OFW SR */
152 addi %r4,%r4,_C_LABEL(ofw_pmap)@l
153 lwz %r0,PM_KERNELSR(%r4)
154 cmpwi %r0,0 /* pm_sr[KERNEL_SR] == 0? */
155 beq 2f /* then skip (not initialized yet) */
156 li %r5,0
157 1: lwz %r0,0(%r4)
158 mtsrin %r0,%r5
159 addi %r4,%r4,4
160 addis %r5,%r5,0x10000000@h
161 cmpwi %r5,0
162 bne 1b
163 2:
164 lis %r4,ofwmsr+16@ha /* Open Firmware msr + sprg[0-3] */
165 lwzu %r5,ofwmsr+16@l(%r4)
166 mtsprg3 %r5
167 lwz %r5,-4(%r4)
168 mtsprg2 %r5
169 lwz %r5,-8(%r4)
170 mtsprg1 %r5
171 lwz %r5,-12(%r4)
172 mtsprg0 %r5
173 lwz %r5,-16(%r4)
174 mtmsr %r5
175 isync
176
177 blrl /* call Open Firmware */
178
179 lis %r4,ofwsrsave@ha /* restore saved SRs */
180 addi %r4,%r4,ofwsrsave@l
181 li %r5,0
182 1: lwz %r0,0(%r4)
183 mtsrin %r0,%r5
184 addi %r4,%r4,4
185 addis %r5,%r5,0x10000000@h
186 cmpwi %r5,0
187 bne 1b
188
189 lwz %r4,8(%r1) /* restore msr */
190 mtmsr %r4
191 isync
192 4:
193 lwz %r5,16(%r1) /* restore saved sprgs (curcpu) */
194 mtsprg0 %r5
195 lwz %r5,20(%r1)
196 mtsprg1 %r5
197 lwz %r5,24(%r1)
198 mtsprg2 %r5
199 lwz %r5,28(%r1)
200 mtsprg3 %r5
201
202 lwz %r1,0(%r1) /* and return */
203 lwz %r0,4(%r1)
204 mtlr %r0
205 blr
206
207 /*
208 * Switch to/from OpenFirmware real mode stack
209 *
210 * Note: has to be called as the very first thing in OpenFirmware interface
211 * routines.
212 * E.g.:
213 * int
214 * OF_xxx(arg1, arg2)
215 * type arg1, arg2;
216 * {
217 * static struct {
218 * char *name;
219 * int nargs;
220 * int nreturns;
221 * char *method;
222 * int arg1;
223 * int arg2;
224 * int ret;
225 * } args = {
226 * "xxx",
227 * 2,
228 * 1,
229 * };
230 *
231 * ofw_stack();
232 * args.arg1 = arg1;
233 * args.arg2 = arg2;
234 * if (openfirmware(&args) < 0)
235 * return -1;
236 * return args.ret;
237 * }
238 */
239
240 ENTRY(ofw_stack)
241 mfmsr %r8 /* turn off interrupts */
242 andi. %r0,%r8,~(PSL_EE|PSL_RI)@l
243 mtmsr %r0
244 stw %r8,4(%r1) /* abuse return address slot */
245
246 lwz %r5,0(%r1) /* get length of stack frame */
247 subf %r5,%r1,%r5
248
249 lis %r7,firmstk+NBPG-8@ha
250 addi %r7,%r7,firmstk+NBPG-8@l
251 lis %r6,ofw_back@ha
252 addi %r6,%r6,ofw_back@l
253 subf %r4,%r5,%r7 /* make room for stack frame on
254 new stack */
255 stw %r6,-4(%r7) /* setup return pointer */
256 stwu %r1,-8(%r7)
257
258 stw %r7,-8(%r4)
259
260 addi %r3,%r1,8
261 addi %r1,%r4,-8
262 subi %r5,%r5,8
263
264 b _C_LABEL(ofbcopy) /* and copy it */
265
266 ofw_back:
267 lwz %r1,0(%r1) /* get callers original stack pointer */
268
269 lwz %r0,4(%r1) /* get saved msr from abused slot */
270 mtmsr %r0
271
272 lwz %r1,0(%r1) /* return */
273 lwz %r0,4(%r1)
274 mtlr %r0
275 blr
276