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