1222613Snwhitehorn/*-
2222613Snwhitehorn * Copyright (C) 2009-2011 Nathan Whitehorn
3222613Snwhitehorn * All rights reserved.
4222613Snwhitehorn *
5222613Snwhitehorn * Redistribution and use in source and binary forms, with or without
6222613Snwhitehorn * modification, are permitted provided that the following conditions
7222613Snwhitehorn * are met:
8222613Snwhitehorn * 1. Redistributions of source code must retain the above copyright
9222613Snwhitehorn *    notice, this list of conditions and the following disclaimer.
10222613Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright
11222613Snwhitehorn *    notice, this list of conditions and the following disclaimer in the
12222613Snwhitehorn *    documentation and/or other materials provided with the distribution.
13222613Snwhitehorn *
14222613Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15222613Snwhitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16222613Snwhitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17222613Snwhitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18222613Snwhitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19222613Snwhitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20222613Snwhitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21222613Snwhitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22222613Snwhitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23222613Snwhitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24222613Snwhitehorn *
25222613Snwhitehorn * $FreeBSD$
26222613Snwhitehorn */
27222613Snwhitehorn
28222613Snwhitehorn#include <sys/syscall.h>
29222613Snwhitehorn
30222613Snwhitehorn#include <machine/trap.h>
31222613Snwhitehorn#include <machine/param.h>
32222613Snwhitehorn#include <machine/spr.h>
33222613Snwhitehorn#include <machine/asm.h>
34222613Snwhitehorn
35222613Snwhitehorn#define	OFWSTKSZ	4096		/* 4K Open Firmware stack */
36222613Snwhitehorn
37222613Snwhitehorn/*
38222613Snwhitehorn * Globals
39222613Snwhitehorn */
40222613Snwhitehorn	.data
41222613Snwhitehorn	.align	4
42222613Snwhitehornofwstk:
43222613Snwhitehorn	.space	OFWSTKSZ
44222613Snwhitehornrtas_regsave:
45222613Snwhitehorn	.space	24 /* 3 * sizeof(register_t) */
46222613SnwhitehornGLOBAL(ofmsr)
47222613Snwhitehorn	.llong  0, 0, 0, 0, 0		/* msr/sprg0-3 used in Open Firmware */
48222613SnwhitehornGLOBAL(rtasmsr)
49222613Snwhitehorn	.llong	0
50222613SnwhitehornGLOBAL(openfirmware_entry)
51222613Snwhitehorn	.llong	0			/* Open Firmware entry point */
52222613SnwhitehornGLOBAL(rtas_entry)
53222613Snwhitehorn	.llong	0			/* RTAS entry point */
54222613Snwhitehorn
55222613Snwhitehorn/*
56222613Snwhitehorn * Open Firmware Real-mode Entry Point. This is a huge pain.
57222613Snwhitehorn */
58222613Snwhitehorn
59230400SandreastASENTRY_NOPROF(ofwcall)
60222613Snwhitehorn	mflr	%r0
61222613Snwhitehorn	std	%r0,16(%r1)
62222613Snwhitehorn	stdu	%r1,-208(%r1)
63222613Snwhitehorn
64222613Snwhitehorn	/*
65222613Snwhitehorn	 * We need to save the following, because OF's register save/
66222613Snwhitehorn	 * restore code assumes that the contents of registers are
67222613Snwhitehorn	 * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
68222613Snwhitehorn	 * get placed in that order in the stack.
69222613Snwhitehorn	 */
70222613Snwhitehorn
71222613Snwhitehorn	mfcr	%r4
72222613Snwhitehorn	std	%r4,48(%r1)
73222613Snwhitehorn	std	%r13,56(%r1)
74222613Snwhitehorn	std	%r14,64(%r1)
75222613Snwhitehorn	std	%r15,72(%r1)
76222613Snwhitehorn	std	%r16,80(%r1)
77222613Snwhitehorn	std	%r17,88(%r1)
78222613Snwhitehorn	std	%r18,96(%r1)
79222613Snwhitehorn	std	%r19,104(%r1)
80222613Snwhitehorn	std	%r20,112(%r1)
81222613Snwhitehorn	std	%r21,120(%r1)
82222613Snwhitehorn	std	%r22,128(%r1)
83222613Snwhitehorn	std	%r23,136(%r1)
84222613Snwhitehorn	std	%r24,144(%r1)
85222613Snwhitehorn	std	%r25,152(%r1)
86222613Snwhitehorn	std	%r26,160(%r1)
87222613Snwhitehorn	std	%r27,168(%r1)
88222613Snwhitehorn	std	%r28,176(%r1)
89222613Snwhitehorn	std	%r29,184(%r1)
90222613Snwhitehorn	std	%r30,192(%r1)
91222613Snwhitehorn	std	%r31,200(%r1)
92222613Snwhitehorn
93222613Snwhitehorn	/* Record the old MSR */
94222613Snwhitehorn	mfmsr	%r6
95222613Snwhitehorn
96222613Snwhitehorn	/* read client interface handler */
97222613Snwhitehorn	lis	%r4,openfirmware_entry@ha
98222613Snwhitehorn	ld	%r4,openfirmware_entry@l(%r4)
99222613Snwhitehorn
100222613Snwhitehorn	/*
101222613Snwhitehorn	 * Set the MSR to the OF value. This has the side effect of disabling
102222613Snwhitehorn	 * exceptions, which is important for the next few steps.
103222613Snwhitehorn	 */
104222613Snwhitehorn
105222613Snwhitehorn	lis	%r5,ofmsr@ha
106222613Snwhitehorn	ld	%r5,ofmsr@l(%r5)
107222613Snwhitehorn	mtmsrd	%r5
108222613Snwhitehorn	isync
109222613Snwhitehorn
110222613Snwhitehorn	/*
111222613Snwhitehorn	 * Set up OF stack. This needs to be accessible in real mode and
112222613Snwhitehorn	 * use the 32-bit ABI stack frame format. The pointer to the current
113222613Snwhitehorn	 * kernel stack is placed at the very top of the stack along with
114222613Snwhitehorn	 * the old MSR so we can get them back later.
115222613Snwhitehorn	 */
116222613Snwhitehorn	mr	%r5,%r1
117222613Snwhitehorn	lis	%r1,(ofwstk+OFWSTKSZ-32)@ha
118222613Snwhitehorn	addi	%r1,%r1,(ofwstk+OFWSTKSZ-32)@l
119222613Snwhitehorn	std	%r5,8(%r1)	/* Save real stack pointer */
120222613Snwhitehorn	std	%r2,16(%r1)	/* Save old TOC */
121222613Snwhitehorn	std	%r6,24(%r1)	/* Save old MSR */
122222613Snwhitehorn	li	%r5,0
123222613Snwhitehorn	stw	%r5,4(%r1)
124222613Snwhitehorn	stw	%r5,0(%r1)
125222613Snwhitehorn
126222613Snwhitehorn	/* Finally, branch to OF */
127222613Snwhitehorn	mtctr	%r4
128222613Snwhitehorn	bctrl
129222613Snwhitehorn
130222613Snwhitehorn	/* Reload stack pointer and MSR from the OFW stack */
131222613Snwhitehorn	ld	%r6,24(%r1)
132222613Snwhitehorn	ld	%r2,16(%r1)
133222613Snwhitehorn	ld	%r1,8(%r1)
134222613Snwhitehorn
135222613Snwhitehorn	/* Now set the real MSR */
136222613Snwhitehorn	mtmsrd	%r6
137222613Snwhitehorn	isync
138222613Snwhitehorn
139222613Snwhitehorn	/* Sign-extend the return value from OF */
140222613Snwhitehorn	extsw	%r3,%r3
141222613Snwhitehorn
142222613Snwhitehorn	/* Restore all the non-volatile registers */
143222613Snwhitehorn	ld	%r5,48(%r1)
144222613Snwhitehorn	mtcr	%r5
145222613Snwhitehorn	ld	%r13,56(%r1)
146222613Snwhitehorn	ld	%r14,64(%r1)
147222613Snwhitehorn	ld	%r15,72(%r1)
148222613Snwhitehorn	ld	%r16,80(%r1)
149222613Snwhitehorn	ld	%r17,88(%r1)
150222613Snwhitehorn	ld	%r18,96(%r1)
151222613Snwhitehorn	ld	%r19,104(%r1)
152222613Snwhitehorn	ld	%r20,112(%r1)
153222613Snwhitehorn	ld	%r21,120(%r1)
154222613Snwhitehorn	ld	%r22,128(%r1)
155222613Snwhitehorn	ld	%r23,136(%r1)
156222613Snwhitehorn	ld	%r24,144(%r1)
157222613Snwhitehorn	ld	%r25,152(%r1)
158222613Snwhitehorn	ld	%r26,160(%r1)
159222613Snwhitehorn	ld	%r27,168(%r1)
160222613Snwhitehorn	ld	%r28,176(%r1)
161222613Snwhitehorn	ld	%r29,184(%r1)
162222613Snwhitehorn	ld	%r30,192(%r1)
163222613Snwhitehorn	ld	%r31,200(%r1)
164222613Snwhitehorn
165222613Snwhitehorn	/* Restore the stack and link register */
166222613Snwhitehorn	ld	%r1,0(%r1)
167222613Snwhitehorn	ld	%r0,16(%r1)
168222613Snwhitehorn	mtlr 	%r0
169222613Snwhitehorn	blr
170222613Snwhitehorn
171222613Snwhitehorn/*
172222613Snwhitehorn * RTAS 32-bit Entry Point. Similar to the OF one, but simpler (no separate
173222613Snwhitehorn * stack)
174222613Snwhitehorn *
175222613Snwhitehorn * C prototype: int rtascall(void *callbuffer, void *rtas_privdat);
176222613Snwhitehorn */
177222613Snwhitehorn
178230400SandreastASENTRY_NOPROF(rtascall)
179222613Snwhitehorn	mflr	%r0
180222613Snwhitehorn	std	%r0,16(%r1)
181222613Snwhitehorn	stdu	%r1,-208(%r1)
182222613Snwhitehorn
183222613Snwhitehorn	/*
184222613Snwhitehorn	 * We need to save the following, because RTAS's register save/
185222613Snwhitehorn	 * restore code assumes that the contents of registers are
186222613Snwhitehorn	 * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
187222613Snwhitehorn	 * get placed in that order in the stack.
188222613Snwhitehorn	 */
189222613Snwhitehorn
190222613Snwhitehorn	mfcr	%r5
191222613Snwhitehorn	std	%r5,48(%r1)
192222613Snwhitehorn	std	%r13,56(%r1)
193222613Snwhitehorn	std	%r14,64(%r1)
194222613Snwhitehorn	std	%r15,72(%r1)
195222613Snwhitehorn	std	%r16,80(%r1)
196222613Snwhitehorn	std	%r17,88(%r1)
197222613Snwhitehorn	std	%r18,96(%r1)
198222613Snwhitehorn	std	%r19,104(%r1)
199222613Snwhitehorn	std	%r20,112(%r1)
200222613Snwhitehorn	std	%r21,120(%r1)
201222613Snwhitehorn	std	%r22,128(%r1)
202222613Snwhitehorn	std	%r23,136(%r1)
203222613Snwhitehorn	std	%r24,144(%r1)
204222613Snwhitehorn	std	%r25,152(%r1)
205222613Snwhitehorn	std	%r26,160(%r1)
206222613Snwhitehorn	std	%r27,168(%r1)
207222613Snwhitehorn	std	%r28,176(%r1)
208222613Snwhitehorn	std	%r29,184(%r1)
209222613Snwhitehorn	std	%r30,192(%r1)
210222613Snwhitehorn	std	%r31,200(%r1)
211222613Snwhitehorn
212222613Snwhitehorn	/* Record the old MSR */
213222613Snwhitehorn	mfmsr	%r6
214222613Snwhitehorn
215222613Snwhitehorn	/* read client interface handler */
216222613Snwhitehorn	lis	%r5,rtas_entry@ha
217222613Snwhitehorn	ld	%r5,rtas_entry@l(%r5)
218222613Snwhitehorn
219222613Snwhitehorn	/*
220222613Snwhitehorn	 * Set the MSR to the RTAS value. This has the side effect of disabling
221222613Snwhitehorn	 * exceptions, which is important for the next few steps.
222222613Snwhitehorn	 */
223222613Snwhitehorn
224222613Snwhitehorn	lis	%r7,rtasmsr@ha
225222613Snwhitehorn	ld	%r7,rtasmsr@l(%r7)
226222613Snwhitehorn	mtmsrd	%r7
227222613Snwhitehorn	isync
228222613Snwhitehorn
229222613Snwhitehorn	/*
230222613Snwhitehorn	 * Set up RTAS register save area, so that we can get back all of
231222613Snwhitehorn	 * our 64-bit pointers. Save our stack pointer, the TOC, and the MSR.
232222613Snwhitehorn	 * Put this in r1, since RTAS is obliged to save it. Kernel globals
233222613Snwhitehorn	 * are below 4 GB, so this is safe.
234222613Snwhitehorn	 */
235222613Snwhitehorn	mr	%r7,%r1
236222613Snwhitehorn	lis	%r1,rtas_regsave@ha
237222613Snwhitehorn	addi	%r1,%r1,rtas_regsave@l
238222613Snwhitehorn	std	%r7,0(%r1)	/* Save 64-bit stack pointer */
239222613Snwhitehorn	std	%r2,8(%r1)	/* Save TOC */
240222613Snwhitehorn	std	%r6,16(%r1)	/* Save MSR */
241222613Snwhitehorn
242222613Snwhitehorn	/* Finally, branch to RTAS */
243222613Snwhitehorn	mtctr	%r5
244222613Snwhitehorn	bctrl
245222613Snwhitehorn
246222613Snwhitehorn	/*
247222613Snwhitehorn	 * Reload stack pointer and MSR from the reg save area in r1. We are
248222613Snwhitehorn	 * running in 32-bit mode at this point, so it doesn't matter if r1
249222613Snwhitehorn	 * has become sign-extended.
250222613Snwhitehorn	 */
251222613Snwhitehorn	ld	%r6,16(%r1)
252222613Snwhitehorn	ld	%r2,8(%r1)
253222613Snwhitehorn	ld	%r1,0(%r1)
254222613Snwhitehorn
255222613Snwhitehorn	/* Now set the real MSR */
256222613Snwhitehorn	mtmsrd	%r6
257222613Snwhitehorn	isync
258222613Snwhitehorn
259222613Snwhitehorn	/* Sign-extend the return value from RTAS */
260222613Snwhitehorn	extsw	%r3,%r3
261222613Snwhitehorn
262222613Snwhitehorn	/* Restore all the non-volatile registers */
263222613Snwhitehorn	ld	%r5,48(%r1)
264222613Snwhitehorn	mtcr	%r5
265222613Snwhitehorn	ld	%r13,56(%r1)
266222613Snwhitehorn	ld	%r14,64(%r1)
267222613Snwhitehorn	ld	%r15,72(%r1)
268222613Snwhitehorn	ld	%r16,80(%r1)
269222613Snwhitehorn	ld	%r17,88(%r1)
270222613Snwhitehorn	ld	%r18,96(%r1)
271222613Snwhitehorn	ld	%r19,104(%r1)
272222613Snwhitehorn	ld	%r20,112(%r1)
273222613Snwhitehorn	ld	%r21,120(%r1)
274222613Snwhitehorn	ld	%r22,128(%r1)
275222613Snwhitehorn	ld	%r23,136(%r1)
276222613Snwhitehorn	ld	%r24,144(%r1)
277222613Snwhitehorn	ld	%r25,152(%r1)
278222613Snwhitehorn	ld	%r26,160(%r1)
279222613Snwhitehorn	ld	%r27,168(%r1)
280222613Snwhitehorn	ld	%r28,176(%r1)
281222613Snwhitehorn	ld	%r29,184(%r1)
282222613Snwhitehorn	ld	%r30,192(%r1)
283222613Snwhitehorn	ld	%r31,200(%r1)
284222613Snwhitehorn
285222613Snwhitehorn	/* Restore the stack and link register */
286222613Snwhitehorn	ld	%r1,0(%r1)
287222613Snwhitehorn	ld	%r0,16(%r1)
288222613Snwhitehorn	mtlr 	%r0
289222613Snwhitehorn	blr
290222613Snwhitehorn
291