/* * OpenRISC entry.S * * Linux architectural port borrowing liberally from similar works of * others. All original copyrights apply as per the original source * declaration. * * Modifications for the OpenRISC architecture: * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> * Copyright (C) 2005 Gyorgy Jeney <nog@bsemi.com> * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ #include <linux/linkage.h> #include <asm/processor.h>#include <asm/unistd.h>#include <asm/thread_info.h>#include <asm/errno.h>#include <asm/spr_defs.h>#include <asm/page.h>#include <asm/mmu.h>#include <asm/pgtable.h>#include <asm/asm-offsets.h> #define DISABLE_INTERRUPTS(t1,t2) \ l.mfspr t2,r0,SPR_SR ;\ l.movhi t1,hi(~(SPR_SR_IEE|SPR_SR_TEE)) ;\ l.ori t1,t1,lo(~(SPR_SR_IEE|SPR_SR_TEE)) ;\ l.and t2,t2,t1 ;\ l.mtspr r0,t2,SPR_SR #define ENABLE_INTERRUPTS(t1) \ l.mfspr t1,r0,SPR_SR ;\ l.ori t1,t1,lo(SPR_SR_IEE|SPR_SR_TEE) ;\ l.mtspr r0,t1,SPR_SR /* =========================================================[ macros ]=== */ /* * We need to disable interrupts at beginning of RESTORE_ALL * since interrupt might come in after we've loaded EPC return address * and overwrite EPC with address somewhere in RESTORE_ALL * which is of course wrong! */ #define RESTORE_ALL \ DISABLE_INTERRUPTS(r3,r4) ;\ l.lwz r3,PT_PC(r1) ;\ l.mtspr r0,r3,SPR_EPCR_BASE ;\ l.lwz r3,PT_SR(r1) ;\ l.mtspr r0,r3,SPR_ESR_BASE ;\ l.lwz r2,PT_GPR2(r1) ;\ l.lwz r3,PT_GPR3(r1) ;\ l.lwz r4,PT_GPR4(r1) ;\ l.lwz r5,PT_GPR5(r1) ;\ l.lwz r6,PT_GPR6(r1) ;\ l.lwz r7,PT_GPR7(r1) ;\ l.lwz r8,PT_GPR8(r1) ;\ l.lwz r9,PT_GPR9(r1) ;\ l.lwz r10,PT_GPR10(r1) ;\ l.lwz r11,PT_GPR11(r1) ;\ l.lwz r12,PT_GPR12(r1) ;\ l.lwz r13,PT_GPR13(r1) ;\ l.lwz r14,PT_GPR14(r1) ;\ l.lwz r15,PT_GPR15(r1) ;\ l.lwz r16,PT_GPR16(r1) ;\ l.lwz r17,PT_GPR17(r1) ;\ l.lwz r18,PT_GPR18(r1) ;\ l.lwz r19,PT_GPR19(r1) ;\ l.lwz r20,PT_GPR20(r1) ;\ l.lwz r21,PT_GPR21(r1) ;\ l.lwz r22,PT_GPR22(r1) ;\ l.lwz r23,PT_GPR23(r1) ;\ l.lwz r24,PT_GPR24(r1) ;\ l.lwz r25,PT_GPR25(r1) ;\ l.lwz r26,PT_GPR26(r1) ;\ l.lwz r27,PT_GPR27(r1) ;\ l.lwz r28,PT_GPR28(r1) ;\ l.lwz r29,PT_GPR29(r1) ;\ l.lwz r30,PT_GPR30(r1) ;\ l.lwz r31,PT_GPR31(r1) ;\ l.lwz r1,PT_SP(r1) ;\ l.rfe #define EXCEPTION_ENTRY(handler) \ .global handler ;\handler: ;\ /* r1, EPCR, ESR a already saved */ ;\ l.sw PT_GPR2(r1),r2 ;\ l.sw PT_GPR3(r1),r3 ;\ /* r4 already save */ ;\ l.sw PT_GPR5(r1),r5 ;\ l.sw PT_GPR6(r1),r6 ;\ l.sw PT_GPR7(r1),r7 ;\ l.sw PT_GPR8(r1),r8 ;\ l.sw PT_GPR9(r1),r9 ;\ /* r10 already saved */ ;\ l.sw PT_GPR11(r1),r11 ;\ /* r12 already saved */ ;\ l.sw PT_GPR13(r1),r13 ;\ l.sw PT_GPR14(r1),r14 ;\ l.sw PT_GPR15(r1),r15 ;\ l.sw PT_GPR16(r1),r16 ;\ l.sw PT_GPR17(r1),r17 ;\ l.sw PT_GPR18(r1),r18 ;\ l.sw PT_GPR19(r1),r19 ;\ l.sw PT_GPR20(r1),r20 ;\ l.sw PT_GPR21(r1),r21 ;\ l.sw PT_GPR22(r1),r22 ;\ l.sw PT_GPR23(r1),r23 ;\ l.sw PT_GPR24(r1),r24 ;\ l.sw PT_GPR25(r1),r25 ;\ l.sw PT_GPR26(r1),r26 ;\ l.sw PT_GPR27(r1),r27 ;\ l.sw PT_GPR28(r1),r28 ;\ l.sw PT_GPR29(r1),r29 ;\ /* r30 already save */ ;\/* l.sw PT_GPR30(r1),r30*/ ;\ l.sw PT_GPR31(r1),r31 ;\ /* Store -1 in orig_gpr11 for non-syscall exceptions */ ;\ l.addi r30,r0,-1 ;\ l.sw PT_ORIG_GPR11(r1),r30 #define UNHANDLED_EXCEPTION(handler,vector) \ .global handler ;\handler: ;\ /* r1, EPCR, ESR already saved */ ;\ l.sw PT_GPR2(r1),r2 ;\ l.sw PT_GPR3(r1),r3 ;\ l.sw PT_GPR5(r1),r5 ;\ l.sw PT_GPR6(r1),r6 ;\ l.sw PT_GPR7(r1),r7 ;\ l.sw PT_GPR8(r1),r8 ;\ l.sw PT_GPR9(r1),r9 ;\ /* r10 already saved */ ;\ l.sw PT_GPR11(r1),r11 ;\ /* r12 already saved */ ;\ l.sw PT_GPR13(r1),r13 ;\ l.sw PT_GPR14(r1),r14 ;\ l.sw PT_GPR15(r1),r15 ;\ l.sw PT_GPR16(r1),r16 ;\ l.sw PT_GPR17(r1),r17 ;\ l.sw PT_GPR18(r1),r18 ;\ l.sw PT_GPR19(r1),r19 ;\ l.sw PT_GPR20(r1),r20 ;\ l.sw PT_GPR21(r1),r21 ;\ l.sw PT_GPR22(r1),r22 ;\ l.sw PT_GPR23(r1),r23 ;\ l.sw PT_GPR24(r1),r24 ;\ l.sw PT_GPR25(r1),r25 ;\ l.sw PT_GPR26(r1),r26 ;\ l.sw PT_GPR27(r1),r27 ;\ l.sw PT_GPR28(r1),r28 ;\ l.sw PT_GPR29(r1),r29 ;\ /* r31 already saved */ ;\ l.sw PT_GPR30(r1),r30 ;\/* l.sw PT_GPR31(r1),r31 */ ;\ /* Store -1 in orig_gpr11 for non-syscall exceptions */ ;\ l.addi r30,r0,-1 ;\ l.sw PT_ORIG_GPR11(r1),r30 ;\ l.addi r3,r1,0 ;\ /* r4 is exception EA */ ;\ l.addi r5,r0,vector ;\ l.jal unhandled_exception ;\ l.nop ;\ l.j _ret_from_exception ;\ l.nop /* * NOTE: one should never assume that SPR_EPC, SPR_ESR, SPR_EEAR * contain the same values as when exception we're handling * occured. in fact they never do. if you need them use * values saved on stack (for SPR_EPC, SPR_ESR) or content * of r4 (for SPR_EEAR). for details look at EXCEPTION_HANDLE() * in 'arch/or32/kernel/head.S' */ /* =====================================================[ exceptions] === */ /* ---[ 0x100: RESET exception ]----------------------------------------- */ EXCEPTION_ENTRY(_tng_kernel_start) l.jal _start l.andi r0,r0,0 /* ---[ 0x200: BUS exception ]------------------------------------------- */ EXCEPTION_ENTRY(_bus_fault_handler) /* r4: EA of fault (set by EXCEPTION_HANDLE) */ l.jal do_bus_fault l.addi r3,r1,0 /* pt_regs */ l.j _ret_from_exception l.nop /* ---[ 0x300: Data Page Fault exception ]------------------------------- */EXCEPTION_ENTRY(_dtlb_miss_page_fault_handler) l.and r5,r5,r0 l.j 1f l.nop EXCEPTION_ENTRY(_data_page_fault_handler) /* set up parameters for do_page_fault */ l.ori r5,r0,0x300 // exception vector1: l.addi r3,r1,0 // pt_regs /* r4 set be EXCEPTION_HANDLE */ // effective address of fault /* * __PHX__: TODO * * all this can be written much simpler. look at * DTLB miss handler in the CONFIG_GUARD_PROTECTED_CORE part */#ifdef CONFIG_OPENRISC_NO_SPR_SR_DSX l.lwz r6,PT_PC(r3) // address of an offending insn l.lwz r6,0(r6) // instruction that caused pf l.srli r6,r6,26 // check opcode for jump insn l.sfeqi r6,0 // l.j l.bf 8f l.sfeqi r6,1 // l.jal l.bf 8f l.sfeqi r6,3 // l.bnf l.bf 8f l.sfeqi r6,4 // l.bf l.bf 8f l.sfeqi r6,0x11 // l.jr l.bf 8f l.sfeqi r6,0x12 // l.jalr l.bf 8f l.nop l.j 9f l.nop8: l.lwz r6,PT_PC(r3) // address of an offending insn l.addi r6,r6,4 l.lwz r6,0(r6) // instruction that caused pf l.srli r6,r6,26 // get opcode9: #else l.mfspr r6,r0,SPR_SR // SR// l.lwz r6,PT_SR(r3) // ESR l.andi r6,r6,SPR_SR_DSX // check for delay slot exception l.sfeqi r6,0x1 // exception happened in delay slot l.bnf 7f l.lwz r6,PT_PC(r3) // address of an offending insn l.addi r6,r6,4 // offending insn is in delay slot7: l.lwz r6,0(r6) // instruction that caused pf l.srli r6,r6,26 // check opcode for write access#endif l.sfgeui r6,0x34 // check opcode for write access l.bnf 1f l.sfleui r6,0x37 l.bnf 1f l.ori r6,r0,0x1 // write access l.j 2f l.nop1: l.ori r6,r0,0x0 // !write access2: /* call fault.c handler in or32/mm/fault.c */ l.jal do_page_fault l.nop l.j _ret_from_exception l.nop /* ---[ 0x400: Insn Page Fault exception ]------------------------------- */EXCEPTION_ENTRY(_itlb_miss_page_fault_handler) l.and r5,r5,r0 l.j 1f l.nop EXCEPTION_ENTRY(_insn_page_fault_handler) /* set up parameters for do_page_fault */ l.ori r5,r0,0x400 // exception vector1: l.addi r3,r1,0 // pt_regs /* r4 set be EXCEPTION_HANDLE */ // effective address of fault l.ori r6,r0,0x0 // !write access /* call fault.c handler in or32/mm/fault.c */ l.jal do_page_fault l.nop l.j _ret_from_exception l.nop /* ---[ 0x500: Timer exception ]----------------------------------------- */ EXCEPTION_ENTRY(_timer_handler) l.jal timer_interrupt l.addi r3,r1,0 /* pt_regs */ l.j _ret_from_intr l.nop /* ---[ 0x600: Aligment exception ]-------------------------------------- */ EXCEPTION_ENTRY(_alignment_handler) /* r4: EA of fault (set by EXCEPTION_HANDLE) */ l.jal do_unaligned_access l.addi r3,r1,0 /* pt_regs */ l.j _ret_from_exception l.nop #if 0EXCEPTION_ENTRY(_aligment_handler)// l.mfspr r2,r0,SPR_EEAR_BASE /* Load the efective addres */ l.addi r2,r4,0// l.mfspr r5,r0,SPR_EPCR_BASE /* Load the insn address */ l.lwz r5,PT_PC(r1) l.lwz r3,0(r5) /* Load insn */ l.srli r4,r3,26 /* Shift left to get the insn opcode */ l.sfeqi r4,0x00 /* Check if the load/store insn is in delay slot */ l.bf jmp l.sfeqi r4,0x01 l.bf jmp l.sfeqi r4,0x03 l.bf jmp l.sfeqi r4,0x04 l.bf jmp l.sfeqi r4,0x11 l.bf jr l.sfeqi r4,0x12 l.bf jr l.nop l.j 1f l.addi r5,r5,4 /* Increment PC to get return insn address */ jmp: l.slli r4,r3,6 /* Get the signed extended jump length */ l.srai r4,r4,4 l.lwz r3,4(r5) /* Load the real load/store insn */ l.add r5,r5,r4 /* Calculate jump target address */ l.j 1f l.srli r4,r3,26 /* Shift left to get the insn opcode */ jr: l.slli r4,r3,9 /* Shift to get the reg nb */ l.andi r4,r4,0x7c l.lwz r3,4(r5) /* Load the real load/store insn */ l.add r4,r4,r1 /* Load the jump register value from the stack */ l.lwz r5,0(r4) l.srli r4,r3,26 /* Shift left to get the insn opcode */ 1:// l.mtspr r0,r5,SPR_EPCR_BASE l.sw PT_PC(r1),r5 l.sfeqi r4,0x26 l.bf lhs l.sfeqi r4,0x25 l.bf lhz l.sfeqi r4,0x22 l.bf lws l.sfeqi r4,0x21 l.bf lwz l.sfeqi r4,0x37 l.bf sh l.sfeqi r4,0x35 l.bf sw l.nop 1: l.j 1b /* I don't know what to do */ l.nop lhs: l.lbs r5,0(r2) l.slli r5,r5,8 l.lbz r6,1(r2) l.or r5,r5,r6 l.srli r4,r3,19 l.andi r4,r4,0x7c l.add r4,r4,r1 l.j align_end l.sw 0(r4),r5 lhz: l.lbz r5,0(r2) l.slli r5,r5,8 l.lbz r6,1(r2) l.or r5,r5,r6 l.srli r4,r3,19 l.andi r4,r4,0x7c l.add r4,r4,r1 l.j align_end l.sw 0(r4),r5 lws: l.lbs r5,0(r2) l.slli r5,r5,24 l.lbz r6,1(r2) l.slli r6,r6,16 l.or r5,r5,r6 l.lbz r6,2(r2) l.slli r6,r6,8 l.or r5,r5,r6 l.lbz r6,3(r2) l.or r5,r5,r6 l.srli r4,r3,19 l.andi r4,r4,0x7c l.add r4,r4,r1 l.j align_end l.sw 0(r4),r5 lwz: l.lbz r5,0(r2) l.slli r5,r5,24 l.lbz r6,1(r2) l.slli r6,r6,16 l.or r5,r5,r6 l.lbz r6,2(r2) l.slli r6,r6,8 l.or r5,r5,r6 l.lbz r6,3(r2) l.or r5,r5,r6 l.srli r4,r3,19 l.andi r4,r4,0x7c l.add r4,r4,r1 l.j align_end l.sw 0(r4),r5 sh: l.srli r4,r3,9 l.andi r4,r4,0x7c l.add r4,r4,r1 l.lwz r5,0(r4) l.sb 1(r2),r5 l.srli r5,r5,8 l.j align_end l.sb 0(r2),r5 sw: l.srli r4,r3,9 l.andi r4,r4,0x7c l.add r4,r4,r1 l.lwz r5,0(r4) l.sb 3(r2),r5 l.srli r5,r5,8 l.sb 2(r2),r5 l.srli r5,r5,8 l.sb 1(r2),r5 l.srli r5,r5,8 l.j align_end l.sb 0(r2),r5 align_end: l.j _ret_from_intr l.nop#endif /* ---[ 0x700: Illegal insn exception ]---------------------------------- */ EXCEPTION_ENTRY(_illegal_instruction_handler) /* r4: EA of fault (set by EXCEPTION_HANDLE) */ l.jal do_illegal_instruction l.addi r3,r1,0 /* pt_regs */ l.j _ret_from_exception l.nop /* ---[ 0x800: External interrupt exception ]---------------------------- */ EXCEPTION_ENTRY(_external_irq_handler)#ifdef CONFIG_OPENRISC_ESR_EXCEPTION_BUG_CHECK l.lwz r4,PT_SR(r1) // were interrupts enabled ? l.andi r4,r4,SPR_SR_IEE l.sfeqi r4,0 l.bnf 1f // ext irq enabled, all ok. l.nop l.addi r1,r1,-0x8 l.movhi r3,hi(42f) l.ori r3,r3,lo(42f) l.sw 0x0(r1),r3 l.jal printk l.sw 0x4(r1),r4 l.addi r1,r1,0x8Lines 1–500 of 1125. Load more
/* * OpenRISC entry.S * * Linux architectural port borrowing liberally from similar works of * others. All original copyrights apply as per the original source * declaration. * * Modifications for the OpenRISC architecture: * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> * Copyright (C) 2005 Gyorgy Jeney <nog@bsemi.com> * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ #include <linux/linkage.h> #include <asm/processor.h> #include <asm/unistd.h> #include <asm/thread_info.h> #include <asm/errno.h> #include <asm/spr_defs.h> #include <asm/page.h> #include <asm/mmu.h> #include <asm/pgtable.h> #include <asm/asm-offsets.h> #define DISABLE_INTERRUPTS(t1,t2) \ l.mfspr t2,r0,SPR_SR ;\ l.movhi t1,hi(~(SPR_SR_IEE|SPR_SR_TEE)) ;\ l.ori t1,t1,lo(~(SPR_SR_IEE|SPR_SR_TEE)) ;\ l.and t2,t2,t1 ;\ l.mtspr r0,t2,SPR_SR #define ENABLE_INTERRUPTS(t1) \ l.mfspr t1,r0,SPR_SR ;\ l.ori t1,t1,lo(SPR_SR_IEE|SPR_SR_TEE) ;\ l.mtspr r0,t1,SPR_SR /* =========================================================[ macros ]=== */ /* * We need to disable interrupts at beginning of RESTORE_ALL * since interrupt might come in after we've loaded EPC return address * and overwrite EPC with address somewhere in RESTORE_ALL * which is of course wrong! */ #define RESTORE_ALL \ DISABLE_INTERRUPTS(r3,r4) ;\ l.lwz r3,PT_PC(r1) ;\ l.mtspr r0,r3,SPR_EPCR_BASE ;\ l.lwz r3,PT_SR(r1) ;\ l.mtspr r0,r3,SPR_ESR_BASE ;\ l.lwz r2,PT_GPR2(r1) ;\ l.lwz r3,PT_GPR3(r1) ;\ l.lwz r4,PT_GPR4(r1) ;\ l.lwz r5,PT_GPR5(r1) ;\ l.lwz r6,PT_GPR6(r1) ;\ l.lwz r7,PT_GPR7(r1) ;\ l.lwz r8,PT_GPR8(r1) ;\ l.lwz r9,PT_GPR9(r1) ;\ l.lwz r10,PT_GPR10(r1) ;\ l.lwz r11,PT_GPR11(r1) ;\ l.lwz r12,PT_GPR12(r1) ;\ l.lwz r13,PT_GPR13(r1) ;\ l.lwz r14,PT_GPR14(r1) ;\ l.lwz r15,PT_GPR15(r1) ;\ l.lwz r16,PT_GPR16(r1) ;\ l.lwz r17,PT_GPR17(r1) ;\ l.lwz r18,PT_GPR18(r1) ;\ l.lwz r19,PT_GPR19(r1) ;\ l.lwz r20,PT_GPR20(r1) ;\ l.lwz r21,PT_GPR21(r1) ;\ l.lwz r22,PT_GPR22(r1) ;\ l.lwz r23,PT_GPR23(r1) ;\ l.lwz r24,PT_GPR24(r1) ;\ l.lwz r25,PT_GPR25(r1) ;\ l.lwz r26,PT_GPR26(r1) ;\ l.lwz r27,PT_GPR27(r1) ;\ l.lwz r28,PT_GPR28(r1) ;\ l.lwz r29,PT_GPR29(r1) ;\ l.lwz r30,PT_GPR30(r1) ;\ l.lwz r31,PT_GPR31(r1) ;\ l.lwz r1,PT_SP(r1) ;\ l.rfe #define EXCEPTION_ENTRY(handler) \ .global handler ;\ handler: ;\ /* r1, EPCR, ESR a already saved */ ;\ l.sw PT_GPR2(r1),r2 ;\ l.sw PT_GPR3(r1),r3 ;\ /* r4 already save */ ;\ l.sw PT_GPR5(r1),r5 ;\ l.sw PT_GPR6(r1),r6 ;\ l.sw PT_GPR7(r1),r7 ;\ l.sw PT_GPR8(r1),r8 ;\ l.sw PT_GPR9(r1),r9 ;\ /* r10 already saved */ ;\ l.sw PT_GPR11(r1),r11 ;\ /* r12 already saved */ ;\ l.sw PT_GPR13(r1),r13 ;\ l.sw PT_GPR14(r1),r14 ;\ l.sw PT_GPR15(r1),r15 ;\ l.sw PT_GPR16(r1),r16 ;\ l.sw PT_GPR17(r1),r17 ;\ l.sw PT_GPR18(r1),r18 ;\ l.sw PT_GPR19(r1),r19 ;\ l.sw PT_GPR20(r1),r20 ;\ l.sw PT_GPR21(r1),r21 ;\ l.sw PT_GPR22(r1),r22 ;\ l.sw PT_GPR23(r1),r23 ;\ l.sw PT_GPR24(r1),r24 ;\ l.sw PT_GPR25(r1),r25 ;\ l.sw PT_GPR26(r1),r26 ;\ l.sw PT_GPR27(r1),r27 ;\ l.sw PT_GPR28(r1),r28 ;\ l.sw PT_GPR29(r1),r29 ;\ /* r30 already save */ ;\ /* l.sw PT_GPR30(r1),r30*/ ;\ l.sw PT_GPR31(r1),r31 ;\ /* Store -1 in orig_gpr11 for non-syscall exceptions */ ;\ l.addi r30,r0,-1 ;\ l.sw PT_ORIG_GPR11(r1),r30 #define UNHANDLED_EXCEPTION(handler,vector) \ .global handler ;\ handler: ;\ /* r1, EPCR, ESR already saved */ ;\ l.sw PT_GPR2(r1),r2 ;\ l.sw PT_GPR3(r1),r3 ;\ l.sw PT_GPR5(r1),r5 ;\ l.sw PT_GPR6(r1),r6 ;\ l.sw PT_GPR7(r1),r7 ;\ l.sw PT_GPR8(r1),r8 ;\ l.sw PT_GPR9(r1),r9 ;\ /* r10 already saved */ ;\ l.sw PT_GPR11(r1),r11 ;\ /* r12 already saved */ ;\ l.sw PT_GPR13(r1),r13 ;\ l.sw PT_GPR14(r1),r14 ;\ l.sw PT_GPR15(r1),r15 ;\ l.sw PT_GPR16(r1),r16 ;\ l.sw PT_GPR17(r1),r17 ;\ l.sw PT_GPR18(r1),r18 ;\ l.sw PT_GPR19(r1),r19 ;\ l.sw PT_GPR20(r1),r20 ;\ l.sw PT_GPR21(r1),r21 ;\ l.sw PT_GPR22(r1),r22 ;\ l.sw PT_GPR23(r1),r23 ;\ l.sw PT_GPR24(r1),r24 ;\ l.sw PT_GPR25(r1),r25 ;\ l.sw PT_GPR26(r1),r26 ;\ l.sw PT_GPR27(r1),r27 ;\ l.sw PT_GPR28(r1),r28 ;\ l.sw PT_GPR29(r1),r29 ;\ /* r31 already saved */ ;\ l.sw PT_GPR30(r1),r30 ;\ /* l.sw PT_GPR31(r1),r31 */ ;\ /* Store -1 in orig_gpr11 for non-syscall exceptions */ ;\ l.addi r30,r0,-1 ;\ l.sw PT_ORIG_GPR11(r1),r30 ;\ l.addi r3,r1,0 ;\ /* r4 is exception EA */ ;\ l.addi r5,r0,vector ;\ l.jal unhandled_exception ;\ l.nop ;\ l.j _ret_from_exception ;\ l.nop /* * NOTE: one should never assume that SPR_EPC, SPR_ESR, SPR_EEAR * contain the same values as when exception we're handling * occured. in fact they never do. if you need them use * values saved on stack (for SPR_EPC, SPR_ESR) or content * of r4 (for SPR_EEAR). for details look at EXCEPTION_HANDLE() * in 'arch/or32/kernel/head.S' */ /* =====================================================[ exceptions] === */ /* ---[ 0x100: RESET exception ]----------------------------------------- */ EXCEPTION_ENTRY(_tng_kernel_start) l.jal _start l.andi r0,r0,0 /* ---[ 0x200: BUS exception ]------------------------------------------- */ EXCEPTION_ENTRY(_bus_fault_handler) /* r4: EA of fault (set by EXCEPTION_HANDLE) */ l.jal do_bus_fault l.addi r3,r1,0 /* pt_regs */ l.j _ret_from_exception l.nop /* ---[ 0x300: Data Page Fault exception ]------------------------------- */ EXCEPTION_ENTRY(_dtlb_miss_page_fault_handler) l.and r5,r5,r0 l.j 1f l.nop EXCEPTION_ENTRY(_data_page_fault_handler) /* set up parameters for do_page_fault */ l.ori r5,r0,0x300 // exception vector 1: l.addi r3,r1,0 // pt_regs /* r4 set be EXCEPTION_HANDLE */ // effective address of fault /* * __PHX__: TODO * * all this can be written much simpler. look at * DTLB miss handler in the CONFIG_GUARD_PROTECTED_CORE part */ #ifdef CONFIG_OPENRISC_NO_SPR_SR_DSX l.lwz r6,PT_PC(r3) // address of an offending insn l.lwz r6,0(r6) // instruction that caused pf l.srli r6,r6,26 // check opcode for jump insn l.sfeqi r6,0 // l.j l.bf 8f l.sfeqi r6,1 // l.jal l.bf 8f l.sfeqi r6,3 // l.bnf l.bf 8f l.sfeqi r6,4 // l.bf l.bf 8f l.sfeqi r6,0x11 // l.jr l.bf 8f l.sfeqi r6,0x12 // l.jalr l.bf 8f l.nop l.j 9f l.nop 8: l.lwz r6,PT_PC(r3) // address of an offending insn l.addi r6,r6,4 l.lwz r6,0(r6) // instruction that caused pf l.srli r6,r6,26 // get opcode 9: #else l.mfspr r6,r0,SPR_SR // SR // l.lwz r6,PT_SR(r3) // ESR l.andi r6,r6,SPR_SR_DSX // check for delay slot exception l.sfeqi r6,0x1 // exception happened in delay slot l.bnf 7f l.lwz r6,PT_PC(r3) // address of an offending insn l.addi r6,r6,4 // offending insn is in delay slot 7: l.lwz r6,0(r6) // instruction that caused pf l.srli r6,r6,26 // check opcode for write access #endif l.sfgeui r6,0x34 // check opcode for write access l.bnf 1f l.sfleui r6,0x37 l.bnf 1f l.ori r6,r0,0x1 // write access l.j 2f l.nop 1: l.ori r6,r0,0x0 // !write access 2: /* call fault.c handler in or32/mm/fault.c */ l.jal do_page_fault l.nop l.j _ret_from_exception l.nop /* ---[ 0x400: Insn Page Fault exception ]------------------------------- */ EXCEPTION_ENTRY(_itlb_miss_page_fault_handler) l.and r5,r5,r0 l.j 1f l.nop EXCEPTION_ENTRY(_insn_page_fault_handler) /* set up parameters for do_page_fault */ l.ori r5,r0,0x400 // exception vector 1: l.addi r3,r1,0 // pt_regs /* r4 set be EXCEPTION_HANDLE */ // effective address of fault l.ori r6,r0,0x0 // !write access /* call fault.c handler in or32/mm/fault.c */ l.jal do_page_fault l.nop l.j _ret_from_exception l.nop /* ---[ 0x500: Timer exception ]----------------------------------------- */ EXCEPTION_ENTRY(_timer_handler) l.jal timer_interrupt l.addi r3,r1,0 /* pt_regs */ l.j _ret_from_intr l.nop /* ---[ 0x600: Aligment exception ]-------------------------------------- */ EXCEPTION_ENTRY(_alignment_handler) /* r4: EA of fault (set by EXCEPTION_HANDLE) */ l.jal do_unaligned_access l.addi r3,r1,0 /* pt_regs */ l.j _ret_from_exception l.nop #if 0 EXCEPTION_ENTRY(_aligment_handler) // l.mfspr r2,r0,SPR_EEAR_BASE /* Load the efective addres */ l.addi r2,r4,0 // l.mfspr r5,r0,SPR_EPCR_BASE /* Load the insn address */ l.lwz r5,PT_PC(r1) l.lwz r3,0(r5) /* Load insn */ l.srli r4,r3,26 /* Shift left to get the insn opcode */ l.sfeqi r4,0x00 /* Check if the load/store insn is in delay slot */ l.bf jmp l.sfeqi r4,0x01 l.bf jmp l.sfeqi r4,0x03 l.bf jmp l.sfeqi r4,0x04 l.bf jmp l.sfeqi r4,0x11 l.bf jr l.sfeqi r4,0x12 l.bf jr l.nop l.j 1f l.addi r5,r5,4 /* Increment PC to get return insn address */ jmp: l.slli r4,r3,6 /* Get the signed extended jump length */ l.srai r4,r4,4 l.lwz r3,4(r5) /* Load the real load/store insn */ l.add r5,r5,r4 /* Calculate jump target address */ l.j 1f l.srli r4,r3,26 /* Shift left to get the insn opcode */ jr: l.slli r4,r3,9 /* Shift to get the reg nb */ l.andi r4,r4,0x7c l.lwz r3,4(r5) /* Load the real load/store insn */ l.add r4,r4,r1 /* Load the jump register value from the stack */ l.lwz r5,0(r4) l.srli r4,r3,26 /* Shift left to get the insn opcode */ 1: // l.mtspr r0,r5,SPR_EPCR_BASE l.sw PT_PC(r1),r5 l.sfeqi r4,0x26 l.bf lhs l.sfeqi r4,0x25 l.bf lhz l.sfeqi r4,0x22 l.bf lws l.sfeqi r4,0x21 l.bf lwz l.sfeqi r4,0x37 l.bf sh l.sfeqi r4,0x35 l.bf sw l.nop 1: l.j 1b /* I don't know what to do */ l.nop lhs: l.lbs r5,0(r2) l.slli r5,r5,8 l.lbz r6,1(r2) l.or r5,r5,r6 l.srli r4,r3,19 l.andi r4,r4,0x7c l.add r4,r4,r1 l.j align_end l.sw 0(r4),r5 lhz: l.lbz r5,0(r2) l.slli r5,r5,8 l.lbz r6,1(r2) l.or r5,r5,r6 l.srli r4,r3,19 l.andi r4,r4,0x7c l.add r4,r4,r1 l.j align_end l.sw 0(r4),r5 lws: l.lbs r5,0(r2) l.slli r5,r5,24 l.lbz r6,1(r2) l.slli r6,r6,16 l.or r5,r5,r6 l.lbz r6,2(r2) l.slli r6,r6,8 l.or r5,r5,r6 l.lbz r6,3(r2) l.or r5,r5,r6 l.srli r4,r3,19 l.andi r4,r4,0x7c l.add r4,r4,r1 l.j align_end l.sw 0(r4),r5 lwz: l.lbz r5,0(r2) l.slli r5,r5,24 l.lbz r6,1(r2) l.slli r6,r6,16 l.or r5,r5,r6 l.lbz r6,2(r2) l.slli r6,r6,8 l.or r5,r5,r6 l.lbz r6,3(r2) l.or r5,r5,r6 l.srli r4,r3,19 l.andi r4,r4,0x7c l.add r4,r4,r1 l.j align_end l.sw 0(r4),r5 sh: l.srli r4,r3,9 l.andi r4,r4,0x7c l.add r4,r4,r1 l.lwz r5,0(r4) l.sb 1(r2),r5 l.srli r5,r5,8 l.j align_end l.sb 0(r2),r5 sw: l.srli r4,r3,9 l.andi r4,r4,0x7c l.add r4,r4,r1 l.lwz r5,0(r4) l.sb 3(r2),r5 l.srli r5,r5,8 l.sb 2(r2),r5 l.srli r5,r5,8 l.sb 1(r2),r5 l.srli r5,r5,8 l.j align_end l.sb 0(r2),r5 align_end: l.j _ret_from_intr l.nop #endif /* ---[ 0x700: Illegal insn exception ]---------------------------------- */ EXCEPTION_ENTRY(_illegal_instruction_handler) /* r4: EA of fault (set by EXCEPTION_HANDLE) */ l.jal do_illegal_instruction l.addi r3,r1,0 /* pt_regs */ l.j _ret_from_exception l.nop /* ---[ 0x800: External interrupt exception ]---------------------------- */ EXCEPTION_ENTRY(_external_irq_handler) #ifdef CONFIG_OPENRISC_ESR_EXCEPTION_BUG_CHECK l.lwz r4,PT_SR(r1) // were interrupts enabled ? l.andi r4,r4,SPR_SR_IEE l.sfeqi r4,0 l.bnf 1f // ext irq enabled, all ok. l.nop l.addi r1,r1,-0x8 l.movhi r3,hi(42f) l.ori r3,r3,lo(42f) l.sw 0x0(r1),r3 l.jal printk l.sw 0x4(r1),r4 l.addi r1,r1,0x8