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