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
41222613SnwhitehornGLOBAL(ofmsr)
42222613Snwhitehorn	.long	0, 0, 0, 0, 0		/* msr/sprg0-3 used in Open Firmware */
43222613SnwhitehornGLOBAL(rtasmsr)
44222613Snwhitehorn	.long	0
45222613SnwhitehornGLOBAL(openfirmware_entry)
46222613Snwhitehorn	.long	0			/* Open Firmware entry point */
47222613SnwhitehornGLOBAL(rtas_entry)
48222613Snwhitehorn	.long	0			/* RTAS entry point */
49222613Snwhitehorn
50222613Snwhitehorn	.align	4
51222613Snwhitehornofwstk:
52222613Snwhitehorn	.space	OFWSTKSZ
53222613Snwhitehornrtas_regsave:
54222613Snwhitehorn	.space	4
55222613Snwhitehorn
56222613Snwhitehorn/*
57222613Snwhitehorn * Open Firmware Entry Point. May need to enter real mode.
58222613Snwhitehorn *
59222613Snwhitehorn * C prototype: int ofwcall(void *callbuffer);
60222613Snwhitehorn */
61222613Snwhitehorn
62222613SnwhitehornASENTRY(ofwcall)
63222613Snwhitehorn	mflr	%r0
64222613Snwhitehorn	stw	%r0,4(%r1)
65222613Snwhitehorn
66222613Snwhitehorn	/* Record the old MSR */
67222613Snwhitehorn	mfmsr	%r6
68222613Snwhitehorn
69222613Snwhitehorn	/* read client interface handler */
70222613Snwhitehorn	lis	%r4,openfirmware_entry@ha
71222613Snwhitehorn	lwz	%r4,openfirmware_entry@l(%r4)
72222613Snwhitehorn
73222613Snwhitehorn	/*
74222613Snwhitehorn	 * Set the MSR to the OF value. This has the side effect of disabling
75222613Snwhitehorn	 * exceptions, which prevents preemption later.
76222613Snwhitehorn	 */
77222613Snwhitehorn
78222613Snwhitehorn	lis	%r5,ofmsr@ha
79222613Snwhitehorn	lwz	%r5,ofmsr@l(%r5)
80222613Snwhitehorn	mtmsr	%r5
81222613Snwhitehorn	isync
82222613Snwhitehorn
83222613Snwhitehorn	/*
84222613Snwhitehorn	 * Set up OF stack. This needs to be potentially accessible in real mode
85222613Snwhitehorn	 * The pointer to the current kernel stack is placed at the very
86222613Snwhitehorn	 * top of the stack along with the old MSR so we can get them back
87222613Snwhitehorn	 * later.
88222613Snwhitehorn	 */
89222613Snwhitehorn	mr	%r5,%r1
90223485Snwhitehorn	lis	%r1,(ofwstk+OFWSTKSZ-32)@ha
91223485Snwhitehorn	addi	%r1,%r1,(ofwstk+OFWSTKSZ-32)@l
92223485Snwhitehorn	stw	%r5,20(%r1)	/* Save real stack pointer */
93223485Snwhitehorn	stw	%r2,24(%r1)	/* Save curthread */
94223485Snwhitehorn	stw	%r6,28(%r1)	/* Save old MSR */
95222613Snwhitehorn	li	%r5,0
96222613Snwhitehorn	stw	%r5,4(%r1)
97222613Snwhitehorn	stw	%r5,0(%r1)
98222613Snwhitehorn
99222613Snwhitehorn	/* Finally, branch to OF */
100222613Snwhitehorn	mtctr	%r4
101222613Snwhitehorn	bctrl
102222613Snwhitehorn
103222613Snwhitehorn	/* Reload stack pointer and MSR from the OFW stack */
104223485Snwhitehorn	lwz	%r6,28(%r1)
105223485Snwhitehorn	lwz	%r2,24(%r1)
106223485Snwhitehorn	lwz	%r1,20(%r1)
107222613Snwhitehorn
108222613Snwhitehorn	/* Now set the real MSR */
109222613Snwhitehorn	mtmsr	%r6
110222613Snwhitehorn	isync
111222613Snwhitehorn
112222613Snwhitehorn	/* Return */
113222613Snwhitehorn	lwz	%r0,4(%r1)
114222613Snwhitehorn	mtlr 	%r0
115222613Snwhitehorn	blr
116222613Snwhitehorn
117222613Snwhitehorn/*
118222613Snwhitehorn * RTAS Entry Point. Similar to the OF one, but simpler (no separate stack)
119222613Snwhitehorn *
120222613Snwhitehorn * C prototype: int rtascall(void *callbuffer, void *rtas_privdat);
121222613Snwhitehorn */
122222613Snwhitehorn
123222613SnwhitehornASENTRY(rtascall)
124222613Snwhitehorn	mflr	%r0
125222613Snwhitehorn	stw	%r0,4(%r1)
126222613Snwhitehorn
127222613Snwhitehorn	/* Record the old MSR to real-mode-accessible area */
128222613Snwhitehorn	mfmsr	%r0
129222613Snwhitehorn	lis	%r5,rtas_regsave@ha
130222613Snwhitehorn	stw	%r0,rtas_regsave@l(%r5)
131222613Snwhitehorn
132222613Snwhitehorn	/* read client interface handler */
133222613Snwhitehorn	lis	%r5,rtas_entry@ha
134222613Snwhitehorn	lwz	%r5,rtas_entry@l(%r5)
135222613Snwhitehorn
136222613Snwhitehorn	/* Set the MSR to the RTAS value */
137222613Snwhitehorn	lis	%r6,rtasmsr@ha
138222613Snwhitehorn	lwz	%r6,rtasmsr@l(%r6)
139222613Snwhitehorn	mtmsr	%r6
140222613Snwhitehorn	isync
141222613Snwhitehorn
142222613Snwhitehorn	/* Branch to RTAS */
143222613Snwhitehorn	mtctr	%r5
144222613Snwhitehorn	bctrl
145222613Snwhitehorn
146222613Snwhitehorn	/* Now set the MSR back */
147222613Snwhitehorn	lis	%r6,rtas_regsave@ha
148222613Snwhitehorn	lwz	%r6,rtas_regsave@l(%r6)
149222613Snwhitehorn	mtmsr	%r6
150222613Snwhitehorn	isync
151222613Snwhitehorn
152222613Snwhitehorn	/* And return */
153222613Snwhitehorn	lwz	%r0,4(%r1)
154222613Snwhitehorn	mtlr 	%r0
155222613Snwhitehorn	blr
156222613Snwhitehorn
157