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