/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* OpenRISC head.S
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* Modifications for the OpenRISC architecture:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
*/
#include <linux/linkage.h>
#include <linux/threads.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/serial_reg.h>
#include <linux/pgtable.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/mmu.h>
#include <asm/thread_info.h>
#include <asm/cache.h>
#include <asm/spr_defs.h>
#include <asm/asm-offsets.h>
#include <linux/of_fdt.h>
#define tophys(rd,rs) \
l.movhi rd,hi(-KERNELBASE) ;\
l.add rd,rd,rs
#define CLEAR_GPR(gpr) \
l.movhi gpr,0x0
#define LOAD_SYMBOL_2_GPR(gpr,symbol) \
l.movhi gpr,hi(symbol) ;\
l.ori gpr,gpr,lo(symbol)
#define UART_BASE_ADD 0x90000000
#define EXCEPTION_SR (SPR_SR_DME | SPR_SR_IME | SPR_SR_DCE | SPR_SR_ICE | SPR_SR_SM)
#define SYSCALL_SR (SPR_SR_DME | SPR_SR_IME | SPR_SR_DCE | SPR_SR_ICE | SPR_SR_IEE | SPR_SR_TEE | SPR_SR_SM)
/* ============================================[ tmp store locations ]=== */
#define SPR_SHADOW_GPR(x) ((x) + SPR_GPR_BASE + 32)
/*
* emergency_print temporary stores
*/
#ifdef CONFIG_OPENRISC_HAVE_SHADOW_GPRS
#define EMERGENCY_PRINT_STORE_GPR4 l.mtspr r0,r4,SPR_SHADOW_GPR(14)
#define EMERGENCY_PRINT_LOAD_GPR4 l.mfspr r4,r0,SPR_SHADOW_GPR(14)
#define EMERGENCY_PRINT_STORE_GPR5 l.mtspr r0,r5,SPR_SHADOW_GPR(15)
#define EMERGENCY_PRINT_LOAD_GPR5 l.mfspr r5,r0,SPR_SHADOW_GPR(15)
#define EMERGENCY_PRINT_STORE_GPR6 l.mtspr r0,r6,SPR_SHADOW_GPR(16)
#define EMERGENCY_PRINT_LOAD_GPR6 l.mfspr r6,r0,SPR_SHADOW_GPR(16)
#define EMERGENCY_PRINT_STORE_GPR7 l.mtspr r0,r7,SPR_SHADOW_GPR(7)
#define EMERGENCY_PRINT_LOAD_GPR7 l.mfspr r7,r0,SPR_SHADOW_GPR(7)
#define EMERGENCY_PRINT_STORE_GPR8 l.mtspr r0,r8,SPR_SHADOW_GPR(8)
#define EMERGENCY_PRINT_LOAD_GPR8 l.mfspr r8,r0,SPR_SHADOW_GPR(8)
#define EMERGENCY_PRINT_STORE_GPR9 l.mtspr r0,r9,SPR_SHADOW_GPR(9)
#define EMERGENCY_PRINT_LOAD_GPR9 l.mfspr r9,r0,SPR_SHADOW_GPR(9)
#else /* !CONFIG_OPENRISC_HAVE_SHADOW_GPRS */
#define EMERGENCY_PRINT_STORE_GPR4 l.sw 0x20(r0),r4
#define EMERGENCY_PRINT_LOAD_GPR4 l.lwz r4,0x20(r0)
#define EMERGENCY_PRINT_STORE_GPR5 l.sw 0x24(r0),r5
#define EMERGENCY_PRINT_LOAD_GPR5 l.lwz r5,0x24(r0)
#define EMERGENCY_PRINT_STORE_GPR6 l.sw 0x28(r0),r6
#define EMERGENCY_PRINT_LOAD_GPR6 l.lwz r6,0x28(r0)
#define EMERGENCY_PRINT_STORE_GPR7 l.sw 0x2c(r0),r7
#define EMERGENCY_PRINT_LOAD_GPR7 l.lwz r7,0x2c(r0)
#define EMERGENCY_PRINT_STORE_GPR8 l.sw 0x30(r0),r8
#define EMERGENCY_PRINT_LOAD_GPR8 l.lwz r8,0x30(r0)
#define EMERGENCY_PRINT_STORE_GPR9 l.sw 0x34(r0),r9
#define EMERGENCY_PRINT_LOAD_GPR9 l.lwz r9,0x34(r0)
#endif
/*
* TLB miss handlers temorary stores
*/
#ifdef CONFIG_OPENRISC_HAVE_SHADOW_GPRS
#define EXCEPTION_STORE_GPR2 l.mtspr r0,r2,SPR_SHADOW_GPR(2)
#define EXCEPTION_LOAD_GPR2 l.mfspr r2,r0,SPR_SHADOW_GPR(2)
#define EXCEPTION_STORE_GPR3 l.mtspr r0,r3,SPR_SHADOW_GPR(3)
#define EXCEPTION_LOAD_GPR3 l.mfspr r3,r0,SPR_SHADOW_GPR(3)
#define EXCEPTION_STORE_GPR4 l.mtspr r0,r4,SPR_SHADOW_GPR(4)
#define EXCEPTION_LOAD_GPR4 l.mfspr r4,r0,SPR_SHADOW_GPR(4)
#define EXCEPTION_STORE_GPR5 l.mtspr r0,r5,SPR_SHADOW_GPR(5)
#define EXCEPTION_LOAD_GPR5 l.mfspr r5,r0,SPR_SHADOW_GPR(5)
#define EXCEPTION_STORE_GPR6 l.mtspr r0,r6,SPR_SHADOW_GPR(6)
#define EXCEPTION_LOAD_GPR6 l.mfspr r6,r0,SPR_SHADOW_GPR(6)
#else /* !CONFIG_OPENRISC_HAVE_SHADOW_GPRS */
#define EXCEPTION_STORE_GPR2 l.sw 0x64(r0),r2
#define EXCEPTION_LOAD_GPR2 l.lwz r2,0x64(r0)
#define EXCEPTION_STORE_GPR3 l.sw 0x68(r0),r3
#define EXCEPTION_LOAD_GPR3 l.lwz r3,0x68(r0)
#define EXCEPTION_STORE_GPR4 l.sw 0x6c(r0),r4
#define EXCEPTION_LOAD_GPR4 l.lwz r4,0x6c(r0)
#define EXCEPTION_STORE_GPR5 l.sw 0x70(r0),r5
#define EXCEPTION_LOAD_GPR5 l.lwz r5,0x70(r0)
#define EXCEPTION_STORE_GPR6 l.sw 0x74(r0),r6
#define EXCEPTION_LOAD_GPR6 l.lwz r6,0x74(r0)
#endif
/*
* EXCEPTION_HANDLE temporary stores
*/
#ifdef CONFIG_OPENRISC_HAVE_SHADOW_GPRS
#define EXCEPTION_T_STORE_GPR30 l.mtspr r0,r30,SPR_SHADOW_GPR(30)
#define EXCEPTION_T_LOAD_GPR30(reg) l.mfspr reg,r0,SPR_SHADOW_GPR(30)
#define EXCEPTION_T_STORE_GPR10 l.mtspr r0,r10,SPR_SHADOW_GPR(10)
#define EXCEPTION_T_LOAD_GPR10(reg) l.mfspr reg,r0,SPR_SHADOW_GPR(10)
#define EXCEPTION_T_STORE_SP l.mtspr r0,r1,SPR_SHADOW_GPR(1)
#define EXCEPTION_T_LOAD_SP(reg) l.mfspr reg,r0,SPR_SHADOW_GPR(1)
#else /* !CONFIG_OPENRISC_HAVE_SHADOW_GPRS */
#define EXCEPTION_T_STORE_GPR30 l.sw 0x78(r0),r30
#define EXCEPTION_T_LOAD_GPR30(reg) l.lwz reg,0x78(r0)
#define EXCEPTION_T_STORE_GPR10 l.sw 0x7c(r0),r10
#define EXCEPTION_T_LOAD_GPR10(reg) l.lwz reg,0x7c(r0)
#define EXCEPTION_T_STORE_SP l.sw 0x80(r0),r1
#define EXCEPTION_T_LOAD_SP(reg) l.lwz reg,0x80(r0)
#endif
/* =========================================================[ macros ]=== */
#ifdef CONFIG_SMP
#define GET_CURRENT_PGD(reg,t1) \
LOAD_SYMBOL_2_GPR(reg,current_pgd) ;\
l.mfspr t1,r0,SPR_COREID ;\
l.slli t1,t1,2 ;\
l.add reg,reg,t1 ;\
tophys (t1,reg) ;\
l.lwz reg,0(t1)
#else
#define GET_CURRENT_PGD(reg,t1) \
LOAD_SYMBOL_2_GPR(reg,current_pgd) ;\
tophys (t1,reg) ;\
l.lwz reg,0(t1)
#endif
/* Load r10 from current_thread_info_set - clobbers r1 and r30 */
#ifdef CONFIG_SMP
#define GET_CURRENT_THREAD_INFO \
LOAD_SYMBOL_2_GPR(r1,current_thread_info_set) ;\
tophys (r30,r1) ;\
l.mfspr r10,r0,SPR_COREID ;\
l.slli r10,r10,2 ;\
l.add r30,r30,r10 ;\
/* r10: current_thread_info */ ;\
l.lwz r10,0(r30)
#else
#define GET_CURRENT_
|