xref: /openbmc/linux/arch/powerpc/kernel/head_book3s_32.S (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1533090e5SChristophe Leroy/* SPDX-License-Identifier: GPL-2.0-or-later */
2533090e5SChristophe Leroy/*
3533090e5SChristophe Leroy *  PowerPC version
4533090e5SChristophe Leroy *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
5533090e5SChristophe Leroy *
6533090e5SChristophe Leroy *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
7533090e5SChristophe Leroy *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
8533090e5SChristophe Leroy *  Adapted for Power Macintosh by Paul Mackerras.
9533090e5SChristophe Leroy *  Low-level exception handlers and MMU support
10533090e5SChristophe Leroy *  rewritten by Paul Mackerras.
11533090e5SChristophe Leroy *    Copyright (C) 1996 Paul Mackerras.
12533090e5SChristophe Leroy *  MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
13533090e5SChristophe Leroy *
14533090e5SChristophe Leroy *  This file contains the low-level support and setup for the
15533090e5SChristophe Leroy *  PowerPC platform, including trap and interrupt dispatch.
16533090e5SChristophe Leroy *  (The PPC 8xx embedded CPUs use head_8xx.S instead.)
17533090e5SChristophe Leroy */
18533090e5SChristophe Leroy
19533090e5SChristophe Leroy#include <linux/init.h>
20533090e5SChristophe Leroy#include <linux/pgtable.h>
212da37761SChristophe Leroy#include <linux/linkage.h>
222da37761SChristophe Leroy
23533090e5SChristophe Leroy#include <asm/reg.h>
24533090e5SChristophe Leroy#include <asm/page.h>
25533090e5SChristophe Leroy#include <asm/mmu.h>
26533090e5SChristophe Leroy#include <asm/cputable.h>
27533090e5SChristophe Leroy#include <asm/cache.h>
28533090e5SChristophe Leroy#include <asm/thread_info.h>
29533090e5SChristophe Leroy#include <asm/ppc_asm.h>
30533090e5SChristophe Leroy#include <asm/asm-offsets.h>
31533090e5SChristophe Leroy#include <asm/ptrace.h>
32533090e5SChristophe Leroy#include <asm/bug.h>
33533090e5SChristophe Leroy#include <asm/kvm_book3s_asm.h>
34533090e5SChristophe Leroy#include <asm/feature-fixups.h>
357fab6397SChristophe Leroy#include <asm/interrupt.h>
36533090e5SChristophe Leroy
37533090e5SChristophe Leroy#include "head_32.h"
38533090e5SChristophe Leroy
39533090e5SChristophe Leroy#define LOAD_BAT(n, reg, RA, RB)	\
40533090e5SChristophe Leroy	/* see the comment for clear_bats() -- Cort */ \
41533090e5SChristophe Leroy	li	RA,0;			\
42533090e5SChristophe Leroy	mtspr	SPRN_IBAT##n##U,RA;	\
43533090e5SChristophe Leroy	mtspr	SPRN_DBAT##n##U,RA;	\
44533090e5SChristophe Leroy	lwz	RA,(n*16)+0(reg);	\
45533090e5SChristophe Leroy	lwz	RB,(n*16)+4(reg);	\
46533090e5SChristophe Leroy	mtspr	SPRN_IBAT##n##U,RA;	\
47533090e5SChristophe Leroy	mtspr	SPRN_IBAT##n##L,RB;	\
48533090e5SChristophe Leroy	lwz	RA,(n*16)+8(reg);	\
49533090e5SChristophe Leroy	lwz	RB,(n*16)+12(reg);	\
50533090e5SChristophe Leroy	mtspr	SPRN_DBAT##n##U,RA;	\
51533090e5SChristophe Leroy	mtspr	SPRN_DBAT##n##L,RB
52533090e5SChristophe Leroy
53533090e5SChristophe Leroy	__HEAD
5427e21e8fSChristophe Leroy_GLOBAL(_stext);
55533090e5SChristophe Leroy
56533090e5SChristophe Leroy/*
57533090e5SChristophe Leroy * _start is defined this way because the XCOFF loader in the OpenFirmware
58533090e5SChristophe Leroy * on the powermac expects the entry point to be a procedure descriptor.
59533090e5SChristophe Leroy */
6027e21e8fSChristophe Leroy_GLOBAL(_start);
61533090e5SChristophe Leroy	/*
62533090e5SChristophe Leroy	 * These are here for legacy reasons, the kernel used to
63533090e5SChristophe Leroy	 * need to look like a coff function entry for the pmac
64533090e5SChristophe Leroy	 * but we're always started by some kind of bootloader now.
65533090e5SChristophe Leroy	 *  -- Cort
66533090e5SChristophe Leroy	 */
67533090e5SChristophe Leroy	nop	/* used by __secondary_hold on prep (mtx) and chrp smp */
68533090e5SChristophe Leroy	nop	/* used by __secondary_hold on prep (mtx) and chrp smp */
69533090e5SChristophe Leroy	nop
70533090e5SChristophe Leroy
71533090e5SChristophe Leroy/* PMAC
72533090e5SChristophe Leroy * Enter here with the kernel text, data and bss loaded starting at
73533090e5SChristophe Leroy * 0, running with virtual == physical mapping.
74533090e5SChristophe Leroy * r5 points to the prom entry point (the client interface handler
75533090e5SChristophe Leroy * address).  Address translation is turned on, with the prom
76533090e5SChristophe Leroy * managing the hash table.  Interrupts are disabled.  The stack
77533090e5SChristophe Leroy * pointer (r1) points to just below the end of the half-meg region
78533090e5SChristophe Leroy * from 0x380000 - 0x400000, which is mapped in already.
79533090e5SChristophe Leroy *
80533090e5SChristophe Leroy * If we are booted from MacOS via BootX, we enter with the kernel
81533090e5SChristophe Leroy * image loaded somewhere, and the following values in registers:
82533090e5SChristophe Leroy *  r3: 'BooX' (0x426f6f58)
83533090e5SChristophe Leroy *  r4: virtual address of boot_infos_t
84533090e5SChristophe Leroy *  r5: 0
85533090e5SChristophe Leroy *
86533090e5SChristophe Leroy * PREP
87533090e5SChristophe Leroy * This is jumped to on prep systems right after the kernel is relocated
88533090e5SChristophe Leroy * to its proper place in memory by the boot loader.  The expected layout
89533090e5SChristophe Leroy * of the regs is:
90533090e5SChristophe Leroy *   r3: ptr to residual data
91533090e5SChristophe Leroy *   r4: initrd_start or if no initrd then 0
92533090e5SChristophe Leroy *   r5: initrd_end - unused if r4 is 0
93533090e5SChristophe Leroy *   r6: Start of command line string
94533090e5SChristophe Leroy *   r7: End of command line string
95533090e5SChristophe Leroy *
96533090e5SChristophe Leroy * This just gets a minimal mmu environment setup so we can call
97533090e5SChristophe Leroy * start_here() to do the real work.
98533090e5SChristophe Leroy * -- Cort
99533090e5SChristophe Leroy */
100533090e5SChristophe Leroy
101533090e5SChristophe Leroy	.globl	__start
102533090e5SChristophe Leroy__start:
103533090e5SChristophe Leroy/*
104533090e5SChristophe Leroy * We have to do any OF calls before we map ourselves to KERNELBASE,
105533090e5SChristophe Leroy * because OF may have I/O devices mapped into that area
106533090e5SChristophe Leroy * (particularly on CHRP).
107533090e5SChristophe Leroy */
108533090e5SChristophe Leroy	cmpwi	0,r5,0
109533090e5SChristophe Leroy	beq	1f
110533090e5SChristophe Leroy
111533090e5SChristophe Leroy#ifdef CONFIG_PPC_OF_BOOT_TRAMPOLINE
112533090e5SChristophe Leroy	/* find out where we are now */
113533090e5SChristophe Leroy	bcl	20,31,$+4
114533090e5SChristophe Leroy0:	mflr	r8			/* r8 = runtime addr here */
115533090e5SChristophe Leroy	addis	r8,r8,(_stext - 0b)@ha
116533090e5SChristophe Leroy	addi	r8,r8,(_stext - 0b)@l	/* current runtime base addr */
117533090e5SChristophe Leroy	bl	prom_init
118533090e5SChristophe Leroy#endif /* CONFIG_PPC_OF_BOOT_TRAMPOLINE */
119533090e5SChristophe Leroy
120533090e5SChristophe Leroy	/* We never return. We also hit that trap if trying to boot
121533090e5SChristophe Leroy	 * from OF while CONFIG_PPC_OF_BOOT_TRAMPOLINE isn't selected */
122533090e5SChristophe Leroy	trap
123533090e5SChristophe Leroy
124533090e5SChristophe Leroy/*
125533090e5SChristophe Leroy * Check for BootX signature when supporting PowerMac and branch to
126533090e5SChristophe Leroy * appropriate trampoline if it's present
127533090e5SChristophe Leroy */
128533090e5SChristophe Leroy#ifdef CONFIG_PPC_PMAC
129533090e5SChristophe Leroy1:	lis	r31,0x426f
130533090e5SChristophe Leroy	ori	r31,r31,0x6f58
131533090e5SChristophe Leroy	cmpw	0,r3,r31
132533090e5SChristophe Leroy	bne	1f
133533090e5SChristophe Leroy	bl	bootx_init
134533090e5SChristophe Leroy	trap
135533090e5SChristophe Leroy#endif /* CONFIG_PPC_PMAC */
136533090e5SChristophe Leroy
137533090e5SChristophe Leroy1:	mr	r31,r3			/* save device tree ptr */
138533090e5SChristophe Leroy	li	r24,0			/* cpu # */
139533090e5SChristophe Leroy
140533090e5SChristophe Leroy/*
141533090e5SChristophe Leroy * early_init() does the early machine identification and does
142533090e5SChristophe Leroy * the necessary low-level setup and clears the BSS
143533090e5SChristophe Leroy *  -- Cort <cort@fsmlabs.com>
144533090e5SChristophe Leroy */
145533090e5SChristophe Leroy	bl	early_init
146533090e5SChristophe Leroy
147533090e5SChristophe Leroy/* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains
148533090e5SChristophe Leroy * the physical address we are running at, returned by early_init()
149533090e5SChristophe Leroy */
150533090e5SChristophe Leroy 	bl	mmu_off
151533090e5SChristophe Leroy__after_mmu_off:
152533090e5SChristophe Leroy	bl	clear_bats
153533090e5SChristophe Leroy	bl	flush_tlbs
154533090e5SChristophe Leroy
155533090e5SChristophe Leroy	bl	initial_bats
156533090e5SChristophe Leroy	bl	load_segment_registers
15701776f07SChristophe Leroy	bl	reloc_offset
158533090e5SChristophe Leroy	bl	early_hash_table
159533090e5SChristophe Leroy#if defined(CONFIG_BOOTX_TEXT)
160533090e5SChristophe Leroy	bl	setup_disp_bat
161533090e5SChristophe Leroy#endif
162533090e5SChristophe Leroy#ifdef CONFIG_PPC_EARLY_DEBUG_CPM
163533090e5SChristophe Leroy	bl	setup_cpm_bat
164533090e5SChristophe Leroy#endif
165533090e5SChristophe Leroy#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
166533090e5SChristophe Leroy	bl	setup_usbgecko_bat
167533090e5SChristophe Leroy#endif
168533090e5SChristophe Leroy
169533090e5SChristophe Leroy/*
170533090e5SChristophe Leroy * Call setup_cpu for CPU 0 and initialize 6xx Idle
171533090e5SChristophe Leroy */
172533090e5SChristophe Leroy	bl	reloc_offset
173533090e5SChristophe Leroy	li	r24,0			/* cpu# */
174533090e5SChristophe Leroy	bl	call_setup_cpu		/* Call setup_cpu for this CPU */
175533090e5SChristophe Leroy	bl	reloc_offset
176533090e5SChristophe Leroy	bl	init_idle_6xx
177533090e5SChristophe Leroy
178533090e5SChristophe Leroy
179533090e5SChristophe Leroy/*
180533090e5SChristophe Leroy * We need to run with _start at physical address 0.
181533090e5SChristophe Leroy * On CHRP, we are loaded at 0x10000 since OF on CHRP uses
182533090e5SChristophe Leroy * the exception vectors at 0 (and therefore this copy
183533090e5SChristophe Leroy * overwrites OF's exception vectors with our own).
184533090e5SChristophe Leroy * The MMU is off at this point.
185533090e5SChristophe Leroy */
186533090e5SChristophe Leroy	bl	reloc_offset
187533090e5SChristophe Leroy	mr	r26,r3
188533090e5SChristophe Leroy	addis	r4,r3,KERNELBASE@h	/* current address of _start */
189533090e5SChristophe Leroy	lis	r5,PHYSICAL_START@h
190533090e5SChristophe Leroy	cmplw	0,r4,r5			/* already running at PHYSICAL_START? */
191533090e5SChristophe Leroy	bne	relocate_kernel
192533090e5SChristophe Leroy/*
193533090e5SChristophe Leroy * we now have the 1st 16M of ram mapped with the bats.
194533090e5SChristophe Leroy * prep needs the mmu to be turned on here, but pmac already has it on.
195533090e5SChristophe Leroy * this shouldn't bother the pmac since it just gets turned on again
196533090e5SChristophe Leroy * as we jump to our code at KERNELBASE. -- Cort
197533090e5SChristophe Leroy * Actually no, pmac doesn't have it on any more. BootX enters with MMU
198533090e5SChristophe Leroy * off, and in other cases, we now turn it off before changing BATs above.
199533090e5SChristophe Leroy */
200533090e5SChristophe Leroyturn_on_mmu:
201533090e5SChristophe Leroy	mfmsr	r0
202533090e5SChristophe Leroy	ori	r0,r0,MSR_DR|MSR_IR|MSR_RI
203533090e5SChristophe Leroy	mtspr	SPRN_SRR1,r0
204533090e5SChristophe Leroy	lis	r0,start_here@h
205533090e5SChristophe Leroy	ori	r0,r0,start_here@l
206533090e5SChristophe Leroy	mtspr	SPRN_SRR0,r0
207120c0518SChristophe Leroy	rfi				/* enables MMU */
208533090e5SChristophe Leroy
209533090e5SChristophe Leroy/*
210533090e5SChristophe Leroy * We need __secondary_hold as a place to hold the other cpus on
211533090e5SChristophe Leroy * an SMP machine, even when we are running a UP kernel.
212533090e5SChristophe Leroy */
213533090e5SChristophe Leroy	. = 0xc0			/* for prep bootloader */
214533090e5SChristophe Leroy	li	r3,1			/* MTX only has 1 cpu */
215533090e5SChristophe Leroy	.globl	__secondary_hold
216533090e5SChristophe Leroy__secondary_hold:
217533090e5SChristophe Leroy	/* tell the master we're here */
218533090e5SChristophe Leroy	stw	r3,__secondary_hold_acknowledge@l(0)
219533090e5SChristophe Leroy#ifdef CONFIG_SMP
220533090e5SChristophe Leroy100:	lwz	r4,0(0)
221533090e5SChristophe Leroy	/* wait until we're told to start */
222533090e5SChristophe Leroy	cmpw	0,r4,r3
223533090e5SChristophe Leroy	bne	100b
224533090e5SChristophe Leroy	/* our cpu # was at addr 0 - go */
225533090e5SChristophe Leroy	mr	r24,r3			/* cpu # */
226533090e5SChristophe Leroy	b	__secondary_start
227533090e5SChristophe Leroy#else
228533090e5SChristophe Leroy	b	.
229533090e5SChristophe Leroy#endif /* CONFIG_SMP */
230533090e5SChristophe Leroy
231533090e5SChristophe Leroy	.globl	__secondary_hold_spinloop
232533090e5SChristophe Leroy__secondary_hold_spinloop:
233533090e5SChristophe Leroy	.long	0
234533090e5SChristophe Leroy	.globl	__secondary_hold_acknowledge
235533090e5SChristophe Leroy__secondary_hold_acknowledge:
236533090e5SChristophe Leroy	.long	-1
237533090e5SChristophe Leroy
238533090e5SChristophe Leroy/* System reset */
239533090e5SChristophe Leroy/* core99 pmac starts the seconary here by changing the vector, and
2406c6aee00SNicholas Piggin   putting it back to what it was (unknown_async_exception) when done.  */
2417fab6397SChristophe Leroy	EXCEPTION(INTERRUPT_SYSTEM_RESET, Reset, unknown_async_exception)
242533090e5SChristophe Leroy
243533090e5SChristophe Leroy/* Machine check */
244533090e5SChristophe Leroy/*
245533090e5SChristophe Leroy * On CHRP, this is complicated by the fact that we could get a
246533090e5SChristophe Leroy * machine check inside RTAS, and we have no guarantee that certain
247533090e5SChristophe Leroy * critical registers will have the values we expect.  The set of
248533090e5SChristophe Leroy * registers that might have bad values includes all the GPRs
249533090e5SChristophe Leroy * and all the BATs.  We indicate that we are in RTAS by putting
250533090e5SChristophe Leroy * a non-zero value, the address of the exception frame to use,
251533090e5SChristophe Leroy * in thread.rtas_sp.  The machine check handler checks thread.rtas_sp
252533090e5SChristophe Leroy * and uses its value if it is non-zero.
253533090e5SChristophe Leroy * (Other exception handlers assume that r1 is a valid kernel stack
254533090e5SChristophe Leroy * pointer when we take an exception from supervisor mode.)
255533090e5SChristophe Leroy *	-- paulus.
256533090e5SChristophe Leroy */
2577fab6397SChristophe Leroy	START_EXCEPTION(INTERRUPT_MACHINE_CHECK, MachineCheck)
258533090e5SChristophe Leroy	EXCEPTION_PROLOG_0
259533090e5SChristophe Leroy#ifdef CONFIG_PPC_CHRP
26098bf2d3fSChristophe Leroy	mtspr	SPRN_SPRG_SCRATCH2,r1
26198bf2d3fSChristophe Leroy	mfspr	r1, SPRN_SPRG_THREAD
26298bf2d3fSChristophe Leroy	lwz	r1, RTAS_SP(r1)
26398bf2d3fSChristophe Leroy	cmpwi	cr1, r1, 0
26498bf2d3fSChristophe Leroy	bne	cr1, 7f
26598bf2d3fSChristophe Leroy	mfspr	r1, SPRN_SPRG_SCRATCH2
266533090e5SChristophe Leroy#endif /* CONFIG_PPC_CHRP */
2677aa8dd67SChristophe Leroy	EXCEPTION_PROLOG_1
268719e7e21SChristophe Leroy7:	EXCEPTION_PROLOG_2 0x200 MachineCheck
269533090e5SChristophe Leroy#ifdef CONFIG_PPC_CHRP
270dc13b889SChristophe Leroy	beq	cr1, 1f
271533090e5SChristophe Leroy	twi	31, 0, 0
272533090e5SChristophe Leroy#endif
2734c0104a8SChristophe Leroy1:	prepare_transfer_to_handler
2744c0104a8SChristophe Leroy	bl	machine_check_exception
2754c0104a8SChristophe Leroy	b	interrupt_return
276533090e5SChristophe Leroy
277533090e5SChristophe Leroy/* Data access exception. */
2787fab6397SChristophe Leroy	START_EXCEPTION(INTERRUPT_DATA_STORAGE, DataAccess)
279259149cfSChristophe Leroy#ifdef CONFIG_PPC_BOOK3S_604
280533090e5SChristophe LeroyBEGIN_MMU_FTR_SECTION
281de1cd079SChristophe Leroy	mtspr	SPRN_SPRG_SCRATCH2,r10
282de1cd079SChristophe Leroy	mfspr	r10, SPRN_SPRG_THREAD
283533090e5SChristophe Leroy	stw	r11, THR11(r10)
284533090e5SChristophe Leroy	mfspr	r10, SPRN_DSISR
285533090e5SChristophe Leroy	mfcr	r11
286533090e5SChristophe Leroy	andis.	r10, r10, (DSISR_BAD_FAULT_32S | DSISR_DABRMATCH)@h
287533090e5SChristophe Leroy	mfspr	r10, SPRN_SPRG_THREAD
288533090e5SChristophe Leroy	beq	hash_page_dsi
289533090e5SChristophe Leroy.Lhash_page_dsi_cont:
290533090e5SChristophe Leroy	mtcr	r11
291533090e5SChristophe Leroy	lwz	r11, THR11(r10)
292de1cd079SChristophe Leroy	mfspr	r10, SPRN_SPRG_SCRATCH2
293de1cd079SChristophe LeroyMMU_FTR_SECTION_ELSE
294de1cd079SChristophe Leroy	b	1f
295de1cd079SChristophe LeroyALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_HPTE_TABLE)
296259149cfSChristophe Leroy#endif
297de1cd079SChristophe Leroy1:	EXCEPTION_PROLOG_0 handle_dar_dsisr=1
298533090e5SChristophe Leroy	EXCEPTION_PROLOG_1
2997fab6397SChristophe Leroy	EXCEPTION_PROLOG_2 INTERRUPT_DATA_STORAGE DataAccess handle_dar_dsisr=1
3004c0104a8SChristophe Leroy	prepare_transfer_to_handler
30162376365SChristophe Leroy	lwz	r5, _DSISR(r1)
302dc13b889SChristophe Leroy	andis.	r0, r5, DSISR_DABRMATCH@h
303dc13b889SChristophe Leroy	bne-	1f
3044c0104a8SChristophe Leroy	bl	do_page_fault
3054c0104a8SChristophe Leroy	b	interrupt_return
3064c0104a8SChristophe Leroy1:	bl	do_break
3078f6ff5bdSChristophe Leroy	REST_NVGPRS(r1)
3088f6ff5bdSChristophe Leroy	b	interrupt_return
309dc13b889SChristophe Leroy
310533090e5SChristophe Leroy
311533090e5SChristophe Leroy/* Instruction access exception. */
3127fab6397SChristophe Leroy	START_EXCEPTION(INTERRUPT_INST_STORAGE, InstructionAccess)
313533090e5SChristophe Leroy	mtspr	SPRN_SPRG_SCRATCH0,r10
314533090e5SChristophe Leroy	mtspr	SPRN_SPRG_SCRATCH1,r11
315533090e5SChristophe Leroy	mfspr	r10, SPRN_SPRG_THREAD
316533090e5SChristophe Leroy	mfspr	r11, SPRN_SRR0
317533090e5SChristophe Leroy	stw	r11, SRR0(r10)
318533090e5SChristophe Leroy	mfspr	r11, SPRN_SRR1		/* check whether user or kernel */
319533090e5SChristophe Leroy	stw	r11, SRR1(r10)
320533090e5SChristophe Leroy	mfcr	r10
321259149cfSChristophe Leroy#ifdef CONFIG_PPC_BOOK3S_604
322533090e5SChristophe LeroyBEGIN_MMU_FTR_SECTION
323533090e5SChristophe Leroy	andis.	r11, r11, SRR1_ISI_NOPT@h	/* no pte found? */
324533090e5SChristophe Leroy	bne	hash_page_isi
325533090e5SChristophe Leroy.Lhash_page_isi_cont:
326533090e5SChristophe Leroy	mfspr	r11, SPRN_SRR1		/* check whether user or kernel */
327533090e5SChristophe LeroyEND_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
328259149cfSChristophe Leroy#endif
329533090e5SChristophe Leroy	andi.	r11, r11, MSR_PR
330533090e5SChristophe Leroy
331533090e5SChristophe Leroy	EXCEPTION_PROLOG_1
3327fab6397SChristophe Leroy	EXCEPTION_PROLOG_2 INTERRUPT_INST_STORAGE InstructionAccess
333533090e5SChristophe Leroy	andis.	r5,r9,DSISR_SRR1_MATCH_32S@h /* Filter relevant SRR1 bits */
334a01a3f2dSNicholas Piggin	stw	r5, _DSISR(r11)
335a01a3f2dSNicholas Piggin	stw	r12, _DAR(r11)
3364c0104a8SChristophe Leroy	prepare_transfer_to_handler
3374c0104a8SChristophe Leroy	bl	do_page_fault
3384c0104a8SChristophe Leroy	b	interrupt_return
339533090e5SChristophe Leroy
340533090e5SChristophe Leroy/* External interrupt */
3417fab6397SChristophe Leroy	EXCEPTION(INTERRUPT_EXTERNAL, HardwareInterrupt, do_IRQ)
342533090e5SChristophe Leroy
343533090e5SChristophe Leroy/* Alignment exception */
3447fab6397SChristophe Leroy	START_EXCEPTION(INTERRUPT_ALIGNMENT, Alignment)
3457fab6397SChristophe Leroy	EXCEPTION_PROLOG INTERRUPT_ALIGNMENT Alignment handle_dar_dsisr=1
3468f6ff5bdSChristophe Leroy	prepare_transfer_to_handler
3478f6ff5bdSChristophe Leroy	bl	alignment_exception
3488f6ff5bdSChristophe Leroy	REST_NVGPRS(r1)
3498f6ff5bdSChristophe Leroy	b	interrupt_return
350533090e5SChristophe Leroy
351533090e5SChristophe Leroy/* Program check exception */
3527fab6397SChristophe Leroy	START_EXCEPTION(INTERRUPT_PROGRAM, ProgramCheck)
3537fab6397SChristophe Leroy	EXCEPTION_PROLOG INTERRUPT_PROGRAM ProgramCheck
3548f6ff5bdSChristophe Leroy	prepare_transfer_to_handler
3558f6ff5bdSChristophe Leroy	bl	program_check_exception
3568f6ff5bdSChristophe Leroy	REST_NVGPRS(r1)
3578f6ff5bdSChristophe Leroy	b	interrupt_return
358533090e5SChristophe Leroy
359533090e5SChristophe Leroy/* Floating-point unavailable */
3607bf1d7e1SChristophe Leroy	START_EXCEPTION(0x800, FPUnavailable)
3617d68c891SChristophe Leroy#ifdef CONFIG_PPC_FPU
362533090e5SChristophe LeroyBEGIN_FTR_SECTION
363533090e5SChristophe Leroy/*
364533090e5SChristophe Leroy * Certain Freescale cores don't have a FPU and treat fp instructions
365533090e5SChristophe Leroy * as a FP Unavailable exception.  Redirect to illegal/emulation handling.
366533090e5SChristophe Leroy */
367533090e5SChristophe Leroy	b 	ProgramCheck
368533090e5SChristophe LeroyEND_FTR_SECTION_IFSET(CPU_FTR_FPU_UNAVAILABLE)
3697fab6397SChristophe Leroy	EXCEPTION_PROLOG INTERRUPT_FP_UNAVAIL FPUnavailable
370533090e5SChristophe Leroy	beq	1f
371533090e5SChristophe Leroy	bl	load_up_fpu		/* if from user, just load it up */
372533090e5SChristophe Leroy	b	fast_exception_return
3734c0104a8SChristophe Leroy1:	prepare_transfer_to_handler
3744c0104a8SChristophe Leroy	bl	kernel_fp_unavailable_exception
3754c0104a8SChristophe Leroy	b	interrupt_return
3767d68c891SChristophe Leroy#else
3777d68c891SChristophe Leroy	b 	ProgramCheck
3787d68c891SChristophe Leroy#endif
379533090e5SChristophe Leroy
380533090e5SChristophe Leroy/* Decrementer */
3817fab6397SChristophe Leroy	EXCEPTION(INTERRUPT_DECREMENTER, Decrementer, timer_interrupt)
382533090e5SChristophe Leroy
383acc142b6SChristophe Leroy	EXCEPTION(0xa00, Trap_0a, unknown_exception)
384acc142b6SChristophe Leroy	EXCEPTION(0xb00, Trap_0b, unknown_exception)
385533090e5SChristophe Leroy
386533090e5SChristophe Leroy/* System call */
3877fab6397SChristophe Leroy	START_EXCEPTION(INTERRUPT_SYSCALL, SystemCall)
3887fab6397SChristophe Leroy	SYSCALL_ENTRY	INTERRUPT_SYSCALL
389533090e5SChristophe Leroy
3907fab6397SChristophe Leroy	EXCEPTION(INTERRUPT_TRACE, SingleStep, single_step_exception)
391acc142b6SChristophe Leroy	EXCEPTION(0xe00, Trap_0e, unknown_exception)
392533090e5SChristophe Leroy
393533090e5SChristophe Leroy/*
394533090e5SChristophe Leroy * The Altivec unavailable trap is at 0x0f20.  Foo.
395533090e5SChristophe Leroy * We effectively remap it to 0x3000.
396533090e5SChristophe Leroy * We include an altivec unavailable exception vector even if
397533090e5SChristophe Leroy * not configured for Altivec, so that you can't panic a
398533090e5SChristophe Leroy * non-altivec kernel running on a machine with altivec just
399533090e5SChristophe Leroy * by executing an altivec instruction.
400533090e5SChristophe Leroy */
4017fab6397SChristophe Leroy	START_EXCEPTION(INTERRUPT_PERFMON, PerformanceMonitorTrap)
402533090e5SChristophe Leroy	b	PerformanceMonitor
403533090e5SChristophe Leroy
4047fab6397SChristophe Leroy	START_EXCEPTION(INTERRUPT_ALTIVEC_UNAVAIL, AltiVecUnavailableTrap)
405533090e5SChristophe Leroy	b	AltiVecUnavailable
406533090e5SChristophe Leroy
407dc13b889SChristophe Leroy	__HEAD
408533090e5SChristophe Leroy/*
409533090e5SChristophe Leroy * Handle TLB miss for instruction on 603/603e.
410533090e5SChristophe Leroy * Note: we get an alternate set of r0 - r3 to use automatically.
411533090e5SChristophe Leroy */
4127fab6397SChristophe Leroy	. = INTERRUPT_INST_TLB_MISS_603
413533090e5SChristophe LeroyInstructionTLBMiss:
414533090e5SChristophe Leroy/*
415533090e5SChristophe Leroy * r0:	scratch
416533090e5SChristophe Leroy * r1:	linux style pte ( later becomes ppc hardware pte )
417533090e5SChristophe Leroy * r2:	ptr to linux-style pte
418533090e5SChristophe Leroy * r3:	scratch
419533090e5SChristophe Leroy */
420533090e5SChristophe Leroy	/* Get PTE (linux-style) and check access */
421533090e5SChristophe Leroy	mfspr	r3,SPRN_IMISS
4222a0fb3c1SChristophe Leroy#ifdef CONFIG_MODULES
423533090e5SChristophe Leroy	lis	r1, TASK_SIZE@h		/* check if kernel address */
424533090e5SChristophe Leroy	cmplw	0,r1,r3
425533090e5SChristophe Leroy#endif
426c4a22611SChristophe Leroy	mfspr	r2, SPRN_SDR1
427c119565aSChristophe Leroy	li	r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC | _PAGE_USER
428c4a22611SChristophe Leroy	rlwinm	r2, r2, 28, 0xfffff000
4292a0fb3c1SChristophe Leroy#ifdef CONFIG_MODULES
430533090e5SChristophe Leroy	bgt-	112f
431533090e5SChristophe Leroy	lis	r2, (swapper_pg_dir - PAGE_OFFSET)@ha	/* if kernel address, use */
432c119565aSChristophe Leroy	li	r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
433533090e5SChristophe Leroy	addi	r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l	/* kernel page table */
434533090e5SChristophe Leroy#endif
435533090e5SChristophe Leroy112:	rlwimi	r2,r3,12,20,29		/* insert top 10 bits of address */
436533090e5SChristophe Leroy	lwz	r2,0(r2)		/* get pmd entry */
437533090e5SChristophe Leroy	rlwinm.	r2,r2,0,0,19		/* extract address of pte page */
438533090e5SChristophe Leroy	beq-	InstructionAddressInvalid	/* return if no mapping */
439533090e5SChristophe Leroy	rlwimi	r2,r3,22,20,29		/* insert next 10 bits of address */
440533090e5SChristophe Leroy	lwz	r0,0(r2)		/* get linux-style pte */
441533090e5SChristophe Leroy	andc.	r1,r1,r0		/* check access & ~permission */
442533090e5SChristophe Leroy	bne-	InstructionAddressInvalid /* return if access not permitted */
443533090e5SChristophe Leroy	/* Convert linux-style PTE to low word of PPC-style PTE */
444533090e5SChristophe Leroy	rlwimi	r0,r0,32-2,31,31	/* _PAGE_USER -> PP lsb */
445533090e5SChristophe Leroy	ori	r1, r1, 0xe06		/* clear out reserved bits */
446533090e5SChristophe Leroy	andc	r1, r0, r1		/* PP = user? 1 : 0 */
447533090e5SChristophe LeroyBEGIN_FTR_SECTION
448533090e5SChristophe Leroy	rlwinm	r1,r1,0,~_PAGE_COHERENT	/* clear M (coherence not required) */
449533090e5SChristophe LeroyEND_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
450533090e5SChristophe Leroy	mtspr	SPRN_RPA,r1
451533090e5SChristophe Leroy	tlbli	r3
452533090e5SChristophe Leroy	mfspr	r3,SPRN_SRR1		/* Need to restore CR0 */
453533090e5SChristophe Leroy	mtcrf	0x80,r3
454533090e5SChristophe Leroy	rfi
455533090e5SChristophe LeroyInstructionAddressInvalid:
456533090e5SChristophe Leroy	mfspr	r3,SPRN_SRR1
457533090e5SChristophe Leroy	rlwinm	r1,r3,9,6,6	/* Get load/store bit */
458533090e5SChristophe Leroy
459533090e5SChristophe Leroy	addis	r1,r1,0x2000
460533090e5SChristophe Leroy	mtspr	SPRN_DSISR,r1	/* (shouldn't be needed) */
461533090e5SChristophe Leroy	andi.	r2,r3,0xFFFF	/* Clear upper bits of SRR1 */
462533090e5SChristophe Leroy	or	r2,r2,r1
463533090e5SChristophe Leroy	mtspr	SPRN_SRR1,r2
464533090e5SChristophe Leroy	mfspr	r1,SPRN_IMISS	/* Get failing address */
465533090e5SChristophe Leroy	rlwinm.	r2,r2,0,31,31	/* Check for little endian access */
466533090e5SChristophe Leroy	rlwimi	r2,r2,1,30,30	/* change 1 -> 3 */
467533090e5SChristophe Leroy	xor	r1,r1,r2
468533090e5SChristophe Leroy	mtspr	SPRN_DAR,r1	/* Set fault address */
469533090e5SChristophe Leroy	mfmsr	r0		/* Restore "normal" registers */
470533090e5SChristophe Leroy	xoris	r0,r0,MSR_TGPR>>16
471533090e5SChristophe Leroy	mtcrf	0x80,r3		/* Restore CR0 */
472533090e5SChristophe Leroy	mtmsr	r0
473533090e5SChristophe Leroy	b	InstructionAccess
474533090e5SChristophe Leroy
475533090e5SChristophe Leroy/*
476533090e5SChristophe Leroy * Handle TLB miss for DATA Load operation on 603/603e
477533090e5SChristophe Leroy */
4787fab6397SChristophe Leroy	. = INTERRUPT_DATA_LOAD_TLB_MISS_603
479533090e5SChristophe LeroyDataLoadTLBMiss:
480533090e5SChristophe Leroy/*
481533090e5SChristophe Leroy * r0:	scratch
482533090e5SChristophe Leroy * r1:	linux style pte ( later becomes ppc hardware pte )
483533090e5SChristophe Leroy * r2:	ptr to linux-style pte
484533090e5SChristophe Leroy * r3:	scratch
485533090e5SChristophe Leroy */
486533090e5SChristophe Leroy	/* Get PTE (linux-style) and check access */
487533090e5SChristophe Leroy	mfspr	r3,SPRN_DMISS
488533090e5SChristophe Leroy	lis	r1, TASK_SIZE@h		/* check if kernel address */
489533090e5SChristophe Leroy	cmplw	0,r1,r3
490c4a22611SChristophe Leroy	mfspr	r2, SPRN_SDR1
491c119565aSChristophe Leroy	li	r1, _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_USER
492c4a22611SChristophe Leroy	rlwinm	r2, r2, 28, 0xfffff000
493533090e5SChristophe Leroy	bgt-	112f
494533090e5SChristophe Leroy	lis	r2, (swapper_pg_dir - PAGE_OFFSET)@ha	/* if kernel address, use */
495c119565aSChristophe Leroy	li	r1, _PAGE_PRESENT | _PAGE_ACCESSED
496533090e5SChristophe Leroy	addi	r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l	/* kernel page table */
497533090e5SChristophe Leroy112:	rlwimi	r2,r3,12,20,29		/* insert top 10 bits of address */
498533090e5SChristophe Leroy	lwz	r2,0(r2)		/* get pmd entry */
499533090e5SChristophe Leroy	rlwinm.	r2,r2,0,0,19		/* extract address of pte page */
500533090e5SChristophe Leroy	beq-	DataAddressInvalid	/* return if no mapping */
501533090e5SChristophe Leroy	rlwimi	r2,r3,22,20,29		/* insert next 10 bits of address */
502533090e5SChristophe Leroy	lwz	r0,0(r2)		/* get linux-style pte */
503533090e5SChristophe Leroy	andc.	r1,r1,r0		/* check access & ~permission */
504533090e5SChristophe Leroy	bne-	DataAddressInvalid	/* return if access not permitted */
505533090e5SChristophe Leroy	/* Convert linux-style PTE to low word of PPC-style PTE */
506533090e5SChristophe Leroy	rlwinm	r1,r0,32-9,30,30	/* _PAGE_RW -> PP msb */
507533090e5SChristophe Leroy	rlwimi	r0,r0,32-1,30,30	/* _PAGE_USER -> PP msb */
5084634bf44SChristophe Leroy	rlwimi	r1,r0,32-3,24,24	/* _PAGE_RW -> _PAGE_DIRTY */
509533090e5SChristophe Leroy	rlwimi	r0,r0,32-1,31,31	/* _PAGE_USER -> PP lsb */
5104634bf44SChristophe Leroy	xori	r1,r1,_PAGE_DIRTY	/* clear dirty when not rw */
511533090e5SChristophe Leroy	ori	r1,r1,0xe04		/* clear out reserved bits */
512533090e5SChristophe Leroy	andc	r1,r0,r1		/* PP = user? rw? 1: 3: 0 */
513533090e5SChristophe LeroyBEGIN_FTR_SECTION
514533090e5SChristophe Leroy	rlwinm	r1,r1,0,~_PAGE_COHERENT	/* clear M (coherence not required) */
515533090e5SChristophe LeroyEND_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
516533090e5SChristophe Leroy	mtspr	SPRN_RPA,r1
517533090e5SChristophe LeroyBEGIN_MMU_FTR_SECTION
518533090e5SChristophe Leroy	li	r0,1
519533090e5SChristophe Leroy	mfspr	r1,SPRN_SPRG_603_LRU
520533090e5SChristophe Leroy	rlwinm	r2,r3,20,27,31		/* Get Address bits 15:19 */
521533090e5SChristophe Leroy	slw	r0,r0,r2
522533090e5SChristophe Leroy	xor	r1,r0,r1
523533090e5SChristophe Leroy	srw	r0,r1,r2
524533090e5SChristophe Leroy	mtspr   SPRN_SPRG_603_LRU,r1
525533090e5SChristophe Leroy	mfspr	r2,SPRN_SRR1
526533090e5SChristophe Leroy	rlwimi	r2,r0,31-14,14,14
527533090e5SChristophe Leroy	mtspr   SPRN_SRR1,r2
52870d6ebf8SChristophe Leroy	mtcrf	0x80,r2
529533090e5SChristophe Leroy	tlbld	r3
530533090e5SChristophe Leroy	rfi
53170d6ebf8SChristophe LeroyMMU_FTR_SECTION_ELSE
53270d6ebf8SChristophe Leroy	mfspr	r2,SPRN_SRR1		/* Need to restore CR0 */
53370d6ebf8SChristophe Leroy	mtcrf	0x80,r2
53470d6ebf8SChristophe Leroy	tlbld	r3
53570d6ebf8SChristophe Leroy	rfi
53670d6ebf8SChristophe LeroyALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_NEED_DTLB_SW_LRU)
537533090e5SChristophe LeroyDataAddressInvalid:
538533090e5SChristophe Leroy	mfspr	r3,SPRN_SRR1
539533090e5SChristophe Leroy	rlwinm	r1,r3,9,6,6	/* Get load/store bit */
540533090e5SChristophe Leroy	addis	r1,r1,0x2000
541533090e5SChristophe Leroy	mtspr	SPRN_DSISR,r1
542533090e5SChristophe Leroy	andi.	r2,r3,0xFFFF	/* Clear upper bits of SRR1 */
543533090e5SChristophe Leroy	mtspr	SPRN_SRR1,r2
544533090e5SChristophe Leroy	mfspr	r1,SPRN_DMISS	/* Get failing address */
545533090e5SChristophe Leroy	rlwinm.	r2,r2,0,31,31	/* Check for little endian access */
546533090e5SChristophe Leroy	beq	20f		/* Jump if big endian */
547533090e5SChristophe Leroy	xori	r1,r1,3
548533090e5SChristophe Leroy20:	mtspr	SPRN_DAR,r1	/* Set fault address */
549533090e5SChristophe Leroy	mfmsr	r0		/* Restore "normal" registers */
550533090e5SChristophe Leroy	xoris	r0,r0,MSR_TGPR>>16
551533090e5SChristophe Leroy	mtcrf	0x80,r3		/* Restore CR0 */
552533090e5SChristophe Leroy	mtmsr	r0
553533090e5SChristophe Leroy	b	DataAccess
554533090e5SChristophe Leroy
555533090e5SChristophe Leroy/*
556533090e5SChristophe Leroy * Handle TLB miss for DATA Store on 603/603e
557533090e5SChristophe Leroy */
5587fab6397SChristophe Leroy	. = INTERRUPT_DATA_STORE_TLB_MISS_603
559533090e5SChristophe LeroyDataStoreTLBMiss:
560533090e5SChristophe Leroy/*
561533090e5SChristophe Leroy * r0:	scratch
562533090e5SChristophe Leroy * r1:	linux style pte ( later becomes ppc hardware pte )
563533090e5SChristophe Leroy * r2:	ptr to linux-style pte
564533090e5SChristophe Leroy * r3:	scratch
565533090e5SChristophe Leroy */
566533090e5SChristophe Leroy	/* Get PTE (linux-style) and check access */
567533090e5SChristophe Leroy	mfspr	r3,SPRN_DMISS
568533090e5SChristophe Leroy	lis	r1, TASK_SIZE@h		/* check if kernel address */
569533090e5SChristophe Leroy	cmplw	0,r1,r3
570c4a22611SChristophe Leroy	mfspr	r2, SPRN_SDR1
571c119565aSChristophe Leroy	li	r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_USER
572c4a22611SChristophe Leroy	rlwinm	r2, r2, 28, 0xfffff000
573533090e5SChristophe Leroy	bgt-	112f
574533090e5SChristophe Leroy	lis	r2, (swapper_pg_dir - PAGE_OFFSET)@ha	/* if kernel address, use */
575c119565aSChristophe Leroy	li	r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED
576533090e5SChristophe Leroy	addi	r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l	/* kernel page table */
577533090e5SChristophe Leroy112:	rlwimi	r2,r3,12,20,29		/* insert top 10 bits of address */
578533090e5SChristophe Leroy	lwz	r2,0(r2)		/* get pmd entry */
579533090e5SChristophe Leroy	rlwinm.	r2,r2,0,0,19		/* extract address of pte page */
580533090e5SChristophe Leroy	beq-	DataAddressInvalid	/* return if no mapping */
581533090e5SChristophe Leroy	rlwimi	r2,r3,22,20,29		/* insert next 10 bits of address */
582533090e5SChristophe Leroy	lwz	r0,0(r2)		/* get linux-style pte */
583533090e5SChristophe Leroy	andc.	r1,r1,r0		/* check access & ~permission */
584533090e5SChristophe Leroy	bne-	DataAddressInvalid	/* return if access not permitted */
585533090e5SChristophe Leroy	/* Convert linux-style PTE to low word of PPC-style PTE */
586533090e5SChristophe Leroy	rlwimi	r0,r0,32-2,31,31	/* _PAGE_USER -> PP lsb */
587533090e5SChristophe Leroy	li	r1,0xe06		/* clear out reserved bits & PP msb */
588533090e5SChristophe Leroy	andc	r1,r0,r1		/* PP = user? 1: 0 */
589533090e5SChristophe LeroyBEGIN_FTR_SECTION
590533090e5SChristophe Leroy	rlwinm	r1,r1,0,~_PAGE_COHERENT	/* clear M (coherence not required) */
591533090e5SChristophe LeroyEND_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
592533090e5SChristophe Leroy	mtspr	SPRN_RPA,r1
593533090e5SChristophe Leroy	mfspr	r2,SPRN_SRR1		/* Need to restore CR0 */
594533090e5SChristophe Leroy	mtcrf	0x80,r2
595533090e5SChristophe LeroyBEGIN_MMU_FTR_SECTION
596533090e5SChristophe Leroy	li	r0,1
597533090e5SChristophe Leroy	mfspr	r1,SPRN_SPRG_603_LRU
598533090e5SChristophe Leroy	rlwinm	r2,r3,20,27,31		/* Get Address bits 15:19 */
599533090e5SChristophe Leroy	slw	r0,r0,r2
600533090e5SChristophe Leroy	xor	r1,r0,r1
601533090e5SChristophe Leroy	srw	r0,r1,r2
602533090e5SChristophe Leroy	mtspr   SPRN_SPRG_603_LRU,r1
603533090e5SChristophe Leroy	mfspr	r2,SPRN_SRR1
604533090e5SChristophe Leroy	rlwimi	r2,r0,31-14,14,14
605533090e5SChristophe Leroy	mtspr   SPRN_SRR1,r2
60670d6ebf8SChristophe Leroy	mtcrf	0x80,r2
607533090e5SChristophe Leroy	tlbld	r3
608533090e5SChristophe Leroy	rfi
60970d6ebf8SChristophe LeroyMMU_FTR_SECTION_ELSE
61070d6ebf8SChristophe Leroy	mfspr	r2,SPRN_SRR1		/* Need to restore CR0 */
61170d6ebf8SChristophe Leroy	mtcrf	0x80,r2
61270d6ebf8SChristophe Leroy	tlbld	r3
61370d6ebf8SChristophe Leroy	rfi
61470d6ebf8SChristophe LeroyALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_NEED_DTLB_SW_LRU)
615533090e5SChristophe Leroy
616533090e5SChristophe Leroy#ifndef CONFIG_ALTIVEC
617533090e5SChristophe Leroy#define altivec_assist_exception	unknown_exception
618533090e5SChristophe Leroy#endif
619533090e5SChristophe Leroy
620533090e5SChristophe Leroy#ifndef CONFIG_TAU_INT
6216c6aee00SNicholas Piggin#define TAUException	unknown_async_exception
622533090e5SChristophe Leroy#endif
623533090e5SChristophe Leroy
624acc142b6SChristophe Leroy	EXCEPTION(0x1300, Trap_13, instruction_breakpoint_exception)
625acc142b6SChristophe Leroy	EXCEPTION(0x1400, SMI, SMIException)
626acc142b6SChristophe Leroy	EXCEPTION(0x1500, Trap_15, unknown_exception)
627acc142b6SChristophe Leroy	EXCEPTION(0x1600, Trap_16, altivec_assist_exception)
628acc142b6SChristophe Leroy	EXCEPTION(0x1700, Trap_17, TAUException)
629acc142b6SChristophe Leroy	EXCEPTION(0x1800, Trap_18, unknown_exception)
630acc142b6SChristophe Leroy	EXCEPTION(0x1900, Trap_19, unknown_exception)
631acc142b6SChristophe Leroy	EXCEPTION(0x1a00, Trap_1a, unknown_exception)
632acc142b6SChristophe Leroy	EXCEPTION(0x1b00, Trap_1b, unknown_exception)
633acc142b6SChristophe Leroy	EXCEPTION(0x1c00, Trap_1c, unknown_exception)
634acc142b6SChristophe Leroy	EXCEPTION(0x1d00, Trap_1d, unknown_exception)
635acc142b6SChristophe Leroy	EXCEPTION(0x1e00, Trap_1e, unknown_exception)
636acc142b6SChristophe Leroy	EXCEPTION(0x1f00, Trap_1f, unknown_exception)
637acc142b6SChristophe Leroy	EXCEPTION(0x2000, RunMode, RunModeException)
638acc142b6SChristophe Leroy	EXCEPTION(0x2100, Trap_21, unknown_exception)
639acc142b6SChristophe Leroy	EXCEPTION(0x2200, Trap_22, unknown_exception)
640acc142b6SChristophe Leroy	EXCEPTION(0x2300, Trap_23, unknown_exception)
641acc142b6SChristophe Leroy	EXCEPTION(0x2400, Trap_24, unknown_exception)
642acc142b6SChristophe Leroy	EXCEPTION(0x2500, Trap_25, unknown_exception)
643acc142b6SChristophe Leroy	EXCEPTION(0x2600, Trap_26, unknown_exception)
644acc142b6SChristophe Leroy	EXCEPTION(0x2700, Trap_27, unknown_exception)
645acc142b6SChristophe Leroy	EXCEPTION(0x2800, Trap_28, unknown_exception)
646acc142b6SChristophe Leroy	EXCEPTION(0x2900, Trap_29, unknown_exception)
647acc142b6SChristophe Leroy	EXCEPTION(0x2a00, Trap_2a, unknown_exception)
648acc142b6SChristophe Leroy	EXCEPTION(0x2b00, Trap_2b, unknown_exception)
649acc142b6SChristophe Leroy	EXCEPTION(0x2c00, Trap_2c, unknown_exception)
650acc142b6SChristophe Leroy	EXCEPTION(0x2d00, Trap_2d, unknown_exception)
651acc142b6SChristophe Leroy	EXCEPTION(0x2e00, Trap_2e, unknown_exception)
652acc142b6SChristophe Leroy	EXCEPTION(0x2f00, Trap_2f, unknown_exception)
653533090e5SChristophe Leroy
654dc13b889SChristophe Leroy	__HEAD
655533090e5SChristophe Leroy	. = 0x3000
656533090e5SChristophe Leroy
657259149cfSChristophe Leroy#ifdef CONFIG_PPC_BOOK3S_604
658533090e5SChristophe Leroy.macro save_regs_thread		thread
659533090e5SChristophe Leroy	stw	r0, THR0(\thread)
660533090e5SChristophe Leroy	stw	r3, THR3(\thread)
661533090e5SChristophe Leroy	stw	r4, THR4(\thread)
662533090e5SChristophe Leroy	stw	r5, THR5(\thread)
663533090e5SChristophe Leroy	stw	r6, THR6(\thread)
664533090e5SChristophe Leroy	stw	r8, THR8(\thread)
665533090e5SChristophe Leroy	stw	r9, THR9(\thread)
666533090e5SChristophe Leroy	mflr	r0
667533090e5SChristophe Leroy	stw	r0, THLR(\thread)
668533090e5SChristophe Leroy	mfctr	r0
669533090e5SChristophe Leroy	stw	r0, THCTR(\thread)
670533090e5SChristophe Leroy.endm
671533090e5SChristophe Leroy
672533090e5SChristophe Leroy.macro restore_regs_thread	thread
673533090e5SChristophe Leroy	lwz	r0, THLR(\thread)
674533090e5SChristophe Leroy	mtlr	r0
675533090e5SChristophe Leroy	lwz	r0, THCTR(\thread)
676533090e5SChristophe Leroy	mtctr	r0
677533090e5SChristophe Leroy	lwz	r0, THR0(\thread)
678533090e5SChristophe Leroy	lwz	r3, THR3(\thread)
679533090e5SChristophe Leroy	lwz	r4, THR4(\thread)
680533090e5SChristophe Leroy	lwz	r5, THR5(\thread)
681533090e5SChristophe Leroy	lwz	r6, THR6(\thread)
682533090e5SChristophe Leroy	lwz	r8, THR8(\thread)
683533090e5SChristophe Leroy	lwz	r9, THR9(\thread)
684533090e5SChristophe Leroy.endm
685533090e5SChristophe Leroy
686533090e5SChristophe Leroyhash_page_dsi:
687533090e5SChristophe Leroy	save_regs_thread	r10
688533090e5SChristophe Leroy	mfdsisr	r3
689533090e5SChristophe Leroy	mfdar	r4
690533090e5SChristophe Leroy	mfsrr0	r5
691533090e5SChristophe Leroy	mfsrr1	r9
692533090e5SChristophe Leroy	rlwinm	r3, r3, 32 - 15, _PAGE_RW	/* DSISR_STORE -> _PAGE_RW */
693533090e5SChristophe Leroy	bl	hash_page
694533090e5SChristophe Leroy	mfspr	r10, SPRN_SPRG_THREAD
695533090e5SChristophe Leroy	restore_regs_thread r10
696533090e5SChristophe Leroy	b	.Lhash_page_dsi_cont
697533090e5SChristophe Leroy
698533090e5SChristophe Leroyhash_page_isi:
699533090e5SChristophe Leroy	mr	r11, r10
700533090e5SChristophe Leroy	mfspr	r10, SPRN_SPRG_THREAD
701533090e5SChristophe Leroy	save_regs_thread	r10
702533090e5SChristophe Leroy	li	r3, 0
703533090e5SChristophe Leroy	lwz	r4, SRR0(r10)
704533090e5SChristophe Leroy	lwz	r9, SRR1(r10)
705533090e5SChristophe Leroy	bl	hash_page
706533090e5SChristophe Leroy	mfspr	r10, SPRN_SPRG_THREAD
707533090e5SChristophe Leroy	restore_regs_thread r10
708533090e5SChristophe Leroy	mr	r10, r11
709533090e5SChristophe Leroy	b	.Lhash_page_isi_cont
710533090e5SChristophe Leroy
711533090e5SChristophe Leroy	.globl fast_hash_page_return
712533090e5SChristophe Leroyfast_hash_page_return:
713533090e5SChristophe Leroy	andis.	r10, r9, SRR1_ISI_NOPT@h	/* Set on ISI, cleared on DSI */
714533090e5SChristophe Leroy	mfspr	r10, SPRN_SPRG_THREAD
715533090e5SChristophe Leroy	restore_regs_thread r10
716533090e5SChristophe Leroy	bne	1f
717533090e5SChristophe Leroy
718533090e5SChristophe Leroy	/* DSI */
719533090e5SChristophe Leroy	mtcr	r11
720533090e5SChristophe Leroy	lwz	r11, THR11(r10)
721de1cd079SChristophe Leroy	mfspr	r10, SPRN_SPRG_SCRATCH2
722120c0518SChristophe Leroy	rfi
723533090e5SChristophe Leroy
724533090e5SChristophe Leroy1:	/* ISI */
725533090e5SChristophe Leroy	mtcr	r11
726533090e5SChristophe Leroy	mfspr	r11, SPRN_SPRG_SCRATCH1
727533090e5SChristophe Leroy	mfspr	r10, SPRN_SPRG_SCRATCH0
728120c0518SChristophe Leroy	rfi
729259149cfSChristophe Leroy#endif /* CONFIG_PPC_BOOK3S_604 */
730533090e5SChristophe Leroy
7317aa8dd67SChristophe Leroy#ifdef CONFIG_VMAP_STACK
732533090e5SChristophe Leroy	vmap_stack_overflow_exception
733533090e5SChristophe Leroy#endif
734533090e5SChristophe Leroy
735dc13b889SChristophe Leroy	__HEAD
736533090e5SChristophe LeroyAltiVecUnavailable:
737719e7e21SChristophe Leroy	EXCEPTION_PROLOG 0xf20 AltiVecUnavailable
738533090e5SChristophe Leroy#ifdef CONFIG_ALTIVEC
739533090e5SChristophe Leroy	beq	1f
740533090e5SChristophe Leroy	bl	load_up_altivec		/* if from user, just load it up */
741533090e5SChristophe Leroy	b	fast_exception_return
742533090e5SChristophe Leroy#endif /* CONFIG_ALTIVEC */
7434c0104a8SChristophe Leroy1:	prepare_transfer_to_handler
7444c0104a8SChristophe Leroy	bl	altivec_unavailable_exception
7454c0104a8SChristophe Leroy	b	interrupt_return
746533090e5SChristophe Leroy
747dc13b889SChristophe Leroy	__HEAD
748533090e5SChristophe LeroyPerformanceMonitor:
749719e7e21SChristophe Leroy	EXCEPTION_PROLOG 0xf00 PerformanceMonitor
7504c0104a8SChristophe Leroy	prepare_transfer_to_handler
7514c0104a8SChristophe Leroy	bl	performance_monitor_exception
7524c0104a8SChristophe Leroy	b	interrupt_return
753533090e5SChristophe Leroy
754533090e5SChristophe Leroy
755dc13b889SChristophe Leroy	__HEAD
756533090e5SChristophe Leroy/*
757533090e5SChristophe Leroy * This code is jumped to from the startup code to copy
758533090e5SChristophe Leroy * the kernel image to physical address PHYSICAL_START.
759533090e5SChristophe Leroy */
760533090e5SChristophe Leroyrelocate_kernel:
761533090e5SChristophe Leroy	lis	r3,PHYSICAL_START@h	/* Destination base address */
762533090e5SChristophe Leroy	li	r6,0			/* Destination offset */
763533090e5SChristophe Leroy	li	r5,0x4000		/* # bytes of memory to copy */
764533090e5SChristophe Leroy	bl	copy_and_flush		/* copy the first 0x4000 bytes */
765533090e5SChristophe Leroy	addi	r0,r3,4f@l		/* jump to the address of 4f */
766533090e5SChristophe Leroy	mtctr	r0			/* in copy and do the rest. */
767533090e5SChristophe Leroy	bctr				/* jump to the copy */
76856afad88SChristophe Leroy4:	lis	r5,_end-KERNELBASE@h
76956afad88SChristophe Leroy	ori	r5,r5,_end-KERNELBASE@l
770533090e5SChristophe Leroy	bl	copy_and_flush		/* copy the rest */
771533090e5SChristophe Leroy	b	turn_on_mmu
772533090e5SChristophe Leroy
773533090e5SChristophe Leroy/*
774533090e5SChristophe Leroy * Copy routine used to copy the kernel to start at physical address 0
775533090e5SChristophe Leroy * and flush and invalidate the caches as needed.
776533090e5SChristophe Leroy * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset
777533090e5SChristophe Leroy * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5.
778533090e5SChristophe Leroy */
77927e21e8fSChristophe Leroy_GLOBAL(copy_and_flush)
780533090e5SChristophe Leroy	addi	r5,r5,-4
781533090e5SChristophe Leroy	addi	r6,r6,-4
782533090e5SChristophe Leroy4:	li	r0,L1_CACHE_BYTES/4
783533090e5SChristophe Leroy	mtctr	r0
784533090e5SChristophe Leroy3:	addi	r6,r6,4			/* copy a cache line */
785533090e5SChristophe Leroy	lwzx	r0,r6,r4
786533090e5SChristophe Leroy	stwx	r0,r6,r3
787533090e5SChristophe Leroy	bdnz	3b
788533090e5SChristophe Leroy	dcbst	r6,r3			/* write it to memory */
789533090e5SChristophe Leroy	sync
790533090e5SChristophe Leroy	icbi	r6,r3			/* flush the icache line */
791533090e5SChristophe Leroy	cmplw	0,r6,r5
792533090e5SChristophe Leroy	blt	4b
793533090e5SChristophe Leroy	sync				/* additional sync needed on g4 */
794533090e5SChristophe Leroy	isync
795533090e5SChristophe Leroy	addi	r5,r5,4
796533090e5SChristophe Leroy	addi	r6,r6,4
797533090e5SChristophe Leroy	blr
798533090e5SChristophe Leroy
799533090e5SChristophe Leroy#ifdef CONFIG_SMP
800533090e5SChristophe Leroy	.globl __secondary_start_mpc86xx
801533090e5SChristophe Leroy__secondary_start_mpc86xx:
802533090e5SChristophe Leroy	mfspr	r3, SPRN_PIR
803533090e5SChristophe Leroy	stw	r3, __secondary_hold_acknowledge@l(0)
804533090e5SChristophe Leroy	mr	r24, r3			/* cpu # */
805533090e5SChristophe Leroy	b	__secondary_start
806533090e5SChristophe Leroy
807533090e5SChristophe Leroy	.globl	__secondary_start_pmac_0
808533090e5SChristophe Leroy__secondary_start_pmac_0:
809533090e5SChristophe Leroy	/* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */
810533090e5SChristophe Leroy	li	r24,0
811533090e5SChristophe Leroy	b	1f
812533090e5SChristophe Leroy	li	r24,1
813533090e5SChristophe Leroy	b	1f
814533090e5SChristophe Leroy	li	r24,2
815533090e5SChristophe Leroy	b	1f
816533090e5SChristophe Leroy	li	r24,3
817533090e5SChristophe Leroy1:
818533090e5SChristophe Leroy	/* on powersurge, we come in here with IR=0 and DR=1, and DBAT 0
819533090e5SChristophe Leroy	   set to map the 0xf0000000 - 0xffffffff region */
820533090e5SChristophe Leroy	mfmsr	r0
821533090e5SChristophe Leroy	rlwinm	r0,r0,0,28,26		/* clear DR (0x10) */
822533090e5SChristophe Leroy	mtmsr	r0
823533090e5SChristophe Leroy	isync
824533090e5SChristophe Leroy
825533090e5SChristophe Leroy	.globl	__secondary_start
826533090e5SChristophe Leroy__secondary_start:
827533090e5SChristophe Leroy	/* Copy some CPU settings from CPU 0 */
828533090e5SChristophe Leroy	bl	__restore_cpu_setup
829533090e5SChristophe Leroy
830533090e5SChristophe Leroy	lis	r3,-KERNELBASE@h
831533090e5SChristophe Leroy	mr	r4,r24
832533090e5SChristophe Leroy	bl	call_setup_cpu		/* Call setup_cpu for this CPU */
833533090e5SChristophe Leroy	lis	r3,-KERNELBASE@h
834533090e5SChristophe Leroy	bl	init_idle_6xx
835533090e5SChristophe Leroy
836533090e5SChristophe Leroy	/* get current's stack and current */
837533090e5SChristophe Leroy	lis	r2,secondary_current@ha
838533090e5SChristophe Leroy	tophys(r2,r2)
839533090e5SChristophe Leroy	lwz	r2,secondary_current@l(r2)
840533090e5SChristophe Leroy	tophys(r1,r2)
841533090e5SChristophe Leroy	lwz	r1,TASK_STACK(r1)
842533090e5SChristophe Leroy
843533090e5SChristophe Leroy	/* stack */
844*90f1b431SNicholas Piggin	addi	r1,r1,THREAD_SIZE-STACK_FRAME_MIN_SIZE
845533090e5SChristophe Leroy	li	r0,0
846533090e5SChristophe Leroy	tophys(r3,r1)
847533090e5SChristophe Leroy	stw	r0,0(r3)
848533090e5SChristophe Leroy
849533090e5SChristophe Leroy	/* load up the MMU */
850533090e5SChristophe Leroy	bl	load_segment_registers
851533090e5SChristophe Leroy	bl	load_up_mmu
852533090e5SChristophe Leroy
853533090e5SChristophe Leroy	/* ptr to phys current thread */
854533090e5SChristophe Leroy	tophys(r4,r2)
855533090e5SChristophe Leroy	addi	r4,r4,THREAD	/* phys address of our thread_struct */
856533090e5SChristophe Leroy	mtspr	SPRN_SPRG_THREAD,r4
857c4a22611SChristophe LeroyBEGIN_MMU_FTR_SECTION
858533090e5SChristophe Leroy	lis	r4, (swapper_pg_dir - PAGE_OFFSET)@h
859533090e5SChristophe Leroy	ori	r4, r4, (swapper_pg_dir - PAGE_OFFSET)@l
860c4a22611SChristophe Leroy	rlwinm	r4, r4, 4, 0xffff01ff
861c4a22611SChristophe Leroy	mtspr	SPRN_SDR1, r4
862c4a22611SChristophe LeroyEND_MMU_FTR_SECTION_IFCLR(MMU_FTR_HPTE_TABLE)
863533090e5SChristophe Leroy
864533090e5SChristophe Leroy	/* enable MMU and jump to start_secondary */
865533090e5SChristophe Leroy	li	r4,MSR_KERNEL
866533090e5SChristophe Leroy	lis	r3,start_secondary@h
867533090e5SChristophe Leroy	ori	r3,r3,start_secondary@l
868533090e5SChristophe Leroy	mtspr	SPRN_SRR0,r3
869533090e5SChristophe Leroy	mtspr	SPRN_SRR1,r4
870120c0518SChristophe Leroy	rfi
871533090e5SChristophe Leroy#endif /* CONFIG_SMP */
872533090e5SChristophe Leroy
873533090e5SChristophe Leroy#ifdef CONFIG_KVM_BOOK3S_HANDLER
874533090e5SChristophe Leroy#include "../kvm/book3s_rmhandlers.S"
875533090e5SChristophe Leroy#endif
876533090e5SChristophe Leroy
877533090e5SChristophe Leroy/*
878533090e5SChristophe Leroy * Load stuff into the MMU.  Intended to be called with
879533090e5SChristophe Leroy * IR=0 and DR=0.
880533090e5SChristophe Leroy */
8812da37761SChristophe LeroySYM_FUNC_START_LOCAL(early_hash_table)
882533090e5SChristophe Leroy	sync			/* Force all PTE updates to finish */
883533090e5SChristophe Leroy	isync
884533090e5SChristophe Leroy	tlbia			/* Clear all TLB entries */
885533090e5SChristophe Leroy	sync			/* wait for tlbia/tlbie to finish */
886533090e5SChristophe Leroy	TLBSYNC			/* ... on all CPUs */
887533090e5SChristophe Leroy	/* Load the SDR1 register (hash table base & size) */
888533090e5SChristophe Leroy	lis	r6, early_hash - PAGE_OFFSET@h
889533090e5SChristophe Leroy	ori	r6, r6, 3	/* 256kB table */
890533090e5SChristophe Leroy	mtspr	SPRN_SDR1, r6
891533090e5SChristophe Leroy	blr
8922da37761SChristophe LeroySYM_FUNC_END(early_hash_table)
893533090e5SChristophe Leroy
8942da37761SChristophe LeroySYM_FUNC_START_LOCAL(load_up_mmu)
895533090e5SChristophe Leroy	sync			/* Force all PTE updates to finish */
896533090e5SChristophe Leroy	isync
897533090e5SChristophe Leroy	tlbia			/* Clear all TLB entries */
898533090e5SChristophe Leroy	sync			/* wait for tlbia/tlbie to finish */
899533090e5SChristophe Leroy	TLBSYNC			/* ... on all CPUs */
900c4a22611SChristophe LeroyBEGIN_MMU_FTR_SECTION
901533090e5SChristophe Leroy	/* Load the SDR1 register (hash table base & size) */
902533090e5SChristophe Leroy	lis	r6,_SDR1@ha
903533090e5SChristophe Leroy	tophys(r6,r6)
904533090e5SChristophe Leroy	lwz	r6,_SDR1@l(r6)
905533090e5SChristophe Leroy	mtspr	SPRN_SDR1,r6
906c4a22611SChristophe LeroyEND_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
907533090e5SChristophe Leroy
908533090e5SChristophe Leroy/* Load the BAT registers with the values set up by MMU_init. */
909533090e5SChristophe Leroy	lis	r3,BATS@ha
910533090e5SChristophe Leroy	addi	r3,r3,BATS@l
911533090e5SChristophe Leroy	tophys(r3,r3)
912533090e5SChristophe Leroy	LOAD_BAT(0,r3,r4,r5)
913533090e5SChristophe Leroy	LOAD_BAT(1,r3,r4,r5)
914533090e5SChristophe Leroy	LOAD_BAT(2,r3,r4,r5)
915533090e5SChristophe Leroy	LOAD_BAT(3,r3,r4,r5)
916533090e5SChristophe LeroyBEGIN_MMU_FTR_SECTION
917533090e5SChristophe Leroy	LOAD_BAT(4,r3,r4,r5)
918533090e5SChristophe Leroy	LOAD_BAT(5,r3,r4,r5)
919533090e5SChristophe Leroy	LOAD_BAT(6,r3,r4,r5)
920533090e5SChristophe Leroy	LOAD_BAT(7,r3,r4,r5)
921533090e5SChristophe LeroyEND_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
922533090e5SChristophe Leroy	blr
9232da37761SChristophe LeroySYM_FUNC_END(load_up_mmu)
924533090e5SChristophe Leroy
925533090e5SChristophe Leroy_GLOBAL(load_segment_registers)
926533090e5SChristophe Leroy	li	r0, NUM_USER_SEGMENTS /* load up user segment register values */
927533090e5SChristophe Leroy	mtctr	r0		/* for context 0 */
928526d4a4cSChristophe Leroy#ifdef CONFIG_PPC_KUEP
929526d4a4cSChristophe Leroy	lis	r3, SR_NX@h	/* Kp = 0, Ks = 0, VSID = 0 */
930526d4a4cSChristophe Leroy#else
931533090e5SChristophe Leroy	li	r3, 0		/* Kp = 0, Ks = 0, VSID = 0 */
932526d4a4cSChristophe Leroy#endif
933533090e5SChristophe Leroy	li	r4, 0
934533090e5SChristophe Leroy3:	mtsrin	r3, r4
935533090e5SChristophe Leroy	addi	r3, r3, 0x111	/* increment VSID */
936533090e5SChristophe Leroy	addis	r4, r4, 0x1000	/* address of next segment */
937533090e5SChristophe Leroy	bdnz	3b
938533090e5SChristophe Leroy	li	r0, 16 - NUM_USER_SEGMENTS /* load up kernel segment registers */
939533090e5SChristophe Leroy	mtctr	r0			/* for context 0 */
940533090e5SChristophe Leroy	rlwinm	r3, r3, 0, ~SR_NX	/* Nx = 0 */
941533090e5SChristophe Leroy	rlwinm	r3, r3, 0, ~SR_KS	/* Ks = 0 */
942533090e5SChristophe Leroy	oris	r3, r3, SR_KP@h		/* Kp = 1 */
943533090e5SChristophe Leroy3:	mtsrin	r3, r4
944533090e5SChristophe Leroy	addi	r3, r3, 0x111	/* increment VSID */
945533090e5SChristophe Leroy	addis	r4, r4, 0x1000	/* address of next segment */
946533090e5SChristophe Leroy	bdnz	3b
947533090e5SChristophe Leroy	blr
948533090e5SChristophe Leroy
949533090e5SChristophe Leroy/*
950533090e5SChristophe Leroy * This is where the main kernel code starts.
951533090e5SChristophe Leroy */
952533090e5SChristophe Leroystart_here:
953533090e5SChristophe Leroy	/* ptr to current */
954533090e5SChristophe Leroy	lis	r2,init_task@h
955533090e5SChristophe Leroy	ori	r2,r2,init_task@l
956533090e5SChristophe Leroy	/* Set up for using our exception vectors */
957533090e5SChristophe Leroy	/* ptr to phys current thread */
958533090e5SChristophe Leroy	tophys(r4,r2)
959533090e5SChristophe Leroy	addi	r4,r4,THREAD	/* init task's THREAD */
960533090e5SChristophe Leroy	mtspr	SPRN_SPRG_THREAD,r4
961c4a22611SChristophe LeroyBEGIN_MMU_FTR_SECTION
962533090e5SChristophe Leroy	lis	r4, (swapper_pg_dir - PAGE_OFFSET)@h
963533090e5SChristophe Leroy	ori	r4, r4, (swapper_pg_dir - PAGE_OFFSET)@l
964c4a22611SChristophe Leroy	rlwinm	r4, r4, 4, 0xffff01ff
965c4a22611SChristophe Leroy	mtspr	SPRN_SDR1, r4
966c4a22611SChristophe LeroyEND_MMU_FTR_SECTION_IFCLR(MMU_FTR_HPTE_TABLE)
967533090e5SChristophe Leroy
968533090e5SChristophe Leroy	/* stack */
969533090e5SChristophe Leroy	lis	r1,init_thread_union@ha
970533090e5SChristophe Leroy	addi	r1,r1,init_thread_union@l
971533090e5SChristophe Leroy	li	r0,0
972*90f1b431SNicholas Piggin	stwu	r0,THREAD_SIZE-STACK_FRAME_MIN_SIZE(r1)
973533090e5SChristophe Leroy/*
974533090e5SChristophe Leroy * Do early platform-specific initialization,
975533090e5SChristophe Leroy * and set up the MMU.
976533090e5SChristophe Leroy */
977533090e5SChristophe Leroy#ifdef CONFIG_KASAN
978533090e5SChristophe Leroy	bl	kasan_early_init
979533090e5SChristophe Leroy#endif
980533090e5SChristophe Leroy	li	r3,0
981533090e5SChristophe Leroy	mr	r4,r31
982533090e5SChristophe Leroy	bl	machine_init
983533090e5SChristophe Leroy	bl	__save_cpu_setup
984533090e5SChristophe Leroy	bl	MMU_init
985533090e5SChristophe Leroy	bl	MMU_init_hw_patch
986533090e5SChristophe Leroy
987533090e5SChristophe Leroy/*
988533090e5SChristophe Leroy * Go back to running unmapped so we can load up new values
989533090e5SChristophe Leroy * for SDR1 (hash table pointer) and the segment registers
990533090e5SChristophe Leroy * and change to using our exception vectors.
991533090e5SChristophe Leroy */
992533090e5SChristophe Leroy	lis	r4,2f@h
993533090e5SChristophe Leroy	ori	r4,r4,2f@l
994533090e5SChristophe Leroy	tophys(r4,r4)
995533090e5SChristophe Leroy	li	r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
996533090e5SChristophe Leroy
997533090e5SChristophe Leroy	.align	4
998533090e5SChristophe Leroy	mtspr	SPRN_SRR0,r4
999533090e5SChristophe Leroy	mtspr	SPRN_SRR1,r3
1000120c0518SChristophe Leroy	rfi
1001533090e5SChristophe Leroy/* Load up the kernel context */
1002533090e5SChristophe Leroy2:	bl	load_up_mmu
1003533090e5SChristophe Leroy
1004533090e5SChristophe Leroy#ifdef CONFIG_BDI_SWITCH
1005533090e5SChristophe Leroy	/* Add helper information for the Abatron bdiGDB debugger.
1006533090e5SChristophe Leroy	 * We do this here because we know the mmu is disabled, and
1007533090e5SChristophe Leroy	 * will be enabled for real in just a few instructions.
1008533090e5SChristophe Leroy	 */
1009533090e5SChristophe Leroy	lis	r5, abatron_pteptrs@h
1010533090e5SChristophe Leroy	ori	r5, r5, abatron_pteptrs@l
1011533090e5SChristophe Leroy	stw	r5, 0xf0(0)	/* This much match your Abatron config */
1012533090e5SChristophe Leroy	lis	r6, swapper_pg_dir@h
1013533090e5SChristophe Leroy	ori	r6, r6, swapper_pg_dir@l
1014533090e5SChristophe Leroy	tophys(r5, r5)
1015533090e5SChristophe Leroy	stw	r6, 0(r5)
1016533090e5SChristophe Leroy#endif /* CONFIG_BDI_SWITCH */
1017533090e5SChristophe Leroy
1018533090e5SChristophe Leroy/* Now turn on the MMU for real! */
1019533090e5SChristophe Leroy	li	r4,MSR_KERNEL
1020533090e5SChristophe Leroy	lis	r3,start_kernel@h
1021533090e5SChristophe Leroy	ori	r3,r3,start_kernel@l
1022533090e5SChristophe Leroy	mtspr	SPRN_SRR0,r3
1023533090e5SChristophe Leroy	mtspr	SPRN_SRR1,r4
1024120c0518SChristophe Leroy	rfi
1025533090e5SChristophe Leroy
1026533090e5SChristophe Leroy/*
1027533090e5SChristophe Leroy * An undocumented "feature" of 604e requires that the v bit
1028533090e5SChristophe Leroy * be cleared before changing BAT values.
1029533090e5SChristophe Leroy *
1030533090e5SChristophe Leroy * Also, newer IBM firmware does not clear bat3 and 4 so
1031533090e5SChristophe Leroy * this makes sure it's done.
1032533090e5SChristophe Leroy *  -- Cort
1033533090e5SChristophe Leroy */
10342da37761SChristophe LeroySYM_FUNC_START_LOCAL(clear_bats)
1035533090e5SChristophe Leroy	li	r10,0
1036533090e5SChristophe Leroy
1037533090e5SChristophe Leroy	mtspr	SPRN_DBAT0U,r10
1038533090e5SChristophe Leroy	mtspr	SPRN_DBAT0L,r10
1039533090e5SChristophe Leroy	mtspr	SPRN_DBAT1U,r10
1040533090e5SChristophe Leroy	mtspr	SPRN_DBAT1L,r10
1041533090e5SChristophe Leroy	mtspr	SPRN_DBAT2U,r10
1042533090e5SChristophe Leroy	mtspr	SPRN_DBAT2L,r10
1043533090e5SChristophe Leroy	mtspr	SPRN_DBAT3U,r10
1044533090e5SChristophe Leroy	mtspr	SPRN_DBAT3L,r10
1045533090e5SChristophe Leroy	mtspr	SPRN_IBAT0U,r10
1046533090e5SChristophe Leroy	mtspr	SPRN_IBAT0L,r10
1047533090e5SChristophe Leroy	mtspr	SPRN_IBAT1U,r10
1048533090e5SChristophe Leroy	mtspr	SPRN_IBAT1L,r10
1049533090e5SChristophe Leroy	mtspr	SPRN_IBAT2U,r10
1050533090e5SChristophe Leroy	mtspr	SPRN_IBAT2L,r10
1051533090e5SChristophe Leroy	mtspr	SPRN_IBAT3U,r10
1052533090e5SChristophe Leroy	mtspr	SPRN_IBAT3L,r10
1053533090e5SChristophe LeroyBEGIN_MMU_FTR_SECTION
1054533090e5SChristophe Leroy	/* Here's a tweak: at this point, CPU setup have
1055533090e5SChristophe Leroy	 * not been called yet, so HIGH_BAT_EN may not be
1056533090e5SChristophe Leroy	 * set in HID0 for the 745x processors. However, it
1057533090e5SChristophe Leroy	 * seems that doesn't affect our ability to actually
1058533090e5SChristophe Leroy	 * write to these SPRs.
1059533090e5SChristophe Leroy	 */
1060533090e5SChristophe Leroy	mtspr	SPRN_DBAT4U,r10
1061533090e5SChristophe Leroy	mtspr	SPRN_DBAT4L,r10
1062533090e5SChristophe Leroy	mtspr	SPRN_DBAT5U,r10
1063533090e5SChristophe Leroy	mtspr	SPRN_DBAT5L,r10
1064533090e5SChristophe Leroy	mtspr	SPRN_DBAT6U,r10
1065533090e5SChristophe Leroy	mtspr	SPRN_DBAT6L,r10
1066533090e5SChristophe Leroy	mtspr	SPRN_DBAT7U,r10
1067533090e5SChristophe Leroy	mtspr	SPRN_DBAT7L,r10
1068533090e5SChristophe Leroy	mtspr	SPRN_IBAT4U,r10
1069533090e5SChristophe Leroy	mtspr	SPRN_IBAT4L,r10
1070533090e5SChristophe Leroy	mtspr	SPRN_IBAT5U,r10
1071533090e5SChristophe Leroy	mtspr	SPRN_IBAT5L,r10
1072533090e5SChristophe Leroy	mtspr	SPRN_IBAT6U,r10
1073533090e5SChristophe Leroy	mtspr	SPRN_IBAT6L,r10
1074533090e5SChristophe Leroy	mtspr	SPRN_IBAT7U,r10
1075533090e5SChristophe Leroy	mtspr	SPRN_IBAT7L,r10
1076533090e5SChristophe LeroyEND_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
1077533090e5SChristophe Leroy	blr
10782da37761SChristophe LeroySYM_FUNC_END(clear_bats)
1079533090e5SChristophe Leroy
108027e21e8fSChristophe Leroy_GLOBAL(update_bats)
1081533090e5SChristophe Leroy	lis	r4, 1f@h
1082533090e5SChristophe Leroy	ori	r4, r4, 1f@l
1083533090e5SChristophe Leroy	tophys(r4, r4)
1084533090e5SChristophe Leroy	mfmsr	r6
1085533090e5SChristophe Leroy	mflr	r7
1086533090e5SChristophe Leroy	li	r3, MSR_KERNEL & ~(MSR_IR | MSR_DR)
1087533090e5SChristophe Leroy	rlwinm	r0, r6, 0, ~MSR_RI
1088533090e5SChristophe Leroy	rlwinm	r0, r0, 0, ~MSR_EE
1089533090e5SChristophe Leroy	mtmsr	r0
1090533090e5SChristophe Leroy
1091533090e5SChristophe Leroy	.align	4
1092533090e5SChristophe Leroy	mtspr	SPRN_SRR0, r4
1093533090e5SChristophe Leroy	mtspr	SPRN_SRR1, r3
1094120c0518SChristophe Leroy	rfi
1095533090e5SChristophe Leroy1:	bl	clear_bats
1096533090e5SChristophe Leroy	lis	r3, BATS@ha
1097533090e5SChristophe Leroy	addi	r3, r3, BATS@l
1098533090e5SChristophe Leroy	tophys(r3, r3)
1099533090e5SChristophe Leroy	LOAD_BAT(0, r3, r4, r5)
1100533090e5SChristophe Leroy	LOAD_BAT(1, r3, r4, r5)
1101533090e5SChristophe Leroy	LOAD_BAT(2, r3, r4, r5)
1102533090e5SChristophe Leroy	LOAD_BAT(3, r3, r4, r5)
1103533090e5SChristophe LeroyBEGIN_MMU_FTR_SECTION
1104533090e5SChristophe Leroy	LOAD_BAT(4, r3, r4, r5)
1105533090e5SChristophe Leroy	LOAD_BAT(5, r3, r4, r5)
1106533090e5SChristophe Leroy	LOAD_BAT(6, r3, r4, r5)
1107533090e5SChristophe Leroy	LOAD_BAT(7, r3, r4, r5)
1108533090e5SChristophe LeroyEND_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
1109533090e5SChristophe Leroy	li	r3, MSR_KERNEL & ~(MSR_IR | MSR_DR | MSR_RI)
1110533090e5SChristophe Leroy	mtmsr	r3
1111533090e5SChristophe Leroy	mtspr	SPRN_SRR0, r7
1112533090e5SChristophe Leroy	mtspr	SPRN_SRR1, r6
1113120c0518SChristophe Leroy	rfi
1114533090e5SChristophe Leroy
11152da37761SChristophe LeroySYM_FUNC_START_LOCAL(flush_tlbs)
1116533090e5SChristophe Leroy	lis	r10, 0x40
1117533090e5SChristophe Leroy1:	addic.	r10, r10, -0x1000
1118533090e5SChristophe Leroy	tlbie	r10
1119533090e5SChristophe Leroy	bgt	1b
1120533090e5SChristophe Leroy	sync
1121533090e5SChristophe Leroy	blr
11222da37761SChristophe LeroySYM_FUNC_END(flush_tlbs)
1123533090e5SChristophe Leroy
11242da37761SChristophe LeroySYM_FUNC_START_LOCAL(mmu_off)
1125533090e5SChristophe Leroy 	addi	r4, r3, __after_mmu_off - _start
1126533090e5SChristophe Leroy	mfmsr	r3
1127533090e5SChristophe Leroy	andi.	r0,r3,MSR_DR|MSR_IR		/* MMU enabled? */
1128533090e5SChristophe Leroy	beqlr
1129533090e5SChristophe Leroy	andc	r3,r3,r0
1130533090e5SChristophe Leroy
1131533090e5SChristophe Leroy	.align	4
1132533090e5SChristophe Leroy	mtspr	SPRN_SRR0,r4
1133533090e5SChristophe Leroy	mtspr	SPRN_SRR1,r3
1134533090e5SChristophe Leroy	sync
1135120c0518SChristophe Leroy	rfi
11362da37761SChristophe LeroySYM_FUNC_END(mmu_off)
1137533090e5SChristophe Leroy
1138533090e5SChristophe Leroy/* We use one BAT to map up to 256M of RAM at _PAGE_OFFSET */
11392da37761SChristophe LeroySYM_FUNC_START_LOCAL(initial_bats)
1140533090e5SChristophe Leroy	lis	r11,PAGE_OFFSET@h
1141533090e5SChristophe Leroy	tophys(r8,r11)
1142533090e5SChristophe Leroy#ifdef CONFIG_SMP
1143533090e5SChristophe Leroy	ori	r8,r8,0x12		/* R/W access, M=1 */
1144533090e5SChristophe Leroy#else
1145533090e5SChristophe Leroy	ori	r8,r8,2			/* R/W access */
1146533090e5SChristophe Leroy#endif /* CONFIG_SMP */
1147533090e5SChristophe Leroy	ori	r11,r11,BL_256M<<2|0x2	/* set up BAT registers for 604 */
1148533090e5SChristophe Leroy
1149533090e5SChristophe Leroy	mtspr	SPRN_DBAT0L,r8		/* N.B. 6xx have valid */
1150533090e5SChristophe Leroy	mtspr	SPRN_DBAT0U,r11		/* bit in upper BAT register */
1151533090e5SChristophe Leroy	mtspr	SPRN_IBAT0L,r8
1152533090e5SChristophe Leroy	mtspr	SPRN_IBAT0U,r11
1153533090e5SChristophe Leroy	isync
1154533090e5SChristophe Leroy	blr
11552da37761SChristophe LeroySYM_FUNC_END(initial_bats)
1156533090e5SChristophe Leroy
1157533090e5SChristophe Leroy#ifdef CONFIG_BOOTX_TEXT
11582da37761SChristophe LeroySYM_FUNC_START_LOCAL(setup_disp_bat)
1159533090e5SChristophe Leroy	/*
1160533090e5SChristophe Leroy	 * setup the display bat prepared for us in prom.c
1161533090e5SChristophe Leroy	 */
1162533090e5SChristophe Leroy	mflr	r8
1163533090e5SChristophe Leroy	bl	reloc_offset
1164533090e5SChristophe Leroy	mtlr	r8
1165533090e5SChristophe Leroy	addis	r8,r3,disp_BAT@ha
1166533090e5SChristophe Leroy	addi	r8,r8,disp_BAT@l
1167533090e5SChristophe Leroy	cmpwi	cr0,r8,0
1168533090e5SChristophe Leroy	beqlr
1169533090e5SChristophe Leroy	lwz	r11,0(r8)
1170533090e5SChristophe Leroy	lwz	r8,4(r8)
1171533090e5SChristophe Leroy	mtspr	SPRN_DBAT3L,r8
1172533090e5SChristophe Leroy	mtspr	SPRN_DBAT3U,r11
1173533090e5SChristophe Leroy	blr
11742da37761SChristophe LeroySYM_FUNC_END(setup_disp_bat)
1175533090e5SChristophe Leroy#endif /* CONFIG_BOOTX_TEXT */
1176533090e5SChristophe Leroy
1177533090e5SChristophe Leroy#ifdef CONFIG_PPC_EARLY_DEBUG_CPM
11782da37761SChristophe LeroySYM_FUNC_START_LOCAL(setup_cpm_bat)
1179533090e5SChristophe Leroy	lis	r8, 0xf000
1180533090e5SChristophe Leroy	ori	r8, r8,	0x002a
1181533090e5SChristophe Leroy	mtspr	SPRN_DBAT1L, r8
1182533090e5SChristophe Leroy
1183533090e5SChristophe Leroy	lis	r11, 0xf000
1184533090e5SChristophe Leroy	ori	r11, r11, (BL_1M << 2) | 2
1185533090e5SChristophe Leroy	mtspr	SPRN_DBAT1U, r11
1186533090e5SChristophe Leroy
1187533090e5SChristophe Leroy	blr
11882da37761SChristophe LeroySYM_FUNC_END(setup_cpm_bat)
1189533090e5SChristophe Leroy#endif
1190533090e5SChristophe Leroy
1191533090e5SChristophe Leroy#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
11922da37761SChristophe LeroySYM_FUNC_START_LOCAL(setup_usbgecko_bat)
1193533090e5SChristophe Leroy	/* prepare a BAT for early io */
1194533090e5SChristophe Leroy#if defined(CONFIG_GAMECUBE)
1195533090e5SChristophe Leroy	lis	r8, 0x0c00
1196533090e5SChristophe Leroy#elif defined(CONFIG_WII)
1197533090e5SChristophe Leroy	lis	r8, 0x0d00
1198533090e5SChristophe Leroy#else
1199533090e5SChristophe Leroy#error Invalid platform for USB Gecko based early debugging.
1200533090e5SChristophe Leroy#endif
1201533090e5SChristophe Leroy	/*
1202533090e5SChristophe Leroy	 * The virtual address used must match the virtual address
1203533090e5SChristophe Leroy	 * associated to the fixmap entry FIX_EARLY_DEBUG_BASE.
1204533090e5SChristophe Leroy	 */
1205533090e5SChristophe Leroy	lis	r11, 0xfffe	/* top 128K */
1206533090e5SChristophe Leroy	ori	r8, r8, 0x002a	/* uncached, guarded ,rw */
1207533090e5SChristophe Leroy	ori	r11, r11, 0x2	/* 128K, Vs=1, Vp=0 */
1208533090e5SChristophe Leroy	mtspr	SPRN_DBAT1L, r8
1209533090e5SChristophe Leroy	mtspr	SPRN_DBAT1U, r11
1210533090e5SChristophe Leroy	blr
12112da37761SChristophe LeroySYM_FUNC_END(setup_usbgecko_bat)
1212533090e5SChristophe Leroy#endif
1213533090e5SChristophe Leroy
1214533090e5SChristophe Leroy	.data
1215