xref: /openbmc/linux/arch/openrisc/kernel/head.S (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
12874c5fdSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-or-later */
29d02a428SJonas Bonn/*
39d02a428SJonas Bonn * OpenRISC head.S
49d02a428SJonas Bonn *
59d02a428SJonas Bonn * Linux architectural port borrowing liberally from similar works of
69d02a428SJonas Bonn * others.  All original copyrights apply as per the original source
79d02a428SJonas Bonn * declaration.
89d02a428SJonas Bonn *
99d02a428SJonas Bonn * Modifications for the OpenRISC architecture:
109d02a428SJonas Bonn * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
119d02a428SJonas Bonn * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
129d02a428SJonas Bonn */
139d02a428SJonas Bonn
149d02a428SJonas Bonn#include <linux/linkage.h>
159d02a428SJonas Bonn#include <linux/threads.h>
169d02a428SJonas Bonn#include <linux/errno.h>
179d02a428SJonas Bonn#include <linux/init.h>
18160d8378SStefan Kristiansson#include <linux/serial_reg.h>
1965fddcfcSMike Rapoport#include <linux/pgtable.h>
209d02a428SJonas Bonn#include <asm/processor.h>
219d02a428SJonas Bonn#include <asm/page.h>
229d02a428SJonas Bonn#include <asm/mmu.h>
23c2dc7243SStefan Kristiansson#include <asm/thread_info.h>
249d02a428SJonas Bonn#include <asm/cache.h>
259d02a428SJonas Bonn#include <asm/spr_defs.h>
269d02a428SJonas Bonn#include <asm/asm-offsets.h>
27dec83018SStefan Kristiansson#include <linux/of_fdt.h>
289d02a428SJonas Bonn
299d02a428SJonas Bonn#define tophys(rd,rs)				\
309d02a428SJonas Bonn	l.movhi	rd,hi(-KERNELBASE)		;\
319d02a428SJonas Bonn	l.add	rd,rd,rs
329d02a428SJonas Bonn
339d02a428SJonas Bonn#define CLEAR_GPR(gpr)				\
34a4d44266SStafford Horne	l.movhi	gpr,0x0
359d02a428SJonas Bonn
369d02a428SJonas Bonn#define LOAD_SYMBOL_2_GPR(gpr,symbol)		\
379d02a428SJonas Bonn	l.movhi gpr,hi(symbol)			;\
389d02a428SJonas Bonn	l.ori   gpr,gpr,lo(symbol)
399d02a428SJonas Bonn
409d02a428SJonas Bonn
419d02a428SJonas Bonn#define UART_BASE_ADD      0x90000000
429d02a428SJonas Bonn
439d02a428SJonas Bonn#define EXCEPTION_SR  (SPR_SR_DME | SPR_SR_IME | SPR_SR_DCE | SPR_SR_ICE | SPR_SR_SM)
449d02a428SJonas Bonn#define SYSCALL_SR  (SPR_SR_DME | SPR_SR_IME | SPR_SR_DCE | SPR_SR_ICE | SPR_SR_IEE | SPR_SR_TEE | SPR_SR_SM)
459d02a428SJonas Bonn
469d02a428SJonas Bonn/* ============================================[ tmp store locations ]=== */
479d02a428SJonas Bonn
4891993c8cSStefan Kristiansson#define SPR_SHADOW_GPR(x)	((x) + SPR_GPR_BASE + 32)
4991993c8cSStefan Kristiansson
509d02a428SJonas Bonn/*
519d02a428SJonas Bonn * emergency_print temporary stores
529d02a428SJonas Bonn */
5391993c8cSStefan Kristiansson#ifdef CONFIG_OPENRISC_HAVE_SHADOW_GPRS
5491993c8cSStefan Kristiansson#define EMERGENCY_PRINT_STORE_GPR4	l.mtspr r0,r4,SPR_SHADOW_GPR(14)
5591993c8cSStefan Kristiansson#define EMERGENCY_PRINT_LOAD_GPR4	l.mfspr r4,r0,SPR_SHADOW_GPR(14)
5691993c8cSStefan Kristiansson
5791993c8cSStefan Kristiansson#define EMERGENCY_PRINT_STORE_GPR5	l.mtspr r0,r5,SPR_SHADOW_GPR(15)
5891993c8cSStefan Kristiansson#define EMERGENCY_PRINT_LOAD_GPR5	l.mfspr r5,r0,SPR_SHADOW_GPR(15)
5991993c8cSStefan Kristiansson
6091993c8cSStefan Kristiansson#define EMERGENCY_PRINT_STORE_GPR6	l.mtspr r0,r6,SPR_SHADOW_GPR(16)
6191993c8cSStefan Kristiansson#define EMERGENCY_PRINT_LOAD_GPR6	l.mfspr r6,r0,SPR_SHADOW_GPR(16)
6291993c8cSStefan Kristiansson
6391993c8cSStefan Kristiansson#define EMERGENCY_PRINT_STORE_GPR7	l.mtspr r0,r7,SPR_SHADOW_GPR(7)
6491993c8cSStefan Kristiansson#define EMERGENCY_PRINT_LOAD_GPR7	l.mfspr r7,r0,SPR_SHADOW_GPR(7)
6591993c8cSStefan Kristiansson
6691993c8cSStefan Kristiansson#define EMERGENCY_PRINT_STORE_GPR8	l.mtspr r0,r8,SPR_SHADOW_GPR(8)
6791993c8cSStefan Kristiansson#define EMERGENCY_PRINT_LOAD_GPR8	l.mfspr r8,r0,SPR_SHADOW_GPR(8)
6891993c8cSStefan Kristiansson
6991993c8cSStefan Kristiansson#define EMERGENCY_PRINT_STORE_GPR9	l.mtspr r0,r9,SPR_SHADOW_GPR(9)
7091993c8cSStefan Kristiansson#define EMERGENCY_PRINT_LOAD_GPR9	l.mfspr r9,r0,SPR_SHADOW_GPR(9)
7191993c8cSStefan Kristiansson
7291993c8cSStefan Kristiansson#else /* !CONFIG_OPENRISC_HAVE_SHADOW_GPRS */
739d02a428SJonas Bonn#define EMERGENCY_PRINT_STORE_GPR4	l.sw    0x20(r0),r4
749d02a428SJonas Bonn#define EMERGENCY_PRINT_LOAD_GPR4	l.lwz   r4,0x20(r0)
759d02a428SJonas Bonn
769d02a428SJonas Bonn#define EMERGENCY_PRINT_STORE_GPR5	l.sw    0x24(r0),r5
779d02a428SJonas Bonn#define EMERGENCY_PRINT_LOAD_GPR5	l.lwz   r5,0x24(r0)
789d02a428SJonas Bonn
799d02a428SJonas Bonn#define EMERGENCY_PRINT_STORE_GPR6	l.sw    0x28(r0),r6
809d02a428SJonas Bonn#define EMERGENCY_PRINT_LOAD_GPR6	l.lwz   r6,0x28(r0)
819d02a428SJonas Bonn
829d02a428SJonas Bonn#define EMERGENCY_PRINT_STORE_GPR7	l.sw    0x2c(r0),r7
839d02a428SJonas Bonn#define EMERGENCY_PRINT_LOAD_GPR7	l.lwz   r7,0x2c(r0)
849d02a428SJonas Bonn
859d02a428SJonas Bonn#define EMERGENCY_PRINT_STORE_GPR8	l.sw    0x30(r0),r8
869d02a428SJonas Bonn#define EMERGENCY_PRINT_LOAD_GPR8	l.lwz   r8,0x30(r0)
879d02a428SJonas Bonn
889d02a428SJonas Bonn#define EMERGENCY_PRINT_STORE_GPR9	l.sw    0x34(r0),r9
899d02a428SJonas Bonn#define EMERGENCY_PRINT_LOAD_GPR9	l.lwz   r9,0x34(r0)
909d02a428SJonas Bonn
9191993c8cSStefan Kristiansson#endif
929d02a428SJonas Bonn
939d02a428SJonas Bonn/*
949d02a428SJonas Bonn * TLB miss handlers temorary stores
959d02a428SJonas Bonn */
9691993c8cSStefan Kristiansson#ifdef CONFIG_OPENRISC_HAVE_SHADOW_GPRS
9791993c8cSStefan Kristiansson#define EXCEPTION_STORE_GPR2		l.mtspr r0,r2,SPR_SHADOW_GPR(2)
9891993c8cSStefan Kristiansson#define EXCEPTION_LOAD_GPR2		l.mfspr r2,r0,SPR_SHADOW_GPR(2)
999d02a428SJonas Bonn
10091993c8cSStefan Kristiansson#define EXCEPTION_STORE_GPR3		l.mtspr r0,r3,SPR_SHADOW_GPR(3)
10191993c8cSStefan Kristiansson#define EXCEPTION_LOAD_GPR3		l.mfspr r3,r0,SPR_SHADOW_GPR(3)
10291993c8cSStefan Kristiansson
10391993c8cSStefan Kristiansson#define EXCEPTION_STORE_GPR4		l.mtspr r0,r4,SPR_SHADOW_GPR(4)
10491993c8cSStefan Kristiansson#define EXCEPTION_LOAD_GPR4		l.mfspr r4,r0,SPR_SHADOW_GPR(4)
10591993c8cSStefan Kristiansson
10691993c8cSStefan Kristiansson#define EXCEPTION_STORE_GPR5		l.mtspr r0,r5,SPR_SHADOW_GPR(5)
10791993c8cSStefan Kristiansson#define EXCEPTION_LOAD_GPR5		l.mfspr r5,r0,SPR_SHADOW_GPR(5)
10891993c8cSStefan Kristiansson
10991993c8cSStefan Kristiansson#define EXCEPTION_STORE_GPR6		l.mtspr r0,r6,SPR_SHADOW_GPR(6)
11091993c8cSStefan Kristiansson#define EXCEPTION_LOAD_GPR6		l.mfspr r6,r0,SPR_SHADOW_GPR(6)
11191993c8cSStefan Kristiansson
11291993c8cSStefan Kristiansson#else /* !CONFIG_OPENRISC_HAVE_SHADOW_GPRS */
1139d02a428SJonas Bonn#define EXCEPTION_STORE_GPR2		l.sw    0x64(r0),r2
1149d02a428SJonas Bonn#define EXCEPTION_LOAD_GPR2		l.lwz   r2,0x64(r0)
1159d02a428SJonas Bonn
1169d02a428SJonas Bonn#define EXCEPTION_STORE_GPR3		l.sw    0x68(r0),r3
1179d02a428SJonas Bonn#define EXCEPTION_LOAD_GPR3		l.lwz   r3,0x68(r0)
1189d02a428SJonas Bonn
1199d02a428SJonas Bonn#define EXCEPTION_STORE_GPR4		l.sw    0x6c(r0),r4
1209d02a428SJonas Bonn#define EXCEPTION_LOAD_GPR4		l.lwz   r4,0x6c(r0)
1219d02a428SJonas Bonn
1229d02a428SJonas Bonn#define EXCEPTION_STORE_GPR5		l.sw    0x70(r0),r5
1239d02a428SJonas Bonn#define EXCEPTION_LOAD_GPR5		l.lwz   r5,0x70(r0)
1249d02a428SJonas Bonn
1259d02a428SJonas Bonn#define EXCEPTION_STORE_GPR6		l.sw    0x74(r0),r6
1269d02a428SJonas Bonn#define EXCEPTION_LOAD_GPR6		l.lwz   r6,0x74(r0)
1279d02a428SJonas Bonn
12891993c8cSStefan Kristiansson#endif
1299d02a428SJonas Bonn
1309d02a428SJonas Bonn/*
1319d02a428SJonas Bonn * EXCEPTION_HANDLE temporary stores
1329d02a428SJonas Bonn */
1339d02a428SJonas Bonn
13491993c8cSStefan Kristiansson#ifdef CONFIG_OPENRISC_HAVE_SHADOW_GPRS
13591993c8cSStefan Kristiansson#define EXCEPTION_T_STORE_GPR30		l.mtspr r0,r30,SPR_SHADOW_GPR(30)
13691993c8cSStefan Kristiansson#define EXCEPTION_T_LOAD_GPR30(reg)	l.mfspr reg,r0,SPR_SHADOW_GPR(30)
13791993c8cSStefan Kristiansson
13891993c8cSStefan Kristiansson#define EXCEPTION_T_STORE_GPR10		l.mtspr r0,r10,SPR_SHADOW_GPR(10)
13991993c8cSStefan Kristiansson#define EXCEPTION_T_LOAD_GPR10(reg)	l.mfspr reg,r0,SPR_SHADOW_GPR(10)
14091993c8cSStefan Kristiansson
14191993c8cSStefan Kristiansson#define EXCEPTION_T_STORE_SP		l.mtspr r0,r1,SPR_SHADOW_GPR(1)
14291993c8cSStefan Kristiansson#define EXCEPTION_T_LOAD_SP(reg)	l.mfspr reg,r0,SPR_SHADOW_GPR(1)
14391993c8cSStefan Kristiansson
14491993c8cSStefan Kristiansson#else /* !CONFIG_OPENRISC_HAVE_SHADOW_GPRS */
1459d02a428SJonas Bonn#define EXCEPTION_T_STORE_GPR30		l.sw    0x78(r0),r30
1469d02a428SJonas Bonn#define EXCEPTION_T_LOAD_GPR30(reg)	l.lwz   reg,0x78(r0)
1479d02a428SJonas Bonn
1489d02a428SJonas Bonn#define EXCEPTION_T_STORE_GPR10		l.sw    0x7c(r0),r10
1499d02a428SJonas Bonn#define EXCEPTION_T_LOAD_GPR10(reg)	l.lwz   reg,0x7c(r0)
1509d02a428SJonas Bonn
1519d02a428SJonas Bonn#define EXCEPTION_T_STORE_SP		l.sw    0x80(r0),r1
1529d02a428SJonas Bonn#define EXCEPTION_T_LOAD_SP(reg)	l.lwz   reg,0x80(r0)
15391993c8cSStefan Kristiansson#endif
1549d02a428SJonas Bonn
1559d02a428SJonas Bonn/* =========================================================[ macros ]=== */
1569d02a428SJonas Bonn
1578e6d08e0SStefan Kristiansson#ifdef CONFIG_SMP
1588e6d08e0SStefan Kristiansson#define GET_CURRENT_PGD(reg,t1)					\
1598e6d08e0SStefan Kristiansson	LOAD_SYMBOL_2_GPR(reg,current_pgd)			;\
1608e6d08e0SStefan Kristiansson	l.mfspr	t1,r0,SPR_COREID				;\
1618e6d08e0SStefan Kristiansson	l.slli	t1,t1,2						;\
1628e6d08e0SStefan Kristiansson	l.add	reg,reg,t1					;\
1638e6d08e0SStefan Kristiansson	tophys  (t1,reg)					;\
1648e6d08e0SStefan Kristiansson	l.lwz   reg,0(t1)
1658e6d08e0SStefan Kristiansson#else
1669d02a428SJonas Bonn#define GET_CURRENT_PGD(reg,t1)					\
1679d02a428SJonas Bonn	LOAD_SYMBOL_2_GPR(reg,current_pgd)			;\
1689d02a428SJonas Bonn	tophys  (t1,reg)					;\
1699d02a428SJonas Bonn	l.lwz   reg,0(t1)
1708e6d08e0SStefan Kristiansson#endif
1719d02a428SJonas Bonn
1728e6d08e0SStefan Kristiansson/* Load r10 from current_thread_info_set - clobbers r1 and r30 */
1738e6d08e0SStefan Kristiansson#ifdef CONFIG_SMP
1748e6d08e0SStefan Kristiansson#define GET_CURRENT_THREAD_INFO					\
1758e6d08e0SStefan Kristiansson	LOAD_SYMBOL_2_GPR(r1,current_thread_info_set)		;\
1768e6d08e0SStefan Kristiansson	tophys  (r30,r1)					;\
1778e6d08e0SStefan Kristiansson	l.mfspr	r10,r0,SPR_COREID				;\
1788e6d08e0SStefan Kristiansson	l.slli	r10,r10,2					;\
1798e6d08e0SStefan Kristiansson	l.add	r30,r30,r10					;\
1808e6d08e0SStefan Kristiansson	/* r10: current_thread_info  */				;\
1818e6d08e0SStefan Kristiansson	l.lwz   r10,0(r30)
1828e6d08e0SStefan Kristiansson#else
1838e6d08e0SStefan Kristiansson#define GET_CURRENT_THREAD_INFO					\
1848e6d08e0SStefan Kristiansson	LOAD_SYMBOL_2_GPR(r1,current_thread_info_set)		;\
1858e6d08e0SStefan Kristiansson	tophys  (r30,r1)					;\
1868e6d08e0SStefan Kristiansson	/* r10: current_thread_info  */				;\
1878e6d08e0SStefan Kristiansson	l.lwz   r10,0(r30)
1888e6d08e0SStefan Kristiansson#endif
1899d02a428SJonas Bonn
1909d02a428SJonas Bonn/*
1919d02a428SJonas Bonn * DSCR: this is a common hook for handling exceptions. it will save
1929d02a428SJonas Bonn *       the needed registers, set up stack and pointer to current
1939d02a428SJonas Bonn *	 then jump to the handler while enabling MMU
1949d02a428SJonas Bonn *
1959d02a428SJonas Bonn * PRMS: handler	- a function to jump to. it has to save the
1969d02a428SJonas Bonn *			remaining registers to kernel stack, call
1979d02a428SJonas Bonn *			appropriate arch-independant exception handler
1989d02a428SJonas Bonn *			and finaly jump to ret_from_except
1999d02a428SJonas Bonn *
2009d02a428SJonas Bonn * PREQ: unchanged state from the time exception happened
2019d02a428SJonas Bonn *
2029d02a428SJonas Bonn * POST: SAVED the following registers original value
2039d02a428SJonas Bonn *	       to the new created exception frame pointed to by r1
2049d02a428SJonas Bonn *
2059d02a428SJonas Bonn *	 r1  - ksp	pointing to the new (exception) frame
2069d02a428SJonas Bonn *	 r4  - EEAR     exception EA
2079d02a428SJonas Bonn *	 r10 - current	pointing to current_thread_info struct
2089d02a428SJonas Bonn *	 r12 - syscall  0, since we didn't come from syscall
209ae15a41aSStafford Horne *	 r30 - handler	address of the handler we'll jump to
2109d02a428SJonas Bonn *
2119d02a428SJonas Bonn *	 handler has to save remaining registers to the exception
2129d02a428SJonas Bonn *	 ksp frame *before* tainting them!
2139d02a428SJonas Bonn *
2149d02a428SJonas Bonn * NOTE: this function is not reentrant per se. reentrancy is guaranteed
2159d02a428SJonas Bonn *       by processor disabling all exceptions/interrupts when exception
2169d02a428SJonas Bonn *	 accours.
2179d02a428SJonas Bonn *
2189d02a428SJonas Bonn * OPTM: no need to make it so wasteful to extract ksp when in user mode
2199d02a428SJonas Bonn */
2209d02a428SJonas Bonn
2219d02a428SJonas Bonn#define EXCEPTION_HANDLE(handler)				\
2229d02a428SJonas Bonn	EXCEPTION_T_STORE_GPR30					;\
2239d02a428SJonas Bonn	l.mfspr r30,r0,SPR_ESR_BASE				;\
2249d02a428SJonas Bonn	l.andi  r30,r30,SPR_SR_SM				;\
2259d02a428SJonas Bonn	l.sfeqi r30,0						;\
2269d02a428SJonas Bonn	EXCEPTION_T_STORE_GPR10					;\
2279d02a428SJonas Bonn	l.bnf   2f                            /* kernel_mode */	;\
2289d02a428SJonas Bonn	 EXCEPTION_T_STORE_SP                 /* delay slot */	;\
2299d02a428SJonas Bonn1: /* user_mode:   */						;\
2308e6d08e0SStefan Kristiansson	GET_CURRENT_THREAD_INFO	 				;\
2319d02a428SJonas Bonn	tophys  (r30,r10)					;\
2329d02a428SJonas Bonn	l.lwz   r1,(TI_KSP)(r30)				;\
2339d02a428SJonas Bonn	/* fall through */					;\
2349d02a428SJonas Bonn2: /* kernel_mode: */						;\
2359d02a428SJonas Bonn	/* create new stack frame, save only needed gprs */	;\
2369d02a428SJonas Bonn	/* r1: KSP, r10: current, r4: EEAR, r31: __pa(KSP) */	;\
2379d02a428SJonas Bonn	/* r12:	temp, syscall indicator */			;\
2389d02a428SJonas Bonn	l.addi  r1,r1,-(INT_FRAME_SIZE)				;\
2399d02a428SJonas Bonn	/* r1 is KSP, r30 is __pa(KSP) */			;\
2409d02a428SJonas Bonn	tophys  (r30,r1)					;\
2419d02a428SJonas Bonn	l.sw    PT_GPR12(r30),r12				;\
242ae15a41aSStafford Horne	/* r4 use for tmp before EA */				;\
2439d02a428SJonas Bonn	l.mfspr r12,r0,SPR_EPCR_BASE				;\
2449d02a428SJonas Bonn	l.sw    PT_PC(r30),r12					;\
2459d02a428SJonas Bonn	l.mfspr r12,r0,SPR_ESR_BASE				;\
2469d02a428SJonas Bonn	l.sw    PT_SR(r30),r12					;\
2479d02a428SJonas Bonn	/* save r30 */						;\
2489d02a428SJonas Bonn	EXCEPTION_T_LOAD_GPR30(r12)				;\
2499d02a428SJonas Bonn	l.sw	PT_GPR30(r30),r12				;\
2509d02a428SJonas Bonn	/* save r10 as was prior to exception */		;\
2519d02a428SJonas Bonn	EXCEPTION_T_LOAD_GPR10(r12)				;\
2529d02a428SJonas Bonn	l.sw	PT_GPR10(r30),r12				;\
2539d02a428SJonas Bonn	/* save PT_SP as was prior to exception */		;\
2549d02a428SJonas Bonn	EXCEPTION_T_LOAD_SP(r12)				;\
2559d02a428SJonas Bonn	l.sw	PT_SP(r30),r12					;\
2569d02a428SJonas Bonn	/* save exception r4, set r4 = EA */			;\
2579d02a428SJonas Bonn	l.sw	PT_GPR4(r30),r4					;\
2589d02a428SJonas Bonn	l.mfspr r4,r0,SPR_EEAR_BASE				;\
2599d02a428SJonas Bonn	/* r12 == 1 if we come from syscall */			;\
2609d02a428SJonas Bonn	CLEAR_GPR(r12)						;\
2619d02a428SJonas Bonn	/* ----- turn on MMU ----- */				;\
262ae15a41aSStafford Horne	/* Carry DSX into exception SR */			;\
263ae15a41aSStafford Horne	l.mfspr r30,r0,SPR_SR					;\
264ae15a41aSStafford Horne	l.andi	r30,r30,SPR_SR_DSX				;\
265ae15a41aSStafford Horne	l.ori	r30,r30,(EXCEPTION_SR)				;\
2669d02a428SJonas Bonn	l.mtspr	r0,r30,SPR_ESR_BASE				;\
2679d02a428SJonas Bonn	/* r30:	EA address of handler */			;\
2689d02a428SJonas Bonn	LOAD_SYMBOL_2_GPR(r30,handler)				;\
2699d02a428SJonas Bonn	l.mtspr r0,r30,SPR_EPCR_BASE				;\
2709d02a428SJonas Bonn	l.rfe
2719d02a428SJonas Bonn
2729d02a428SJonas Bonn/*
2739d02a428SJonas Bonn * this doesn't work
2749d02a428SJonas Bonn *
2759d02a428SJonas Bonn *
2769d02a428SJonas Bonn * #ifdef CONFIG_JUMP_UPON_UNHANDLED_EXCEPTION
2779d02a428SJonas Bonn * #define UNHANDLED_EXCEPTION(handler)				\
2789d02a428SJonas Bonn *	l.ori   r3,r0,0x1					;\
2799d02a428SJonas Bonn *	l.mtspr r0,r3,SPR_SR					;\
2809d02a428SJonas Bonn *      l.movhi r3,hi(0xf0000100)				;\
2819d02a428SJonas Bonn *      l.ori   r3,r3,lo(0xf0000100)				;\
2829d02a428SJonas Bonn *	l.jr	r3						;\
2839d02a428SJonas Bonn *	l.nop	1
2849d02a428SJonas Bonn *
2859d02a428SJonas Bonn * #endif
2869d02a428SJonas Bonn */
2879d02a428SJonas Bonn
2889d02a428SJonas Bonn/* DSCR: this is the same as EXCEPTION_HANDLE(), we are just
2899d02a428SJonas Bonn *       a bit more carefull (if we have a PT_SP or current pointer
2909d02a428SJonas Bonn *       corruption) and set them up from 'current_set'
2919d02a428SJonas Bonn *
2929d02a428SJonas Bonn */
2939d02a428SJonas Bonn#define UNHANDLED_EXCEPTION(handler)				\
29491993c8cSStefan Kristiansson	EXCEPTION_T_STORE_GPR30					;\
2959d02a428SJonas Bonn	EXCEPTION_T_STORE_GPR10					;\
2969d02a428SJonas Bonn	EXCEPTION_T_STORE_SP					;\
2979d02a428SJonas Bonn	/* temporary store r3, r9 into r1, r10 */		;\
2989d02a428SJonas Bonn	l.addi	r1,r3,0x0					;\
2999d02a428SJonas Bonn	l.addi	r10,r9,0x0					;\
300e449759cSStafford Horne	LOAD_SYMBOL_2_GPR(r9,_string_unhandled_exception)	;\
301e449759cSStafford Horne	tophys	(r3,r9)						;\
3029d02a428SJonas Bonn	l.jal	_emergency_print				;\
303e449759cSStafford Horne	 l.nop							;\
3049d02a428SJonas Bonn	l.mfspr	r3,r0,SPR_NPC					;\
3059d02a428SJonas Bonn	l.jal	_emergency_print_nr				;\
3069d02a428SJonas Bonn	 l.andi	r3,r3,0x1f00					;\
307e449759cSStafford Horne	LOAD_SYMBOL_2_GPR(r9,_string_epc_prefix)		;\
308e449759cSStafford Horne	tophys	(r3,r9)						;\
3099d02a428SJonas Bonn	l.jal	_emergency_print				;\
310e449759cSStafford Horne	 l.nop							;\
3119d02a428SJonas Bonn	l.jal	_emergency_print_nr				;\
3129d02a428SJonas Bonn	 l.mfspr r3,r0,SPR_EPCR_BASE				;\
313e449759cSStafford Horne	LOAD_SYMBOL_2_GPR(r9,_string_nl)			;\
314e449759cSStafford Horne	tophys	(r3,r9)						;\
3159d02a428SJonas Bonn	l.jal	_emergency_print				;\
316e449759cSStafford Horne	 l.nop							;\
3179d02a428SJonas Bonn	/* end of printing */					;\
3189d02a428SJonas Bonn	l.addi	r3,r1,0x0					;\
3199d02a428SJonas Bonn	l.addi	r9,r10,0x0					;\
3209d02a428SJonas Bonn	/* extract current, ksp from current_set */		;\
3219d02a428SJonas Bonn	LOAD_SYMBOL_2_GPR(r1,_unhandled_stack_top)		;\
3229d02a428SJonas Bonn	LOAD_SYMBOL_2_GPR(r10,init_thread_union)		;\
3239d02a428SJonas Bonn	/* create new stack frame, save only needed gprs */	;\
3249d02a428SJonas Bonn	/* r1: KSP, r10: current, r31: __pa(KSP) */		;\
3259d02a428SJonas Bonn	/* r12:	temp, syscall indicator, r13 temp */		;\
3269d02a428SJonas Bonn	l.addi  r1,r1,-(INT_FRAME_SIZE)				;\
32791993c8cSStefan Kristiansson	/* r1 is KSP, r30 is __pa(KSP) */			;\
32891993c8cSStefan Kristiansson	tophys  (r30,r1)					;\
32991993c8cSStefan Kristiansson	l.sw    PT_GPR12(r30),r12					;\
3309d02a428SJonas Bonn	l.mfspr r12,r0,SPR_EPCR_BASE				;\
33191993c8cSStefan Kristiansson	l.sw    PT_PC(r30),r12					;\
3329d02a428SJonas Bonn	l.mfspr r12,r0,SPR_ESR_BASE				;\
33391993c8cSStefan Kristiansson	l.sw    PT_SR(r30),r12					;\
3349d02a428SJonas Bonn	/* save r31 */						;\
33591993c8cSStefan Kristiansson	EXCEPTION_T_LOAD_GPR30(r12)				;\
33691993c8cSStefan Kristiansson	l.sw	PT_GPR30(r30),r12					;\
3379d02a428SJonas Bonn	/* save r10 as was prior to exception */		;\
3389d02a428SJonas Bonn	EXCEPTION_T_LOAD_GPR10(r12)				;\
33991993c8cSStefan Kristiansson	l.sw	PT_GPR10(r30),r12					;\
3409d02a428SJonas Bonn	/* save PT_SP as was prior to exception */			;\
3419d02a428SJonas Bonn	EXCEPTION_T_LOAD_SP(r12)				;\
34291993c8cSStefan Kristiansson	l.sw	PT_SP(r30),r12					;\
34391993c8cSStefan Kristiansson	l.sw    PT_GPR13(r30),r13					;\
3449d02a428SJonas Bonn	/* --> */						;\
3459d02a428SJonas Bonn	/* save exception r4, set r4 = EA */			;\
34691993c8cSStefan Kristiansson	l.sw	PT_GPR4(r30),r4					;\
3479d02a428SJonas Bonn	l.mfspr r4,r0,SPR_EEAR_BASE				;\
3489d02a428SJonas Bonn	/* r12 == 1 if we come from syscall */			;\
3499d02a428SJonas Bonn	CLEAR_GPR(r12)						;\
3509d02a428SJonas Bonn	/* ----- play a MMU trick ----- */			;\
35191993c8cSStefan Kristiansson	l.ori	r30,r0,(EXCEPTION_SR)				;\
35291993c8cSStefan Kristiansson	l.mtspr	r0,r30,SPR_ESR_BASE				;\
3539d02a428SJonas Bonn	/* r31:	EA address of handler */			;\
35491993c8cSStefan Kristiansson	LOAD_SYMBOL_2_GPR(r30,handler)				;\
35591993c8cSStefan Kristiansson	l.mtspr r0,r30,SPR_EPCR_BASE				;\
3569d02a428SJonas Bonn	l.rfe
3579d02a428SJonas Bonn
3589d02a428SJonas Bonn/* =====================================================[ exceptions] === */
3599d02a428SJonas Bonn
3609d02a428SJonas Bonn/* ---[ 0x100: RESET exception ]----------------------------------------- */
3619d02a428SJonas Bonn    .org 0x100
3629d02a428SJonas Bonn	/* Jump to .init code at _start which lives in the .head section
3639d02a428SJonas Bonn	 * and will be discarded after boot.
3649d02a428SJonas Bonn	 */
36554bd7c51SStefan Kristiansson	LOAD_SYMBOL_2_GPR(r15, _start)
36654bd7c51SStefan Kristiansson	tophys	(r13,r15)			/* MMU disabled */
36754bd7c51SStefan Kristiansson	l.jr	r13
3689d02a428SJonas Bonn	 l.nop
3699d02a428SJonas Bonn
3709d02a428SJonas Bonn/* ---[ 0x200: BUS exception ]------------------------------------------- */
3719d02a428SJonas Bonn    .org 0x200
3729d02a428SJonas Bonn_dispatch_bus_fault:
3739d02a428SJonas Bonn	EXCEPTION_HANDLE(_bus_fault_handler)
3749d02a428SJonas Bonn
3759d02a428SJonas Bonn/* ---[ 0x300: Data Page Fault exception ]------------------------------- */
3769d02a428SJonas Bonn    .org 0x300
3779d02a428SJonas Bonn_dispatch_do_dpage_fault:
3789d02a428SJonas Bonn//      totaly disable timer interrupt
3799d02a428SJonas Bonn// 	l.mtspr	r0,r0,SPR_TTMR
3809d02a428SJonas Bonn//	DEBUG_TLB_PROBE(0x300)
3819d02a428SJonas Bonn//	EXCEPTION_DEBUG_VALUE_ER_ENABLED(0x300)
3829d02a428SJonas Bonn	EXCEPTION_HANDLE(_data_page_fault_handler)
3839d02a428SJonas Bonn
3849d02a428SJonas Bonn/* ---[ 0x400: Insn Page Fault exception ]------------------------------- */
3859d02a428SJonas Bonn    .org 0x400
3869d02a428SJonas Bonn_dispatch_do_ipage_fault:
3879d02a428SJonas Bonn//      totaly disable timer interrupt
3889d02a428SJonas Bonn//	l.mtspr	r0,r0,SPR_TTMR
3899d02a428SJonas Bonn//	DEBUG_TLB_PROBE(0x400)
3909d02a428SJonas Bonn//	EXCEPTION_DEBUG_VALUE_ER_ENABLED(0x400)
3919d02a428SJonas Bonn	EXCEPTION_HANDLE(_insn_page_fault_handler)
3929d02a428SJonas Bonn
3939d02a428SJonas Bonn/* ---[ 0x500: Timer exception ]----------------------------------------- */
3949d02a428SJonas Bonn    .org 0x500
3959d02a428SJonas Bonn	EXCEPTION_HANDLE(_timer_handler)
3969d02a428SJonas Bonn
397550116d2SMasahiro Yamada/* ---[ 0x600: Alignment exception ]-------------------------------------- */
3989d02a428SJonas Bonn    .org 0x600
3999d02a428SJonas Bonn	EXCEPTION_HANDLE(_alignment_handler)
4009d02a428SJonas Bonn
4019d02a428SJonas Bonn/* ---[ 0x700: Illegal insn exception ]---------------------------------- */
4029d02a428SJonas Bonn    .org 0x700
4039d02a428SJonas Bonn	EXCEPTION_HANDLE(_illegal_instruction_handler)
4049d02a428SJonas Bonn
4059d02a428SJonas Bonn/* ---[ 0x800: External interrupt exception ]---------------------------- */
4069d02a428SJonas Bonn    .org 0x800
4079d02a428SJonas Bonn	EXCEPTION_HANDLE(_external_irq_handler)
4089d02a428SJonas Bonn
4099d02a428SJonas Bonn/* ---[ 0x900: DTLB miss exception ]------------------------------------- */
4109d02a428SJonas Bonn    .org 0x900
4119d02a428SJonas Bonn	l.j	boot_dtlb_miss_handler
4129d02a428SJonas Bonn	l.nop
4139d02a428SJonas Bonn
4149d02a428SJonas Bonn/* ---[ 0xa00: ITLB miss exception ]------------------------------------- */
4159d02a428SJonas Bonn    .org 0xa00
4169d02a428SJonas Bonn	l.j	boot_itlb_miss_handler
4179d02a428SJonas Bonn	l.nop
4189d02a428SJonas Bonn
4199d02a428SJonas Bonn/* ---[ 0xb00: Range exception ]----------------------------------------- */
4209d02a428SJonas Bonn    .org 0xb00
4219d02a428SJonas Bonn	UNHANDLED_EXCEPTION(_vector_0xb00)
4229d02a428SJonas Bonn
4239d02a428SJonas Bonn/* ---[ 0xc00: Syscall exception ]--------------------------------------- */
4249d02a428SJonas Bonn    .org 0xc00
4259d02a428SJonas Bonn	EXCEPTION_HANDLE(_sys_call_handler)
4269d02a428SJonas Bonn
427*27267655SStafford Horne/* ---[ 0xd00: Floating point exception ]--------------------------------- */
4289d02a428SJonas Bonn    .org 0xd00
429*27267655SStafford Horne	EXCEPTION_HANDLE(_fpe_trap_handler)
4309d02a428SJonas Bonn
4319d02a428SJonas Bonn/* ---[ 0xe00: Trap exception ]------------------------------------------ */
4329d02a428SJonas Bonn    .org 0xe00
4339d02a428SJonas Bonn//	UNHANDLED_EXCEPTION(_vector_0xe00)
4349d02a428SJonas Bonn	EXCEPTION_HANDLE(_trap_handler)
4359d02a428SJonas Bonn
4369d02a428SJonas Bonn/* ---[ 0xf00: Reserved exception ]-------------------------------------- */
4379d02a428SJonas Bonn    .org 0xf00
4389d02a428SJonas Bonn	UNHANDLED_EXCEPTION(_vector_0xf00)
4399d02a428SJonas Bonn
4409d02a428SJonas Bonn/* ---[ 0x1000: Reserved exception ]------------------------------------- */
4419d02a428SJonas Bonn    .org 0x1000
4429d02a428SJonas Bonn	UNHANDLED_EXCEPTION(_vector_0x1000)
4439d02a428SJonas Bonn
4449d02a428SJonas Bonn/* ---[ 0x1100: Reserved exception ]------------------------------------- */
4459d02a428SJonas Bonn    .org 0x1100
4469d02a428SJonas Bonn	UNHANDLED_EXCEPTION(_vector_0x1100)
4479d02a428SJonas Bonn
4489d02a428SJonas Bonn/* ---[ 0x1200: Reserved exception ]------------------------------------- */
4499d02a428SJonas Bonn    .org 0x1200
4509d02a428SJonas Bonn	UNHANDLED_EXCEPTION(_vector_0x1200)
4519d02a428SJonas Bonn
4529d02a428SJonas Bonn/* ---[ 0x1300: Reserved exception ]------------------------------------- */
4539d02a428SJonas Bonn    .org 0x1300
4549d02a428SJonas Bonn	UNHANDLED_EXCEPTION(_vector_0x1300)
4559d02a428SJonas Bonn
4569d02a428SJonas Bonn/* ---[ 0x1400: Reserved exception ]------------------------------------- */
4579d02a428SJonas Bonn    .org 0x1400
4589d02a428SJonas Bonn	UNHANDLED_EXCEPTION(_vector_0x1400)
4599d02a428SJonas Bonn
4609d02a428SJonas Bonn/* ---[ 0x1500: Reserved exception ]------------------------------------- */
4619d02a428SJonas Bonn    .org 0x1500
4629d02a428SJonas Bonn	UNHANDLED_EXCEPTION(_vector_0x1500)
4639d02a428SJonas Bonn
4649d02a428SJonas Bonn/* ---[ 0x1600: Reserved exception ]------------------------------------- */
4659d02a428SJonas Bonn    .org 0x1600
4669d02a428SJonas Bonn	UNHANDLED_EXCEPTION(_vector_0x1600)
4679d02a428SJonas Bonn
4689d02a428SJonas Bonn/* ---[ 0x1700: Reserved exception ]------------------------------------- */
4699d02a428SJonas Bonn    .org 0x1700
4709d02a428SJonas Bonn	UNHANDLED_EXCEPTION(_vector_0x1700)
4719d02a428SJonas Bonn
4729d02a428SJonas Bonn/* ---[ 0x1800: Reserved exception ]------------------------------------- */
4739d02a428SJonas Bonn    .org 0x1800
4749d02a428SJonas Bonn	UNHANDLED_EXCEPTION(_vector_0x1800)
4759d02a428SJonas Bonn
4769d02a428SJonas Bonn/* ---[ 0x1900: Reserved exception ]------------------------------------- */
4779d02a428SJonas Bonn    .org 0x1900
4789d02a428SJonas Bonn	UNHANDLED_EXCEPTION(_vector_0x1900)
4799d02a428SJonas Bonn
4809d02a428SJonas Bonn/* ---[ 0x1a00: Reserved exception ]------------------------------------- */
4819d02a428SJonas Bonn    .org 0x1a00
4829d02a428SJonas Bonn	UNHANDLED_EXCEPTION(_vector_0x1a00)
4839d02a428SJonas Bonn
4849d02a428SJonas Bonn/* ---[ 0x1b00: Reserved exception ]------------------------------------- */
4859d02a428SJonas Bonn    .org 0x1b00
4869d02a428SJonas Bonn	UNHANDLED_EXCEPTION(_vector_0x1b00)
4879d02a428SJonas Bonn
4889d02a428SJonas Bonn/* ---[ 0x1c00: Reserved exception ]------------------------------------- */
4899d02a428SJonas Bonn    .org 0x1c00
4909d02a428SJonas Bonn	UNHANDLED_EXCEPTION(_vector_0x1c00)
4919d02a428SJonas Bonn
4929d02a428SJonas Bonn/* ---[ 0x1d00: Reserved exception ]------------------------------------- */
4939d02a428SJonas Bonn    .org 0x1d00
4949d02a428SJonas Bonn	UNHANDLED_EXCEPTION(_vector_0x1d00)
4959d02a428SJonas Bonn
4969d02a428SJonas Bonn/* ---[ 0x1e00: Reserved exception ]------------------------------------- */
4979d02a428SJonas Bonn    .org 0x1e00
4989d02a428SJonas Bonn	UNHANDLED_EXCEPTION(_vector_0x1e00)
4999d02a428SJonas Bonn
5009d02a428SJonas Bonn/* ---[ 0x1f00: Reserved exception ]------------------------------------- */
5019d02a428SJonas Bonn    .org 0x1f00
5029d02a428SJonas Bonn	UNHANDLED_EXCEPTION(_vector_0x1f00)
5039d02a428SJonas Bonn
5049d02a428SJonas Bonn    .org 0x2000
5059d02a428SJonas Bonn/* ===================================================[ kernel start ]=== */
5069d02a428SJonas Bonn
5079d02a428SJonas Bonn/*    .text*/
5089d02a428SJonas Bonn
5099d02a428SJonas Bonn/* This early stuff belongs in HEAD, but some of the functions below definitely
5109d02a428SJonas Bonn * don't... */
5119d02a428SJonas Bonn
5129d02a428SJonas Bonn	__HEAD
5139d02a428SJonas Bonn	.global _start
5149d02a428SJonas Bonn_start:
515a4d44266SStafford Horne	/* Init r0 to zero as per spec */
516a4d44266SStafford Horne	CLEAR_GPR(r0)
517a4d44266SStafford Horne
518dec83018SStefan Kristiansson	/* save kernel parameters */
519dec83018SStefan Kristiansson	l.or	r25,r0,r3	/* pointer to fdt */
520dec83018SStefan Kristiansson
5219d02a428SJonas Bonn	/*
5229d02a428SJonas Bonn	 * ensure a deterministic start
5239d02a428SJonas Bonn	 */
5249d02a428SJonas Bonn
5259d02a428SJonas Bonn	l.ori	r3,r0,0x1
5269d02a428SJonas Bonn	l.mtspr	r0,r3,SPR_SR
5279d02a428SJonas Bonn
528516dd4aaSJason A. Donenfeld	/*
529516dd4aaSJason A. Donenfeld	 * Start the TTCR as early as possible, so that the RNG can make use of
530516dd4aaSJason A. Donenfeld	 * measurements of boot time from the earliest opportunity. Especially
531516dd4aaSJason A. Donenfeld	 * important is that the TTCR does not return zero by the time we reach
5322f14062bSJason A. Donenfeld	 * random_init().
533516dd4aaSJason A. Donenfeld	 */
534516dd4aaSJason A. Donenfeld	l.movhi r3,hi(SPR_TTMR_CR)
535516dd4aaSJason A. Donenfeld	l.mtspr r0,r3,SPR_TTMR
536516dd4aaSJason A. Donenfeld
5379d02a428SJonas Bonn	CLEAR_GPR(r1)
5389d02a428SJonas Bonn	CLEAR_GPR(r2)
5399d02a428SJonas Bonn	CLEAR_GPR(r3)
5409d02a428SJonas Bonn	CLEAR_GPR(r4)
5419d02a428SJonas Bonn	CLEAR_GPR(r5)
5429d02a428SJonas Bonn	CLEAR_GPR(r6)
5439d02a428SJonas Bonn	CLEAR_GPR(r7)
5449d02a428SJonas Bonn	CLEAR_GPR(r8)
5459d02a428SJonas Bonn	CLEAR_GPR(r9)
5469d02a428SJonas Bonn	CLEAR_GPR(r10)
5479d02a428SJonas Bonn	CLEAR_GPR(r11)
5489d02a428SJonas Bonn	CLEAR_GPR(r12)
5499d02a428SJonas Bonn	CLEAR_GPR(r13)
5509d02a428SJonas Bonn	CLEAR_GPR(r14)
5519d02a428SJonas Bonn	CLEAR_GPR(r15)
5529d02a428SJonas Bonn	CLEAR_GPR(r16)
5539d02a428SJonas Bonn	CLEAR_GPR(r17)
5549d02a428SJonas Bonn	CLEAR_GPR(r18)
5559d02a428SJonas Bonn	CLEAR_GPR(r19)
5569d02a428SJonas Bonn	CLEAR_GPR(r20)
5579d02a428SJonas Bonn	CLEAR_GPR(r21)
5589d02a428SJonas Bonn	CLEAR_GPR(r22)
5599d02a428SJonas Bonn	CLEAR_GPR(r23)
5609d02a428SJonas Bonn	CLEAR_GPR(r24)
5619d02a428SJonas Bonn	CLEAR_GPR(r26)
5629d02a428SJonas Bonn	CLEAR_GPR(r27)
5639d02a428SJonas Bonn	CLEAR_GPR(r28)
5649d02a428SJonas Bonn	CLEAR_GPR(r29)
5659d02a428SJonas Bonn	CLEAR_GPR(r30)
5669d02a428SJonas Bonn	CLEAR_GPR(r31)
5679d02a428SJonas Bonn
5688e6d08e0SStefan Kristiansson#ifdef CONFIG_SMP
5698e6d08e0SStefan Kristiansson	l.mfspr	r26,r0,SPR_COREID
5708e6d08e0SStefan Kristiansson	l.sfeq	r26,r0
5718e6d08e0SStefan Kristiansson	l.bnf	secondary_wait
5728e6d08e0SStefan Kristiansson	 l.nop
5738e6d08e0SStefan Kristiansson#endif
5749d02a428SJonas Bonn	/*
5759d02a428SJonas Bonn	 * set up initial ksp and current
5769d02a428SJonas Bonn	 */
577c2dc7243SStefan Kristiansson	/* setup kernel stack */
578c2dc7243SStefan Kristiansson	LOAD_SYMBOL_2_GPR(r1,init_thread_union + THREAD_SIZE)
5799d02a428SJonas Bonn	LOAD_SYMBOL_2_GPR(r10,init_thread_union)	// setup current
5809d02a428SJonas Bonn	tophys	(r31,r10)
5819d02a428SJonas Bonn	l.sw	TI_KSP(r31), r1
5829d02a428SJonas Bonn
5839d02a428SJonas Bonn	l.ori	r4,r0,0x0
5849d02a428SJonas Bonn
5859d02a428SJonas Bonn
5869d02a428SJonas Bonn	/*
5879d02a428SJonas Bonn	 * .data contains initialized data,
5889d02a428SJonas Bonn	 * .bss contains uninitialized data - clear it up
5899d02a428SJonas Bonn	 */
5909d02a428SJonas Bonnclear_bss:
5919d02a428SJonas Bonn	LOAD_SYMBOL_2_GPR(r24, __bss_start)
5929d02a428SJonas Bonn	LOAD_SYMBOL_2_GPR(r26, _end)
5939d02a428SJonas Bonn	tophys(r28,r24)
5949d02a428SJonas Bonn	tophys(r30,r26)
5959d02a428SJonas Bonn	CLEAR_GPR(r24)
5969d02a428SJonas Bonn	CLEAR_GPR(r26)
5979d02a428SJonas Bonn1:
5989d02a428SJonas Bonn	l.sw    (0)(r28),r0
5999d02a428SJonas Bonn	l.sfltu r28,r30
6009d02a428SJonas Bonn	l.bf    1b
6019d02a428SJonas Bonn	l.addi  r28,r28,4
6029d02a428SJonas Bonn
6039d02a428SJonas Bonnenable_ic:
6049d02a428SJonas Bonn	l.jal	_ic_enable
6059d02a428SJonas Bonn	 l.nop
6069d02a428SJonas Bonn
6079d02a428SJonas Bonnenable_dc:
6089d02a428SJonas Bonn	l.jal	_dc_enable
6099d02a428SJonas Bonn	 l.nop
6109d02a428SJonas Bonn
6119d02a428SJonas Bonnflush_tlb:
6128c9b7db0SStefan Kristiansson	l.jal	_flush_tlb
6138c9b7db0SStefan Kristiansson	 l.nop
6149d02a428SJonas Bonn
61511648cbbSRandy Dunlap/* The MMU needs to be enabled before or1k_early_setup is called */
6169d02a428SJonas Bonn
6179d02a428SJonas Bonnenable_mmu:
6189d02a428SJonas Bonn	/*
6199d02a428SJonas Bonn	 * enable dmmu & immu
6209d02a428SJonas Bonn	 * SR[5] = 0, SR[6] = 0, 6th and 7th bit of SR set to 0
6219d02a428SJonas Bonn	 */
6229d02a428SJonas Bonn	l.mfspr	r30,r0,SPR_SR
6239d02a428SJonas Bonn	l.movhi	r28,hi(SPR_SR_DME | SPR_SR_IME)
6249d02a428SJonas Bonn	l.ori	r28,r28,lo(SPR_SR_DME | SPR_SR_IME)
6259d02a428SJonas Bonn	l.or	r30,r30,r28
6269d02a428SJonas Bonn	l.mtspr	r0,r30,SPR_SR
6279d02a428SJonas Bonn	l.nop
6289d02a428SJonas Bonn	l.nop
6299d02a428SJonas Bonn	l.nop
6309d02a428SJonas Bonn	l.nop
6319d02a428SJonas Bonn	l.nop
6329d02a428SJonas Bonn	l.nop
6339d02a428SJonas Bonn	l.nop
6349d02a428SJonas Bonn	l.nop
6359d02a428SJonas Bonn	l.nop
6369d02a428SJonas Bonn	l.nop
6379d02a428SJonas Bonn	l.nop
6389d02a428SJonas Bonn	l.nop
6399d02a428SJonas Bonn	l.nop
6409d02a428SJonas Bonn	l.nop
6419d02a428SJonas Bonn	l.nop
6429d02a428SJonas Bonn	l.nop
6439d02a428SJonas Bonn
6449d02a428SJonas Bonn	// reset the simulation counters
6459d02a428SJonas Bonn	l.nop 5
6469d02a428SJonas Bonn
647dec83018SStefan Kristiansson	/* check fdt header magic word */
648dec83018SStefan Kristiansson	l.lwz	r3,0(r25)	/* load magic from fdt into r3 */
649dec83018SStefan Kristiansson	l.movhi	r4,hi(OF_DT_HEADER)
650dec83018SStefan Kristiansson	l.ori	r4,r4,lo(OF_DT_HEADER)
651dec83018SStefan Kristiansson	l.sfeq	r3,r4
652dec83018SStefan Kristiansson	l.bf	_fdt_found
653dec83018SStefan Kristiansson	 l.nop
654dec83018SStefan Kristiansson	/* magic number mismatch, set fdt pointer to null */
655dec83018SStefan Kristiansson	l.or	r25,r0,r0
656dec83018SStefan Kristiansson_fdt_found:
65711648cbbSRandy Dunlap	/* pass fdt pointer to or1k_early_setup in r3 */
658dec83018SStefan Kristiansson	l.or	r3,r0,r25
65911648cbbSRandy Dunlap	LOAD_SYMBOL_2_GPR(r24, or1k_early_setup)
6609d02a428SJonas Bonn	l.jalr r24
6619d02a428SJonas Bonn	 l.nop
6629d02a428SJonas Bonn
6639d02a428SJonas Bonnclear_regs:
6649d02a428SJonas Bonn	/*
6659d02a428SJonas Bonn	 * clear all GPRS to increase determinism
6669d02a428SJonas Bonn	 */
6679d02a428SJonas Bonn	CLEAR_GPR(r2)
6689d02a428SJonas Bonn	CLEAR_GPR(r3)
6699d02a428SJonas Bonn	CLEAR_GPR(r4)
6709d02a428SJonas Bonn	CLEAR_GPR(r5)
6719d02a428SJonas Bonn	CLEAR_GPR(r6)
6729d02a428SJonas Bonn	CLEAR_GPR(r7)
6739d02a428SJonas Bonn	CLEAR_GPR(r8)
6749d02a428SJonas Bonn	CLEAR_GPR(r9)
6759d02a428SJonas Bonn	CLEAR_GPR(r11)
6769d02a428SJonas Bonn	CLEAR_GPR(r12)
6779d02a428SJonas Bonn	CLEAR_GPR(r13)
6789d02a428SJonas Bonn	CLEAR_GPR(r14)
6799d02a428SJonas Bonn	CLEAR_GPR(r15)
6809d02a428SJonas Bonn	CLEAR_GPR(r16)
6819d02a428SJonas Bonn	CLEAR_GPR(r17)
6829d02a428SJonas Bonn	CLEAR_GPR(r18)
6839d02a428SJonas Bonn	CLEAR_GPR(r19)
6849d02a428SJonas Bonn	CLEAR_GPR(r20)
6859d02a428SJonas Bonn	CLEAR_GPR(r21)
6869d02a428SJonas Bonn	CLEAR_GPR(r22)
6879d02a428SJonas Bonn	CLEAR_GPR(r23)
6889d02a428SJonas Bonn	CLEAR_GPR(r24)
6899d02a428SJonas Bonn	CLEAR_GPR(r25)
6909d02a428SJonas Bonn	CLEAR_GPR(r26)
6919d02a428SJonas Bonn	CLEAR_GPR(r27)
6929d02a428SJonas Bonn	CLEAR_GPR(r28)
6939d02a428SJonas Bonn	CLEAR_GPR(r29)
6949d02a428SJonas Bonn	CLEAR_GPR(r30)
6959d02a428SJonas Bonn	CLEAR_GPR(r31)
6969d02a428SJonas Bonn
6979d02a428SJonas Bonnjump_start_kernel:
6989d02a428SJonas Bonn	/*
6999d02a428SJonas Bonn	 * jump to kernel entry (start_kernel)
7009d02a428SJonas Bonn	 */
7019d02a428SJonas Bonn	LOAD_SYMBOL_2_GPR(r30, start_kernel)
7029d02a428SJonas Bonn	l.jr    r30
7039d02a428SJonas Bonn	 l.nop
7049d02a428SJonas Bonn
7058c9b7db0SStefan Kristiansson_flush_tlb:
7068c9b7db0SStefan Kristiansson	/*
7078c9b7db0SStefan Kristiansson	 *  I N V A L I D A T E   T L B   e n t r i e s
7088c9b7db0SStefan Kristiansson	 */
7098c9b7db0SStefan Kristiansson	LOAD_SYMBOL_2_GPR(r5,SPR_DTLBMR_BASE(0))
7108c9b7db0SStefan Kristiansson	LOAD_SYMBOL_2_GPR(r6,SPR_ITLBMR_BASE(0))
7118c9b7db0SStefan Kristiansson	l.addi	r7,r0,128 /* Maximum number of sets */
7128c9b7db0SStefan Kristiansson1:
7138c9b7db0SStefan Kristiansson	l.mtspr	r5,r0,0x0
7148c9b7db0SStefan Kristiansson	l.mtspr	r6,r0,0x0
7158c9b7db0SStefan Kristiansson
7168c9b7db0SStefan Kristiansson	l.addi	r5,r5,1
7178c9b7db0SStefan Kristiansson	l.addi	r6,r6,1
7188c9b7db0SStefan Kristiansson	l.sfeq	r7,r0
7198c9b7db0SStefan Kristiansson	l.bnf	1b
7208c9b7db0SStefan Kristiansson	 l.addi	r7,r7,-1
7218c9b7db0SStefan Kristiansson
7228c9b7db0SStefan Kristiansson	l.jr	r9
7238c9b7db0SStefan Kristiansson	 l.nop
7248c9b7db0SStefan Kristiansson
7258e6d08e0SStefan Kristiansson#ifdef CONFIG_SMP
7268e6d08e0SStefan Kristianssonsecondary_wait:
727c0567184SStafford Horne	/* Doze the cpu until we are asked to run */
728c0567184SStafford Horne	/* If we dont have power management skip doze */
729c0567184SStafford Horne	l.mfspr r25,r0,SPR_UPR
730c0567184SStafford Horne	l.andi  r25,r25,SPR_UPR_PMP
731c0567184SStafford Horne	l.sfeq  r25,r0
732c0567184SStafford Horne	l.bf	secondary_check_release
733c0567184SStafford Horne	 l.nop
734c0567184SStafford Horne
735c0567184SStafford Horne	/* Setup special secondary exception handler */
736c0567184SStafford Horne	LOAD_SYMBOL_2_GPR(r3, _secondary_evbar)
737c0567184SStafford Horne	tophys(r25,r3)
738c0567184SStafford Horne	l.mtspr	r0,r25,SPR_EVBAR
739c0567184SStafford Horne
740c0567184SStafford Horne	/* Enable Interrupts */
741c0567184SStafford Horne	l.mfspr	r25,r0,SPR_SR
742c0567184SStafford Horne	l.ori	r25,r25,SPR_SR_IEE
743c0567184SStafford Horne	l.mtspr	r0,r25,SPR_SR
744c0567184SStafford Horne
745c0567184SStafford Horne	/* Unmask interrupts interrupts */
746c0567184SStafford Horne	l.mfspr r25,r0,SPR_PICMR
747c0567184SStafford Horne	l.ori   r25,r25,0xffff
748c0567184SStafford Horne	l.mtspr	r0,r25,SPR_PICMR
749c0567184SStafford Horne
750c0567184SStafford Horne	/* Doze */
751c0567184SStafford Horne	l.mfspr r25,r0,SPR_PMR
752c0567184SStafford Horne	LOAD_SYMBOL_2_GPR(r3, SPR_PMR_DME)
753c0567184SStafford Horne	l.or    r25,r25,r3
754c0567184SStafford Horne	l.mtspr r0,r25,SPR_PMR
755c0567184SStafford Horne
756c0567184SStafford Horne	/* Wakeup - Restore exception handler */
757c0567184SStafford Horne	l.mtspr	r0,r0,SPR_EVBAR
758c0567184SStafford Horne
759c0567184SStafford Hornesecondary_check_release:
760c0567184SStafford Horne	/*
761c0567184SStafford Horne	 * Check if we actually got the release signal, if not go-back to
762c0567184SStafford Horne	 * sleep.
763c0567184SStafford Horne	 */
7648e6d08e0SStefan Kristiansson	l.mfspr	r25,r0,SPR_COREID
765c0567184SStafford Horne	LOAD_SYMBOL_2_GPR(r3, secondary_release)
7668e6d08e0SStefan Kristiansson	tophys(r4, r3)
7678e6d08e0SStefan Kristiansson	l.lwz	r3,0(r4)
7688e6d08e0SStefan Kristiansson	l.sfeq	r25,r3
7698e6d08e0SStefan Kristiansson	l.bnf	secondary_wait
7708e6d08e0SStefan Kristiansson	 l.nop
7718e6d08e0SStefan Kristiansson	/* fall through to secondary_init */
7728e6d08e0SStefan Kristiansson
7738e6d08e0SStefan Kristianssonsecondary_init:
7748e6d08e0SStefan Kristiansson	/*
7758e6d08e0SStefan Kristiansson	 * set up initial ksp and current
7768e6d08e0SStefan Kristiansson	 */
7778e6d08e0SStefan Kristiansson	LOAD_SYMBOL_2_GPR(r10, secondary_thread_info)
7788e6d08e0SStefan Kristiansson	tophys	(r30,r10)
7798e6d08e0SStefan Kristiansson	l.lwz	r10,0(r30)
7808e6d08e0SStefan Kristiansson	l.addi	r1,r10,THREAD_SIZE
7818e6d08e0SStefan Kristiansson	tophys	(r30,r10)
7828e6d08e0SStefan Kristiansson	l.sw	TI_KSP(r30),r1
7838e6d08e0SStefan Kristiansson
7848e6d08e0SStefan Kristiansson	l.jal	_ic_enable
7858e6d08e0SStefan Kristiansson	 l.nop
7868e6d08e0SStefan Kristiansson
7878e6d08e0SStefan Kristiansson	l.jal	_dc_enable
7888e6d08e0SStefan Kristiansson	 l.nop
7898e6d08e0SStefan Kristiansson
7908e6d08e0SStefan Kristiansson	l.jal	_flush_tlb
7918e6d08e0SStefan Kristiansson	 l.nop
7928e6d08e0SStefan Kristiansson
7938e6d08e0SStefan Kristiansson	/*
7948e6d08e0SStefan Kristiansson	 * enable dmmu & immu
7958e6d08e0SStefan Kristiansson	 */
7968e6d08e0SStefan Kristiansson	l.mfspr	r30,r0,SPR_SR
7978e6d08e0SStefan Kristiansson	l.movhi	r28,hi(SPR_SR_DME | SPR_SR_IME)
7988e6d08e0SStefan Kristiansson	l.ori	r28,r28,lo(SPR_SR_DME | SPR_SR_IME)
7998e6d08e0SStefan Kristiansson	l.or	r30,r30,r28
8008e6d08e0SStefan Kristiansson	/*
8018e6d08e0SStefan Kristiansson	 * This is a bit tricky, we need to switch over from physical addresses
8028e6d08e0SStefan Kristiansson	 * to virtual addresses on the fly.
8038e6d08e0SStefan Kristiansson	 * To do that, we first set up ESR with the IME and DME bits set.
8048e6d08e0SStefan Kristiansson	 * Then EPCR is set to secondary_start and then a l.rfe is issued to
8058e6d08e0SStefan Kristiansson	 * "jump" to that.
8068e6d08e0SStefan Kristiansson	 */
8078e6d08e0SStefan Kristiansson	l.mtspr	r0,r30,SPR_ESR_BASE
8088e6d08e0SStefan Kristiansson	LOAD_SYMBOL_2_GPR(r30, secondary_start)
8098e6d08e0SStefan Kristiansson	l.mtspr	r0,r30,SPR_EPCR_BASE
8108e6d08e0SStefan Kristiansson	l.rfe
8118e6d08e0SStefan Kristiansson
8128e6d08e0SStefan Kristianssonsecondary_start:
8138e6d08e0SStefan Kristiansson	LOAD_SYMBOL_2_GPR(r30, secondary_start_kernel)
8148e6d08e0SStefan Kristiansson	l.jr    r30
8158e6d08e0SStefan Kristiansson	 l.nop
8168e6d08e0SStefan Kristiansson
8178e6d08e0SStefan Kristiansson#endif
8188e6d08e0SStefan Kristiansson
8199d02a428SJonas Bonn/* ========================================[ cache ]=== */
8209d02a428SJonas Bonn
821550116d2SMasahiro Yamada	/* alignment here so we don't change memory offsets with
822550116d2SMasahiro Yamada	 * memory controller defined
8239d02a428SJonas Bonn	 */
8249d02a428SJonas Bonn	.align 0x2000
8259d02a428SJonas Bonn
8269d02a428SJonas Bonn_ic_enable:
8279d02a428SJonas Bonn	/* Check if IC present and skip enabling otherwise */
8289d02a428SJonas Bonn	l.mfspr r24,r0,SPR_UPR
8299d02a428SJonas Bonn	l.andi  r26,r24,SPR_UPR_ICP
8309d02a428SJonas Bonn	l.sfeq  r26,r0
8319d02a428SJonas Bonn	l.bf	9f
8329d02a428SJonas Bonn	l.nop
8339d02a428SJonas Bonn
8349d02a428SJonas Bonn	/* Disable IC */
8359d02a428SJonas Bonn	l.mfspr r6,r0,SPR_SR
8369d02a428SJonas Bonn	l.addi  r5,r0,-1
8379d02a428SJonas Bonn	l.xori  r5,r5,SPR_SR_ICE
8389d02a428SJonas Bonn	l.and   r5,r6,r5
8399d02a428SJonas Bonn	l.mtspr r0,r5,SPR_SR
8409d02a428SJonas Bonn
8419d02a428SJonas Bonn	/* Establish cache block size
8429d02a428SJonas Bonn	   If BS=0, 16;
8439d02a428SJonas Bonn	   If BS=1, 32;
8449d02a428SJonas Bonn	   r14 contain block size
8459d02a428SJonas Bonn	*/
8469d02a428SJonas Bonn	l.mfspr r24,r0,SPR_ICCFGR
8479d02a428SJonas Bonn	l.andi	r26,r24,SPR_ICCFGR_CBS
8489d02a428SJonas Bonn	l.srli	r28,r26,7
8499d02a428SJonas Bonn	l.ori	r30,r0,16
8509d02a428SJonas Bonn	l.sll	r14,r30,r28
8519d02a428SJonas Bonn
8529d02a428SJonas Bonn	/* Establish number of cache sets
8539d02a428SJonas Bonn	   r16 contains number of cache sets
8549d02a428SJonas Bonn	   r28 contains log(# of cache sets)
8559d02a428SJonas Bonn	*/
8569d02a428SJonas Bonn	l.andi  r26,r24,SPR_ICCFGR_NCS
8579d02a428SJonas Bonn	l.srli 	r28,r26,3
8589d02a428SJonas Bonn	l.ori   r30,r0,1
8599d02a428SJonas Bonn	l.sll   r16,r30,r28
8609d02a428SJonas Bonn
8619d02a428SJonas Bonn	/* Invalidate IC */
8629d02a428SJonas Bonn	l.addi  r6,r0,0
8639d02a428SJonas Bonn	l.sll   r5,r14,r28
8649d02a428SJonas Bonn//        l.mul   r5,r14,r16
8659d02a428SJonas Bonn//	l.trap  1
8669d02a428SJonas Bonn//	l.addi  r5,r0,IC_SIZE
8679d02a428SJonas Bonn1:
8689d02a428SJonas Bonn	l.mtspr r0,r6,SPR_ICBIR
8699d02a428SJonas Bonn	l.sfne  r6,r5
8709d02a428SJonas Bonn	l.bf    1b
8719d02a428SJonas Bonn	l.add   r6,r6,r14
8729d02a428SJonas Bonn //       l.addi   r6,r6,IC_LINE
8739d02a428SJonas Bonn
8749d02a428SJonas Bonn	/* Enable IC */
8759d02a428SJonas Bonn	l.mfspr r6,r0,SPR_SR
8769d02a428SJonas Bonn	l.ori   r6,r6,SPR_SR_ICE
8779d02a428SJonas Bonn	l.mtspr r0,r6,SPR_SR
8789d02a428SJonas Bonn	l.nop
8799d02a428SJonas Bonn	l.nop
8809d02a428SJonas Bonn	l.nop
8819d02a428SJonas Bonn	l.nop
8829d02a428SJonas Bonn	l.nop
8839d02a428SJonas Bonn	l.nop
8849d02a428SJonas Bonn	l.nop
8859d02a428SJonas Bonn	l.nop
8869d02a428SJonas Bonn	l.nop
8879d02a428SJonas Bonn	l.nop
8889d02a428SJonas Bonn9:
8899d02a428SJonas Bonn	l.jr    r9
8909d02a428SJonas Bonn	l.nop
8919d02a428SJonas Bonn
8929d02a428SJonas Bonn_dc_enable:
8939d02a428SJonas Bonn	/* Check if DC present and skip enabling otherwise */
8949d02a428SJonas Bonn	l.mfspr r24,r0,SPR_UPR
8959d02a428SJonas Bonn	l.andi  r26,r24,SPR_UPR_DCP
8969d02a428SJonas Bonn	l.sfeq  r26,r0
8979d02a428SJonas Bonn	l.bf	9f
8989d02a428SJonas Bonn	l.nop
8999d02a428SJonas Bonn
9009d02a428SJonas Bonn	/* Disable DC */
9019d02a428SJonas Bonn	l.mfspr r6,r0,SPR_SR
9029d02a428SJonas Bonn	l.addi  r5,r0,-1
9039d02a428SJonas Bonn	l.xori  r5,r5,SPR_SR_DCE
9049d02a428SJonas Bonn	l.and   r5,r6,r5
9059d02a428SJonas Bonn	l.mtspr r0,r5,SPR_SR
9069d02a428SJonas Bonn
9079d02a428SJonas Bonn	/* Establish cache block size
9089d02a428SJonas Bonn	   If BS=0, 16;
9099d02a428SJonas Bonn	   If BS=1, 32;
9109d02a428SJonas Bonn	   r14 contain block size
9119d02a428SJonas Bonn	*/
9129d02a428SJonas Bonn	l.mfspr r24,r0,SPR_DCCFGR
9139d02a428SJonas Bonn	l.andi	r26,r24,SPR_DCCFGR_CBS
9149d02a428SJonas Bonn	l.srli	r28,r26,7
9159d02a428SJonas Bonn	l.ori	r30,r0,16
9169d02a428SJonas Bonn	l.sll	r14,r30,r28
9179d02a428SJonas Bonn
9189d02a428SJonas Bonn	/* Establish number of cache sets
9199d02a428SJonas Bonn	   r16 contains number of cache sets
9209d02a428SJonas Bonn	   r28 contains log(# of cache sets)
9219d02a428SJonas Bonn	*/
9229d02a428SJonas Bonn	l.andi  r26,r24,SPR_DCCFGR_NCS
9239d02a428SJonas Bonn	l.srli 	r28,r26,3
9249d02a428SJonas Bonn	l.ori   r30,r0,1
9259d02a428SJonas Bonn	l.sll   r16,r30,r28
9269d02a428SJonas Bonn
9279d02a428SJonas Bonn	/* Invalidate DC */
9289d02a428SJonas Bonn	l.addi  r6,r0,0
9299d02a428SJonas Bonn	l.sll   r5,r14,r28
9309d02a428SJonas Bonn1:
9319d02a428SJonas Bonn	l.mtspr r0,r6,SPR_DCBIR
9329d02a428SJonas Bonn	l.sfne  r6,r5
9339d02a428SJonas Bonn	l.bf    1b
9349d02a428SJonas Bonn	l.add   r6,r6,r14
9359d02a428SJonas Bonn
9369d02a428SJonas Bonn	/* Enable DC */
9379d02a428SJonas Bonn	l.mfspr r6,r0,SPR_SR
9389d02a428SJonas Bonn	l.ori   r6,r6,SPR_SR_DCE
9399d02a428SJonas Bonn	l.mtspr r0,r6,SPR_SR
9409d02a428SJonas Bonn9:
9419d02a428SJonas Bonn	l.jr    r9
9429d02a428SJonas Bonn	l.nop
9439d02a428SJonas Bonn
9449d02a428SJonas Bonn/* ===============================================[ page table masks ]=== */
9459d02a428SJonas Bonn
9469d02a428SJonas Bonn#define DTLB_UP_CONVERT_MASK  0x3fa
9479d02a428SJonas Bonn#define ITLB_UP_CONVERT_MASK  0x3a
9489d02a428SJonas Bonn
9499d02a428SJonas Bonn/* for SMP we'd have (this is a bit subtle, CC must be always set
9509d02a428SJonas Bonn * for SMP, but since we have _PAGE_PRESENT bit always defined
9519d02a428SJonas Bonn * we can just modify the mask)
9529d02a428SJonas Bonn */
9539d02a428SJonas Bonn#define DTLB_SMP_CONVERT_MASK  0x3fb
9549d02a428SJonas Bonn#define ITLB_SMP_CONVERT_MASK  0x3b
9559d02a428SJonas Bonn
9569d02a428SJonas Bonn/* ---[ boot dtlb miss handler ]----------------------------------------- */
9579d02a428SJonas Bonn
9589d02a428SJonas Bonnboot_dtlb_miss_handler:
9599d02a428SJonas Bonn
9609d02a428SJonas Bonn/* mask for DTLB_MR register: - (0) sets V (valid) bit,
9619d02a428SJonas Bonn *                            - (31-12) sets bits belonging to VPN (31-12)
9629d02a428SJonas Bonn */
9639d02a428SJonas Bonn#define DTLB_MR_MASK 0xfffff001
9649d02a428SJonas Bonn
9659d02a428SJonas Bonn/* mask for DTLB_TR register: - (2) sets CI (cache inhibit) bit,
9669d02a428SJonas Bonn *			      - (4) sets A (access) bit,
9679d02a428SJonas Bonn *                            - (5) sets D (dirty) bit,
9689d02a428SJonas Bonn *                            - (8) sets SRE (superuser read) bit
9699d02a428SJonas Bonn *                            - (9) sets SWE (superuser write) bit
9709d02a428SJonas Bonn *                            - (31-12) sets bits belonging to VPN (31-12)
9719d02a428SJonas Bonn */
9729d02a428SJonas Bonn#define DTLB_TR_MASK 0xfffff332
9739d02a428SJonas Bonn
9749d02a428SJonas Bonn/* These are for masking out the VPN/PPN value from the MR/TR registers...
9759d02a428SJonas Bonn * it's not the same as the PFN */
9769d02a428SJonas Bonn#define VPN_MASK 0xfffff000
9779d02a428SJonas Bonn#define PPN_MASK 0xfffff000
9789d02a428SJonas Bonn
9799d02a428SJonas Bonn
9809d02a428SJonas Bonn	EXCEPTION_STORE_GPR6
9819d02a428SJonas Bonn
9829d02a428SJonas Bonn#if 0
9839d02a428SJonas Bonn	l.mfspr r6,r0,SPR_ESR_BASE	   //
9849d02a428SJonas Bonn	l.andi  r6,r6,SPR_SR_SM            // are we in kernel mode ?
9859d02a428SJonas Bonn	l.sfeqi r6,0                       // r6 == 0x1 --> SM
9869d02a428SJonas Bonn	l.bf    exit_with_no_dtranslation  //
9879d02a428SJonas Bonn	l.nop
9889d02a428SJonas Bonn#endif
9899d02a428SJonas Bonn
9909d02a428SJonas Bonn	/* this could be optimized by moving storing of
9919d02a428SJonas Bonn	 * non r6 registers here, and jumping r6 restore
9929d02a428SJonas Bonn	 * if not in supervisor mode
9939d02a428SJonas Bonn	 */
9949d02a428SJonas Bonn
9959d02a428SJonas Bonn	EXCEPTION_STORE_GPR2
9969d02a428SJonas Bonn	EXCEPTION_STORE_GPR3
9979d02a428SJonas Bonn	EXCEPTION_STORE_GPR4
9989d02a428SJonas Bonn	EXCEPTION_STORE_GPR5
9999d02a428SJonas Bonn
10009d02a428SJonas Bonn	l.mfspr r4,r0,SPR_EEAR_BASE        // get the offending EA
10019d02a428SJonas Bonn
10029d02a428SJonas Bonnimmediate_translation:
10039d02a428SJonas Bonn	CLEAR_GPR(r6)
10049d02a428SJonas Bonn
10059d02a428SJonas Bonn	l.srli	r3,r4,0xd                  // r3 <- r4 / 8192 (sets are relative to page size (8Kb) NOT VPN size (4Kb)
10069d02a428SJonas Bonn
10079d02a428SJonas Bonn	l.mfspr r6, r0, SPR_DMMUCFGR
10089d02a428SJonas Bonn	l.andi	r6, r6, SPR_DMMUCFGR_NTS
10099d02a428SJonas Bonn	l.srli	r6, r6, SPR_DMMUCFGR_NTS_OFF
10109d02a428SJonas Bonn	l.ori	r5, r0, 0x1
10119d02a428SJonas Bonn	l.sll	r5, r5, r6 	// r5 = number DMMU sets
10129d02a428SJonas Bonn	l.addi	r6, r5, -1  	// r6 = nsets mask
10139d02a428SJonas Bonn	l.and	r2, r3, r6	// r2 <- r3 % NSETS_MASK
10149d02a428SJonas Bonn
10159d02a428SJonas Bonn	l.or    r6,r6,r4                   // r6 <- r4
10169d02a428SJonas Bonn	l.ori   r6,r6,~(VPN_MASK)          // r6 <- VPN :VPN .xfff - clear up lo(r6) to 0x**** *fff
10179d02a428SJonas Bonn	l.movhi r5,hi(DTLB_MR_MASK)        // r5 <- ffff:0000.x000
10189d02a428SJonas Bonn	l.ori   r5,r5,lo(DTLB_MR_MASK)     // r5 <- ffff:1111.x001 - apply DTLB_MR_MASK
10199d02a428SJonas Bonn	l.and   r5,r5,r6                   // r5 <- VPN :VPN .x001 - we have DTLBMR entry
10209d02a428SJonas Bonn	l.mtspr r2,r5,SPR_DTLBMR_BASE(0)   // set DTLBMR
10219d02a428SJonas Bonn
10229d02a428SJonas Bonn	/* set up DTLB with no translation for EA <= 0xbfffffff */
10239d02a428SJonas Bonn	LOAD_SYMBOL_2_GPR(r6,0xbfffffff)
10249d02a428SJonas Bonn	l.sfgeu  r6,r4                     // flag if r6 >= r4 (if 0xbfffffff >= EA)
10259d02a428SJonas Bonn	l.bf     1f                        // goto out
10269d02a428SJonas Bonn	l.and    r3,r4,r4                  // delay slot :: 24 <- r4 (if flag==1)
10279d02a428SJonas Bonn
10289d02a428SJonas Bonn	tophys(r3,r4)                      // r3 <- PA
10299d02a428SJonas Bonn1:
10309d02a428SJonas Bonn	l.ori   r3,r3,~(PPN_MASK)          // r3 <- PPN :PPN .xfff - clear up lo(r6) to 0x**** *fff
10319d02a428SJonas Bonn	l.movhi r5,hi(DTLB_TR_MASK)        // r5 <- ffff:0000.x000
10329d02a428SJonas Bonn	l.ori   r5,r5,lo(DTLB_TR_MASK)     // r5 <- ffff:1111.x330 - apply DTLB_MR_MASK
10339d02a428SJonas Bonn	l.and   r5,r5,r3                   // r5 <- PPN :PPN .x330 - we have DTLBTR entry
10349d02a428SJonas Bonn	l.mtspr r2,r5,SPR_DTLBTR_BASE(0)   // set DTLBTR
10359d02a428SJonas Bonn
10369d02a428SJonas Bonn	EXCEPTION_LOAD_GPR6
10379d02a428SJonas Bonn	EXCEPTION_LOAD_GPR5
10389d02a428SJonas Bonn	EXCEPTION_LOAD_GPR4
10399d02a428SJonas Bonn	EXCEPTION_LOAD_GPR3
10409d02a428SJonas Bonn	EXCEPTION_LOAD_GPR2
10419d02a428SJonas Bonn
10429d02a428SJonas Bonn	l.rfe                              // SR <- ESR, PC <- EPC
10439d02a428SJonas Bonn
10449d02a428SJonas Bonnexit_with_no_dtranslation:
10459d02a428SJonas Bonn	/* EA out of memory or not in supervisor mode */
10469d02a428SJonas Bonn	EXCEPTION_LOAD_GPR6
10479d02a428SJonas Bonn	EXCEPTION_LOAD_GPR4
10489d02a428SJonas Bonn	l.j	_dispatch_bus_fault
10499d02a428SJonas Bonn
10509d02a428SJonas Bonn/* ---[ boot itlb miss handler ]----------------------------------------- */
10519d02a428SJonas Bonn
10529d02a428SJonas Bonnboot_itlb_miss_handler:
10539d02a428SJonas Bonn
10549d02a428SJonas Bonn/* mask for ITLB_MR register: - sets V (valid) bit,
10559d02a428SJonas Bonn *                            - sets bits belonging to VPN (15-12)
10569d02a428SJonas Bonn */
10579d02a428SJonas Bonn#define ITLB_MR_MASK 0xfffff001
10589d02a428SJonas Bonn
10599d02a428SJonas Bonn/* mask for ITLB_TR register: - sets A (access) bit,
10609d02a428SJonas Bonn *                            - sets SXE (superuser execute) bit
10619d02a428SJonas Bonn *                            - sets bits belonging to VPN (15-12)
10629d02a428SJonas Bonn */
10639d02a428SJonas Bonn#define ITLB_TR_MASK 0xfffff050
10649d02a428SJonas Bonn
10659d02a428SJonas Bonn/*
10669d02a428SJonas Bonn#define VPN_MASK 0xffffe000
10679d02a428SJonas Bonn#define PPN_MASK 0xffffe000
10689d02a428SJonas Bonn*/
10699d02a428SJonas Bonn
10709d02a428SJonas Bonn
10719d02a428SJonas Bonn
10729d02a428SJonas Bonn	EXCEPTION_STORE_GPR2
10739d02a428SJonas Bonn	EXCEPTION_STORE_GPR3
10749d02a428SJonas Bonn	EXCEPTION_STORE_GPR4
10759d02a428SJonas Bonn	EXCEPTION_STORE_GPR5
10769d02a428SJonas Bonn	EXCEPTION_STORE_GPR6
10779d02a428SJonas Bonn
10789d02a428SJonas Bonn#if 0
10799d02a428SJonas Bonn	l.mfspr r6,r0,SPR_ESR_BASE         //
10809d02a428SJonas Bonn	l.andi  r6,r6,SPR_SR_SM            // are we in kernel mode ?
10819d02a428SJonas Bonn	l.sfeqi r6,0                       // r6 == 0x1 --> SM
10829d02a428SJonas Bonn	l.bf    exit_with_no_itranslation
10839d02a428SJonas Bonn	l.nop
10849d02a428SJonas Bonn#endif
10859d02a428SJonas Bonn
10869d02a428SJonas Bonn
10879d02a428SJonas Bonn	l.mfspr r4,r0,SPR_EEAR_BASE        // get the offending EA
10889d02a428SJonas Bonn
10899d02a428SJonas Bonnearlyearly:
10909d02a428SJonas Bonn	CLEAR_GPR(r6)
10919d02a428SJonas Bonn
10929d02a428SJonas Bonn	l.srli  r3,r4,0xd                  // r3 <- r4 / 8192 (sets are relative to page size (8Kb) NOT VPN size (4Kb)
10939d02a428SJonas Bonn
10949d02a428SJonas Bonn	l.mfspr r6, r0, SPR_IMMUCFGR
10959d02a428SJonas Bonn	l.andi	r6, r6, SPR_IMMUCFGR_NTS
10969d02a428SJonas Bonn	l.srli	r6, r6, SPR_IMMUCFGR_NTS_OFF
10979d02a428SJonas Bonn	l.ori	r5, r0, 0x1
10989d02a428SJonas Bonn	l.sll	r5, r5, r6 	// r5 = number IMMU sets from IMMUCFGR
10999d02a428SJonas Bonn	l.addi	r6, r5, -1  	// r6 = nsets mask
11009d02a428SJonas Bonn	l.and	r2, r3, r6	// r2 <- r3 % NSETS_MASK
11019d02a428SJonas Bonn
11029d02a428SJonas Bonn	l.or    r6,r6,r4                   // r6 <- r4
11039d02a428SJonas Bonn	l.ori   r6,r6,~(VPN_MASK)          // r6 <- VPN :VPN .xfff - clear up lo(r6) to 0x**** *fff
11049d02a428SJonas Bonn	l.movhi r5,hi(ITLB_MR_MASK)        // r5 <- ffff:0000.x000
11059d02a428SJonas Bonn	l.ori   r5,r5,lo(ITLB_MR_MASK)     // r5 <- ffff:1111.x001 - apply ITLB_MR_MASK
11069d02a428SJonas Bonn	l.and   r5,r5,r6                   // r5 <- VPN :VPN .x001 - we have ITLBMR entry
11079d02a428SJonas Bonn	l.mtspr r2,r5,SPR_ITLBMR_BASE(0)   // set ITLBMR
11089d02a428SJonas Bonn
11099d02a428SJonas Bonn	/*
11109d02a428SJonas Bonn	 * set up ITLB with no translation for EA <= 0x0fffffff
11119d02a428SJonas Bonn	 *
11129d02a428SJonas Bonn	 * we need this for head.S mapping (EA = PA). if we move all functions
11139d02a428SJonas Bonn	 * which run with mmu enabled into entry.S, we might be able to eliminate this.
11149d02a428SJonas Bonn	 *
11159d02a428SJonas Bonn	 */
11169d02a428SJonas Bonn	LOAD_SYMBOL_2_GPR(r6,0x0fffffff)
11179d02a428SJonas Bonn	l.sfgeu  r6,r4                     // flag if r6 >= r4 (if 0xb0ffffff >= EA)
11189d02a428SJonas Bonn	l.bf     1f                        // goto out
11199d02a428SJonas Bonn	l.and    r3,r4,r4                  // delay slot :: 24 <- r4 (if flag==1)
11209d02a428SJonas Bonn
11219d02a428SJonas Bonn	tophys(r3,r4)                      // r3 <- PA
11229d02a428SJonas Bonn1:
11239d02a428SJonas Bonn	l.ori   r3,r3,~(PPN_MASK)          // r3 <- PPN :PPN .xfff - clear up lo(r6) to 0x**** *fff
11249d02a428SJonas Bonn	l.movhi r5,hi(ITLB_TR_MASK)        // r5 <- ffff:0000.x000
11259d02a428SJonas Bonn	l.ori   r5,r5,lo(ITLB_TR_MASK)     // r5 <- ffff:1111.x050 - apply ITLB_MR_MASK
11269d02a428SJonas Bonn	l.and   r5,r5,r3                   // r5 <- PPN :PPN .x050 - we have ITLBTR entry
11279d02a428SJonas Bonn	l.mtspr r2,r5,SPR_ITLBTR_BASE(0)   // set ITLBTR
11289d02a428SJonas Bonn
11299d02a428SJonas Bonn	EXCEPTION_LOAD_GPR6
11309d02a428SJonas Bonn	EXCEPTION_LOAD_GPR5
11319d02a428SJonas Bonn	EXCEPTION_LOAD_GPR4
11329d02a428SJonas Bonn	EXCEPTION_LOAD_GPR3
11339d02a428SJonas Bonn	EXCEPTION_LOAD_GPR2
11349d02a428SJonas Bonn
11359d02a428SJonas Bonn	l.rfe                              // SR <- ESR, PC <- EPC
11369d02a428SJonas Bonn
11379d02a428SJonas Bonnexit_with_no_itranslation:
11389d02a428SJonas Bonn	EXCEPTION_LOAD_GPR4
11399d02a428SJonas Bonn	EXCEPTION_LOAD_GPR6
11409d02a428SJonas Bonn	l.j    _dispatch_bus_fault
11419d02a428SJonas Bonn	l.nop
11429d02a428SJonas Bonn
11439d02a428SJonas Bonn/* ====================================================================== */
11449d02a428SJonas Bonn/*
11459d02a428SJonas Bonn * Stuff below here shouldn't go into .head section... maybe this stuff
11469d02a428SJonas Bonn * can be moved to entry.S ???
11479d02a428SJonas Bonn */
11489d02a428SJonas Bonn
11499d02a428SJonas Bonn/* ==============================================[ DTLB miss handler ]=== */
11509d02a428SJonas Bonn
11519d02a428SJonas Bonn/*
11529d02a428SJonas Bonn * Comments:
11539d02a428SJonas Bonn *   Exception handlers are entered with MMU off so the following handler
11549d02a428SJonas Bonn *   needs to use physical addressing
11559d02a428SJonas Bonn *
11569d02a428SJonas Bonn */
11579d02a428SJonas Bonn
11589d02a428SJonas Bonn	.text
11599d02a428SJonas BonnENTRY(dtlb_miss_handler)
11609d02a428SJonas Bonn	EXCEPTION_STORE_GPR2
11619d02a428SJonas Bonn	EXCEPTION_STORE_GPR3
11629d02a428SJonas Bonn	EXCEPTION_STORE_GPR4
11639d02a428SJonas Bonn	/*
11649d02a428SJonas Bonn	 * get EA of the miss
11659d02a428SJonas Bonn	 */
11669d02a428SJonas Bonn	l.mfspr	r2,r0,SPR_EEAR_BASE
11679d02a428SJonas Bonn	/*
11689d02a428SJonas Bonn	 * pmd = (pmd_t *)(current_pgd + pgd_index(daddr));
11699d02a428SJonas Bonn	 */
1170742fb582SStefan Kristiansson	GET_CURRENT_PGD(r3,r4)		// r3 is current_pgd, r4 is temp
11719d02a428SJonas Bonn	l.srli	r4,r2,0x18		// >> PAGE_SHIFT + (PAGE_SHIFT - 2)
11729d02a428SJonas Bonn	l.slli	r4,r4,0x2		// to get address << 2
1173742fb582SStefan Kristiansson	l.add	r3,r4,r3		// r4 is pgd_index(daddr)
11749d02a428SJonas Bonn	/*
11759d02a428SJonas Bonn	 * if (pmd_none(*pmd))
11769d02a428SJonas Bonn	 *   goto pmd_none:
11779d02a428SJonas Bonn	 */
1178742fb582SStefan Kristiansson	tophys	(r4,r3)
11799d02a428SJonas Bonn	l.lwz	r3,0x0(r4)		// get *pmd value
11809d02a428SJonas Bonn	l.sfne	r3,r0
11819d02a428SJonas Bonn	l.bnf	d_pmd_none
11829d02a428SJonas Bonn	 l.addi	r3,r0,0xffffe000	// PAGE_MASK
1183742fb582SStefan Kristiansson
11849d02a428SJonas Bonnd_pmd_good:
11859d02a428SJonas Bonn	/*
11869d02a428SJonas Bonn	 * pte = *pte_offset(pmd, daddr);
11879d02a428SJonas Bonn	 */
11889d02a428SJonas Bonn	l.lwz	r4,0x0(r4)		// get **pmd value
11899d02a428SJonas Bonn	l.and	r4,r4,r3		// & PAGE_MASK
1190742fb582SStefan Kristiansson	l.srli	r2,r2,0xd		// >> PAGE_SHIFT, r2 == EEAR
1191742fb582SStefan Kristiansson	l.andi	r3,r2,0x7ff		// (1UL << PAGE_SHIFT - 2) - 1
11929d02a428SJonas Bonn	l.slli	r3,r3,0x2		// to get address << 2
11939d02a428SJonas Bonn	l.add	r3,r3,r4
1194742fb582SStefan Kristiansson	l.lwz	r3,0x0(r3)		// this is pte at last
11959d02a428SJonas Bonn	/*
11969d02a428SJonas Bonn	 * if (!pte_present(pte))
11979d02a428SJonas Bonn	 */
1198742fb582SStefan Kristiansson	l.andi	r4,r3,0x1
11999d02a428SJonas Bonn	l.sfne	r4,r0			// is pte present
12009d02a428SJonas Bonn	l.bnf	d_pte_not_present
1201742fb582SStefan Kristiansson	l.addi	r4,r0,0xffffe3fa	// PAGE_MASK | DTLB_UP_CONVERT_MASK
12029d02a428SJonas Bonn	/*
12039d02a428SJonas Bonn	 * fill DTLB TR register
12049d02a428SJonas Bonn	 */
1205742fb582SStefan Kristiansson	l.and	r4,r3,r4		// apply the mask
12069d02a428SJonas Bonn	// Determine number of DMMU sets
1207742fb582SStefan Kristiansson	l.mfspr r2, r0, SPR_DMMUCFGR
1208742fb582SStefan Kristiansson	l.andi	r2, r2, SPR_DMMUCFGR_NTS
1209742fb582SStefan Kristiansson	l.srli	r2, r2, SPR_DMMUCFGR_NTS_OFF
12109d02a428SJonas Bonn	l.ori	r3, r0, 0x1
1211742fb582SStefan Kristiansson	l.sll	r3, r3, r2 	// r3 = number DMMU sets DMMUCFGR
1212742fb582SStefan Kristiansson	l.addi	r2, r3, -1  	// r2 = nsets mask
1213742fb582SStefan Kristiansson	l.mfspr	r3, r0, SPR_EEAR_BASE
1214742fb582SStefan Kristiansson	l.srli	r3, r3, 0xd	// >> PAGE_SHIFT
1215742fb582SStefan Kristiansson	l.and	r2, r3, r2	// calc offset:	 & (NUM_TLB_ENTRIES-1)
12169d02a428SJonas Bonn	                                                   //NUM_TLB_ENTRIES
1217742fb582SStefan Kristiansson	l.mtspr	r2,r4,SPR_DTLBTR_BASE(0)
12189d02a428SJonas Bonn	/*
12199d02a428SJonas Bonn	 * fill DTLB MR register
12209d02a428SJonas Bonn	 */
1221742fb582SStefan Kristiansson	l.slli	r3, r3, 0xd		/* << PAGE_SHIFT => EA & PAGE_MASK */
1222742fb582SStefan Kristiansson	l.ori	r4,r3,0x1		// set hardware valid bit: DTBL_MR entry
1223742fb582SStefan Kristiansson	l.mtspr	r2,r4,SPR_DTLBMR_BASE(0)
12249d02a428SJonas Bonn
12259d02a428SJonas Bonn	EXCEPTION_LOAD_GPR2
12269d02a428SJonas Bonn	EXCEPTION_LOAD_GPR3
12279d02a428SJonas Bonn	EXCEPTION_LOAD_GPR4
12289d02a428SJonas Bonn	l.rfe
12299d02a428SJonas Bonnd_pmd_none:
12309d02a428SJonas Bonnd_pte_not_present:
12319d02a428SJonas Bonn	EXCEPTION_LOAD_GPR2
12329d02a428SJonas Bonn	EXCEPTION_LOAD_GPR3
12339d02a428SJonas Bonn	EXCEPTION_LOAD_GPR4
1234a81252d7SJonas Bonn	EXCEPTION_HANDLE(_dtlb_miss_page_fault_handler)
12359d02a428SJonas Bonn
12369d02a428SJonas Bonn/* ==============================================[ ITLB miss handler ]=== */
12379d02a428SJonas BonnENTRY(itlb_miss_handler)
12389d02a428SJonas Bonn	EXCEPTION_STORE_GPR2
12399d02a428SJonas Bonn	EXCEPTION_STORE_GPR3
12409d02a428SJonas Bonn	EXCEPTION_STORE_GPR4
12419d02a428SJonas Bonn	/*
12429d02a428SJonas Bonn	 * get EA of the miss
12439d02a428SJonas Bonn	 */
12449d02a428SJonas Bonn	l.mfspr	r2,r0,SPR_EEAR_BASE
12459d02a428SJonas Bonn
12469d02a428SJonas Bonn	/*
12479d02a428SJonas Bonn	 * pmd = (pmd_t *)(current_pgd + pgd_index(daddr));
12489d02a428SJonas Bonn	 *
12499d02a428SJonas Bonn	 */
1250742fb582SStefan Kristiansson	GET_CURRENT_PGD(r3,r4)		// r3 is current_pgd, r5 is temp
12519d02a428SJonas Bonn	l.srli	r4,r2,0x18		// >> PAGE_SHIFT + (PAGE_SHIFT - 2)
12529d02a428SJonas Bonn	l.slli	r4,r4,0x2		// to get address << 2
1253742fb582SStefan Kristiansson	l.add	r3,r4,r3		// r4 is pgd_index(daddr)
12549d02a428SJonas Bonn	/*
12559d02a428SJonas Bonn	 * if (pmd_none(*pmd))
12569d02a428SJonas Bonn	 *   goto pmd_none:
12579d02a428SJonas Bonn	 */
1258742fb582SStefan Kristiansson	tophys	(r4,r3)
12599d02a428SJonas Bonn	l.lwz	r3,0x0(r4)		// get *pmd value
12609d02a428SJonas Bonn	l.sfne	r3,r0
12619d02a428SJonas Bonn	l.bnf	i_pmd_none
12629d02a428SJonas Bonn	 l.addi	r3,r0,0xffffe000	// PAGE_MASK
12639d02a428SJonas Bonn
12649d02a428SJonas Bonni_pmd_good:
12659d02a428SJonas Bonn	/*
12669d02a428SJonas Bonn	 * pte = *pte_offset(pmd, iaddr);
12679d02a428SJonas Bonn	 *
12689d02a428SJonas Bonn	 */
12699d02a428SJonas Bonn	l.lwz	r4,0x0(r4)		// get **pmd value
12709d02a428SJonas Bonn	l.and	r4,r4,r3		// & PAGE_MASK
1271742fb582SStefan Kristiansson	l.srli	r2,r2,0xd		// >> PAGE_SHIFT, r2 == EEAR
1272742fb582SStefan Kristiansson	l.andi	r3,r2,0x7ff		// (1UL << PAGE_SHIFT - 2) - 1
12739d02a428SJonas Bonn	l.slli	r3,r3,0x2		// to get address << 2
12749d02a428SJonas Bonn	l.add	r3,r3,r4
1275742fb582SStefan Kristiansson	l.lwz	r3,0x0(r3)		// this is pte at last
12769d02a428SJonas Bonn	/*
12779d02a428SJonas Bonn	 * if (!pte_present(pte))
12789d02a428SJonas Bonn	 *
12799d02a428SJonas Bonn	 */
1280742fb582SStefan Kristiansson	l.andi	r4,r3,0x1
12819d02a428SJonas Bonn	l.sfne	r4,r0			// is pte present
12829d02a428SJonas Bonn	l.bnf	i_pte_not_present
1283742fb582SStefan Kristiansson	 l.addi	r4,r0,0xffffe03a	// PAGE_MASK | ITLB_UP_CONVERT_MASK
12849d02a428SJonas Bonn	/*
12859d02a428SJonas Bonn	 * fill ITLB TR register
12869d02a428SJonas Bonn	 */
1287742fb582SStefan Kristiansson	l.and	r4,r3,r4		// apply the mask
1288742fb582SStefan Kristiansson	l.andi	r3,r3,0x7c0		// _PAGE_EXEC | _PAGE_SRE | _PAGE_SWE |  _PAGE_URE | _PAGE_UWE
12899d02a428SJonas Bonn	l.sfeq	r3,r0
12909d02a428SJonas Bonn	l.bf	itlb_tr_fill //_workaround
12919d02a428SJonas Bonn	// Determine number of IMMU sets
1292742fb582SStefan Kristiansson	l.mfspr r2, r0, SPR_IMMUCFGR
1293742fb582SStefan Kristiansson	l.andi	r2, r2, SPR_IMMUCFGR_NTS
1294742fb582SStefan Kristiansson	l.srli	r2, r2, SPR_IMMUCFGR_NTS_OFF
12959d02a428SJonas Bonn	l.ori	r3, r0, 0x1
1296742fb582SStefan Kristiansson	l.sll	r3, r3, r2 	// r3 = number IMMU sets IMMUCFGR
1297742fb582SStefan Kristiansson	l.addi	r2, r3, -1  	// r2 = nsets mask
1298742fb582SStefan Kristiansson	l.mfspr	r3, r0, SPR_EEAR_BASE
1299742fb582SStefan Kristiansson	l.srli	r3, r3, 0xd	// >> PAGE_SHIFT
1300742fb582SStefan Kristiansson	l.and	r2, r3, r2	// calc offset:	 & (NUM_TLB_ENTRIES-1)
13019d02a428SJonas Bonn
13029d02a428SJonas Bonn/*
13039d02a428SJonas Bonn * __PHX__ :: fixme
13049d02a428SJonas Bonn * we should not just blindly set executable flags,
13059d02a428SJonas Bonn * but it does help with ping. the clean way would be to find out
13069d02a428SJonas Bonn * (and fix it) why stack doesn't have execution permissions
13079d02a428SJonas Bonn */
13089d02a428SJonas Bonn
13099d02a428SJonas Bonnitlb_tr_fill_workaround:
13109d02a428SJonas Bonn	l.ori	r4,r4,0xc0		// | (SPR_ITLBTR_UXE | ITLBTR_SXE)
13119d02a428SJonas Bonnitlb_tr_fill:
1312742fb582SStefan Kristiansson	l.mtspr	r2,r4,SPR_ITLBTR_BASE(0)
13139d02a428SJonas Bonn	/*
13149d02a428SJonas Bonn	 * fill DTLB MR register
13159d02a428SJonas Bonn	 */
1316742fb582SStefan Kristiansson	l.slli	r3, r3, 0xd		/* << PAGE_SHIFT => EA & PAGE_MASK */
1317742fb582SStefan Kristiansson	l.ori	r4,r3,0x1		// set hardware valid bit: ITBL_MR entry
1318742fb582SStefan Kristiansson	l.mtspr	r2,r4,SPR_ITLBMR_BASE(0)
13199d02a428SJonas Bonn
13209d02a428SJonas Bonn	EXCEPTION_LOAD_GPR2
13219d02a428SJonas Bonn	EXCEPTION_LOAD_GPR3
13229d02a428SJonas Bonn	EXCEPTION_LOAD_GPR4
13239d02a428SJonas Bonn	l.rfe
13249d02a428SJonas Bonn
13259d02a428SJonas Bonni_pmd_none:
13269d02a428SJonas Bonni_pte_not_present:
13279d02a428SJonas Bonn	EXCEPTION_LOAD_GPR2
13289d02a428SJonas Bonn	EXCEPTION_LOAD_GPR3
13299d02a428SJonas Bonn	EXCEPTION_LOAD_GPR4
1330a81252d7SJonas Bonn	EXCEPTION_HANDLE(_itlb_miss_page_fault_handler)
13319d02a428SJonas Bonn
13329d02a428SJonas Bonn/* ==============================================[ boot tlb handlers ]=== */
13339d02a428SJonas Bonn
13349d02a428SJonas Bonn
13359d02a428SJonas Bonn/* =================================================[ debugging aids ]=== */
13369d02a428SJonas Bonn
1337e449759cSStafford Horne/*
1338e449759cSStafford Horne * DESC: Prints ASCII character stored in r7
13399d02a428SJonas Bonn *
1340e449759cSStafford Horne * PRMS: r7	- a 32-bit value with an ASCII character in the first byte
1341e449759cSStafford Horne *		position.
13429d02a428SJonas Bonn *
1343e449759cSStafford Horne * PREQ: The UART at UART_BASE_ADD has to be initialized
1344e449759cSStafford Horne *
1345e449759cSStafford Horne * POST: internally used but restores:
1346e449759cSStafford Horne * 	 r4	- to store UART_BASE_ADD
1347e449759cSStafford Horne *	 r5	- for loading OFF_TXFULL / THRE,TEMT
1348e449759cSStafford Horne *	 r6	- for storing bitmask (SERIAL_8250)
13499d02a428SJonas Bonn */
1350e449759cSStafford HorneENTRY(_emergency_putc)
1351e449759cSStafford Horne	EMERGENCY_PRINT_STORE_GPR4
1352e449759cSStafford Horne	EMERGENCY_PRINT_STORE_GPR5
1353e449759cSStafford Horne	EMERGENCY_PRINT_STORE_GPR6
13549d02a428SJonas Bonn
1355e449759cSStafford Horne	l.movhi r4,hi(UART_BASE_ADD)
1356e449759cSStafford Horne	l.ori	r4,r4,lo(UART_BASE_ADD)
13579d02a428SJonas Bonn
135829bbb2a9SStafford Horne#if defined(CONFIG_SERIAL_LITEUART)
135929bbb2a9SStafford Horne	/* Check OFF_TXFULL status */
136029bbb2a9SStafford Horne1:      l.lwz	r5,4(r4)
136129bbb2a9SStafford Horne	l.andi	r5,r5,0xff
136229bbb2a9SStafford Horne	l.sfnei	r5,0
136329bbb2a9SStafford Horne	l.bf	1b
13649d02a428SJonas Bonn	 l.nop
13659d02a428SJonas Bonn
136629bbb2a9SStafford Horne	/* Write character */
136729bbb2a9SStafford Horne	l.andi	r7,r7,0xff
136829bbb2a9SStafford Horne	l.sw	0(r4),r7
136929bbb2a9SStafford Horne#elif defined(CONFIG_SERIAL_8250)
1370e449759cSStafford Horne	/* Check UART LSR THRE (hold) bit */
1371e449759cSStafford Horne	l.addi  r6,r0,0x20
1372e449759cSStafford Horne1:      l.lbz   r5,5(r4)
1373e449759cSStafford Horne	l.andi  r5,r5,0x20
1374e449759cSStafford Horne	l.sfeq  r5,r6
1375e449759cSStafford Horne	l.bnf   1b
1376e449759cSStafford Horne	 l.nop
13779d02a428SJonas Bonn
1378e449759cSStafford Horne	/* Write character */
1379e449759cSStafford Horne	l.sb    0(r4),r7
13809d02a428SJonas Bonn
1381e449759cSStafford Horne	/* Check UART LSR THRE|TEMT (hold, empty) bits */
1382e449759cSStafford Horne	l.addi  r6,r0,0x60
1383e449759cSStafford Horne1:      l.lbz   r5,5(r4)
1384e449759cSStafford Horne	l.andi  r5,r5,0x60
1385e449759cSStafford Horne	l.sfeq  r5,r6
1386e449759cSStafford Horne	l.bnf   1b
1387e449759cSStafford Horne	 l.nop
1388e449759cSStafford Horne#endif
1389e449759cSStafford Horne	EMERGENCY_PRINT_LOAD_GPR6
1390e449759cSStafford Horne	EMERGENCY_PRINT_LOAD_GPR5
1391e449759cSStafford Horne	EMERGENCY_PRINT_LOAD_GPR4
13929d02a428SJonas Bonn	l.jr	r9
13939d02a428SJonas Bonn	 l.nop
13949d02a428SJonas Bonn
13959d02a428SJonas Bonn/*
13969d02a428SJonas Bonn * DSCR: prints a string referenced by r3.
13979d02a428SJonas Bonn *
13989d02a428SJonas Bonn * PRMS: r3     	- address of the first character of null
13999d02a428SJonas Bonn *			terminated string to be printed
14009d02a428SJonas Bonn *
14019d02a428SJonas Bonn * PREQ: UART at UART_BASE_ADD has to be initialized
14029d02a428SJonas Bonn *
14039d02a428SJonas Bonn * POST: caller should be aware that r3, r9 are changed
14049d02a428SJonas Bonn */
14059d02a428SJonas BonnENTRY(_emergency_print)
14069d02a428SJonas Bonn	EMERGENCY_PRINT_STORE_GPR7
1407e449759cSStafford Horne	EMERGENCY_PRINT_STORE_GPR9
1408e449759cSStafford Horne
1409e449759cSStafford Horne	/* Load character to r7, check for null terminator */
1410e449759cSStafford Horne2:	l.lbz	r7,0(r3)
1411e449759cSStafford Horne	l.sfeqi	r7,0x0
14129d02a428SJonas Bonn	l.bf	9f
14139d02a428SJonas Bonn	 l.nop
14149d02a428SJonas Bonn
1415e449759cSStafford Horne	l.jal	_emergency_putc
14169d02a428SJonas Bonn	 l.nop
14179d02a428SJonas Bonn
14189d02a428SJonas Bonn	/* next character */
14199d02a428SJonas Bonn	l.j	2b
14209d02a428SJonas Bonn	 l.addi	r3,r3,0x1
14219d02a428SJonas Bonn
14229d02a428SJonas Bonn9:
1423e449759cSStafford Horne	EMERGENCY_PRINT_LOAD_GPR9
14249d02a428SJonas Bonn	EMERGENCY_PRINT_LOAD_GPR7
14259d02a428SJonas Bonn	l.jr	r9
14269d02a428SJonas Bonn	 l.nop
14279d02a428SJonas Bonn
1428e449759cSStafford Horne/*
1429e449759cSStafford Horne * DSCR: prints a number in r3 in hex.
1430e449759cSStafford Horne *
1431e449759cSStafford Horne * PRMS: r3     	- a 32-bit unsigned integer
1432e449759cSStafford Horne *
1433e449759cSStafford Horne * PREQ: UART at UART_BASE_ADD has to be initialized
1434e449759cSStafford Horne *
1435e449759cSStafford Horne * POST: caller should be aware that r3, r9 are changed
1436e449759cSStafford Horne */
14379d02a428SJonas BonnENTRY(_emergency_print_nr)
14389d02a428SJonas Bonn	EMERGENCY_PRINT_STORE_GPR7
14399d02a428SJonas Bonn	EMERGENCY_PRINT_STORE_GPR8
1440e449759cSStafford Horne	EMERGENCY_PRINT_STORE_GPR9
14419d02a428SJonas Bonn
14429d02a428SJonas Bonn	l.addi	r8,r0,32		// shift register
14439d02a428SJonas Bonn
14449d02a428SJonas Bonn1:	/* remove leading zeros */
14459d02a428SJonas Bonn	l.addi	r8,r8,-0x4
14469d02a428SJonas Bonn	l.srl	r7,r3,r8
14479d02a428SJonas Bonn	l.andi	r7,r7,0xf
14489d02a428SJonas Bonn
14499d02a428SJonas Bonn	/* don't skip the last zero if number == 0x0 */
14509d02a428SJonas Bonn	l.sfeqi	r8,0x4
14519d02a428SJonas Bonn	l.bf	2f
14529d02a428SJonas Bonn	 l.nop
14539d02a428SJonas Bonn
14549d02a428SJonas Bonn	l.sfeq	r7,r0
14559d02a428SJonas Bonn	l.bf	1b
14569d02a428SJonas Bonn	 l.nop
14579d02a428SJonas Bonn
14589d02a428SJonas Bonn2:
14599d02a428SJonas Bonn	l.srl	r7,r3,r8
14609d02a428SJonas Bonn
14619d02a428SJonas Bonn	l.andi	r7,r7,0xf
14629d02a428SJonas Bonn	l.sflts	r8,r0
14639d02a428SJonas Bonn	 l.bf	9f
14649d02a428SJonas Bonn
1465e449759cSStafford Horne	/* Numbers greater than 9 translate to a-f */
14669d02a428SJonas Bonn	l.sfgtui r7,0x9
14679d02a428SJonas Bonn	l.bnf	8f
14689d02a428SJonas Bonn	 l.nop
14699d02a428SJonas Bonn	l.addi	r7,r7,0x27
14709d02a428SJonas Bonn
1471e449759cSStafford Horne	/* Convert to ascii and output character */
1472e449759cSStafford Horne8:	l.jal	_emergency_putc
14739d02a428SJonas Bonn	 l.addi	r7,r7,0x30
14749d02a428SJonas Bonn
14759d02a428SJonas Bonn	/* next character */
14769d02a428SJonas Bonn	l.j	2b
14779d02a428SJonas Bonn	l.addi	r8,r8,-0x4
14789d02a428SJonas Bonn
14799d02a428SJonas Bonn9:
1480e449759cSStafford Horne	EMERGENCY_PRINT_LOAD_GPR9
14819d02a428SJonas Bonn	EMERGENCY_PRINT_LOAD_GPR8
14829d02a428SJonas Bonn	EMERGENCY_PRINT_LOAD_GPR7
14839d02a428SJonas Bonn	l.jr	r9
14849d02a428SJonas Bonn	 l.nop
14859d02a428SJonas Bonn
14869d02a428SJonas Bonn/*
14879d02a428SJonas Bonn * This should be used for debugging only.
14889d02a428SJonas Bonn * It messes up the Linux early serial output
14899d02a428SJonas Bonn * somehow, so use it sparingly and essentially
14909d02a428SJonas Bonn * only if you need to debug something that goes wrong
14919d02a428SJonas Bonn * before Linux gets the early serial going.
14929d02a428SJonas Bonn *
14939d02a428SJonas Bonn * Furthermore, you'll have to make sure you set the
14949d02a428SJonas Bonn * UART_DEVISOR correctly according to the system
14959d02a428SJonas Bonn * clock rate.
14969d02a428SJonas Bonn *
14979d02a428SJonas Bonn *
14989d02a428SJonas Bonn */
14999d02a428SJonas Bonn
15009d02a428SJonas Bonn
15019d02a428SJonas Bonn
15029d02a428SJonas Bonn#define SYS_CLK            20000000
15039d02a428SJonas Bonn//#define SYS_CLK            1843200
15049d02a428SJonas Bonn#define OR32_CONSOLE_BAUD  115200
15059d02a428SJonas Bonn#define UART_DIVISOR       SYS_CLK/(16*OR32_CONSOLE_BAUD)
15069d02a428SJonas Bonn
15079d02a428SJonas BonnENTRY(_early_uart_init)
15089d02a428SJonas Bonn	l.movhi	r3,hi(UART_BASE_ADD)
1509e449759cSStafford Horne	l.ori	r3,r3,lo(UART_BASE_ADD)
15109d02a428SJonas Bonn
1511e449759cSStafford Horne#if defined(CONFIG_SERIAL_8250)
15129d02a428SJonas Bonn	l.addi	r4,r0,0x7
15139d02a428SJonas Bonn	l.sb	0x2(r3),r4
15149d02a428SJonas Bonn
15159d02a428SJonas Bonn	l.addi	r4,r0,0x0
15169d02a428SJonas Bonn	l.sb	0x1(r3),r4
15179d02a428SJonas Bonn
15189d02a428SJonas Bonn	l.addi	r4,r0,0x3
15199d02a428SJonas Bonn	l.sb	0x3(r3),r4
15209d02a428SJonas Bonn
15219d02a428SJonas Bonn	l.lbz	r5,3(r3)
15229d02a428SJonas Bonn	l.ori	r4,r5,0x80
15239d02a428SJonas Bonn	l.sb	0x3(r3),r4
15249d02a428SJonas Bonn	l.addi	r4,r0,((UART_DIVISOR>>8) & 0x000000ff)
15259d02a428SJonas Bonn	l.sb	UART_DLM(r3),r4
15269d02a428SJonas Bonn	l.addi  r4,r0,((UART_DIVISOR) & 0x000000ff)
15279d02a428SJonas Bonn	l.sb	UART_DLL(r3),r4
15289d02a428SJonas Bonn	l.sb	0x3(r3),r5
1529e449759cSStafford Horne#endif
15309d02a428SJonas Bonn
15319d02a428SJonas Bonn	l.jr	r9
15329d02a428SJonas Bonn	 l.nop
15339d02a428SJonas Bonn
1534c0567184SStafford Horne	.align	0x1000
1535c0567184SStafford Horne	.global _secondary_evbar
1536c0567184SStafford Horne_secondary_evbar:
1537c0567184SStafford Horne
1538c0567184SStafford Horne	.space 0x800
1539c0567184SStafford Horne	/* Just disable interrupts and Return */
1540c0567184SStafford Horne	l.ori	r3,r0,SPR_SR_SM
1541c0567184SStafford Horne	l.mtspr	r0,r3,SPR_ESR_BASE
1542c0567184SStafford Horne	l.rfe
1543c0567184SStafford Horne
1544c0567184SStafford Horne
1545da99f00eSStafford Horne	.section .rodata
15469d02a428SJonas Bonn_string_unhandled_exception:
1547e449759cSStafford Horne	.string "\r\nRunarunaround: Unhandled exception 0x\0"
15489d02a428SJonas Bonn
15499d02a428SJonas Bonn_string_epc_prefix:
15509d02a428SJonas Bonn	.string ": EPC=0x\0"
15519d02a428SJonas Bonn
15529d02a428SJonas Bonn_string_nl:
1553e449759cSStafford Horne	.string "\r\n\0"
15549d02a428SJonas Bonn
15559d02a428SJonas Bonn
15569d02a428SJonas Bonn/* ========================================[ page aligned structures ]=== */
15579d02a428SJonas Bonn
15589d02a428SJonas Bonn/*
15599d02a428SJonas Bonn * .data section should be page aligned
156057ce8ba0SGeert Uytterhoeven *	(look into arch/openrisc/kernel/vmlinux.lds.S)
15619d02a428SJonas Bonn */
15629d02a428SJonas Bonn	.section .data,"aw"
15639d02a428SJonas Bonn	.align	8192
15649d02a428SJonas Bonn	.global  empty_zero_page
15659d02a428SJonas Bonnempty_zero_page:
15669d02a428SJonas Bonn	.space  8192
15679d02a428SJonas Bonn
15689d02a428SJonas Bonn	.global  swapper_pg_dir
15699d02a428SJonas Bonnswapper_pg_dir:
15709d02a428SJonas Bonn	.space  8192
15719d02a428SJonas Bonn
15729d02a428SJonas Bonn	.global	_unhandled_stack
15739d02a428SJonas Bonn_unhandled_stack:
15749d02a428SJonas Bonn	.space	8192
15759d02a428SJonas Bonn_unhandled_stack_top:
15769d02a428SJonas Bonn
15779d02a428SJonas Bonn/* ============================================================[ EOF ]=== */
1578