xref: /netbsd/sys/arch/macppc/macppc/locore.S (revision bf9ec67e)
1/*	$NetBSD: locore.S,v 1.44 2002/03/09 23:35:57 chs 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#include "opt_ddb.h"
35#include "opt_kgdb.h"
36#include "opt_ipkdb.h"
37#include "opt_lockdebug.h"
38#include "opt_multiprocessor.h"
39#include "assym.h"
40
41#include <sys/syscall.h>
42
43#include <machine/param.h>
44#include <machine/pmap.h>
45#include <machine/psl.h>
46#include <machine/trap.h>
47#include <machine/asm.h>
48#ifndef OLDPMAP
49#include <machine/vmparam.h>
50#endif
51
52#include <powerpc/spr.h>
53/*
54 * Some instructions gas doesn't understand (yet?)
55 */
56#define	bdneq	bdnzf 2,
57
58#if defined(MULTIPROCESSOR)
59/*
60 * Get varios per-cpu values.
61 */
62#if 1
63#define GET_CPUINFO(r)	\
64	mfsprg	r,0
65#else
66#define	GET_CPUINFO(r)						\
67	mfspr	r,SPR_PIR;		/* r = cpu_number() */	\
68	mulli	r,r,CI_SIZE;					\
69	addis	r,r,_C_LABEL(cpu_info)@ha;			\
70	addi	r,r,_C_LABEL(cpu_info)@l;
71#endif
72#endif
73
74#define	INTSTK   8192			/* 8K interrupt stack */
75#define	SPILLSTK 4096			/* 4K spill stack */
76
77/*
78 * Globals
79 */
80	.data
81GLOBAL(esym)
82	.long	0			/* end of symbol table */
83GLOBAL(proc0paddr)
84	.long	0			/* proc0 p_addr */
85
86GLOBAL(intrnames)
87	.asciz	"irq0", "irq1", "irq2", "irq3"
88	.asciz	"irq4", "irq5", "irq6", "irq7"
89	.asciz	"irq8", "irq9", "irq10", "irq11"
90	.asciz	"irq12", "irq13", "irq14", "irq15"
91	.asciz	"irq16", "irq17", "irq18", "irq19"
92	.asciz	"irq20", "irq21", "irq22", "irq23"
93	.asciz	"irq24", "irq25", "irq26", "irq27"
94	.asciz	"irq28", "irq29", "irq30", "irq31"
95	.asciz	"irq32", "irq33", "irq34", "irq35"
96	.asciz	"irq36", "irq37", "irq38", "irq39"
97	.asciz	"irq40", "irq41", "irq42", "irq43"
98	.asciz	"irq44", "irq45", "irq46", "irq47"
99	.asciz	"irq48", "irq49", "irq50", "irq51"
100	.asciz	"irq52", "irq53", "irq54", "irq55"
101	.asciz	"irq56", "irq57", "irq58", "irq59"
102	.asciz	"irq60", "irq61", "irq62", "irq63"
103	.asciz	"clock", "softclock", "softnet", "softserial"
104GLOBAL(eintrnames)
105	.align	4
106GLOBAL(intrcnt)
107	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
108	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
109	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
110	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
111	.long	0,0,0,0
112GLOBAL(eintrcnt)
113
114GLOBAL(ofmsr)
115	.long	0,0,0,0,0		/* msr & sprg[0-3] used in Open Firmware */
116
117/*
118 * File-scope for locore.S
119 */
120#if !defined(MULTIPROCESSOR)
121idle_u:
122	.long	0			/* fake uarea during idle after exit */
123#endif
124openfirmware_entry:
125	.long	0			/* openfirmware entry point */
126srsave:
127	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
128
129/*
130 * This symbol is here for the benefit of kvm_mkdb, and is supposed to
131 * mark the start of kernel text.
132 */
133	.text
134	.globl	_C_LABEL(kernel_text)
135_C_LABEL(kernel_text):
136
137/*
138 * Startup entry.  Note, this must be the first thing in the text
139 * segment!
140 */
141	.text
142	.globl	__start
143__start:
144#ifdef	FIRMWORKSBUGS
145	mfmsr	0
146	andi.	0,0,PSL_IR|PSL_DR
147	beq	1f
148
149	bl	_C_LABEL(ofwr_init)
1501:
151#endif
152	mfmsr	0
153	lis	9,ofmsr@ha
154	stw	0,ofmsr@l(9)
155        mfsprg  0,0
156       	stw	0,ofmsr+4@l(9)
157        mfsprg  0,1
158       	stw	0,ofmsr+8@l(9)
159        mfsprg  0,2
160       	stw	0,ofmsr+12@l(9)
161        mfsprg  0,3
162       	stw	0,ofmsr+16@l(9)
163
164	li	0,0
165	mtmsr	0			/* Disable FPU/MMU/exceptions */
166	isync
167
168/* compute end of kernel memory */
169	lis	8,_C_LABEL(end)@ha
170	addi	8,8,_C_LABEL(end)@l
171#ifdef DDB
172	/* skip symbol table */
173	cmpwi	6,0
174	beq	1f
175	add	9,6,7			/* r9 = args + l */
176	lwz	9,-8(9)			/* esym */
177	cmpwi	9,0
178	beq	1f
179	mr	8,9
1801:
181#endif
182	li	9,PGOFSET
183	add	8,8,9
184	andc	8,8,9
185	lis	9,_C_LABEL(OF_buf)@ha
186	stw	8,_C_LABEL(OF_buf)@l(9)
187	addi	8,8,NBPG
188#if defined(MULTIPROCESSOR)
189	lis	9,_C_LABEL(cpu_info)@ha
190	addi	9,9,_C_LABEL(cpu_info)@l
191	addi	8,8,INTSTK
192	stw	8,CI_INTSTK(9)
193	addi	8,8,SPILLSTK
194	stw	8,CI_SPILLSTK(9)
195	stw	8,CI_IDLE_PCB(9)
196#else
197	lis	9,idle_u@ha
198	stw	8,idle_u@l(9)
199#endif
200	addi	8,8,USPACE		/* space for idle_u */
201	lis	9,_C_LABEL(proc0paddr)@ha
202	stw	8,_C_LABEL(proc0paddr)@l(9)
203	addi	1,8,USPACE-FRAMELEN	/* stackpointer for proc0 */
204	mr	4,1			/* end of mem reserved for kernel */
205	xor	0,0,0
206	stwu	0,-16(1)		/* end of stack chain */
207
208	lis	8,openfirmware_entry@ha
209	stw	5,openfirmware_entry@l(8) /* save client interface handler */
210	lis	3,__start@ha
211	addi	3,3,__start@l
212	mr	5,6			/* args string */
213	bl	_C_LABEL(initppc)
214	bl	_C_LABEL(main)
215	b	_C_LABEL(OF_exit)
216
217/*
218 * OpenFirmware entry point
219 */
220ENTRY(openfirmware)
221	mflr	0			/* save return address */
222	stw	0,4(1)
223	stwu	1,-16(1)		/* setup stack frame */
224
225	mfmsr	4			/* save msr */
226	stw	4,8(1)
227
228	lis	4,openfirmware_entry@ha	/* get firmware entry point */
229	lwz	4,openfirmware_entry@l(4)
230	mtlr	4
231
232	li	0,0			/* clear battable translations */
233	mtdbatu	2,0
234	mtdbatu	3,0
235	mtibatu	2,0
236	mtibatu	3,0
237
238	lis	4,srsave@ha		/* save old SR */
239	addi	4,4,srsave@l
240	li	5,0
2411:	mfsrin	0,5
242	stw	0,0(4)
243	addi	4,4,4
244	addis	5,5,0x10000000@h
245	cmpwi	5,0
246	bne	1b
247
248	lis	4,_C_LABEL(ofw_pmap)@ha	/* load OFW SR */
249	addi	4,4,_C_LABEL(ofw_pmap)@l
250	lwz	0,PM_KERNELSR(4)
251	cmpwi	0,0			/* pm_sr[KERNEL_SR] == 0? */
252	beq	2f			/* then skip (not initialized yet) */
253	li	5,0
2541:	lwz	0,0(4)
255	mtsrin	0,5
256	addi	4,4,4
257	addis	5,5,0x10000000@h
258	cmpwi	5,0
259	bne	1b
2602:
261	lis	4,ofmsr@ha		/* Open Firmware msr + sprg[0-3] */
262	lwz	5,ofmsr+4@l(4)
263	mtsprg	0,5
264	lwz	5,ofmsr+8@l(4)
265	mtsprg	1,5
266	lwz	5,ofmsr+12@l(4)
267	mtsprg	2,5
268	lwz	5,ofmsr+16@l(4)
269	mtsprg	3,5
270	lwz	5,ofmsr@l(4)
271	mtmsr	5
272	isync
273
274	blrl				/* call Open Firmware */
275
276	lis	4,srsave@ha		/* restore saved SR */
277	addi	4,4,srsave@l
278	li	5,0
2791:	lwz	0,0(4)
280	mtsrin	0,5
281	addi	4,4,4
282	addis	5,5,0x10000000@h
283	cmpwi	5,0
284	bne	1b
285
286	lwz	4,8(1)			/* restore msr */
287	mtmsr	4
288	isync
289
290	lwz	1,0(1)			/* and return */
291	lwz	0,4(1)
292	mtlr	0
293	blr
294
295/*
296 * Switch to/from OpenFirmware real mode stack
297 *
298 * Note: has to be called as the very first thing in OpenFirmware interface
299 * routines.
300 * E.g.:
301 * int
302 * OF_xxx(arg1, arg2)
303 * type arg1, arg2;
304 * {
305 *	static struct {
306 *		char *name;
307 *		int nargs;
308 *		int nreturns;
309 *		char *method;
310 *		int arg1;
311 *		int arg2;
312 *		int ret;
313 *	} args = {
314 *		"xxx",
315 *		2,
316 *		1,
317 *	};
318 *
319 *	ofw_stack();
320 *	args.arg1 = arg1;
321 *	args.arg2 = arg2;
322 *	if (openfirmware(&args) < 0)
323 *		return -1;
324 *	return args.ret;
325 * }
326 */
327
328	.local	firmstk
329	.comm	firmstk,NBPG,8
330
331ENTRY(ofw_stack)
332	mfmsr	8			/* turn off interrupts */
333	andi.	0,8,~(PSL_EE|PSL_RI)@l
334	mtmsr	0
335	stw	8,4(1)			/* abuse return address slot */
336
337	lwz	5,0(1)			/* get length of stack frame */
338	subf	5,1,5
339
340	lis	7,firmstk+NBPG-8@ha
341	addi	7,7,firmstk+NBPG-8@l
342	lis	6,ofw_back@ha
343	addi	6,6,ofw_back@l
344	subf	4,5,7			/* make room for stack frame on
345					   new stack */
346	stw	6,-4(7)			/* setup return pointer */
347	stwu	1,-8(7)
348
349	stw	7,-8(4)
350
351	addi	3,1,8
352	addi	1,4,-8
353	subi	5,5,8
354
355	b	_C_LABEL(ofbcopy)	/* and copy it */
356
357ofw_back:
358	lwz	1,0(1)			/* get callers original stack pointer */
359
360	lwz	0,4(1)			/* get saved msr from abused slot */
361	mtmsr	0
362
363	lwz	1,0(1)			/* return */
364	lwz	0,4(1)
365	mtlr	0
366	blr
367
368#if defined(MULTIPROCESSOR)
369	.globl	_C_LABEL(cpu_spinup_trampoline)
370_C_LABEL(cpu_spinup_trampoline):
371	li	0,0
372	mtmsr	0
373	isync
374
375	lis	3,_C_LABEL(cpu_hatch_stack)@ha
376	lwz	1,_C_LABEL(cpu_hatch_stack)@l(3)
377
378	bl	_C_LABEL(cpu_hatch)
379	bl      _C_LABEL(sched_lock_idle)
380	li      30,0
381	b       _ASM_LABEL(Idle)
382#endif
383
384/*
385 * Pull in common switch and setfault code.
386 */
387#include <powerpc/powerpc/locore_subr.S>
388
389/*
390 * Pull in common trap vector code.
391 */
392#if defined(MULTIPROCESSOR)
393#include <powerpc/powerpc/trap_subr_mp.S>
394#else
395#include <powerpc/powerpc/trap_subr.S>
396#endif
397