/* SPDX-License-Identifier: GPL-2.0-or-later *//* * 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> */ #include <linux/linkage.h>#include <linux/pgtable.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/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 ]=== */ #ifdef CONFIG_TRACE_IRQFLAGS/* * Trace irq on/off creating a stack frame. */#define TRACE_IRQS_OP(trace_op) \ l.sw -8(r1),r2 /* store frame pointer */ ;\ l.sw -4(r1),r9 /* store return address */ ;\ l.addi r2,r1,0 /* move sp to fp */ ;\ l.jal trace_op ;\ l.addi r1,r1,-8 ;\ l.ori r1,r2,0 /* restore sp */ ;\ l.lwz r9,-4(r1) /* restore return address */ ;\ l.lwz r2,-8(r1) /* restore fp */ ;\/* * Trace irq on/off and save registers we need that would otherwise be * clobbered. */#define TRACE_IRQS_SAVE(t1,trace_op) \ l.sw -12(r1),t1 /* save extra reg */ ;\ l.sw -8(r1),r2 /* store frame pointer */ ;\ l.sw -4(r1),r9 /* store return address */ ;\ l.addi r2,r1,0 /* move sp to fp */ ;\ l.jal trace_op ;\ l.addi r1,r1,-12 ;\ l.ori r1,r2,0 /* restore sp */ ;\ l.lwz r9,-4(r1) /* restore return address */ ;\ l.lwz r2,-8(r1) /* restore fp */ ;\ l.lwz t1,-12(r1) /* restore extra reg */ #define TRACE_IRQS_OFF TRACE_IRQS_OP(trace_hardirqs_off)#define TRACE_IRQS_ON TRACE_IRQS_OP(trace_hardirqs_on)#define TRACE_IRQS_ON_SYSCALL \ TRACE_IRQS_SAVE(r10,trace_hardirqs_on) ;\ 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 r11,PT_GPR11(r1)#define TRACE_IRQS_OFF_ENTRY \ l.lwz r5,PT_SR(r1) ;\ l.andi r3,r5,(SPR_SR_IEE|SPR_SR_TEE) ;\ l.sfeq r5,r0 /* skip trace if irqs were already off */;\ l.bf 1f ;\ l.nop ;\ TRACE_IRQS_SAVE(r4,trace_hardirqs_off) ;\1:#else#define TRACE_IRQS_OFF#define TRACE_IRQS_ON#define TRACE_IRQS_OFF_ENTRY#define TRACE_IRQS_ON_SYSCALL#endif /* * 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_GPR31(r1),r31 ;\ TRACE_IRQS_OFF_ENTRY ;\ /* 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 ;\ /* r30 already saved */ ;\ 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 /* clobbers 'reg' */#define CLEAR_LWA_FLAG(reg) \ l.movhi reg,hi(lwa_flag) ;\ l.ori reg,reg,lo(lwa_flag) ;\ l.sw 0(reg),r0/* * 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/openrisc/kernel/head.S' */ /* =====================================================[ exceptions] === */ __REF /* ---[ 0x100: RESET exception ]----------------------------------------- */ EXCEPTION_ENTRY(_tng_kernel_start) l.jal _start l.andi r0,r0,0 /* ---[ 0x200: BUS exception ]------------------------------------------- */ EXCEPTION_ENTRY(_bus_fault_handler) CLEAR_LWA_FLAG(r3) /* 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) CLEAR_LWA_FLAG(r3) l.and r5,r5,r0 l.j 1f l.nop EXCEPTION_ENTRY(_data_page_fault_handler) CLEAR_LWA_FLAG(r3) /* 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 #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: // offending insn is in delay slot 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: // offending instruction opcode loaded in r6 #else l.mfspr r6,r0,SPR_SR // SR l.andi r6,r6,SPR_SR_DSX // check for delay slot exception l.sfne r6,r0 // 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,0x33 // 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 openrisc/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) CLEAR_LWA_FLAG(r3) l.and r5,r5,r0 l.j 1f l.nop EXCEPTION_ENTRY(_insn_page_fault_handler) CLEAR_LWA_FLAG(r3) /* 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 openrisc/mm/fault.c */ l.jal do_page_fault l.nop l.j _ret_from_exception l.nop /* ---[ 0x500: Timer exception ]----------------------------------------- */ EXCEPTION_ENTRY(_timer_handler) CLEAR_LWA_FLAG(r3) l.jal timer_interrupt l.addi r3,r1,0 /* pt_regs */ l.j _ret_from_intr l.nop /* ---[ 0x600: Alignment exception ]-------------------------------------- */ EXCEPTION_ENTRY(_alignment_handler) CLEAR_LWA_FLAG(r3) /* 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(_alignment_handler)// l.mfspr r2,r0,SPR_EEAR_BASE /* Load the effective address */ 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 Lines 1–500 of 1272. Load more
/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * 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> */ #include <linux/linkage.h> #include <linux/pgtable.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/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 ]=== */ #ifdef CONFIG_TRACE_IRQFLAGS /* * Trace irq on/off creating a stack frame. */ #define TRACE_IRQS_OP(trace_op) \ l.sw -8(r1),r2 /* store frame pointer */ ;\ l.sw -4(r1),r9 /* store return address */ ;\ l.addi r2,r1,0 /* move sp to fp */ ;\ l.jal trace_op ;\ l.addi r1,r1,-8 ;\ l.ori r1,r2,0 /* restore sp */ ;\ l.lwz r9,-4(r1) /* restore return address */ ;\ l.lwz r2,-8(r1) /* restore fp */ ;\ /* * Trace irq on/off and save registers we need that would otherwise be * clobbered. */ #define TRACE_IRQS_SAVE(t1,trace_op) \ l.sw -12(r1),t1 /* save extra reg */ ;\ l.sw -8(r1),r2 /* store frame pointer */ ;\ l.sw -4(r1),r9 /* store return address */ ;\ l.addi r2,r1,0 /* move sp to fp */ ;\ l.jal trace_op ;\ l.addi r1,r1,-12 ;\ l.ori r1,r2,0 /* restore sp */ ;\ l.lwz r9,-4(r1) /* restore return address */ ;\ l.lwz r2,-8(r1) /* restore fp */ ;\ l.lwz t1,-12(r1) /* restore extra reg */ #define TRACE_IRQS_OFF TRACE_IRQS_OP(trace_hardirqs_off) #define TRACE_IRQS_ON TRACE_IRQS_OP(trace_hardirqs_on) #define TRACE_IRQS_ON_SYSCALL \ TRACE_IRQS_SAVE(r10,trace_hardirqs_on) ;\ 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 r11,PT_GPR11(r1) #define TRACE_IRQS_OFF_ENTRY \ l.lwz r5,PT_SR(r1) ;\ l.andi r3,r5,(SPR_SR_IEE|SPR_SR_TEE) ;\ l.sfeq r5,r0 /* skip trace if irqs were already off */;\ l.bf 1f ;\ l.nop ;\ TRACE_IRQS_SAVE(r4,trace_hardirqs_off) ;\ 1: #else #define TRACE_IRQS_OFF #define TRACE_IRQS_ON #define TRACE_IRQS_OFF_ENTRY #define TRACE_IRQS_ON_SYSCALL #endif /* * 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_GPR31(r1),r31 ;\ TRACE_IRQS_OFF_ENTRY ;\ /* 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 ;\ /* r30 already saved */ ;\ 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 /* clobbers 'reg' */ #define CLEAR_LWA_FLAG(reg) \ l.movhi reg,hi(lwa_flag) ;\ l.ori reg,reg,lo(lwa_flag) ;\ l.sw 0(reg),r0 /* * 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/openrisc/kernel/head.S' */ /* =====================================================[ exceptions] === */ __REF /* ---[ 0x100: RESET exception ]----------------------------------------- */ EXCEPTION_ENTRY(_tng_kernel_start) l.jal _start l.andi r0,r0,0 /* ---[ 0x200: BUS exception ]------------------------------------------- */ EXCEPTION_ENTRY(_bus_fault_handler) CLEAR_LWA_FLAG(r3) /* 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) CLEAR_LWA_FLAG(r3) l.and r5,r5,r0 l.j 1f l.nop EXCEPTION_ENTRY(_data_page_fault_handler) CLEAR_LWA_FLAG(r3) /* 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 #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: // offending insn is in delay slot 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: // offending instruction opcode loaded in r6 #else l.mfspr r6,r0,SPR_SR // SR l.andi r6,r6,SPR_SR_DSX // check for delay slot exception l.sfne r6,r0 // 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,0x33 // 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 openrisc/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) CLEAR_LWA_FLAG(r3) l.and r5,r5,r0 l.j 1f l.nop EXCEPTION_ENTRY(_insn_page_fault_handler) CLEAR_LWA_FLAG(r3) /* 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 openrisc/mm/fault.c */ l.jal do_page_fault l.nop l.j _ret_from_exception l.nop /* ---[ 0x500: Timer exception ]----------------------------------------- */ EXCEPTION_ENTRY(_timer_handler) CLEAR_LWA_FLAG(r3) l.jal timer_interrupt l.addi r3,r1,0 /* pt_regs */ l.j _ret_from_intr l.nop /* ---[ 0x600: Alignment exception ]-------------------------------------- */ EXCEPTION_ENTRY(_alignment_handler) CLEAR_LWA_FLAG(r3) /* 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(_alignment_handler) // l.mfspr r2,r0,SPR_EEAR_BASE /* Load the effective address */ 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