18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * OpenRISC head.S
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Linux architectural port borrowing liberally from similar works of
68c2ecf20Sopenharmony_ci * others.  All original copyrights apply as per the original source
78c2ecf20Sopenharmony_ci * declaration.
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Modifications for the OpenRISC architecture:
108c2ecf20Sopenharmony_ci * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
118c2ecf20Sopenharmony_ci * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <linux/linkage.h>
158c2ecf20Sopenharmony_ci#include <linux/threads.h>
168c2ecf20Sopenharmony_ci#include <linux/errno.h>
178c2ecf20Sopenharmony_ci#include <linux/init.h>
188c2ecf20Sopenharmony_ci#include <linux/serial_reg.h>
198c2ecf20Sopenharmony_ci#include <linux/pgtable.h>
208c2ecf20Sopenharmony_ci#include <asm/processor.h>
218c2ecf20Sopenharmony_ci#include <asm/page.h>
228c2ecf20Sopenharmony_ci#include <asm/mmu.h>
238c2ecf20Sopenharmony_ci#include <asm/thread_info.h>
248c2ecf20Sopenharmony_ci#include <asm/cache.h>
258c2ecf20Sopenharmony_ci#include <asm/spr_defs.h>
268c2ecf20Sopenharmony_ci#include <asm/asm-offsets.h>
278c2ecf20Sopenharmony_ci#include <linux/of_fdt.h>
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#define tophys(rd,rs)				\
308c2ecf20Sopenharmony_ci	l.movhi	rd,hi(-KERNELBASE)		;\
318c2ecf20Sopenharmony_ci	l.add	rd,rd,rs
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#define CLEAR_GPR(gpr)				\
348c2ecf20Sopenharmony_ci	l.movhi	gpr,0x0
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#define LOAD_SYMBOL_2_GPR(gpr,symbol)		\
378c2ecf20Sopenharmony_ci	l.movhi gpr,hi(symbol)			;\
388c2ecf20Sopenharmony_ci	l.ori   gpr,gpr,lo(symbol)
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#define UART_BASE_ADD      0x90000000
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#define EXCEPTION_SR  (SPR_SR_DME | SPR_SR_IME | SPR_SR_DCE | SPR_SR_ICE | SPR_SR_SM)
448c2ecf20Sopenharmony_ci#define SYSCALL_SR  (SPR_SR_DME | SPR_SR_IME | SPR_SR_DCE | SPR_SR_ICE | SPR_SR_IEE | SPR_SR_TEE | SPR_SR_SM)
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci/* ============================================[ tmp store locations ]=== */
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci#define SPR_SHADOW_GPR(x)	((x) + SPR_GPR_BASE + 32)
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci/*
518c2ecf20Sopenharmony_ci * emergency_print temporary stores
528c2ecf20Sopenharmony_ci */
538c2ecf20Sopenharmony_ci#ifdef CONFIG_OPENRISC_HAVE_SHADOW_GPRS
548c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_STORE_GPR4	l.mtspr r0,r4,SPR_SHADOW_GPR(14)
558c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_LOAD_GPR4	l.mfspr r4,r0,SPR_SHADOW_GPR(14)
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_STORE_GPR5	l.mtspr r0,r5,SPR_SHADOW_GPR(15)
588c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_LOAD_GPR5	l.mfspr r5,r0,SPR_SHADOW_GPR(15)
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_STORE_GPR6	l.mtspr r0,r6,SPR_SHADOW_GPR(16)
618c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_LOAD_GPR6	l.mfspr r6,r0,SPR_SHADOW_GPR(16)
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_STORE_GPR7	l.mtspr r0,r7,SPR_SHADOW_GPR(7)
648c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_LOAD_GPR7	l.mfspr r7,r0,SPR_SHADOW_GPR(7)
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_STORE_GPR8	l.mtspr r0,r8,SPR_SHADOW_GPR(8)
678c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_LOAD_GPR8	l.mfspr r8,r0,SPR_SHADOW_GPR(8)
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_STORE_GPR9	l.mtspr r0,r9,SPR_SHADOW_GPR(9)
708c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_LOAD_GPR9	l.mfspr r9,r0,SPR_SHADOW_GPR(9)
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci#else /* !CONFIG_OPENRISC_HAVE_SHADOW_GPRS */
738c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_STORE_GPR4	l.sw    0x20(r0),r4
748c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_LOAD_GPR4	l.lwz   r4,0x20(r0)
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_STORE_GPR5	l.sw    0x24(r0),r5
778c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_LOAD_GPR5	l.lwz   r5,0x24(r0)
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_STORE_GPR6	l.sw    0x28(r0),r6
808c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_LOAD_GPR6	l.lwz   r6,0x28(r0)
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_STORE_GPR7	l.sw    0x2c(r0),r7
838c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_LOAD_GPR7	l.lwz   r7,0x2c(r0)
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_STORE_GPR8	l.sw    0x30(r0),r8
868c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_LOAD_GPR8	l.lwz   r8,0x30(r0)
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_STORE_GPR9	l.sw    0x34(r0),r9
898c2ecf20Sopenharmony_ci#define EMERGENCY_PRINT_LOAD_GPR9	l.lwz   r9,0x34(r0)
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci#endif
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci/*
948c2ecf20Sopenharmony_ci * TLB miss handlers temorary stores
958c2ecf20Sopenharmony_ci */
968c2ecf20Sopenharmony_ci#ifdef CONFIG_OPENRISC_HAVE_SHADOW_GPRS
978c2ecf20Sopenharmony_ci#define EXCEPTION_STORE_GPR2		l.mtspr r0,r2,SPR_SHADOW_GPR(2)
988c2ecf20Sopenharmony_ci#define EXCEPTION_LOAD_GPR2		l.mfspr r2,r0,SPR_SHADOW_GPR(2)
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci#define EXCEPTION_STORE_GPR3		l.mtspr r0,r3,SPR_SHADOW_GPR(3)
1018c2ecf20Sopenharmony_ci#define EXCEPTION_LOAD_GPR3		l.mfspr r3,r0,SPR_SHADOW_GPR(3)
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci#define EXCEPTION_STORE_GPR4		l.mtspr r0,r4,SPR_SHADOW_GPR(4)
1048c2ecf20Sopenharmony_ci#define EXCEPTION_LOAD_GPR4		l.mfspr r4,r0,SPR_SHADOW_GPR(4)
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci#define EXCEPTION_STORE_GPR5		l.mtspr r0,r5,SPR_SHADOW_GPR(5)
1078c2ecf20Sopenharmony_ci#define EXCEPTION_LOAD_GPR5		l.mfspr r5,r0,SPR_SHADOW_GPR(5)
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci#define EXCEPTION_STORE_GPR6		l.mtspr r0,r6,SPR_SHADOW_GPR(6)
1108c2ecf20Sopenharmony_ci#define EXCEPTION_LOAD_GPR6		l.mfspr r6,r0,SPR_SHADOW_GPR(6)
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci#else /* !CONFIG_OPENRISC_HAVE_SHADOW_GPRS */
1138c2ecf20Sopenharmony_ci#define EXCEPTION_STORE_GPR2		l.sw    0x64(r0),r2
1148c2ecf20Sopenharmony_ci#define EXCEPTION_LOAD_GPR2		l.lwz   r2,0x64(r0)
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci#define EXCEPTION_STORE_GPR3		l.sw    0x68(r0),r3
1178c2ecf20Sopenharmony_ci#define EXCEPTION_LOAD_GPR3		l.lwz   r3,0x68(r0)
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci#define EXCEPTION_STORE_GPR4		l.sw    0x6c(r0),r4
1208c2ecf20Sopenharmony_ci#define EXCEPTION_LOAD_GPR4		l.lwz   r4,0x6c(r0)
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci#define EXCEPTION_STORE_GPR5		l.sw    0x70(r0),r5
1238c2ecf20Sopenharmony_ci#define EXCEPTION_LOAD_GPR5		l.lwz   r5,0x70(r0)
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci#define EXCEPTION_STORE_GPR6		l.sw    0x74(r0),r6
1268c2ecf20Sopenharmony_ci#define EXCEPTION_LOAD_GPR6		l.lwz   r6,0x74(r0)
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci#endif
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci/*
1318c2ecf20Sopenharmony_ci * EXCEPTION_HANDLE temporary stores
1328c2ecf20Sopenharmony_ci */
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci#ifdef CONFIG_OPENRISC_HAVE_SHADOW_GPRS
1358c2ecf20Sopenharmony_ci#define EXCEPTION_T_STORE_GPR30		l.mtspr r0,r30,SPR_SHADOW_GPR(30)
1368c2ecf20Sopenharmony_ci#define EXCEPTION_T_LOAD_GPR30(reg)	l.mfspr reg,r0,SPR_SHADOW_GPR(30)
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci#define EXCEPTION_T_STORE_GPR10		l.mtspr r0,r10,SPR_SHADOW_GPR(10)
1398c2ecf20Sopenharmony_ci#define EXCEPTION_T_LOAD_GPR10(reg)	l.mfspr reg,r0,SPR_SHADOW_GPR(10)
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci#define EXCEPTION_T_STORE_SP		l.mtspr r0,r1,SPR_SHADOW_GPR(1)
1428c2ecf20Sopenharmony_ci#define EXCEPTION_T_LOAD_SP(reg)	l.mfspr reg,r0,SPR_SHADOW_GPR(1)
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci#else /* !CONFIG_OPENRISC_HAVE_SHADOW_GPRS */
1458c2ecf20Sopenharmony_ci#define EXCEPTION_T_STORE_GPR30		l.sw    0x78(r0),r30
1468c2ecf20Sopenharmony_ci#define EXCEPTION_T_LOAD_GPR30(reg)	l.lwz   reg,0x78(r0)
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci#define EXCEPTION_T_STORE_GPR10		l.sw    0x7c(r0),r10
1498c2ecf20Sopenharmony_ci#define EXCEPTION_T_LOAD_GPR10(reg)	l.lwz   reg,0x7c(r0)
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci#define EXCEPTION_T_STORE_SP		l.sw    0x80(r0),r1
1528c2ecf20Sopenharmony_ci#define EXCEPTION_T_LOAD_SP(reg)	l.lwz   reg,0x80(r0)
1538c2ecf20Sopenharmony_ci#endif
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci/* =========================================================[ macros ]=== */
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP
1588c2ecf20Sopenharmony_ci#define GET_CURRENT_PGD(reg,t1)					\
1598c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(reg,current_pgd)			;\
1608c2ecf20Sopenharmony_ci	l.mfspr	t1,r0,SPR_COREID				;\
1618c2ecf20Sopenharmony_ci	l.slli	t1,t1,2						;\
1628c2ecf20Sopenharmony_ci	l.add	reg,reg,t1					;\
1638c2ecf20Sopenharmony_ci	tophys  (t1,reg)					;\
1648c2ecf20Sopenharmony_ci	l.lwz   reg,0(t1)
1658c2ecf20Sopenharmony_ci#else
1668c2ecf20Sopenharmony_ci#define GET_CURRENT_PGD(reg,t1)					\
1678c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(reg,current_pgd)			;\
1688c2ecf20Sopenharmony_ci	tophys  (t1,reg)					;\
1698c2ecf20Sopenharmony_ci	l.lwz   reg,0(t1)
1708c2ecf20Sopenharmony_ci#endif
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci/* Load r10 from current_thread_info_set - clobbers r1 and r30 */
1738c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP
1748c2ecf20Sopenharmony_ci#define GET_CURRENT_THREAD_INFO					\
1758c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r1,current_thread_info_set)		;\
1768c2ecf20Sopenharmony_ci	tophys  (r30,r1)					;\
1778c2ecf20Sopenharmony_ci	l.mfspr	r10,r0,SPR_COREID				;\
1788c2ecf20Sopenharmony_ci	l.slli	r10,r10,2					;\
1798c2ecf20Sopenharmony_ci	l.add	r30,r30,r10					;\
1808c2ecf20Sopenharmony_ci	/* r10: current_thread_info  */				;\
1818c2ecf20Sopenharmony_ci	l.lwz   r10,0(r30)
1828c2ecf20Sopenharmony_ci#else
1838c2ecf20Sopenharmony_ci#define GET_CURRENT_THREAD_INFO					\
1848c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r1,current_thread_info_set)		;\
1858c2ecf20Sopenharmony_ci	tophys  (r30,r1)					;\
1868c2ecf20Sopenharmony_ci	/* r10: current_thread_info  */				;\
1878c2ecf20Sopenharmony_ci	l.lwz   r10,0(r30)
1888c2ecf20Sopenharmony_ci#endif
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci/*
1918c2ecf20Sopenharmony_ci * DSCR: this is a common hook for handling exceptions. it will save
1928c2ecf20Sopenharmony_ci *       the needed registers, set up stack and pointer to current
1938c2ecf20Sopenharmony_ci *	 then jump to the handler while enabling MMU
1948c2ecf20Sopenharmony_ci *
1958c2ecf20Sopenharmony_ci * PRMS: handler	- a function to jump to. it has to save the
1968c2ecf20Sopenharmony_ci *			remaining registers to kernel stack, call
1978c2ecf20Sopenharmony_ci *			appropriate arch-independant exception handler
1988c2ecf20Sopenharmony_ci *			and finaly jump to ret_from_except
1998c2ecf20Sopenharmony_ci *
2008c2ecf20Sopenharmony_ci * PREQ: unchanged state from the time exception happened
2018c2ecf20Sopenharmony_ci *
2028c2ecf20Sopenharmony_ci * POST: SAVED the following registers original value
2038c2ecf20Sopenharmony_ci *	       to the new created exception frame pointed to by r1
2048c2ecf20Sopenharmony_ci *
2058c2ecf20Sopenharmony_ci *	 r1  - ksp	pointing to the new (exception) frame
2068c2ecf20Sopenharmony_ci *	 r4  - EEAR     exception EA
2078c2ecf20Sopenharmony_ci *	 r10 - current	pointing to current_thread_info struct
2088c2ecf20Sopenharmony_ci *	 r12 - syscall  0, since we didn't come from syscall
2098c2ecf20Sopenharmony_ci *	 r30 - handler	address of the handler we'll jump to
2108c2ecf20Sopenharmony_ci *
2118c2ecf20Sopenharmony_ci *	 handler has to save remaining registers to the exception
2128c2ecf20Sopenharmony_ci *	 ksp frame *before* tainting them!
2138c2ecf20Sopenharmony_ci *
2148c2ecf20Sopenharmony_ci * NOTE: this function is not reentrant per se. reentrancy is guaranteed
2158c2ecf20Sopenharmony_ci *       by processor disabling all exceptions/interrupts when exception
2168c2ecf20Sopenharmony_ci *	 accours.
2178c2ecf20Sopenharmony_ci *
2188c2ecf20Sopenharmony_ci * OPTM: no need to make it so wasteful to extract ksp when in user mode
2198c2ecf20Sopenharmony_ci */
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci#define EXCEPTION_HANDLE(handler)				\
2228c2ecf20Sopenharmony_ci	EXCEPTION_T_STORE_GPR30					;\
2238c2ecf20Sopenharmony_ci	l.mfspr r30,r0,SPR_ESR_BASE				;\
2248c2ecf20Sopenharmony_ci	l.andi  r30,r30,SPR_SR_SM				;\
2258c2ecf20Sopenharmony_ci	l.sfeqi r30,0						;\
2268c2ecf20Sopenharmony_ci	EXCEPTION_T_STORE_GPR10					;\
2278c2ecf20Sopenharmony_ci	l.bnf   2f                            /* kernel_mode */	;\
2288c2ecf20Sopenharmony_ci	 EXCEPTION_T_STORE_SP                 /* delay slot */	;\
2298c2ecf20Sopenharmony_ci1: /* user_mode:   */						;\
2308c2ecf20Sopenharmony_ci	GET_CURRENT_THREAD_INFO	 				;\
2318c2ecf20Sopenharmony_ci	tophys  (r30,r10)					;\
2328c2ecf20Sopenharmony_ci	l.lwz   r1,(TI_KSP)(r30)				;\
2338c2ecf20Sopenharmony_ci	/* fall through */					;\
2348c2ecf20Sopenharmony_ci2: /* kernel_mode: */						;\
2358c2ecf20Sopenharmony_ci	/* create new stack frame, save only needed gprs */	;\
2368c2ecf20Sopenharmony_ci	/* r1: KSP, r10: current, r4: EEAR, r31: __pa(KSP) */	;\
2378c2ecf20Sopenharmony_ci	/* r12:	temp, syscall indicator */			;\
2388c2ecf20Sopenharmony_ci	l.addi  r1,r1,-(INT_FRAME_SIZE)				;\
2398c2ecf20Sopenharmony_ci	/* r1 is KSP, r30 is __pa(KSP) */			;\
2408c2ecf20Sopenharmony_ci	tophys  (r30,r1)					;\
2418c2ecf20Sopenharmony_ci	l.sw    PT_GPR12(r30),r12				;\
2428c2ecf20Sopenharmony_ci	/* r4 use for tmp before EA */				;\
2438c2ecf20Sopenharmony_ci	l.mfspr r12,r0,SPR_EPCR_BASE				;\
2448c2ecf20Sopenharmony_ci	l.sw    PT_PC(r30),r12					;\
2458c2ecf20Sopenharmony_ci	l.mfspr r12,r0,SPR_ESR_BASE				;\
2468c2ecf20Sopenharmony_ci	l.sw    PT_SR(r30),r12					;\
2478c2ecf20Sopenharmony_ci	/* save r30 */						;\
2488c2ecf20Sopenharmony_ci	EXCEPTION_T_LOAD_GPR30(r12)				;\
2498c2ecf20Sopenharmony_ci	l.sw	PT_GPR30(r30),r12				;\
2508c2ecf20Sopenharmony_ci	/* save r10 as was prior to exception */		;\
2518c2ecf20Sopenharmony_ci	EXCEPTION_T_LOAD_GPR10(r12)				;\
2528c2ecf20Sopenharmony_ci	l.sw	PT_GPR10(r30),r12				;\
2538c2ecf20Sopenharmony_ci	/* save PT_SP as was prior to exception */		;\
2548c2ecf20Sopenharmony_ci	EXCEPTION_T_LOAD_SP(r12)				;\
2558c2ecf20Sopenharmony_ci	l.sw	PT_SP(r30),r12					;\
2568c2ecf20Sopenharmony_ci	/* save exception r4, set r4 = EA */			;\
2578c2ecf20Sopenharmony_ci	l.sw	PT_GPR4(r30),r4					;\
2588c2ecf20Sopenharmony_ci	l.mfspr r4,r0,SPR_EEAR_BASE				;\
2598c2ecf20Sopenharmony_ci	/* r12 == 1 if we come from syscall */			;\
2608c2ecf20Sopenharmony_ci	CLEAR_GPR(r12)						;\
2618c2ecf20Sopenharmony_ci	/* ----- turn on MMU ----- */				;\
2628c2ecf20Sopenharmony_ci	/* Carry DSX into exception SR */			;\
2638c2ecf20Sopenharmony_ci	l.mfspr r30,r0,SPR_SR					;\
2648c2ecf20Sopenharmony_ci	l.andi	r30,r30,SPR_SR_DSX				;\
2658c2ecf20Sopenharmony_ci	l.ori	r30,r30,(EXCEPTION_SR)				;\
2668c2ecf20Sopenharmony_ci	l.mtspr	r0,r30,SPR_ESR_BASE				;\
2678c2ecf20Sopenharmony_ci	/* r30:	EA address of handler */			;\
2688c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r30,handler)				;\
2698c2ecf20Sopenharmony_ci	l.mtspr r0,r30,SPR_EPCR_BASE				;\
2708c2ecf20Sopenharmony_ci	l.rfe
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci/*
2738c2ecf20Sopenharmony_ci * this doesn't work
2748c2ecf20Sopenharmony_ci *
2758c2ecf20Sopenharmony_ci *
2768c2ecf20Sopenharmony_ci * #ifdef CONFIG_JUMP_UPON_UNHANDLED_EXCEPTION
2778c2ecf20Sopenharmony_ci * #define UNHANDLED_EXCEPTION(handler)				\
2788c2ecf20Sopenharmony_ci *	l.ori   r3,r0,0x1					;\
2798c2ecf20Sopenharmony_ci *	l.mtspr r0,r3,SPR_SR					;\
2808c2ecf20Sopenharmony_ci *      l.movhi r3,hi(0xf0000100)				;\
2818c2ecf20Sopenharmony_ci *      l.ori   r3,r3,lo(0xf0000100)				;\
2828c2ecf20Sopenharmony_ci *	l.jr	r3						;\
2838c2ecf20Sopenharmony_ci *	l.nop	1
2848c2ecf20Sopenharmony_ci *
2858c2ecf20Sopenharmony_ci * #endif
2868c2ecf20Sopenharmony_ci */
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci/* DSCR: this is the same as EXCEPTION_HANDLE(), we are just
2898c2ecf20Sopenharmony_ci *       a bit more carefull (if we have a PT_SP or current pointer
2908c2ecf20Sopenharmony_ci *       corruption) and set them up from 'current_set'
2918c2ecf20Sopenharmony_ci *
2928c2ecf20Sopenharmony_ci */
2938c2ecf20Sopenharmony_ci#define UNHANDLED_EXCEPTION(handler)				\
2948c2ecf20Sopenharmony_ci	EXCEPTION_T_STORE_GPR30					;\
2958c2ecf20Sopenharmony_ci	EXCEPTION_T_STORE_GPR10					;\
2968c2ecf20Sopenharmony_ci	EXCEPTION_T_STORE_SP					;\
2978c2ecf20Sopenharmony_ci	/* temporary store r3, r9 into r1, r10 */		;\
2988c2ecf20Sopenharmony_ci	l.addi	r1,r3,0x0					;\
2998c2ecf20Sopenharmony_ci	l.addi	r10,r9,0x0					;\
3008c2ecf20Sopenharmony_ci	/* the string referenced by r3 must be low enough */	;\
3018c2ecf20Sopenharmony_ci	l.jal	_emergency_print				;\
3028c2ecf20Sopenharmony_ci	l.ori	r3,r0,lo(_string_unhandled_exception)		;\
3038c2ecf20Sopenharmony_ci	l.mfspr	r3,r0,SPR_NPC					;\
3048c2ecf20Sopenharmony_ci	l.jal	_emergency_print_nr				;\
3058c2ecf20Sopenharmony_ci	l.andi	r3,r3,0x1f00					;\
3068c2ecf20Sopenharmony_ci	/* the string referenced by r3 must be low enough */	;\
3078c2ecf20Sopenharmony_ci	l.jal	_emergency_print				;\
3088c2ecf20Sopenharmony_ci	l.ori	r3,r0,lo(_string_epc_prefix)			;\
3098c2ecf20Sopenharmony_ci	l.jal	_emergency_print_nr				;\
3108c2ecf20Sopenharmony_ci	l.mfspr	r3,r0,SPR_EPCR_BASE				;\
3118c2ecf20Sopenharmony_ci	l.jal	_emergency_print				;\
3128c2ecf20Sopenharmony_ci	l.ori	r3,r0,lo(_string_nl)				;\
3138c2ecf20Sopenharmony_ci	/* end of printing */					;\
3148c2ecf20Sopenharmony_ci	l.addi	r3,r1,0x0					;\
3158c2ecf20Sopenharmony_ci	l.addi	r9,r10,0x0					;\
3168c2ecf20Sopenharmony_ci	/* extract current, ksp from current_set */		;\
3178c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r1,_unhandled_stack_top)		;\
3188c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r10,init_thread_union)		;\
3198c2ecf20Sopenharmony_ci	/* create new stack frame, save only needed gprs */	;\
3208c2ecf20Sopenharmony_ci	/* r1: KSP, r10: current, r31: __pa(KSP) */		;\
3218c2ecf20Sopenharmony_ci	/* r12:	temp, syscall indicator, r13 temp */		;\
3228c2ecf20Sopenharmony_ci	l.addi  r1,r1,-(INT_FRAME_SIZE)				;\
3238c2ecf20Sopenharmony_ci	/* r1 is KSP, r30 is __pa(KSP) */			;\
3248c2ecf20Sopenharmony_ci	tophys  (r30,r1)					;\
3258c2ecf20Sopenharmony_ci	l.sw    PT_GPR12(r30),r12					;\
3268c2ecf20Sopenharmony_ci	l.mfspr r12,r0,SPR_EPCR_BASE				;\
3278c2ecf20Sopenharmony_ci	l.sw    PT_PC(r30),r12					;\
3288c2ecf20Sopenharmony_ci	l.mfspr r12,r0,SPR_ESR_BASE				;\
3298c2ecf20Sopenharmony_ci	l.sw    PT_SR(r30),r12					;\
3308c2ecf20Sopenharmony_ci	/* save r31 */						;\
3318c2ecf20Sopenharmony_ci	EXCEPTION_T_LOAD_GPR30(r12)				;\
3328c2ecf20Sopenharmony_ci	l.sw	PT_GPR30(r30),r12					;\
3338c2ecf20Sopenharmony_ci	/* save r10 as was prior to exception */		;\
3348c2ecf20Sopenharmony_ci	EXCEPTION_T_LOAD_GPR10(r12)				;\
3358c2ecf20Sopenharmony_ci	l.sw	PT_GPR10(r30),r12					;\
3368c2ecf20Sopenharmony_ci	/* save PT_SP as was prior to exception */			;\
3378c2ecf20Sopenharmony_ci	EXCEPTION_T_LOAD_SP(r12)				;\
3388c2ecf20Sopenharmony_ci	l.sw	PT_SP(r30),r12					;\
3398c2ecf20Sopenharmony_ci	l.sw    PT_GPR13(r30),r13					;\
3408c2ecf20Sopenharmony_ci	/* --> */						;\
3418c2ecf20Sopenharmony_ci	/* save exception r4, set r4 = EA */			;\
3428c2ecf20Sopenharmony_ci	l.sw	PT_GPR4(r30),r4					;\
3438c2ecf20Sopenharmony_ci	l.mfspr r4,r0,SPR_EEAR_BASE				;\
3448c2ecf20Sopenharmony_ci	/* r12 == 1 if we come from syscall */			;\
3458c2ecf20Sopenharmony_ci	CLEAR_GPR(r12)						;\
3468c2ecf20Sopenharmony_ci	/* ----- play a MMU trick ----- */			;\
3478c2ecf20Sopenharmony_ci	l.ori	r30,r0,(EXCEPTION_SR)				;\
3488c2ecf20Sopenharmony_ci	l.mtspr	r0,r30,SPR_ESR_BASE				;\
3498c2ecf20Sopenharmony_ci	/* r31:	EA address of handler */			;\
3508c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r30,handler)				;\
3518c2ecf20Sopenharmony_ci	l.mtspr r0,r30,SPR_EPCR_BASE				;\
3528c2ecf20Sopenharmony_ci	l.rfe
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci/* =====================================================[ exceptions] === */
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci/* ---[ 0x100: RESET exception ]----------------------------------------- */
3578c2ecf20Sopenharmony_ci    .org 0x100
3588c2ecf20Sopenharmony_ci	/* Jump to .init code at _start which lives in the .head section
3598c2ecf20Sopenharmony_ci	 * and will be discarded after boot.
3608c2ecf20Sopenharmony_ci	 */
3618c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r15, _start)
3628c2ecf20Sopenharmony_ci	tophys	(r13,r15)			/* MMU disabled */
3638c2ecf20Sopenharmony_ci	l.jr	r13
3648c2ecf20Sopenharmony_ci	 l.nop
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci/* ---[ 0x200: BUS exception ]------------------------------------------- */
3678c2ecf20Sopenharmony_ci    .org 0x200
3688c2ecf20Sopenharmony_ci_dispatch_bus_fault:
3698c2ecf20Sopenharmony_ci	EXCEPTION_HANDLE(_bus_fault_handler)
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci/* ---[ 0x300: Data Page Fault exception ]------------------------------- */
3728c2ecf20Sopenharmony_ci    .org 0x300
3738c2ecf20Sopenharmony_ci_dispatch_do_dpage_fault:
3748c2ecf20Sopenharmony_ci//      totaly disable timer interrupt
3758c2ecf20Sopenharmony_ci// 	l.mtspr	r0,r0,SPR_TTMR
3768c2ecf20Sopenharmony_ci//	DEBUG_TLB_PROBE(0x300)
3778c2ecf20Sopenharmony_ci//	EXCEPTION_DEBUG_VALUE_ER_ENABLED(0x300)
3788c2ecf20Sopenharmony_ci	EXCEPTION_HANDLE(_data_page_fault_handler)
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci/* ---[ 0x400: Insn Page Fault exception ]------------------------------- */
3818c2ecf20Sopenharmony_ci    .org 0x400
3828c2ecf20Sopenharmony_ci_dispatch_do_ipage_fault:
3838c2ecf20Sopenharmony_ci//      totaly disable timer interrupt
3848c2ecf20Sopenharmony_ci//	l.mtspr	r0,r0,SPR_TTMR
3858c2ecf20Sopenharmony_ci//	DEBUG_TLB_PROBE(0x400)
3868c2ecf20Sopenharmony_ci//	EXCEPTION_DEBUG_VALUE_ER_ENABLED(0x400)
3878c2ecf20Sopenharmony_ci	EXCEPTION_HANDLE(_insn_page_fault_handler)
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci/* ---[ 0x500: Timer exception ]----------------------------------------- */
3908c2ecf20Sopenharmony_ci    .org 0x500
3918c2ecf20Sopenharmony_ci	EXCEPTION_HANDLE(_timer_handler)
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci/* ---[ 0x600: Alignment exception ]-------------------------------------- */
3948c2ecf20Sopenharmony_ci    .org 0x600
3958c2ecf20Sopenharmony_ci	EXCEPTION_HANDLE(_alignment_handler)
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci/* ---[ 0x700: Illegal insn exception ]---------------------------------- */
3988c2ecf20Sopenharmony_ci    .org 0x700
3998c2ecf20Sopenharmony_ci	EXCEPTION_HANDLE(_illegal_instruction_handler)
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci/* ---[ 0x800: External interrupt exception ]---------------------------- */
4028c2ecf20Sopenharmony_ci    .org 0x800
4038c2ecf20Sopenharmony_ci	EXCEPTION_HANDLE(_external_irq_handler)
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci/* ---[ 0x900: DTLB miss exception ]------------------------------------- */
4068c2ecf20Sopenharmony_ci    .org 0x900
4078c2ecf20Sopenharmony_ci	l.j	boot_dtlb_miss_handler
4088c2ecf20Sopenharmony_ci	l.nop
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci/* ---[ 0xa00: ITLB miss exception ]------------------------------------- */
4118c2ecf20Sopenharmony_ci    .org 0xa00
4128c2ecf20Sopenharmony_ci	l.j	boot_itlb_miss_handler
4138c2ecf20Sopenharmony_ci	l.nop
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci/* ---[ 0xb00: Range exception ]----------------------------------------- */
4168c2ecf20Sopenharmony_ci    .org 0xb00
4178c2ecf20Sopenharmony_ci	UNHANDLED_EXCEPTION(_vector_0xb00)
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci/* ---[ 0xc00: Syscall exception ]--------------------------------------- */
4208c2ecf20Sopenharmony_ci    .org 0xc00
4218c2ecf20Sopenharmony_ci	EXCEPTION_HANDLE(_sys_call_handler)
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci/* ---[ 0xd00: Trap exception ]------------------------------------------ */
4248c2ecf20Sopenharmony_ci    .org 0xd00
4258c2ecf20Sopenharmony_ci	UNHANDLED_EXCEPTION(_vector_0xd00)
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci/* ---[ 0xe00: Trap exception ]------------------------------------------ */
4288c2ecf20Sopenharmony_ci    .org 0xe00
4298c2ecf20Sopenharmony_ci//	UNHANDLED_EXCEPTION(_vector_0xe00)
4308c2ecf20Sopenharmony_ci	EXCEPTION_HANDLE(_trap_handler)
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci/* ---[ 0xf00: Reserved exception ]-------------------------------------- */
4338c2ecf20Sopenharmony_ci    .org 0xf00
4348c2ecf20Sopenharmony_ci	UNHANDLED_EXCEPTION(_vector_0xf00)
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci/* ---[ 0x1000: Reserved exception ]------------------------------------- */
4378c2ecf20Sopenharmony_ci    .org 0x1000
4388c2ecf20Sopenharmony_ci	UNHANDLED_EXCEPTION(_vector_0x1000)
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci/* ---[ 0x1100: Reserved exception ]------------------------------------- */
4418c2ecf20Sopenharmony_ci    .org 0x1100
4428c2ecf20Sopenharmony_ci	UNHANDLED_EXCEPTION(_vector_0x1100)
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci/* ---[ 0x1200: Reserved exception ]------------------------------------- */
4458c2ecf20Sopenharmony_ci    .org 0x1200
4468c2ecf20Sopenharmony_ci	UNHANDLED_EXCEPTION(_vector_0x1200)
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci/* ---[ 0x1300: Reserved exception ]------------------------------------- */
4498c2ecf20Sopenharmony_ci    .org 0x1300
4508c2ecf20Sopenharmony_ci	UNHANDLED_EXCEPTION(_vector_0x1300)
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci/* ---[ 0x1400: Reserved exception ]------------------------------------- */
4538c2ecf20Sopenharmony_ci    .org 0x1400
4548c2ecf20Sopenharmony_ci	UNHANDLED_EXCEPTION(_vector_0x1400)
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci/* ---[ 0x1500: Reserved exception ]------------------------------------- */
4578c2ecf20Sopenharmony_ci    .org 0x1500
4588c2ecf20Sopenharmony_ci	UNHANDLED_EXCEPTION(_vector_0x1500)
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci/* ---[ 0x1600: Reserved exception ]------------------------------------- */
4618c2ecf20Sopenharmony_ci    .org 0x1600
4628c2ecf20Sopenharmony_ci	UNHANDLED_EXCEPTION(_vector_0x1600)
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci/* ---[ 0x1700: Reserved exception ]------------------------------------- */
4658c2ecf20Sopenharmony_ci    .org 0x1700
4668c2ecf20Sopenharmony_ci	UNHANDLED_EXCEPTION(_vector_0x1700)
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci/* ---[ 0x1800: Reserved exception ]------------------------------------- */
4698c2ecf20Sopenharmony_ci    .org 0x1800
4708c2ecf20Sopenharmony_ci	UNHANDLED_EXCEPTION(_vector_0x1800)
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci/* ---[ 0x1900: Reserved exception ]------------------------------------- */
4738c2ecf20Sopenharmony_ci    .org 0x1900
4748c2ecf20Sopenharmony_ci	UNHANDLED_EXCEPTION(_vector_0x1900)
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ci/* ---[ 0x1a00: Reserved exception ]------------------------------------- */
4778c2ecf20Sopenharmony_ci    .org 0x1a00
4788c2ecf20Sopenharmony_ci	UNHANDLED_EXCEPTION(_vector_0x1a00)
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci/* ---[ 0x1b00: Reserved exception ]------------------------------------- */
4818c2ecf20Sopenharmony_ci    .org 0x1b00
4828c2ecf20Sopenharmony_ci	UNHANDLED_EXCEPTION(_vector_0x1b00)
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci/* ---[ 0x1c00: Reserved exception ]------------------------------------- */
4858c2ecf20Sopenharmony_ci    .org 0x1c00
4868c2ecf20Sopenharmony_ci	UNHANDLED_EXCEPTION(_vector_0x1c00)
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci/* ---[ 0x1d00: Reserved exception ]------------------------------------- */
4898c2ecf20Sopenharmony_ci    .org 0x1d00
4908c2ecf20Sopenharmony_ci	UNHANDLED_EXCEPTION(_vector_0x1d00)
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci/* ---[ 0x1e00: Reserved exception ]------------------------------------- */
4938c2ecf20Sopenharmony_ci    .org 0x1e00
4948c2ecf20Sopenharmony_ci	UNHANDLED_EXCEPTION(_vector_0x1e00)
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci/* ---[ 0x1f00: Reserved exception ]------------------------------------- */
4978c2ecf20Sopenharmony_ci    .org 0x1f00
4988c2ecf20Sopenharmony_ci	UNHANDLED_EXCEPTION(_vector_0x1f00)
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci    .org 0x2000
5018c2ecf20Sopenharmony_ci/* ===================================================[ kernel start ]=== */
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci/*    .text*/
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci/* This early stuff belongs in HEAD, but some of the functions below definitely
5068c2ecf20Sopenharmony_ci * don't... */
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	__HEAD
5098c2ecf20Sopenharmony_ci	.global _start
5108c2ecf20Sopenharmony_ci_start:
5118c2ecf20Sopenharmony_ci	/* Init r0 to zero as per spec */
5128c2ecf20Sopenharmony_ci	CLEAR_GPR(r0)
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	/* save kernel parameters */
5158c2ecf20Sopenharmony_ci	l.or	r25,r0,r3	/* pointer to fdt */
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	/*
5188c2ecf20Sopenharmony_ci	 * ensure a deterministic start
5198c2ecf20Sopenharmony_ci	 */
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	l.ori	r3,r0,0x1
5228c2ecf20Sopenharmony_ci	l.mtspr	r0,r3,SPR_SR
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	/*
5258c2ecf20Sopenharmony_ci	 * Start the TTCR as early as possible, so that the RNG can make use of
5268c2ecf20Sopenharmony_ci	 * measurements of boot time from the earliest opportunity. Especially
5278c2ecf20Sopenharmony_ci	 * important is that the TTCR does not return zero by the time we reach
5288c2ecf20Sopenharmony_ci	 * rand_initialize().
5298c2ecf20Sopenharmony_ci	 */
5308c2ecf20Sopenharmony_ci	l.movhi r3,hi(SPR_TTMR_CR)
5318c2ecf20Sopenharmony_ci	l.mtspr r0,r3,SPR_TTMR
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci	CLEAR_GPR(r1)
5348c2ecf20Sopenharmony_ci	CLEAR_GPR(r2)
5358c2ecf20Sopenharmony_ci	CLEAR_GPR(r3)
5368c2ecf20Sopenharmony_ci	CLEAR_GPR(r4)
5378c2ecf20Sopenharmony_ci	CLEAR_GPR(r5)
5388c2ecf20Sopenharmony_ci	CLEAR_GPR(r6)
5398c2ecf20Sopenharmony_ci	CLEAR_GPR(r7)
5408c2ecf20Sopenharmony_ci	CLEAR_GPR(r8)
5418c2ecf20Sopenharmony_ci	CLEAR_GPR(r9)
5428c2ecf20Sopenharmony_ci	CLEAR_GPR(r10)
5438c2ecf20Sopenharmony_ci	CLEAR_GPR(r11)
5448c2ecf20Sopenharmony_ci	CLEAR_GPR(r12)
5458c2ecf20Sopenharmony_ci	CLEAR_GPR(r13)
5468c2ecf20Sopenharmony_ci	CLEAR_GPR(r14)
5478c2ecf20Sopenharmony_ci	CLEAR_GPR(r15)
5488c2ecf20Sopenharmony_ci	CLEAR_GPR(r16)
5498c2ecf20Sopenharmony_ci	CLEAR_GPR(r17)
5508c2ecf20Sopenharmony_ci	CLEAR_GPR(r18)
5518c2ecf20Sopenharmony_ci	CLEAR_GPR(r19)
5528c2ecf20Sopenharmony_ci	CLEAR_GPR(r20)
5538c2ecf20Sopenharmony_ci	CLEAR_GPR(r21)
5548c2ecf20Sopenharmony_ci	CLEAR_GPR(r22)
5558c2ecf20Sopenharmony_ci	CLEAR_GPR(r23)
5568c2ecf20Sopenharmony_ci	CLEAR_GPR(r24)
5578c2ecf20Sopenharmony_ci	CLEAR_GPR(r26)
5588c2ecf20Sopenharmony_ci	CLEAR_GPR(r27)
5598c2ecf20Sopenharmony_ci	CLEAR_GPR(r28)
5608c2ecf20Sopenharmony_ci	CLEAR_GPR(r29)
5618c2ecf20Sopenharmony_ci	CLEAR_GPR(r30)
5628c2ecf20Sopenharmony_ci	CLEAR_GPR(r31)
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP
5658c2ecf20Sopenharmony_ci	l.mfspr	r26,r0,SPR_COREID
5668c2ecf20Sopenharmony_ci	l.sfeq	r26,r0
5678c2ecf20Sopenharmony_ci	l.bnf	secondary_wait
5688c2ecf20Sopenharmony_ci	 l.nop
5698c2ecf20Sopenharmony_ci#endif
5708c2ecf20Sopenharmony_ci	/*
5718c2ecf20Sopenharmony_ci	 * set up initial ksp and current
5728c2ecf20Sopenharmony_ci	 */
5738c2ecf20Sopenharmony_ci	/* setup kernel stack */
5748c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r1,init_thread_union + THREAD_SIZE)
5758c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r10,init_thread_union)	// setup current
5768c2ecf20Sopenharmony_ci	tophys	(r31,r10)
5778c2ecf20Sopenharmony_ci	l.sw	TI_KSP(r31), r1
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	l.ori	r4,r0,0x0
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci	/*
5838c2ecf20Sopenharmony_ci	 * .data contains initialized data,
5848c2ecf20Sopenharmony_ci	 * .bss contains uninitialized data - clear it up
5858c2ecf20Sopenharmony_ci	 */
5868c2ecf20Sopenharmony_ciclear_bss:
5878c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r24, __bss_start)
5888c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r26, _end)
5898c2ecf20Sopenharmony_ci	tophys(r28,r24)
5908c2ecf20Sopenharmony_ci	tophys(r30,r26)
5918c2ecf20Sopenharmony_ci	CLEAR_GPR(r24)
5928c2ecf20Sopenharmony_ci	CLEAR_GPR(r26)
5938c2ecf20Sopenharmony_ci1:
5948c2ecf20Sopenharmony_ci	l.sw    (0)(r28),r0
5958c2ecf20Sopenharmony_ci	l.sfltu r28,r30
5968c2ecf20Sopenharmony_ci	l.bf    1b
5978c2ecf20Sopenharmony_ci	l.addi  r28,r28,4
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_cienable_ic:
6008c2ecf20Sopenharmony_ci	l.jal	_ic_enable
6018c2ecf20Sopenharmony_ci	 l.nop
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_cienable_dc:
6048c2ecf20Sopenharmony_ci	l.jal	_dc_enable
6058c2ecf20Sopenharmony_ci	 l.nop
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ciflush_tlb:
6088c2ecf20Sopenharmony_ci	l.jal	_flush_tlb
6098c2ecf20Sopenharmony_ci	 l.nop
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci/* The MMU needs to be enabled before or32_early_setup is called */
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_cienable_mmu:
6148c2ecf20Sopenharmony_ci	/*
6158c2ecf20Sopenharmony_ci	 * enable dmmu & immu
6168c2ecf20Sopenharmony_ci	 * SR[5] = 0, SR[6] = 0, 6th and 7th bit of SR set to 0
6178c2ecf20Sopenharmony_ci	 */
6188c2ecf20Sopenharmony_ci	l.mfspr	r30,r0,SPR_SR
6198c2ecf20Sopenharmony_ci	l.movhi	r28,hi(SPR_SR_DME | SPR_SR_IME)
6208c2ecf20Sopenharmony_ci	l.ori	r28,r28,lo(SPR_SR_DME | SPR_SR_IME)
6218c2ecf20Sopenharmony_ci	l.or	r30,r30,r28
6228c2ecf20Sopenharmony_ci	l.mtspr	r0,r30,SPR_SR
6238c2ecf20Sopenharmony_ci	l.nop
6248c2ecf20Sopenharmony_ci	l.nop
6258c2ecf20Sopenharmony_ci	l.nop
6268c2ecf20Sopenharmony_ci	l.nop
6278c2ecf20Sopenharmony_ci	l.nop
6288c2ecf20Sopenharmony_ci	l.nop
6298c2ecf20Sopenharmony_ci	l.nop
6308c2ecf20Sopenharmony_ci	l.nop
6318c2ecf20Sopenharmony_ci	l.nop
6328c2ecf20Sopenharmony_ci	l.nop
6338c2ecf20Sopenharmony_ci	l.nop
6348c2ecf20Sopenharmony_ci	l.nop
6358c2ecf20Sopenharmony_ci	l.nop
6368c2ecf20Sopenharmony_ci	l.nop
6378c2ecf20Sopenharmony_ci	l.nop
6388c2ecf20Sopenharmony_ci	l.nop
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci	// reset the simulation counters
6418c2ecf20Sopenharmony_ci	l.nop 5
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci	/* check fdt header magic word */
6448c2ecf20Sopenharmony_ci	l.lwz	r3,0(r25)	/* load magic from fdt into r3 */
6458c2ecf20Sopenharmony_ci	l.movhi	r4,hi(OF_DT_HEADER)
6468c2ecf20Sopenharmony_ci	l.ori	r4,r4,lo(OF_DT_HEADER)
6478c2ecf20Sopenharmony_ci	l.sfeq	r3,r4
6488c2ecf20Sopenharmony_ci	l.bf	_fdt_found
6498c2ecf20Sopenharmony_ci	 l.nop
6508c2ecf20Sopenharmony_ci	/* magic number mismatch, set fdt pointer to null */
6518c2ecf20Sopenharmony_ci	l.or	r25,r0,r0
6528c2ecf20Sopenharmony_ci_fdt_found:
6538c2ecf20Sopenharmony_ci	/* pass fdt pointer to or32_early_setup in r3 */
6548c2ecf20Sopenharmony_ci	l.or	r3,r0,r25
6558c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r24, or32_early_setup)
6568c2ecf20Sopenharmony_ci	l.jalr r24
6578c2ecf20Sopenharmony_ci	 l.nop
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ciclear_regs:
6608c2ecf20Sopenharmony_ci	/*
6618c2ecf20Sopenharmony_ci	 * clear all GPRS to increase determinism
6628c2ecf20Sopenharmony_ci	 */
6638c2ecf20Sopenharmony_ci	CLEAR_GPR(r2)
6648c2ecf20Sopenharmony_ci	CLEAR_GPR(r3)
6658c2ecf20Sopenharmony_ci	CLEAR_GPR(r4)
6668c2ecf20Sopenharmony_ci	CLEAR_GPR(r5)
6678c2ecf20Sopenharmony_ci	CLEAR_GPR(r6)
6688c2ecf20Sopenharmony_ci	CLEAR_GPR(r7)
6698c2ecf20Sopenharmony_ci	CLEAR_GPR(r8)
6708c2ecf20Sopenharmony_ci	CLEAR_GPR(r9)
6718c2ecf20Sopenharmony_ci	CLEAR_GPR(r11)
6728c2ecf20Sopenharmony_ci	CLEAR_GPR(r12)
6738c2ecf20Sopenharmony_ci	CLEAR_GPR(r13)
6748c2ecf20Sopenharmony_ci	CLEAR_GPR(r14)
6758c2ecf20Sopenharmony_ci	CLEAR_GPR(r15)
6768c2ecf20Sopenharmony_ci	CLEAR_GPR(r16)
6778c2ecf20Sopenharmony_ci	CLEAR_GPR(r17)
6788c2ecf20Sopenharmony_ci	CLEAR_GPR(r18)
6798c2ecf20Sopenharmony_ci	CLEAR_GPR(r19)
6808c2ecf20Sopenharmony_ci	CLEAR_GPR(r20)
6818c2ecf20Sopenharmony_ci	CLEAR_GPR(r21)
6828c2ecf20Sopenharmony_ci	CLEAR_GPR(r22)
6838c2ecf20Sopenharmony_ci	CLEAR_GPR(r23)
6848c2ecf20Sopenharmony_ci	CLEAR_GPR(r24)
6858c2ecf20Sopenharmony_ci	CLEAR_GPR(r25)
6868c2ecf20Sopenharmony_ci	CLEAR_GPR(r26)
6878c2ecf20Sopenharmony_ci	CLEAR_GPR(r27)
6888c2ecf20Sopenharmony_ci	CLEAR_GPR(r28)
6898c2ecf20Sopenharmony_ci	CLEAR_GPR(r29)
6908c2ecf20Sopenharmony_ci	CLEAR_GPR(r30)
6918c2ecf20Sopenharmony_ci	CLEAR_GPR(r31)
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_cijump_start_kernel:
6948c2ecf20Sopenharmony_ci	/*
6958c2ecf20Sopenharmony_ci	 * jump to kernel entry (start_kernel)
6968c2ecf20Sopenharmony_ci	 */
6978c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r30, start_kernel)
6988c2ecf20Sopenharmony_ci	l.jr    r30
6998c2ecf20Sopenharmony_ci	 l.nop
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci_flush_tlb:
7028c2ecf20Sopenharmony_ci	/*
7038c2ecf20Sopenharmony_ci	 *  I N V A L I D A T E   T L B   e n t r i e s
7048c2ecf20Sopenharmony_ci	 */
7058c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r5,SPR_DTLBMR_BASE(0))
7068c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r6,SPR_ITLBMR_BASE(0))
7078c2ecf20Sopenharmony_ci	l.addi	r7,r0,128 /* Maximum number of sets */
7088c2ecf20Sopenharmony_ci1:
7098c2ecf20Sopenharmony_ci	l.mtspr	r5,r0,0x0
7108c2ecf20Sopenharmony_ci	l.mtspr	r6,r0,0x0
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ci	l.addi	r5,r5,1
7138c2ecf20Sopenharmony_ci	l.addi	r6,r6,1
7148c2ecf20Sopenharmony_ci	l.sfeq	r7,r0
7158c2ecf20Sopenharmony_ci	l.bnf	1b
7168c2ecf20Sopenharmony_ci	 l.addi	r7,r7,-1
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci	l.jr	r9
7198c2ecf20Sopenharmony_ci	 l.nop
7208c2ecf20Sopenharmony_ci
7218c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP
7228c2ecf20Sopenharmony_cisecondary_wait:
7238c2ecf20Sopenharmony_ci	/* Doze the cpu until we are asked to run */
7248c2ecf20Sopenharmony_ci	/* If we dont have power management skip doze */
7258c2ecf20Sopenharmony_ci	l.mfspr r25,r0,SPR_UPR
7268c2ecf20Sopenharmony_ci	l.andi  r25,r25,SPR_UPR_PMP
7278c2ecf20Sopenharmony_ci	l.sfeq  r25,r0
7288c2ecf20Sopenharmony_ci	l.bf	secondary_check_release
7298c2ecf20Sopenharmony_ci	 l.nop
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	/* Setup special secondary exception handler */
7328c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r3, _secondary_evbar)
7338c2ecf20Sopenharmony_ci	tophys(r25,r3)
7348c2ecf20Sopenharmony_ci	l.mtspr	r0,r25,SPR_EVBAR
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci	/* Enable Interrupts */
7378c2ecf20Sopenharmony_ci	l.mfspr	r25,r0,SPR_SR
7388c2ecf20Sopenharmony_ci	l.ori	r25,r25,SPR_SR_IEE
7398c2ecf20Sopenharmony_ci	l.mtspr	r0,r25,SPR_SR
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci	/* Unmask interrupts interrupts */
7428c2ecf20Sopenharmony_ci	l.mfspr r25,r0,SPR_PICMR
7438c2ecf20Sopenharmony_ci	l.ori   r25,r25,0xffff
7448c2ecf20Sopenharmony_ci	l.mtspr	r0,r25,SPR_PICMR
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	/* Doze */
7478c2ecf20Sopenharmony_ci	l.mfspr r25,r0,SPR_PMR
7488c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r3, SPR_PMR_DME)
7498c2ecf20Sopenharmony_ci	l.or    r25,r25,r3
7508c2ecf20Sopenharmony_ci	l.mtspr r0,r25,SPR_PMR
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci	/* Wakeup - Restore exception handler */
7538c2ecf20Sopenharmony_ci	l.mtspr	r0,r0,SPR_EVBAR
7548c2ecf20Sopenharmony_ci
7558c2ecf20Sopenharmony_cisecondary_check_release:
7568c2ecf20Sopenharmony_ci	/*
7578c2ecf20Sopenharmony_ci	 * Check if we actually got the release signal, if not go-back to
7588c2ecf20Sopenharmony_ci	 * sleep.
7598c2ecf20Sopenharmony_ci	 */
7608c2ecf20Sopenharmony_ci	l.mfspr	r25,r0,SPR_COREID
7618c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r3, secondary_release)
7628c2ecf20Sopenharmony_ci	tophys(r4, r3)
7638c2ecf20Sopenharmony_ci	l.lwz	r3,0(r4)
7648c2ecf20Sopenharmony_ci	l.sfeq	r25,r3
7658c2ecf20Sopenharmony_ci	l.bnf	secondary_wait
7668c2ecf20Sopenharmony_ci	 l.nop
7678c2ecf20Sopenharmony_ci	/* fall through to secondary_init */
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_cisecondary_init:
7708c2ecf20Sopenharmony_ci	/*
7718c2ecf20Sopenharmony_ci	 * set up initial ksp and current
7728c2ecf20Sopenharmony_ci	 */
7738c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r10, secondary_thread_info)
7748c2ecf20Sopenharmony_ci	tophys	(r30,r10)
7758c2ecf20Sopenharmony_ci	l.lwz	r10,0(r30)
7768c2ecf20Sopenharmony_ci	l.addi	r1,r10,THREAD_SIZE
7778c2ecf20Sopenharmony_ci	tophys	(r30,r10)
7788c2ecf20Sopenharmony_ci	l.sw	TI_KSP(r30),r1
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci	l.jal	_ic_enable
7818c2ecf20Sopenharmony_ci	 l.nop
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci	l.jal	_dc_enable
7848c2ecf20Sopenharmony_ci	 l.nop
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci	l.jal	_flush_tlb
7878c2ecf20Sopenharmony_ci	 l.nop
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ci	/*
7908c2ecf20Sopenharmony_ci	 * enable dmmu & immu
7918c2ecf20Sopenharmony_ci	 */
7928c2ecf20Sopenharmony_ci	l.mfspr	r30,r0,SPR_SR
7938c2ecf20Sopenharmony_ci	l.movhi	r28,hi(SPR_SR_DME | SPR_SR_IME)
7948c2ecf20Sopenharmony_ci	l.ori	r28,r28,lo(SPR_SR_DME | SPR_SR_IME)
7958c2ecf20Sopenharmony_ci	l.or	r30,r30,r28
7968c2ecf20Sopenharmony_ci	/*
7978c2ecf20Sopenharmony_ci	 * This is a bit tricky, we need to switch over from physical addresses
7988c2ecf20Sopenharmony_ci	 * to virtual addresses on the fly.
7998c2ecf20Sopenharmony_ci	 * To do that, we first set up ESR with the IME and DME bits set.
8008c2ecf20Sopenharmony_ci	 * Then EPCR is set to secondary_start and then a l.rfe is issued to
8018c2ecf20Sopenharmony_ci	 * "jump" to that.
8028c2ecf20Sopenharmony_ci	 */
8038c2ecf20Sopenharmony_ci	l.mtspr	r0,r30,SPR_ESR_BASE
8048c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r30, secondary_start)
8058c2ecf20Sopenharmony_ci	l.mtspr	r0,r30,SPR_EPCR_BASE
8068c2ecf20Sopenharmony_ci	l.rfe
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_cisecondary_start:
8098c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r30, secondary_start_kernel)
8108c2ecf20Sopenharmony_ci	l.jr    r30
8118c2ecf20Sopenharmony_ci	 l.nop
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci#endif
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci/* ========================================[ cache ]=== */
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci	/* alignment here so we don't change memory offsets with
8188c2ecf20Sopenharmony_ci	 * memory controller defined
8198c2ecf20Sopenharmony_ci	 */
8208c2ecf20Sopenharmony_ci	.align 0x2000
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci_ic_enable:
8238c2ecf20Sopenharmony_ci	/* Check if IC present and skip enabling otherwise */
8248c2ecf20Sopenharmony_ci	l.mfspr r24,r0,SPR_UPR
8258c2ecf20Sopenharmony_ci	l.andi  r26,r24,SPR_UPR_ICP
8268c2ecf20Sopenharmony_ci	l.sfeq  r26,r0
8278c2ecf20Sopenharmony_ci	l.bf	9f
8288c2ecf20Sopenharmony_ci	l.nop
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_ci	/* Disable IC */
8318c2ecf20Sopenharmony_ci	l.mfspr r6,r0,SPR_SR
8328c2ecf20Sopenharmony_ci	l.addi  r5,r0,-1
8338c2ecf20Sopenharmony_ci	l.xori  r5,r5,SPR_SR_ICE
8348c2ecf20Sopenharmony_ci	l.and   r5,r6,r5
8358c2ecf20Sopenharmony_ci	l.mtspr r0,r5,SPR_SR
8368c2ecf20Sopenharmony_ci
8378c2ecf20Sopenharmony_ci	/* Establish cache block size
8388c2ecf20Sopenharmony_ci	   If BS=0, 16;
8398c2ecf20Sopenharmony_ci	   If BS=1, 32;
8408c2ecf20Sopenharmony_ci	   r14 contain block size
8418c2ecf20Sopenharmony_ci	*/
8428c2ecf20Sopenharmony_ci	l.mfspr r24,r0,SPR_ICCFGR
8438c2ecf20Sopenharmony_ci	l.andi	r26,r24,SPR_ICCFGR_CBS
8448c2ecf20Sopenharmony_ci	l.srli	r28,r26,7
8458c2ecf20Sopenharmony_ci	l.ori	r30,r0,16
8468c2ecf20Sopenharmony_ci	l.sll	r14,r30,r28
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci	/* Establish number of cache sets
8498c2ecf20Sopenharmony_ci	   r16 contains number of cache sets
8508c2ecf20Sopenharmony_ci	   r28 contains log(# of cache sets)
8518c2ecf20Sopenharmony_ci	*/
8528c2ecf20Sopenharmony_ci	l.andi  r26,r24,SPR_ICCFGR_NCS
8538c2ecf20Sopenharmony_ci	l.srli 	r28,r26,3
8548c2ecf20Sopenharmony_ci	l.ori   r30,r0,1
8558c2ecf20Sopenharmony_ci	l.sll   r16,r30,r28
8568c2ecf20Sopenharmony_ci
8578c2ecf20Sopenharmony_ci	/* Invalidate IC */
8588c2ecf20Sopenharmony_ci	l.addi  r6,r0,0
8598c2ecf20Sopenharmony_ci	l.sll   r5,r14,r28
8608c2ecf20Sopenharmony_ci//        l.mul   r5,r14,r16
8618c2ecf20Sopenharmony_ci//	l.trap  1
8628c2ecf20Sopenharmony_ci//	l.addi  r5,r0,IC_SIZE
8638c2ecf20Sopenharmony_ci1:
8648c2ecf20Sopenharmony_ci	l.mtspr r0,r6,SPR_ICBIR
8658c2ecf20Sopenharmony_ci	l.sfne  r6,r5
8668c2ecf20Sopenharmony_ci	l.bf    1b
8678c2ecf20Sopenharmony_ci	l.add   r6,r6,r14
8688c2ecf20Sopenharmony_ci //       l.addi   r6,r6,IC_LINE
8698c2ecf20Sopenharmony_ci
8708c2ecf20Sopenharmony_ci	/* Enable IC */
8718c2ecf20Sopenharmony_ci	l.mfspr r6,r0,SPR_SR
8728c2ecf20Sopenharmony_ci	l.ori   r6,r6,SPR_SR_ICE
8738c2ecf20Sopenharmony_ci	l.mtspr r0,r6,SPR_SR
8748c2ecf20Sopenharmony_ci	l.nop
8758c2ecf20Sopenharmony_ci	l.nop
8768c2ecf20Sopenharmony_ci	l.nop
8778c2ecf20Sopenharmony_ci	l.nop
8788c2ecf20Sopenharmony_ci	l.nop
8798c2ecf20Sopenharmony_ci	l.nop
8808c2ecf20Sopenharmony_ci	l.nop
8818c2ecf20Sopenharmony_ci	l.nop
8828c2ecf20Sopenharmony_ci	l.nop
8838c2ecf20Sopenharmony_ci	l.nop
8848c2ecf20Sopenharmony_ci9:
8858c2ecf20Sopenharmony_ci	l.jr    r9
8868c2ecf20Sopenharmony_ci	l.nop
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_ci_dc_enable:
8898c2ecf20Sopenharmony_ci	/* Check if DC present and skip enabling otherwise */
8908c2ecf20Sopenharmony_ci	l.mfspr r24,r0,SPR_UPR
8918c2ecf20Sopenharmony_ci	l.andi  r26,r24,SPR_UPR_DCP
8928c2ecf20Sopenharmony_ci	l.sfeq  r26,r0
8938c2ecf20Sopenharmony_ci	l.bf	9f
8948c2ecf20Sopenharmony_ci	l.nop
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci	/* Disable DC */
8978c2ecf20Sopenharmony_ci	l.mfspr r6,r0,SPR_SR
8988c2ecf20Sopenharmony_ci	l.addi  r5,r0,-1
8998c2ecf20Sopenharmony_ci	l.xori  r5,r5,SPR_SR_DCE
9008c2ecf20Sopenharmony_ci	l.and   r5,r6,r5
9018c2ecf20Sopenharmony_ci	l.mtspr r0,r5,SPR_SR
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_ci	/* Establish cache block size
9048c2ecf20Sopenharmony_ci	   If BS=0, 16;
9058c2ecf20Sopenharmony_ci	   If BS=1, 32;
9068c2ecf20Sopenharmony_ci	   r14 contain block size
9078c2ecf20Sopenharmony_ci	*/
9088c2ecf20Sopenharmony_ci	l.mfspr r24,r0,SPR_DCCFGR
9098c2ecf20Sopenharmony_ci	l.andi	r26,r24,SPR_DCCFGR_CBS
9108c2ecf20Sopenharmony_ci	l.srli	r28,r26,7
9118c2ecf20Sopenharmony_ci	l.ori	r30,r0,16
9128c2ecf20Sopenharmony_ci	l.sll	r14,r30,r28
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_ci	/* Establish number of cache sets
9158c2ecf20Sopenharmony_ci	   r16 contains number of cache sets
9168c2ecf20Sopenharmony_ci	   r28 contains log(# of cache sets)
9178c2ecf20Sopenharmony_ci	*/
9188c2ecf20Sopenharmony_ci	l.andi  r26,r24,SPR_DCCFGR_NCS
9198c2ecf20Sopenharmony_ci	l.srli 	r28,r26,3
9208c2ecf20Sopenharmony_ci	l.ori   r30,r0,1
9218c2ecf20Sopenharmony_ci	l.sll   r16,r30,r28
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_ci	/* Invalidate DC */
9248c2ecf20Sopenharmony_ci	l.addi  r6,r0,0
9258c2ecf20Sopenharmony_ci	l.sll   r5,r14,r28
9268c2ecf20Sopenharmony_ci1:
9278c2ecf20Sopenharmony_ci	l.mtspr r0,r6,SPR_DCBIR
9288c2ecf20Sopenharmony_ci	l.sfne  r6,r5
9298c2ecf20Sopenharmony_ci	l.bf    1b
9308c2ecf20Sopenharmony_ci	l.add   r6,r6,r14
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci	/* Enable DC */
9338c2ecf20Sopenharmony_ci	l.mfspr r6,r0,SPR_SR
9348c2ecf20Sopenharmony_ci	l.ori   r6,r6,SPR_SR_DCE
9358c2ecf20Sopenharmony_ci	l.mtspr r0,r6,SPR_SR
9368c2ecf20Sopenharmony_ci9:
9378c2ecf20Sopenharmony_ci	l.jr    r9
9388c2ecf20Sopenharmony_ci	l.nop
9398c2ecf20Sopenharmony_ci
9408c2ecf20Sopenharmony_ci/* ===============================================[ page table masks ]=== */
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci#define DTLB_UP_CONVERT_MASK  0x3fa
9438c2ecf20Sopenharmony_ci#define ITLB_UP_CONVERT_MASK  0x3a
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ci/* for SMP we'd have (this is a bit subtle, CC must be always set
9468c2ecf20Sopenharmony_ci * for SMP, but since we have _PAGE_PRESENT bit always defined
9478c2ecf20Sopenharmony_ci * we can just modify the mask)
9488c2ecf20Sopenharmony_ci */
9498c2ecf20Sopenharmony_ci#define DTLB_SMP_CONVERT_MASK  0x3fb
9508c2ecf20Sopenharmony_ci#define ITLB_SMP_CONVERT_MASK  0x3b
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci/* ---[ boot dtlb miss handler ]----------------------------------------- */
9538c2ecf20Sopenharmony_ci
9548c2ecf20Sopenharmony_ciboot_dtlb_miss_handler:
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci/* mask for DTLB_MR register: - (0) sets V (valid) bit,
9578c2ecf20Sopenharmony_ci *                            - (31-12) sets bits belonging to VPN (31-12)
9588c2ecf20Sopenharmony_ci */
9598c2ecf20Sopenharmony_ci#define DTLB_MR_MASK 0xfffff001
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_ci/* mask for DTLB_TR register: - (2) sets CI (cache inhibit) bit,
9628c2ecf20Sopenharmony_ci *			      - (4) sets A (access) bit,
9638c2ecf20Sopenharmony_ci *                            - (5) sets D (dirty) bit,
9648c2ecf20Sopenharmony_ci *                            - (8) sets SRE (superuser read) bit
9658c2ecf20Sopenharmony_ci *                            - (9) sets SWE (superuser write) bit
9668c2ecf20Sopenharmony_ci *                            - (31-12) sets bits belonging to VPN (31-12)
9678c2ecf20Sopenharmony_ci */
9688c2ecf20Sopenharmony_ci#define DTLB_TR_MASK 0xfffff332
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_ci/* These are for masking out the VPN/PPN value from the MR/TR registers...
9718c2ecf20Sopenharmony_ci * it's not the same as the PFN */
9728c2ecf20Sopenharmony_ci#define VPN_MASK 0xfffff000
9738c2ecf20Sopenharmony_ci#define PPN_MASK 0xfffff000
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci	EXCEPTION_STORE_GPR6
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_ci#if 0
9798c2ecf20Sopenharmony_ci	l.mfspr r6,r0,SPR_ESR_BASE	   //
9808c2ecf20Sopenharmony_ci	l.andi  r6,r6,SPR_SR_SM            // are we in kernel mode ?
9818c2ecf20Sopenharmony_ci	l.sfeqi r6,0                       // r6 == 0x1 --> SM
9828c2ecf20Sopenharmony_ci	l.bf    exit_with_no_dtranslation  //
9838c2ecf20Sopenharmony_ci	l.nop
9848c2ecf20Sopenharmony_ci#endif
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ci	/* this could be optimized by moving storing of
9878c2ecf20Sopenharmony_ci	 * non r6 registers here, and jumping r6 restore
9888c2ecf20Sopenharmony_ci	 * if not in supervisor mode
9898c2ecf20Sopenharmony_ci	 */
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_ci	EXCEPTION_STORE_GPR2
9928c2ecf20Sopenharmony_ci	EXCEPTION_STORE_GPR3
9938c2ecf20Sopenharmony_ci	EXCEPTION_STORE_GPR4
9948c2ecf20Sopenharmony_ci	EXCEPTION_STORE_GPR5
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_ci	l.mfspr r4,r0,SPR_EEAR_BASE        // get the offending EA
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_ciimmediate_translation:
9998c2ecf20Sopenharmony_ci	CLEAR_GPR(r6)
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_ci	l.srli	r3,r4,0xd                  // r3 <- r4 / 8192 (sets are relative to page size (8Kb) NOT VPN size (4Kb)
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci	l.mfspr r6, r0, SPR_DMMUCFGR
10048c2ecf20Sopenharmony_ci	l.andi	r6, r6, SPR_DMMUCFGR_NTS
10058c2ecf20Sopenharmony_ci	l.srli	r6, r6, SPR_DMMUCFGR_NTS_OFF
10068c2ecf20Sopenharmony_ci	l.ori	r5, r0, 0x1
10078c2ecf20Sopenharmony_ci	l.sll	r5, r5, r6 	// r5 = number DMMU sets
10088c2ecf20Sopenharmony_ci	l.addi	r6, r5, -1  	// r6 = nsets mask
10098c2ecf20Sopenharmony_ci	l.and	r2, r3, r6	// r2 <- r3 % NSETS_MASK
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_ci	l.or    r6,r6,r4                   // r6 <- r4
10128c2ecf20Sopenharmony_ci	l.ori   r6,r6,~(VPN_MASK)          // r6 <- VPN :VPN .xfff - clear up lo(r6) to 0x**** *fff
10138c2ecf20Sopenharmony_ci	l.movhi r5,hi(DTLB_MR_MASK)        // r5 <- ffff:0000.x000
10148c2ecf20Sopenharmony_ci	l.ori   r5,r5,lo(DTLB_MR_MASK)     // r5 <- ffff:1111.x001 - apply DTLB_MR_MASK
10158c2ecf20Sopenharmony_ci	l.and   r5,r5,r6                   // r5 <- VPN :VPN .x001 - we have DTLBMR entry
10168c2ecf20Sopenharmony_ci	l.mtspr r2,r5,SPR_DTLBMR_BASE(0)   // set DTLBMR
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ci	/* set up DTLB with no translation for EA <= 0xbfffffff */
10198c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r6,0xbfffffff)
10208c2ecf20Sopenharmony_ci	l.sfgeu  r6,r4                     // flag if r6 >= r4 (if 0xbfffffff >= EA)
10218c2ecf20Sopenharmony_ci	l.bf     1f                        // goto out
10228c2ecf20Sopenharmony_ci	l.and    r3,r4,r4                  // delay slot :: 24 <- r4 (if flag==1)
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ci	tophys(r3,r4)                      // r3 <- PA
10258c2ecf20Sopenharmony_ci1:
10268c2ecf20Sopenharmony_ci	l.ori   r3,r3,~(PPN_MASK)          // r3 <- PPN :PPN .xfff - clear up lo(r6) to 0x**** *fff
10278c2ecf20Sopenharmony_ci	l.movhi r5,hi(DTLB_TR_MASK)        // r5 <- ffff:0000.x000
10288c2ecf20Sopenharmony_ci	l.ori   r5,r5,lo(DTLB_TR_MASK)     // r5 <- ffff:1111.x330 - apply DTLB_MR_MASK
10298c2ecf20Sopenharmony_ci	l.and   r5,r5,r3                   // r5 <- PPN :PPN .x330 - we have DTLBTR entry
10308c2ecf20Sopenharmony_ci	l.mtspr r2,r5,SPR_DTLBTR_BASE(0)   // set DTLBTR
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR6
10338c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR5
10348c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR4
10358c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR3
10368c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR2
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ci	l.rfe                              // SR <- ESR, PC <- EPC
10398c2ecf20Sopenharmony_ci
10408c2ecf20Sopenharmony_ciexit_with_no_dtranslation:
10418c2ecf20Sopenharmony_ci	/* EA out of memory or not in supervisor mode */
10428c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR6
10438c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR4
10448c2ecf20Sopenharmony_ci	l.j	_dispatch_bus_fault
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci/* ---[ boot itlb miss handler ]----------------------------------------- */
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_ciboot_itlb_miss_handler:
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci/* mask for ITLB_MR register: - sets V (valid) bit,
10518c2ecf20Sopenharmony_ci *                            - sets bits belonging to VPN (15-12)
10528c2ecf20Sopenharmony_ci */
10538c2ecf20Sopenharmony_ci#define ITLB_MR_MASK 0xfffff001
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ci/* mask for ITLB_TR register: - sets A (access) bit,
10568c2ecf20Sopenharmony_ci *                            - sets SXE (superuser execute) bit
10578c2ecf20Sopenharmony_ci *                            - sets bits belonging to VPN (15-12)
10588c2ecf20Sopenharmony_ci */
10598c2ecf20Sopenharmony_ci#define ITLB_TR_MASK 0xfffff050
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci/*
10628c2ecf20Sopenharmony_ci#define VPN_MASK 0xffffe000
10638c2ecf20Sopenharmony_ci#define PPN_MASK 0xffffe000
10648c2ecf20Sopenharmony_ci*/
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_ci
10688c2ecf20Sopenharmony_ci	EXCEPTION_STORE_GPR2
10698c2ecf20Sopenharmony_ci	EXCEPTION_STORE_GPR3
10708c2ecf20Sopenharmony_ci	EXCEPTION_STORE_GPR4
10718c2ecf20Sopenharmony_ci	EXCEPTION_STORE_GPR5
10728c2ecf20Sopenharmony_ci	EXCEPTION_STORE_GPR6
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci#if 0
10758c2ecf20Sopenharmony_ci	l.mfspr r6,r0,SPR_ESR_BASE         //
10768c2ecf20Sopenharmony_ci	l.andi  r6,r6,SPR_SR_SM            // are we in kernel mode ?
10778c2ecf20Sopenharmony_ci	l.sfeqi r6,0                       // r6 == 0x1 --> SM
10788c2ecf20Sopenharmony_ci	l.bf    exit_with_no_itranslation
10798c2ecf20Sopenharmony_ci	l.nop
10808c2ecf20Sopenharmony_ci#endif
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci
10838c2ecf20Sopenharmony_ci	l.mfspr r4,r0,SPR_EEAR_BASE        // get the offending EA
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_ciearlyearly:
10868c2ecf20Sopenharmony_ci	CLEAR_GPR(r6)
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci	l.srli  r3,r4,0xd                  // r3 <- r4 / 8192 (sets are relative to page size (8Kb) NOT VPN size (4Kb)
10898c2ecf20Sopenharmony_ci
10908c2ecf20Sopenharmony_ci	l.mfspr r6, r0, SPR_IMMUCFGR
10918c2ecf20Sopenharmony_ci	l.andi	r6, r6, SPR_IMMUCFGR_NTS
10928c2ecf20Sopenharmony_ci	l.srli	r6, r6, SPR_IMMUCFGR_NTS_OFF
10938c2ecf20Sopenharmony_ci	l.ori	r5, r0, 0x1
10948c2ecf20Sopenharmony_ci	l.sll	r5, r5, r6 	// r5 = number IMMU sets from IMMUCFGR
10958c2ecf20Sopenharmony_ci	l.addi	r6, r5, -1  	// r6 = nsets mask
10968c2ecf20Sopenharmony_ci	l.and	r2, r3, r6	// r2 <- r3 % NSETS_MASK
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_ci	l.or    r6,r6,r4                   // r6 <- r4
10998c2ecf20Sopenharmony_ci	l.ori   r6,r6,~(VPN_MASK)          // r6 <- VPN :VPN .xfff - clear up lo(r6) to 0x**** *fff
11008c2ecf20Sopenharmony_ci	l.movhi r5,hi(ITLB_MR_MASK)        // r5 <- ffff:0000.x000
11018c2ecf20Sopenharmony_ci	l.ori   r5,r5,lo(ITLB_MR_MASK)     // r5 <- ffff:1111.x001 - apply ITLB_MR_MASK
11028c2ecf20Sopenharmony_ci	l.and   r5,r5,r6                   // r5 <- VPN :VPN .x001 - we have ITLBMR entry
11038c2ecf20Sopenharmony_ci	l.mtspr r2,r5,SPR_ITLBMR_BASE(0)   // set ITLBMR
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci	/*
11068c2ecf20Sopenharmony_ci	 * set up ITLB with no translation for EA <= 0x0fffffff
11078c2ecf20Sopenharmony_ci	 *
11088c2ecf20Sopenharmony_ci	 * we need this for head.S mapping (EA = PA). if we move all functions
11098c2ecf20Sopenharmony_ci	 * which run with mmu enabled into entry.S, we might be able to eliminate this.
11108c2ecf20Sopenharmony_ci	 *
11118c2ecf20Sopenharmony_ci	 */
11128c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r6,0x0fffffff)
11138c2ecf20Sopenharmony_ci	l.sfgeu  r6,r4                     // flag if r6 >= r4 (if 0xb0ffffff >= EA)
11148c2ecf20Sopenharmony_ci	l.bf     1f                        // goto out
11158c2ecf20Sopenharmony_ci	l.and    r3,r4,r4                  // delay slot :: 24 <- r4 (if flag==1)
11168c2ecf20Sopenharmony_ci
11178c2ecf20Sopenharmony_ci	tophys(r3,r4)                      // r3 <- PA
11188c2ecf20Sopenharmony_ci1:
11198c2ecf20Sopenharmony_ci	l.ori   r3,r3,~(PPN_MASK)          // r3 <- PPN :PPN .xfff - clear up lo(r6) to 0x**** *fff
11208c2ecf20Sopenharmony_ci	l.movhi r5,hi(ITLB_TR_MASK)        // r5 <- ffff:0000.x000
11218c2ecf20Sopenharmony_ci	l.ori   r5,r5,lo(ITLB_TR_MASK)     // r5 <- ffff:1111.x050 - apply ITLB_MR_MASK
11228c2ecf20Sopenharmony_ci	l.and   r5,r5,r3                   // r5 <- PPN :PPN .x050 - we have ITLBTR entry
11238c2ecf20Sopenharmony_ci	l.mtspr r2,r5,SPR_ITLBTR_BASE(0)   // set ITLBTR
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR6
11268c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR5
11278c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR4
11288c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR3
11298c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR2
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci	l.rfe                              // SR <- ESR, PC <- EPC
11328c2ecf20Sopenharmony_ci
11338c2ecf20Sopenharmony_ciexit_with_no_itranslation:
11348c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR4
11358c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR6
11368c2ecf20Sopenharmony_ci	l.j    _dispatch_bus_fault
11378c2ecf20Sopenharmony_ci	l.nop
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_ci/* ====================================================================== */
11408c2ecf20Sopenharmony_ci/*
11418c2ecf20Sopenharmony_ci * Stuff below here shouldn't go into .head section... maybe this stuff
11428c2ecf20Sopenharmony_ci * can be moved to entry.S ???
11438c2ecf20Sopenharmony_ci */
11448c2ecf20Sopenharmony_ci
11458c2ecf20Sopenharmony_ci/* ==============================================[ DTLB miss handler ]=== */
11468c2ecf20Sopenharmony_ci
11478c2ecf20Sopenharmony_ci/*
11488c2ecf20Sopenharmony_ci * Comments:
11498c2ecf20Sopenharmony_ci *   Exception handlers are entered with MMU off so the following handler
11508c2ecf20Sopenharmony_ci *   needs to use physical addressing
11518c2ecf20Sopenharmony_ci *
11528c2ecf20Sopenharmony_ci */
11538c2ecf20Sopenharmony_ci
11548c2ecf20Sopenharmony_ci	.text
11558c2ecf20Sopenharmony_ciENTRY(dtlb_miss_handler)
11568c2ecf20Sopenharmony_ci	EXCEPTION_STORE_GPR2
11578c2ecf20Sopenharmony_ci	EXCEPTION_STORE_GPR3
11588c2ecf20Sopenharmony_ci	EXCEPTION_STORE_GPR4
11598c2ecf20Sopenharmony_ci	/*
11608c2ecf20Sopenharmony_ci	 * get EA of the miss
11618c2ecf20Sopenharmony_ci	 */
11628c2ecf20Sopenharmony_ci	l.mfspr	r2,r0,SPR_EEAR_BASE
11638c2ecf20Sopenharmony_ci	/*
11648c2ecf20Sopenharmony_ci	 * pmd = (pmd_t *)(current_pgd + pgd_index(daddr));
11658c2ecf20Sopenharmony_ci	 */
11668c2ecf20Sopenharmony_ci	GET_CURRENT_PGD(r3,r4)		// r3 is current_pgd, r4 is temp
11678c2ecf20Sopenharmony_ci	l.srli	r4,r2,0x18		// >> PAGE_SHIFT + (PAGE_SHIFT - 2)
11688c2ecf20Sopenharmony_ci	l.slli	r4,r4,0x2		// to get address << 2
11698c2ecf20Sopenharmony_ci	l.add	r3,r4,r3		// r4 is pgd_index(daddr)
11708c2ecf20Sopenharmony_ci	/*
11718c2ecf20Sopenharmony_ci	 * if (pmd_none(*pmd))
11728c2ecf20Sopenharmony_ci	 *   goto pmd_none:
11738c2ecf20Sopenharmony_ci	 */
11748c2ecf20Sopenharmony_ci	tophys	(r4,r3)
11758c2ecf20Sopenharmony_ci	l.lwz	r3,0x0(r4)		// get *pmd value
11768c2ecf20Sopenharmony_ci	l.sfne	r3,r0
11778c2ecf20Sopenharmony_ci	l.bnf	d_pmd_none
11788c2ecf20Sopenharmony_ci	 l.addi	r3,r0,0xffffe000	// PAGE_MASK
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_cid_pmd_good:
11818c2ecf20Sopenharmony_ci	/*
11828c2ecf20Sopenharmony_ci	 * pte = *pte_offset(pmd, daddr);
11838c2ecf20Sopenharmony_ci	 */
11848c2ecf20Sopenharmony_ci	l.lwz	r4,0x0(r4)		// get **pmd value
11858c2ecf20Sopenharmony_ci	l.and	r4,r4,r3		// & PAGE_MASK
11868c2ecf20Sopenharmony_ci	l.srli	r2,r2,0xd		// >> PAGE_SHIFT, r2 == EEAR
11878c2ecf20Sopenharmony_ci	l.andi	r3,r2,0x7ff		// (1UL << PAGE_SHIFT - 2) - 1
11888c2ecf20Sopenharmony_ci	l.slli	r3,r3,0x2		// to get address << 2
11898c2ecf20Sopenharmony_ci	l.add	r3,r3,r4
11908c2ecf20Sopenharmony_ci	l.lwz	r3,0x0(r3)		// this is pte at last
11918c2ecf20Sopenharmony_ci	/*
11928c2ecf20Sopenharmony_ci	 * if (!pte_present(pte))
11938c2ecf20Sopenharmony_ci	 */
11948c2ecf20Sopenharmony_ci	l.andi	r4,r3,0x1
11958c2ecf20Sopenharmony_ci	l.sfne	r4,r0			// is pte present
11968c2ecf20Sopenharmony_ci	l.bnf	d_pte_not_present
11978c2ecf20Sopenharmony_ci	l.addi	r4,r0,0xffffe3fa	// PAGE_MASK | DTLB_UP_CONVERT_MASK
11988c2ecf20Sopenharmony_ci	/*
11998c2ecf20Sopenharmony_ci	 * fill DTLB TR register
12008c2ecf20Sopenharmony_ci	 */
12018c2ecf20Sopenharmony_ci	l.and	r4,r3,r4		// apply the mask
12028c2ecf20Sopenharmony_ci	// Determine number of DMMU sets
12038c2ecf20Sopenharmony_ci	l.mfspr r2, r0, SPR_DMMUCFGR
12048c2ecf20Sopenharmony_ci	l.andi	r2, r2, SPR_DMMUCFGR_NTS
12058c2ecf20Sopenharmony_ci	l.srli	r2, r2, SPR_DMMUCFGR_NTS_OFF
12068c2ecf20Sopenharmony_ci	l.ori	r3, r0, 0x1
12078c2ecf20Sopenharmony_ci	l.sll	r3, r3, r2 	// r3 = number DMMU sets DMMUCFGR
12088c2ecf20Sopenharmony_ci	l.addi	r2, r3, -1  	// r2 = nsets mask
12098c2ecf20Sopenharmony_ci	l.mfspr	r3, r0, SPR_EEAR_BASE
12108c2ecf20Sopenharmony_ci	l.srli	r3, r3, 0xd	// >> PAGE_SHIFT
12118c2ecf20Sopenharmony_ci	l.and	r2, r3, r2	// calc offset:	 & (NUM_TLB_ENTRIES-1)
12128c2ecf20Sopenharmony_ci	                                                   //NUM_TLB_ENTRIES
12138c2ecf20Sopenharmony_ci	l.mtspr	r2,r4,SPR_DTLBTR_BASE(0)
12148c2ecf20Sopenharmony_ci	/*
12158c2ecf20Sopenharmony_ci	 * fill DTLB MR register
12168c2ecf20Sopenharmony_ci	 */
12178c2ecf20Sopenharmony_ci	l.slli	r3, r3, 0xd		/* << PAGE_SHIFT => EA & PAGE_MASK */
12188c2ecf20Sopenharmony_ci	l.ori	r4,r3,0x1		// set hardware valid bit: DTBL_MR entry
12198c2ecf20Sopenharmony_ci	l.mtspr	r2,r4,SPR_DTLBMR_BASE(0)
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR2
12228c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR3
12238c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR4
12248c2ecf20Sopenharmony_ci	l.rfe
12258c2ecf20Sopenharmony_cid_pmd_none:
12268c2ecf20Sopenharmony_cid_pte_not_present:
12278c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR2
12288c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR3
12298c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR4
12308c2ecf20Sopenharmony_ci	EXCEPTION_HANDLE(_dtlb_miss_page_fault_handler)
12318c2ecf20Sopenharmony_ci
12328c2ecf20Sopenharmony_ci/* ==============================================[ ITLB miss handler ]=== */
12338c2ecf20Sopenharmony_ciENTRY(itlb_miss_handler)
12348c2ecf20Sopenharmony_ci	EXCEPTION_STORE_GPR2
12358c2ecf20Sopenharmony_ci	EXCEPTION_STORE_GPR3
12368c2ecf20Sopenharmony_ci	EXCEPTION_STORE_GPR4
12378c2ecf20Sopenharmony_ci	/*
12388c2ecf20Sopenharmony_ci	 * get EA of the miss
12398c2ecf20Sopenharmony_ci	 */
12408c2ecf20Sopenharmony_ci	l.mfspr	r2,r0,SPR_EEAR_BASE
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_ci	/*
12438c2ecf20Sopenharmony_ci	 * pmd = (pmd_t *)(current_pgd + pgd_index(daddr));
12448c2ecf20Sopenharmony_ci	 *
12458c2ecf20Sopenharmony_ci	 */
12468c2ecf20Sopenharmony_ci	GET_CURRENT_PGD(r3,r4)		// r3 is current_pgd, r5 is temp
12478c2ecf20Sopenharmony_ci	l.srli	r4,r2,0x18		// >> PAGE_SHIFT + (PAGE_SHIFT - 2)
12488c2ecf20Sopenharmony_ci	l.slli	r4,r4,0x2		// to get address << 2
12498c2ecf20Sopenharmony_ci	l.add	r3,r4,r3		// r4 is pgd_index(daddr)
12508c2ecf20Sopenharmony_ci	/*
12518c2ecf20Sopenharmony_ci	 * if (pmd_none(*pmd))
12528c2ecf20Sopenharmony_ci	 *   goto pmd_none:
12538c2ecf20Sopenharmony_ci	 */
12548c2ecf20Sopenharmony_ci	tophys	(r4,r3)
12558c2ecf20Sopenharmony_ci	l.lwz	r3,0x0(r4)		// get *pmd value
12568c2ecf20Sopenharmony_ci	l.sfne	r3,r0
12578c2ecf20Sopenharmony_ci	l.bnf	i_pmd_none
12588c2ecf20Sopenharmony_ci	 l.addi	r3,r0,0xffffe000	// PAGE_MASK
12598c2ecf20Sopenharmony_ci
12608c2ecf20Sopenharmony_cii_pmd_good:
12618c2ecf20Sopenharmony_ci	/*
12628c2ecf20Sopenharmony_ci	 * pte = *pte_offset(pmd, iaddr);
12638c2ecf20Sopenharmony_ci	 *
12648c2ecf20Sopenharmony_ci	 */
12658c2ecf20Sopenharmony_ci	l.lwz	r4,0x0(r4)		// get **pmd value
12668c2ecf20Sopenharmony_ci	l.and	r4,r4,r3		// & PAGE_MASK
12678c2ecf20Sopenharmony_ci	l.srli	r2,r2,0xd		// >> PAGE_SHIFT, r2 == EEAR
12688c2ecf20Sopenharmony_ci	l.andi	r3,r2,0x7ff		// (1UL << PAGE_SHIFT - 2) - 1
12698c2ecf20Sopenharmony_ci	l.slli	r3,r3,0x2		// to get address << 2
12708c2ecf20Sopenharmony_ci	l.add	r3,r3,r4
12718c2ecf20Sopenharmony_ci	l.lwz	r3,0x0(r3)		// this is pte at last
12728c2ecf20Sopenharmony_ci	/*
12738c2ecf20Sopenharmony_ci	 * if (!pte_present(pte))
12748c2ecf20Sopenharmony_ci	 *
12758c2ecf20Sopenharmony_ci	 */
12768c2ecf20Sopenharmony_ci	l.andi	r4,r3,0x1
12778c2ecf20Sopenharmony_ci	l.sfne	r4,r0			// is pte present
12788c2ecf20Sopenharmony_ci	l.bnf	i_pte_not_present
12798c2ecf20Sopenharmony_ci	 l.addi	r4,r0,0xffffe03a	// PAGE_MASK | ITLB_UP_CONVERT_MASK
12808c2ecf20Sopenharmony_ci	/*
12818c2ecf20Sopenharmony_ci	 * fill ITLB TR register
12828c2ecf20Sopenharmony_ci	 */
12838c2ecf20Sopenharmony_ci	l.and	r4,r3,r4		// apply the mask
12848c2ecf20Sopenharmony_ci	l.andi	r3,r3,0x7c0		// _PAGE_EXEC | _PAGE_SRE | _PAGE_SWE |  _PAGE_URE | _PAGE_UWE
12858c2ecf20Sopenharmony_ci	l.sfeq	r3,r0
12868c2ecf20Sopenharmony_ci	l.bf	itlb_tr_fill //_workaround
12878c2ecf20Sopenharmony_ci	// Determine number of IMMU sets
12888c2ecf20Sopenharmony_ci	l.mfspr r2, r0, SPR_IMMUCFGR
12898c2ecf20Sopenharmony_ci	l.andi	r2, r2, SPR_IMMUCFGR_NTS
12908c2ecf20Sopenharmony_ci	l.srli	r2, r2, SPR_IMMUCFGR_NTS_OFF
12918c2ecf20Sopenharmony_ci	l.ori	r3, r0, 0x1
12928c2ecf20Sopenharmony_ci	l.sll	r3, r3, r2 	// r3 = number IMMU sets IMMUCFGR
12938c2ecf20Sopenharmony_ci	l.addi	r2, r3, -1  	// r2 = nsets mask
12948c2ecf20Sopenharmony_ci	l.mfspr	r3, r0, SPR_EEAR_BASE
12958c2ecf20Sopenharmony_ci	l.srli	r3, r3, 0xd	// >> PAGE_SHIFT
12968c2ecf20Sopenharmony_ci	l.and	r2, r3, r2	// calc offset:	 & (NUM_TLB_ENTRIES-1)
12978c2ecf20Sopenharmony_ci
12988c2ecf20Sopenharmony_ci/*
12998c2ecf20Sopenharmony_ci * __PHX__ :: fixme
13008c2ecf20Sopenharmony_ci * we should not just blindly set executable flags,
13018c2ecf20Sopenharmony_ci * but it does help with ping. the clean way would be to find out
13028c2ecf20Sopenharmony_ci * (and fix it) why stack doesn't have execution permissions
13038c2ecf20Sopenharmony_ci */
13048c2ecf20Sopenharmony_ci
13058c2ecf20Sopenharmony_ciitlb_tr_fill_workaround:
13068c2ecf20Sopenharmony_ci	l.ori	r4,r4,0xc0		// | (SPR_ITLBTR_UXE | ITLBTR_SXE)
13078c2ecf20Sopenharmony_ciitlb_tr_fill:
13088c2ecf20Sopenharmony_ci	l.mtspr	r2,r4,SPR_ITLBTR_BASE(0)
13098c2ecf20Sopenharmony_ci	/*
13108c2ecf20Sopenharmony_ci	 * fill DTLB MR register
13118c2ecf20Sopenharmony_ci	 */
13128c2ecf20Sopenharmony_ci	l.slli	r3, r3, 0xd		/* << PAGE_SHIFT => EA & PAGE_MASK */
13138c2ecf20Sopenharmony_ci	l.ori	r4,r3,0x1		// set hardware valid bit: ITBL_MR entry
13148c2ecf20Sopenharmony_ci	l.mtspr	r2,r4,SPR_ITLBMR_BASE(0)
13158c2ecf20Sopenharmony_ci
13168c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR2
13178c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR3
13188c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR4
13198c2ecf20Sopenharmony_ci	l.rfe
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_cii_pmd_none:
13228c2ecf20Sopenharmony_cii_pte_not_present:
13238c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR2
13248c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR3
13258c2ecf20Sopenharmony_ci	EXCEPTION_LOAD_GPR4
13268c2ecf20Sopenharmony_ci	EXCEPTION_HANDLE(_itlb_miss_page_fault_handler)
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_ci/* ==============================================[ boot tlb handlers ]=== */
13298c2ecf20Sopenharmony_ci
13308c2ecf20Sopenharmony_ci
13318c2ecf20Sopenharmony_ci/* =================================================[ debugging aids ]=== */
13328c2ecf20Sopenharmony_ci
13338c2ecf20Sopenharmony_ci	.align 64
13348c2ecf20Sopenharmony_ci_immu_trampoline:
13358c2ecf20Sopenharmony_ci	.space 64
13368c2ecf20Sopenharmony_ci_immu_trampoline_top:
13378c2ecf20Sopenharmony_ci
13388c2ecf20Sopenharmony_ci#define TRAMP_SLOT_0		(0x0)
13398c2ecf20Sopenharmony_ci#define TRAMP_SLOT_1		(0x4)
13408c2ecf20Sopenharmony_ci#define TRAMP_SLOT_2		(0x8)
13418c2ecf20Sopenharmony_ci#define TRAMP_SLOT_3		(0xc)
13428c2ecf20Sopenharmony_ci#define TRAMP_SLOT_4		(0x10)
13438c2ecf20Sopenharmony_ci#define TRAMP_SLOT_5		(0x14)
13448c2ecf20Sopenharmony_ci#define TRAMP_FRAME_SIZE	(0x18)
13458c2ecf20Sopenharmony_ci
13468c2ecf20Sopenharmony_ciENTRY(_immu_trampoline_workaround)
13478c2ecf20Sopenharmony_ci	// r2 EEA
13488c2ecf20Sopenharmony_ci	// r6 is physical EEA
13498c2ecf20Sopenharmony_ci	tophys(r6,r2)
13508c2ecf20Sopenharmony_ci
13518c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r5,_immu_trampoline)
13528c2ecf20Sopenharmony_ci	tophys	(r3,r5)			// r3 is trampoline (physical)
13538c2ecf20Sopenharmony_ci
13548c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r4,0x15000000)
13558c2ecf20Sopenharmony_ci	l.sw	TRAMP_SLOT_0(r3),r4
13568c2ecf20Sopenharmony_ci	l.sw	TRAMP_SLOT_1(r3),r4
13578c2ecf20Sopenharmony_ci	l.sw	TRAMP_SLOT_4(r3),r4
13588c2ecf20Sopenharmony_ci	l.sw	TRAMP_SLOT_5(r3),r4
13598c2ecf20Sopenharmony_ci
13608c2ecf20Sopenharmony_ci					// EPC = EEA - 0x4
13618c2ecf20Sopenharmony_ci	l.lwz	r4,0x0(r6)		// load op @ EEA + 0x0 (fc address)
13628c2ecf20Sopenharmony_ci	l.sw	TRAMP_SLOT_3(r3),r4	// store it to _immu_trampoline_data
13638c2ecf20Sopenharmony_ci	l.lwz	r4,-0x4(r6)		// load op @ EEA - 0x4 (f8 address)
13648c2ecf20Sopenharmony_ci	l.sw	TRAMP_SLOT_2(r3),r4	// store it to _immu_trampoline_data
13658c2ecf20Sopenharmony_ci
13668c2ecf20Sopenharmony_ci	l.srli  r5,r4,26                // check opcode for write access
13678c2ecf20Sopenharmony_ci	l.sfeqi r5,0                    // l.j
13688c2ecf20Sopenharmony_ci	l.bf    0f
13698c2ecf20Sopenharmony_ci	l.sfeqi r5,0x11                 // l.jr
13708c2ecf20Sopenharmony_ci	l.bf    1f
13718c2ecf20Sopenharmony_ci	l.sfeqi r5,1                    // l.jal
13728c2ecf20Sopenharmony_ci	l.bf    2f
13738c2ecf20Sopenharmony_ci	l.sfeqi r5,0x12                 // l.jalr
13748c2ecf20Sopenharmony_ci	l.bf    3f
13758c2ecf20Sopenharmony_ci	l.sfeqi r5,3                    // l.bnf
13768c2ecf20Sopenharmony_ci	l.bf    4f
13778c2ecf20Sopenharmony_ci	l.sfeqi r5,4                    // l.bf
13788c2ecf20Sopenharmony_ci	l.bf    5f
13798c2ecf20Sopenharmony_ci99:
13808c2ecf20Sopenharmony_ci	l.nop
13818c2ecf20Sopenharmony_ci	l.j	99b			// should never happen
13828c2ecf20Sopenharmony_ci	l.nop	1
13838c2ecf20Sopenharmony_ci
13848c2ecf20Sopenharmony_ci	// r2 is EEA
13858c2ecf20Sopenharmony_ci	// r3 is trampoline address (physical)
13868c2ecf20Sopenharmony_ci	// r4 is instruction
13878c2ecf20Sopenharmony_ci	// r6 is physical(EEA)
13888c2ecf20Sopenharmony_ci	//
13898c2ecf20Sopenharmony_ci	// r5
13908c2ecf20Sopenharmony_ci
13918c2ecf20Sopenharmony_ci2:	// l.jal
13928c2ecf20Sopenharmony_ci
13938c2ecf20Sopenharmony_ci	/* 19 20 aa aa	l.movhi r9,0xaaaa
13948c2ecf20Sopenharmony_ci	 * a9 29 bb bb  l.ori	r9,0xbbbb
13958c2ecf20Sopenharmony_ci	 *
13968c2ecf20Sopenharmony_ci	 * where 0xaaaabbbb is EEA + 0x4 shifted right 2
13978c2ecf20Sopenharmony_ci	 */
13988c2ecf20Sopenharmony_ci
13998c2ecf20Sopenharmony_ci	l.addi	r6,r2,0x4		// this is 0xaaaabbbb
14008c2ecf20Sopenharmony_ci
14018c2ecf20Sopenharmony_ci					// l.movhi r9,0xaaaa
14028c2ecf20Sopenharmony_ci	l.ori	r5,r0,0x1920		// 0x1920 == l.movhi r9
14038c2ecf20Sopenharmony_ci	l.sh	(TRAMP_SLOT_0+0x0)(r3),r5
14048c2ecf20Sopenharmony_ci	l.srli	r5,r6,16
14058c2ecf20Sopenharmony_ci	l.sh	(TRAMP_SLOT_0+0x2)(r3),r5
14068c2ecf20Sopenharmony_ci
14078c2ecf20Sopenharmony_ci					// l.ori   r9,0xbbbb
14088c2ecf20Sopenharmony_ci	l.ori	r5,r0,0xa929		// 0xa929 == l.ori r9
14098c2ecf20Sopenharmony_ci	l.sh	(TRAMP_SLOT_1+0x0)(r3),r5
14108c2ecf20Sopenharmony_ci	l.andi	r5,r6,0xffff
14118c2ecf20Sopenharmony_ci	l.sh	(TRAMP_SLOT_1+0x2)(r3),r5
14128c2ecf20Sopenharmony_ci
14138c2ecf20Sopenharmony_ci	/* falthrough, need to set up new jump offset */
14148c2ecf20Sopenharmony_ci
14158c2ecf20Sopenharmony_ci
14168c2ecf20Sopenharmony_ci0:	// l.j
14178c2ecf20Sopenharmony_ci	l.slli	r6,r4,6			// original offset shifted left 6 - 2
14188c2ecf20Sopenharmony_ci//	l.srli	r6,r6,6			// original offset shifted right 2
14198c2ecf20Sopenharmony_ci
14208c2ecf20Sopenharmony_ci	l.slli	r4,r2,4			// old jump position: EEA shifted left 4
14218c2ecf20Sopenharmony_ci//	l.srli	r4,r4,6			// old jump position: shifted right 2
14228c2ecf20Sopenharmony_ci
14238c2ecf20Sopenharmony_ci	l.addi	r5,r3,0xc		// new jump position (physical)
14248c2ecf20Sopenharmony_ci	l.slli	r5,r5,4			// new jump position: shifted left 4
14258c2ecf20Sopenharmony_ci
14268c2ecf20Sopenharmony_ci	// calculate new jump offset
14278c2ecf20Sopenharmony_ci	// new_off = old_off + (old_jump - new_jump)
14288c2ecf20Sopenharmony_ci
14298c2ecf20Sopenharmony_ci	l.sub	r5,r4,r5		// old_jump - new_jump
14308c2ecf20Sopenharmony_ci	l.add	r5,r6,r5		// orig_off + (old_jump - new_jump)
14318c2ecf20Sopenharmony_ci	l.srli	r5,r5,6			// new offset shifted right 2
14328c2ecf20Sopenharmony_ci
14338c2ecf20Sopenharmony_ci	// r5 is new jump offset
14348c2ecf20Sopenharmony_ci					// l.j has opcode 0x0...
14358c2ecf20Sopenharmony_ci	l.sw	TRAMP_SLOT_2(r3),r5	// write it back
14368c2ecf20Sopenharmony_ci
14378c2ecf20Sopenharmony_ci	l.j	trampoline_out
14388c2ecf20Sopenharmony_ci	l.nop
14398c2ecf20Sopenharmony_ci
14408c2ecf20Sopenharmony_ci/* ----------------------------- */
14418c2ecf20Sopenharmony_ci
14428c2ecf20Sopenharmony_ci3:	// l.jalr
14438c2ecf20Sopenharmony_ci
14448c2ecf20Sopenharmony_ci	/* 19 20 aa aa	l.movhi r9,0xaaaa
14458c2ecf20Sopenharmony_ci	 * a9 29 bb bb  l.ori	r9,0xbbbb
14468c2ecf20Sopenharmony_ci	 *
14478c2ecf20Sopenharmony_ci	 * where 0xaaaabbbb is EEA + 0x4 shifted right 2
14488c2ecf20Sopenharmony_ci	 */
14498c2ecf20Sopenharmony_ci
14508c2ecf20Sopenharmony_ci	l.addi	r6,r2,0x4		// this is 0xaaaabbbb
14518c2ecf20Sopenharmony_ci
14528c2ecf20Sopenharmony_ci					// l.movhi r9,0xaaaa
14538c2ecf20Sopenharmony_ci	l.ori	r5,r0,0x1920		// 0x1920 == l.movhi r9
14548c2ecf20Sopenharmony_ci	l.sh	(TRAMP_SLOT_0+0x0)(r3),r5
14558c2ecf20Sopenharmony_ci	l.srli	r5,r6,16
14568c2ecf20Sopenharmony_ci	l.sh	(TRAMP_SLOT_0+0x2)(r3),r5
14578c2ecf20Sopenharmony_ci
14588c2ecf20Sopenharmony_ci					// l.ori   r9,0xbbbb
14598c2ecf20Sopenharmony_ci	l.ori	r5,r0,0xa929		// 0xa929 == l.ori r9
14608c2ecf20Sopenharmony_ci	l.sh	(TRAMP_SLOT_1+0x0)(r3),r5
14618c2ecf20Sopenharmony_ci	l.andi	r5,r6,0xffff
14628c2ecf20Sopenharmony_ci	l.sh	(TRAMP_SLOT_1+0x2)(r3),r5
14638c2ecf20Sopenharmony_ci
14648c2ecf20Sopenharmony_ci	l.lhz	r5,(TRAMP_SLOT_2+0x0)(r3)	// load hi part of jump instruction
14658c2ecf20Sopenharmony_ci	l.andi	r5,r5,0x3ff		// clear out opcode part
14668c2ecf20Sopenharmony_ci	l.ori	r5,r5,0x4400		// opcode changed from l.jalr -> l.jr
14678c2ecf20Sopenharmony_ci	l.sh	(TRAMP_SLOT_2+0x0)(r3),r5 // write it back
14688c2ecf20Sopenharmony_ci
14698c2ecf20Sopenharmony_ci	/* falthrough */
14708c2ecf20Sopenharmony_ci
14718c2ecf20Sopenharmony_ci1:	// l.jr
14728c2ecf20Sopenharmony_ci	l.j	trampoline_out
14738c2ecf20Sopenharmony_ci	l.nop
14748c2ecf20Sopenharmony_ci
14758c2ecf20Sopenharmony_ci/* ----------------------------- */
14768c2ecf20Sopenharmony_ci
14778c2ecf20Sopenharmony_ci4:	// l.bnf
14788c2ecf20Sopenharmony_ci5:	// l.bf
14798c2ecf20Sopenharmony_ci	l.slli	r6,r4,6			// original offset shifted left 6 - 2
14808c2ecf20Sopenharmony_ci//	l.srli	r6,r6,6			// original offset shifted right 2
14818c2ecf20Sopenharmony_ci
14828c2ecf20Sopenharmony_ci	l.slli	r4,r2,4			// old jump position: EEA shifted left 4
14838c2ecf20Sopenharmony_ci//	l.srli	r4,r4,6			// old jump position: shifted right 2
14848c2ecf20Sopenharmony_ci
14858c2ecf20Sopenharmony_ci	l.addi	r5,r3,0xc		// new jump position (physical)
14868c2ecf20Sopenharmony_ci	l.slli	r5,r5,4			// new jump position: shifted left 4
14878c2ecf20Sopenharmony_ci
14888c2ecf20Sopenharmony_ci	// calculate new jump offset
14898c2ecf20Sopenharmony_ci	// new_off = old_off + (old_jump - new_jump)
14908c2ecf20Sopenharmony_ci
14918c2ecf20Sopenharmony_ci	l.add	r6,r6,r4		// (orig_off + old_jump)
14928c2ecf20Sopenharmony_ci	l.sub	r6,r6,r5		// (orig_off + old_jump) - new_jump
14938c2ecf20Sopenharmony_ci	l.srli	r6,r6,6			// new offset shifted right 2
14948c2ecf20Sopenharmony_ci
14958c2ecf20Sopenharmony_ci	// r6 is new jump offset
14968c2ecf20Sopenharmony_ci	l.lwz	r4,(TRAMP_SLOT_2+0x0)(r3)	// load jump instruction
14978c2ecf20Sopenharmony_ci	l.srli	r4,r4,16
14988c2ecf20Sopenharmony_ci	l.andi	r4,r4,0xfc00		// get opcode part
14998c2ecf20Sopenharmony_ci	l.slli	r4,r4,16
15008c2ecf20Sopenharmony_ci	l.or	r6,r4,r6		// l.b(n)f new offset
15018c2ecf20Sopenharmony_ci	l.sw	TRAMP_SLOT_2(r3),r6	// write it back
15028c2ecf20Sopenharmony_ci
15038c2ecf20Sopenharmony_ci	/* we need to add l.j to EEA + 0x8 */
15048c2ecf20Sopenharmony_ci	tophys	(r4,r2)			// may not be needed (due to shifts down_
15058c2ecf20Sopenharmony_ci	l.addi	r4,r4,(0x8 - 0x8)	// jump target = r2 + 0x8 (compensate for 0x8)
15068c2ecf20Sopenharmony_ci					// jump position = r5 + 0x8 (0x8 compensated)
15078c2ecf20Sopenharmony_ci	l.sub	r4,r4,r5		// jump offset = target - new_position + 0x8
15088c2ecf20Sopenharmony_ci
15098c2ecf20Sopenharmony_ci	l.slli	r4,r4,4			// the amount of info in imediate of jump
15108c2ecf20Sopenharmony_ci	l.srli	r4,r4,6			// jump instruction with offset
15118c2ecf20Sopenharmony_ci	l.sw	TRAMP_SLOT_4(r3),r4	// write it to 4th slot
15128c2ecf20Sopenharmony_ci
15138c2ecf20Sopenharmony_ci	/* fallthrough */
15148c2ecf20Sopenharmony_ci
15158c2ecf20Sopenharmony_citrampoline_out:
15168c2ecf20Sopenharmony_ci	// set up new EPC to point to our trampoline code
15178c2ecf20Sopenharmony_ci	LOAD_SYMBOL_2_GPR(r5,_immu_trampoline)
15188c2ecf20Sopenharmony_ci	l.mtspr	r0,r5,SPR_EPCR_BASE
15198c2ecf20Sopenharmony_ci
15208c2ecf20Sopenharmony_ci	// immu_trampoline is (4x) CACHE_LINE aligned
15218c2ecf20Sopenharmony_ci	// and only 6 instructions long,
15228c2ecf20Sopenharmony_ci	// so we need to invalidate only 2 lines
15238c2ecf20Sopenharmony_ci
15248c2ecf20Sopenharmony_ci	/* Establish cache block size
15258c2ecf20Sopenharmony_ci	   If BS=0, 16;
15268c2ecf20Sopenharmony_ci	   If BS=1, 32;
15278c2ecf20Sopenharmony_ci	   r14 contain block size
15288c2ecf20Sopenharmony_ci	*/
15298c2ecf20Sopenharmony_ci	l.mfspr r21,r0,SPR_ICCFGR
15308c2ecf20Sopenharmony_ci	l.andi	r21,r21,SPR_ICCFGR_CBS
15318c2ecf20Sopenharmony_ci	l.srli	r21,r21,7
15328c2ecf20Sopenharmony_ci	l.ori	r23,r0,16
15338c2ecf20Sopenharmony_ci	l.sll	r14,r23,r21
15348c2ecf20Sopenharmony_ci
15358c2ecf20Sopenharmony_ci	l.mtspr	r0,r5,SPR_ICBIR
15368c2ecf20Sopenharmony_ci	l.add	r5,r5,r14
15378c2ecf20Sopenharmony_ci	l.mtspr	r0,r5,SPR_ICBIR
15388c2ecf20Sopenharmony_ci
15398c2ecf20Sopenharmony_ci	l.jr	r9
15408c2ecf20Sopenharmony_ci	l.nop
15418c2ecf20Sopenharmony_ci
15428c2ecf20Sopenharmony_ci
15438c2ecf20Sopenharmony_ci/*
15448c2ecf20Sopenharmony_ci * DSCR: prints a string referenced by r3.
15458c2ecf20Sopenharmony_ci *
15468c2ecf20Sopenharmony_ci * PRMS: r3     	- address of the first character of null
15478c2ecf20Sopenharmony_ci *			terminated string to be printed
15488c2ecf20Sopenharmony_ci *
15498c2ecf20Sopenharmony_ci * PREQ: UART at UART_BASE_ADD has to be initialized
15508c2ecf20Sopenharmony_ci *
15518c2ecf20Sopenharmony_ci * POST: caller should be aware that r3, r9 are changed
15528c2ecf20Sopenharmony_ci */
15538c2ecf20Sopenharmony_ciENTRY(_emergency_print)
15548c2ecf20Sopenharmony_ci	EMERGENCY_PRINT_STORE_GPR4
15558c2ecf20Sopenharmony_ci	EMERGENCY_PRINT_STORE_GPR5
15568c2ecf20Sopenharmony_ci	EMERGENCY_PRINT_STORE_GPR6
15578c2ecf20Sopenharmony_ci	EMERGENCY_PRINT_STORE_GPR7
15588c2ecf20Sopenharmony_ci2:
15598c2ecf20Sopenharmony_ci	l.lbz	r7,0(r3)
15608c2ecf20Sopenharmony_ci	l.sfeq	r7,r0
15618c2ecf20Sopenharmony_ci	l.bf	9f
15628c2ecf20Sopenharmony_ci	l.nop
15638c2ecf20Sopenharmony_ci
15648c2ecf20Sopenharmony_ci// putc:
15658c2ecf20Sopenharmony_ci	l.movhi r4,hi(UART_BASE_ADD)
15668c2ecf20Sopenharmony_ci
15678c2ecf20Sopenharmony_ci	l.addi  r6,r0,0x20
15688c2ecf20Sopenharmony_ci1:      l.lbz   r5,5(r4)
15698c2ecf20Sopenharmony_ci	l.andi  r5,r5,0x20
15708c2ecf20Sopenharmony_ci	l.sfeq  r5,r6
15718c2ecf20Sopenharmony_ci	l.bnf   1b
15728c2ecf20Sopenharmony_ci	l.nop
15738c2ecf20Sopenharmony_ci
15748c2ecf20Sopenharmony_ci	l.sb    0(r4),r7
15758c2ecf20Sopenharmony_ci
15768c2ecf20Sopenharmony_ci	l.addi  r6,r0,0x60
15778c2ecf20Sopenharmony_ci1:      l.lbz   r5,5(r4)
15788c2ecf20Sopenharmony_ci	l.andi  r5,r5,0x60
15798c2ecf20Sopenharmony_ci	l.sfeq  r5,r6
15808c2ecf20Sopenharmony_ci	l.bnf   1b
15818c2ecf20Sopenharmony_ci	l.nop
15828c2ecf20Sopenharmony_ci
15838c2ecf20Sopenharmony_ci	/* next character */
15848c2ecf20Sopenharmony_ci	l.j	2b
15858c2ecf20Sopenharmony_ci	l.addi	r3,r3,0x1
15868c2ecf20Sopenharmony_ci
15878c2ecf20Sopenharmony_ci9:
15888c2ecf20Sopenharmony_ci	EMERGENCY_PRINT_LOAD_GPR7
15898c2ecf20Sopenharmony_ci	EMERGENCY_PRINT_LOAD_GPR6
15908c2ecf20Sopenharmony_ci	EMERGENCY_PRINT_LOAD_GPR5
15918c2ecf20Sopenharmony_ci	EMERGENCY_PRINT_LOAD_GPR4
15928c2ecf20Sopenharmony_ci	l.jr	r9
15938c2ecf20Sopenharmony_ci	l.nop
15948c2ecf20Sopenharmony_ci
15958c2ecf20Sopenharmony_ciENTRY(_emergency_print_nr)
15968c2ecf20Sopenharmony_ci	EMERGENCY_PRINT_STORE_GPR4
15978c2ecf20Sopenharmony_ci	EMERGENCY_PRINT_STORE_GPR5
15988c2ecf20Sopenharmony_ci	EMERGENCY_PRINT_STORE_GPR6
15998c2ecf20Sopenharmony_ci	EMERGENCY_PRINT_STORE_GPR7
16008c2ecf20Sopenharmony_ci	EMERGENCY_PRINT_STORE_GPR8
16018c2ecf20Sopenharmony_ci
16028c2ecf20Sopenharmony_ci	l.addi	r8,r0,32		// shift register
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_ci1:	/* remove leading zeros */
16058c2ecf20Sopenharmony_ci	l.addi	r8,r8,-0x4
16068c2ecf20Sopenharmony_ci	l.srl	r7,r3,r8
16078c2ecf20Sopenharmony_ci	l.andi	r7,r7,0xf
16088c2ecf20Sopenharmony_ci
16098c2ecf20Sopenharmony_ci	/* don't skip the last zero if number == 0x0 */
16108c2ecf20Sopenharmony_ci	l.sfeqi	r8,0x4
16118c2ecf20Sopenharmony_ci	l.bf	2f
16128c2ecf20Sopenharmony_ci	l.nop
16138c2ecf20Sopenharmony_ci
16148c2ecf20Sopenharmony_ci	l.sfeq	r7,r0
16158c2ecf20Sopenharmony_ci	l.bf	1b
16168c2ecf20Sopenharmony_ci	l.nop
16178c2ecf20Sopenharmony_ci
16188c2ecf20Sopenharmony_ci2:
16198c2ecf20Sopenharmony_ci	l.srl	r7,r3,r8
16208c2ecf20Sopenharmony_ci
16218c2ecf20Sopenharmony_ci	l.andi	r7,r7,0xf
16228c2ecf20Sopenharmony_ci	l.sflts	r8,r0
16238c2ecf20Sopenharmony_ci	l.bf	9f
16248c2ecf20Sopenharmony_ci
16258c2ecf20Sopenharmony_ci	l.sfgtui r7,0x9
16268c2ecf20Sopenharmony_ci	l.bnf	8f
16278c2ecf20Sopenharmony_ci	l.nop
16288c2ecf20Sopenharmony_ci	l.addi	r7,r7,0x27
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci8:
16318c2ecf20Sopenharmony_ci	l.addi	r7,r7,0x30
16328c2ecf20Sopenharmony_ci// putc:
16338c2ecf20Sopenharmony_ci	l.movhi r4,hi(UART_BASE_ADD)
16348c2ecf20Sopenharmony_ci
16358c2ecf20Sopenharmony_ci	l.addi  r6,r0,0x20
16368c2ecf20Sopenharmony_ci1:      l.lbz   r5,5(r4)
16378c2ecf20Sopenharmony_ci	l.andi  r5,r5,0x20
16388c2ecf20Sopenharmony_ci	l.sfeq  r5,r6
16398c2ecf20Sopenharmony_ci	l.bnf   1b
16408c2ecf20Sopenharmony_ci	l.nop
16418c2ecf20Sopenharmony_ci
16428c2ecf20Sopenharmony_ci	l.sb    0(r4),r7
16438c2ecf20Sopenharmony_ci
16448c2ecf20Sopenharmony_ci	l.addi  r6,r0,0x60
16458c2ecf20Sopenharmony_ci1:      l.lbz   r5,5(r4)
16468c2ecf20Sopenharmony_ci	l.andi  r5,r5,0x60
16478c2ecf20Sopenharmony_ci	l.sfeq  r5,r6
16488c2ecf20Sopenharmony_ci	l.bnf   1b
16498c2ecf20Sopenharmony_ci	l.nop
16508c2ecf20Sopenharmony_ci
16518c2ecf20Sopenharmony_ci	/* next character */
16528c2ecf20Sopenharmony_ci	l.j	2b
16538c2ecf20Sopenharmony_ci	l.addi	r8,r8,-0x4
16548c2ecf20Sopenharmony_ci
16558c2ecf20Sopenharmony_ci9:
16568c2ecf20Sopenharmony_ci	EMERGENCY_PRINT_LOAD_GPR8
16578c2ecf20Sopenharmony_ci	EMERGENCY_PRINT_LOAD_GPR7
16588c2ecf20Sopenharmony_ci	EMERGENCY_PRINT_LOAD_GPR6
16598c2ecf20Sopenharmony_ci	EMERGENCY_PRINT_LOAD_GPR5
16608c2ecf20Sopenharmony_ci	EMERGENCY_PRINT_LOAD_GPR4
16618c2ecf20Sopenharmony_ci	l.jr	r9
16628c2ecf20Sopenharmony_ci	l.nop
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_ci
16658c2ecf20Sopenharmony_ci/*
16668c2ecf20Sopenharmony_ci * This should be used for debugging only.
16678c2ecf20Sopenharmony_ci * It messes up the Linux early serial output
16688c2ecf20Sopenharmony_ci * somehow, so use it sparingly and essentially
16698c2ecf20Sopenharmony_ci * only if you need to debug something that goes wrong
16708c2ecf20Sopenharmony_ci * before Linux gets the early serial going.
16718c2ecf20Sopenharmony_ci *
16728c2ecf20Sopenharmony_ci * Furthermore, you'll have to make sure you set the
16738c2ecf20Sopenharmony_ci * UART_DEVISOR correctly according to the system
16748c2ecf20Sopenharmony_ci * clock rate.
16758c2ecf20Sopenharmony_ci *
16768c2ecf20Sopenharmony_ci *
16778c2ecf20Sopenharmony_ci */
16788c2ecf20Sopenharmony_ci
16798c2ecf20Sopenharmony_ci
16808c2ecf20Sopenharmony_ci
16818c2ecf20Sopenharmony_ci#define SYS_CLK            20000000
16828c2ecf20Sopenharmony_ci//#define SYS_CLK            1843200
16838c2ecf20Sopenharmony_ci#define OR32_CONSOLE_BAUD  115200
16848c2ecf20Sopenharmony_ci#define UART_DIVISOR       SYS_CLK/(16*OR32_CONSOLE_BAUD)
16858c2ecf20Sopenharmony_ci
16868c2ecf20Sopenharmony_ciENTRY(_early_uart_init)
16878c2ecf20Sopenharmony_ci	l.movhi	r3,hi(UART_BASE_ADD)
16888c2ecf20Sopenharmony_ci
16898c2ecf20Sopenharmony_ci	l.addi	r4,r0,0x7
16908c2ecf20Sopenharmony_ci	l.sb	0x2(r3),r4
16918c2ecf20Sopenharmony_ci
16928c2ecf20Sopenharmony_ci	l.addi	r4,r0,0x0
16938c2ecf20Sopenharmony_ci	l.sb	0x1(r3),r4
16948c2ecf20Sopenharmony_ci
16958c2ecf20Sopenharmony_ci	l.addi	r4,r0,0x3
16968c2ecf20Sopenharmony_ci	l.sb	0x3(r3),r4
16978c2ecf20Sopenharmony_ci
16988c2ecf20Sopenharmony_ci	l.lbz	r5,3(r3)
16998c2ecf20Sopenharmony_ci	l.ori	r4,r5,0x80
17008c2ecf20Sopenharmony_ci	l.sb	0x3(r3),r4
17018c2ecf20Sopenharmony_ci	l.addi	r4,r0,((UART_DIVISOR>>8) & 0x000000ff)
17028c2ecf20Sopenharmony_ci	l.sb	UART_DLM(r3),r4
17038c2ecf20Sopenharmony_ci	l.addi  r4,r0,((UART_DIVISOR) & 0x000000ff)
17048c2ecf20Sopenharmony_ci	l.sb	UART_DLL(r3),r4
17058c2ecf20Sopenharmony_ci	l.sb	0x3(r3),r5
17068c2ecf20Sopenharmony_ci
17078c2ecf20Sopenharmony_ci	l.jr	r9
17088c2ecf20Sopenharmony_ci	l.nop
17098c2ecf20Sopenharmony_ci
17108c2ecf20Sopenharmony_ci	.align	0x1000
17118c2ecf20Sopenharmony_ci	.global _secondary_evbar
17128c2ecf20Sopenharmony_ci_secondary_evbar:
17138c2ecf20Sopenharmony_ci
17148c2ecf20Sopenharmony_ci	.space 0x800
17158c2ecf20Sopenharmony_ci	/* Just disable interrupts and Return */
17168c2ecf20Sopenharmony_ci	l.ori	r3,r0,SPR_SR_SM
17178c2ecf20Sopenharmony_ci	l.mtspr	r0,r3,SPR_ESR_BASE
17188c2ecf20Sopenharmony_ci	l.rfe
17198c2ecf20Sopenharmony_ci
17208c2ecf20Sopenharmony_ci
17218c2ecf20Sopenharmony_ci	.section .rodata
17228c2ecf20Sopenharmony_ci_string_unhandled_exception:
17238c2ecf20Sopenharmony_ci	.string "\n\rRunarunaround: Unhandled exception 0x\0"
17248c2ecf20Sopenharmony_ci
17258c2ecf20Sopenharmony_ci_string_epc_prefix:
17268c2ecf20Sopenharmony_ci	.string ": EPC=0x\0"
17278c2ecf20Sopenharmony_ci
17288c2ecf20Sopenharmony_ci_string_nl:
17298c2ecf20Sopenharmony_ci	.string "\n\r\0"
17308c2ecf20Sopenharmony_ci
17318c2ecf20Sopenharmony_ci
17328c2ecf20Sopenharmony_ci/* ========================================[ page aligned structures ]=== */
17338c2ecf20Sopenharmony_ci
17348c2ecf20Sopenharmony_ci/*
17358c2ecf20Sopenharmony_ci * .data section should be page aligned
17368c2ecf20Sopenharmony_ci *	(look into arch/openrisc/kernel/vmlinux.lds.S)
17378c2ecf20Sopenharmony_ci */
17388c2ecf20Sopenharmony_ci	.section .data,"aw"
17398c2ecf20Sopenharmony_ci	.align	8192
17408c2ecf20Sopenharmony_ci	.global  empty_zero_page
17418c2ecf20Sopenharmony_ciempty_zero_page:
17428c2ecf20Sopenharmony_ci	.space  8192
17438c2ecf20Sopenharmony_ci
17448c2ecf20Sopenharmony_ci	.global  swapper_pg_dir
17458c2ecf20Sopenharmony_ciswapper_pg_dir:
17468c2ecf20Sopenharmony_ci	.space  8192
17478c2ecf20Sopenharmony_ci
17488c2ecf20Sopenharmony_ci	.global	_unhandled_stack
17498c2ecf20Sopenharmony_ci_unhandled_stack:
17508c2ecf20Sopenharmony_ci	.space	8192
17518c2ecf20Sopenharmony_ci_unhandled_stack_top:
17528c2ecf20Sopenharmony_ci
17538c2ecf20Sopenharmony_ci/* ============================================================[ EOF ]=== */
1754