xref: /openbmc/linux/arch/arc/kernel/entry-compact.S (revision 5f888087455c5199195c2ba17b91ac7285a33921)
16d1a20b1SVineet Gupta/*
26d1a20b1SVineet Gupta * Low Level Interrupts/Traps/Exceptions(non-TLB) Handling for ARCompact ISA
36d1a20b1SVineet Gupta *
46d1a20b1SVineet Gupta * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
56d1a20b1SVineet Gupta * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
66d1a20b1SVineet Gupta *
76d1a20b1SVineet Gupta * This program is free software; you can redistribute it and/or modify
86d1a20b1SVineet Gupta * it under the terms of the GNU General Public License version 2 as
96d1a20b1SVineet Gupta * published by the Free Software Foundation.
106d1a20b1SVineet Gupta *
116d1a20b1SVineet Gupta * vineetg: May 2011
126d1a20b1SVineet Gupta *  -Userspace unaligned access emulation
136d1a20b1SVineet Gupta *
146d1a20b1SVineet Gupta * vineetg: Feb 2011 (ptrace low level code fixes)
156d1a20b1SVineet Gupta *  -traced syscall return code (r0) was not saved into pt_regs for restoring
166d1a20b1SVineet Gupta *   into user reg-file when traded task rets to user space.
176d1a20b1SVineet Gupta *  -syscalls needing arch-wrappers (mainly for passing sp as pt_regs)
186d1a20b1SVineet Gupta *   were not invoking post-syscall trace hook (jumping directly into
196d1a20b1SVineet Gupta *   ret_from_system_call)
206d1a20b1SVineet Gupta *
216d1a20b1SVineet Gupta * vineetg: Nov 2010:
226d1a20b1SVineet Gupta *  -Vector table jumps (@8 bytes) converted into branches (@4 bytes)
236d1a20b1SVineet Gupta *  -To maintain the slot size of 8 bytes/vector, added nop, which is
246d1a20b1SVineet Gupta *   not executed at runtime.
256d1a20b1SVineet Gupta *
266d1a20b1SVineet Gupta * vineetg: Nov 2009 (Everything needed for TIF_RESTORE_SIGMASK)
276d1a20b1SVineet Gupta *  -do_signal()invoked upon TIF_RESTORE_SIGMASK as well
286d1a20b1SVineet Gupta *  -Wrappers for sys_{,rt_}sigsuspend() nolonger needed as they don't
296d1a20b1SVineet Gupta *   need ptregs anymore
306d1a20b1SVineet Gupta *
316d1a20b1SVineet Gupta * Vineetg: Oct 2009
326d1a20b1SVineet Gupta *  -In a rare scenario, Process gets a Priv-V exception and gets scheduled
336d1a20b1SVineet Gupta *   out. Since we don't do FAKE RTIE for Priv-V, CPU excpetion state remains
346d1a20b1SVineet Gupta *   active (AE bit enabled).  This causes a double fault for a subseq valid
356d1a20b1SVineet Gupta *   exception. Thus FAKE RTIE needed in low level Priv-Violation handler.
366d1a20b1SVineet Gupta *   Instr Error could also cause similar scenario, so same there as well.
376d1a20b1SVineet Gupta *
386d1a20b1SVineet Gupta * Vineetg: March 2009 (Supporting 2 levels of Interrupts)
396d1a20b1SVineet Gupta *
406d1a20b1SVineet Gupta * Vineetg: Aug 28th 2008: Bug #94984
416d1a20b1SVineet Gupta *  -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap
426d1a20b1SVineet Gupta *   Normally CPU does this automatically, however when doing FAKE rtie,
436d1a20b1SVineet Gupta *   we need to explicitly do this. The problem in macros
446d1a20b1SVineet Gupta *   FAKE_RET_FROM_EXCPN and FAKE_RET_FROM_EXCPN_LOCK_IRQ was that this bit
456d1a20b1SVineet Gupta *   was being "CLEARED" rather then "SET". Since it is Loop INHIBIT Bit,
466d1a20b1SVineet Gupta *   setting it and not clearing it clears ZOL context
476d1a20b1SVineet Gupta *
486d1a20b1SVineet Gupta * Vineetg: May 16th, 2008
496d1a20b1SVineet Gupta *  - r25 now contains the Current Task when in kernel
506d1a20b1SVineet Gupta *
516d1a20b1SVineet Gupta * Vineetg: Dec 22, 2007
526d1a20b1SVineet Gupta *    Minor Surgery of Low Level ISR to make it SMP safe
536d1a20b1SVineet Gupta *    - MMU_SCRATCH0 Reg used for freeing up r9 in Level 1 ISR
546d1a20b1SVineet Gupta *    - _current_task is made an array of NR_CPUS
556d1a20b1SVineet Gupta *    - Access of _current_task wrapped inside a macro so that if hardware
566d1a20b1SVineet Gupta *       team agrees for a dedicated reg, no other code is touched
576d1a20b1SVineet Gupta *
586d1a20b1SVineet Gupta * Amit Bhor, Rahul Trivedi, Kanika Nema, Sameer Dhavale : Codito Tech 2004
596d1a20b1SVineet Gupta */
606d1a20b1SVineet Gupta
616d1a20b1SVineet Gupta#include <linux/errno.h>
626d1a20b1SVineet Gupta#include <linux/linkage.h>	/* {EXTRY,EXIT} */
636d1a20b1SVineet Gupta#include <asm/entry.h>
646d1a20b1SVineet Gupta#include <asm/irqflags.h>
656d1a20b1SVineet Gupta
666d1a20b1SVineet Gupta	.cpu A7
676d1a20b1SVineet Gupta
686d1a20b1SVineet Gupta;############################ Vector Table #################################
696d1a20b1SVineet Gupta
706d1a20b1SVineet Gupta.macro VECTOR  lbl
716d1a20b1SVineet Gupta#if 1   /* Just in case, build breaks */
726d1a20b1SVineet Gupta	j   \lbl
736d1a20b1SVineet Gupta#else
746d1a20b1SVineet Gupta	b   \lbl
756d1a20b1SVineet Gupta	nop
766d1a20b1SVineet Gupta#endif
776d1a20b1SVineet Gupta.endm
786d1a20b1SVineet Gupta
796d1a20b1SVineet Gupta	.section .vector, "ax",@progbits
806d1a20b1SVineet Gupta	.align 4
816d1a20b1SVineet Gupta
826d1a20b1SVineet Gupta/* Each entry in the vector table must occupy 2 words. Since it is a jump
836d1a20b1SVineet Gupta * across sections (.vector to .text) we are gauranteed that 'j somewhere'
846d1a20b1SVineet Gupta * will use the 'j limm' form of the intrsuction as long as somewhere is in
856d1a20b1SVineet Gupta * a section other than .vector.
866d1a20b1SVineet Gupta */
876d1a20b1SVineet Gupta
886d1a20b1SVineet Gupta; ********* Critical System Events **********************
896d1a20b1SVineet GuptaVECTOR   res_service             ; 0x0, Restart Vector  (0x0)
906d1a20b1SVineet GuptaVECTOR   mem_service             ; 0x8, Mem exception   (0x1)
916d1a20b1SVineet GuptaVECTOR   instr_service           ; 0x10, Instrn Error   (0x2)
926d1a20b1SVineet Gupta
936d1a20b1SVineet Gupta; ******************** Device ISRs **********************
946d1a20b1SVineet Gupta#ifdef CONFIG_ARC_IRQ3_LV2
956d1a20b1SVineet GuptaVECTOR   handle_interrupt_level2
966d1a20b1SVineet Gupta#else
976d1a20b1SVineet GuptaVECTOR   handle_interrupt_level1
986d1a20b1SVineet Gupta#endif
996d1a20b1SVineet Gupta
1006d1a20b1SVineet GuptaVECTOR   handle_interrupt_level1
1016d1a20b1SVineet Gupta
1026d1a20b1SVineet Gupta#ifdef CONFIG_ARC_IRQ5_LV2
1036d1a20b1SVineet GuptaVECTOR   handle_interrupt_level2
1046d1a20b1SVineet Gupta#else
1056d1a20b1SVineet GuptaVECTOR   handle_interrupt_level1
1066d1a20b1SVineet Gupta#endif
1076d1a20b1SVineet Gupta
1086d1a20b1SVineet Gupta#ifdef CONFIG_ARC_IRQ6_LV2
1096d1a20b1SVineet GuptaVECTOR   handle_interrupt_level2
1106d1a20b1SVineet Gupta#else
1116d1a20b1SVineet GuptaVECTOR   handle_interrupt_level1
1126d1a20b1SVineet Gupta#endif
1136d1a20b1SVineet Gupta
1146d1a20b1SVineet Gupta.rept   25
1156d1a20b1SVineet GuptaVECTOR   handle_interrupt_level1 ; Other devices
1166d1a20b1SVineet Gupta.endr
1176d1a20b1SVineet Gupta
1186d1a20b1SVineet Gupta/* FOR ARC600: timer = 0x3, uart = 0x8, emac = 0x10 */
1196d1a20b1SVineet Gupta
1206d1a20b1SVineet Gupta; ******************** Exceptions **********************
1216d1a20b1SVineet GuptaVECTOR   EV_MachineCheck         ; 0x100, Fatal Machine check   (0x20)
1226d1a20b1SVineet GuptaVECTOR   EV_TLBMissI             ; 0x108, Intruction TLB miss   (0x21)
1236d1a20b1SVineet GuptaVECTOR   EV_TLBMissD             ; 0x110, Data TLB miss         (0x22)
1246d1a20b1SVineet GuptaVECTOR   EV_TLBProtV             ; 0x118, Protection Violation  (0x23)
1256d1a20b1SVineet Gupta				 ;         or Misaligned Access
1266d1a20b1SVineet GuptaVECTOR   EV_PrivilegeV           ; 0x120, Privilege Violation   (0x24)
1276d1a20b1SVineet GuptaVECTOR   EV_Trap                 ; 0x128, Trap exception        (0x25)
1286d1a20b1SVineet GuptaVECTOR   EV_Extension            ; 0x130, Extn Intruction Excp  (0x26)
1296d1a20b1SVineet Gupta
1306d1a20b1SVineet Gupta.rept   24
1316d1a20b1SVineet GuptaVECTOR   reserved                ; Reserved Exceptions
1326d1a20b1SVineet Gupta.endr
1336d1a20b1SVineet Gupta
1346d1a20b1SVineet Gupta
1356d1a20b1SVineet Gupta;##################### Scratch Mem for IRQ stack switching #############
1366d1a20b1SVineet Gupta
1376d1a20b1SVineet GuptaARCFP_DATA int1_saved_reg
1386d1a20b1SVineet Gupta	.align 32
1396d1a20b1SVineet Gupta	.type   int1_saved_reg, @object
1406d1a20b1SVineet Gupta	.size   int1_saved_reg, 4
1416d1a20b1SVineet Guptaint1_saved_reg:
1426d1a20b1SVineet Gupta	.zero 4
1436d1a20b1SVineet Gupta
1446d1a20b1SVineet Gupta/* Each Interrupt level needs its own scratch */
1456d1a20b1SVineet Gupta#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
1466d1a20b1SVineet Gupta
1476d1a20b1SVineet GuptaARCFP_DATA int2_saved_reg
1486d1a20b1SVineet Gupta	.type   int2_saved_reg, @object
1496d1a20b1SVineet Gupta	.size   int2_saved_reg, 4
1506d1a20b1SVineet Guptaint2_saved_reg:
1516d1a20b1SVineet Gupta	.zero 4
1526d1a20b1SVineet Gupta
1536d1a20b1SVineet Gupta#endif
1546d1a20b1SVineet Gupta
1556d1a20b1SVineet Gupta; ---------------------------------------------
1566d1a20b1SVineet Gupta	.section .text, "ax",@progbits
1576d1a20b1SVineet Gupta
1586d1a20b1SVineet Guptares_service:		; processor restart
1596d1a20b1SVineet Gupta	flag    0x1     ; not implemented
1606d1a20b1SVineet Gupta	nop
1616d1a20b1SVineet Gupta	nop
1626d1a20b1SVineet Gupta
1636d1a20b1SVineet Guptareserved:		; processor restart
1646d1a20b1SVineet Gupta	rtie            ; jump to processor initializations
1656d1a20b1SVineet Gupta
1666d1a20b1SVineet Gupta;##################### Interrupt Handling ##############################
1676d1a20b1SVineet Gupta
1686d1a20b1SVineet Gupta#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
1696d1a20b1SVineet Gupta; ---------------------------------------------
1706d1a20b1SVineet Gupta;  Level 2 ISR: Can interrupt a Level 1 ISR
1716d1a20b1SVineet Gupta; ---------------------------------------------
1726d1a20b1SVineet GuptaENTRY(handle_interrupt_level2)
1736d1a20b1SVineet Gupta
1746d1a20b1SVineet Gupta	INTERRUPT_PROLOGUE 2
1756d1a20b1SVineet Gupta
1766d1a20b1SVineet Gupta	;------------------------------------------------------
1776d1a20b1SVineet Gupta	; if L2 IRQ interrupted a L1 ISR, disable preemption
178*5f888087SVineet Gupta	;
179*5f888087SVineet Gupta	; This is to avoid a potential L1-L2-L1 scenario
180*5f888087SVineet Gupta	;  -L1 IRQ taken
181*5f888087SVineet Gupta	;  -L2 interrupts L1 (before L1 ISR could run)
182*5f888087SVineet Gupta	;  -preemption off IRQ, user task in syscall picked to run
183*5f888087SVineet Gupta	;  -RTIE to userspace
184*5f888087SVineet Gupta	;	Returns from L2 context fine
185*5f888087SVineet Gupta	;	But both L1 and L2 re-enabled, so another L1 can be taken
186*5f888087SVineet Gupta	;	while prev L1 is still unserviced
187*5f888087SVineet Gupta	;
1886d1a20b1SVineet Gupta	;------------------------------------------------------
1896d1a20b1SVineet Gupta
190*5f888087SVineet Gupta	; L2 interrupting L1 implies both L2 and L1 active
191*5f888087SVineet Gupta	; However both A2 and A1 are NOT set in STATUS32, thus
192*5f888087SVineet Gupta	; need to check STATUS32_L2 to determine if L1 was active
193*5f888087SVineet Gupta
1946d1a20b1SVineet Gupta	ld r9, [sp, PT_status32]        ; get statu32_l2 (saved in pt_regs)
1956d1a20b1SVineet Gupta	bbit0 r9, STATUS_A1_BIT, 1f     ; L1 not active when L2 IRQ, so normal
1966d1a20b1SVineet Gupta
1976d1a20b1SVineet Gupta	; bump thread_info->preempt_count (Disable preemption)
1986d1a20b1SVineet Gupta	GET_CURR_THR_INFO_FROM_SP   r10
1996d1a20b1SVineet Gupta	ld      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
2006d1a20b1SVineet Gupta	add     r9, r9, 1
2016d1a20b1SVineet Gupta	st      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
2026d1a20b1SVineet Gupta
2036d1a20b1SVineet Gupta1:
2046d1a20b1SVineet Gupta	;------------------------------------------------------
2056d1a20b1SVineet Gupta	; setup params for Linux common ISR and invoke it
2066d1a20b1SVineet Gupta	;------------------------------------------------------
2076d1a20b1SVineet Gupta	lr  r0, [icause2]
2086d1a20b1SVineet Gupta	and r0, r0, 0x1f
2096d1a20b1SVineet Gupta
2106d1a20b1SVineet Gupta	bl.d  @arch_do_IRQ
2116d1a20b1SVineet Gupta	mov r1, sp
2126d1a20b1SVineet Gupta
2136d1a20b1SVineet Gupta	mov r8,0x2
2146d1a20b1SVineet Gupta	sr r8, [AUX_IRQ_LV12]       ; clear bit in Sticky Status Reg
2156d1a20b1SVineet Gupta
2166d1a20b1SVineet Gupta	b   ret_from_exception
2176d1a20b1SVineet Gupta
2186d1a20b1SVineet GuptaEND(handle_interrupt_level2)
2196d1a20b1SVineet Gupta
2206d1a20b1SVineet Gupta#endif
2216d1a20b1SVineet Gupta
2226d1a20b1SVineet Gupta; ---------------------------------------------
2236d1a20b1SVineet Gupta;  Level 1 ISR
2246d1a20b1SVineet Gupta; ---------------------------------------------
2256d1a20b1SVineet GuptaENTRY(handle_interrupt_level1)
2266d1a20b1SVineet Gupta
2276d1a20b1SVineet Gupta	INTERRUPT_PROLOGUE 1
2286d1a20b1SVineet Gupta
2296d1a20b1SVineet Gupta	lr  r0, [icause1]
2306d1a20b1SVineet Gupta	and r0, r0, 0x1f
2316d1a20b1SVineet Gupta
2326d1a20b1SVineet Gupta#ifdef CONFIG_TRACE_IRQFLAGS
2336d1a20b1SVineet Gupta	; icause1 needs to be read early, before calling tracing, which
2346d1a20b1SVineet Gupta	; can clobber scratch regs, hence use of stack to stash it
2356d1a20b1SVineet Gupta	push r0
2366d1a20b1SVineet Gupta	TRACE_ASM_IRQ_DISABLE
2376d1a20b1SVineet Gupta	pop  r0
2386d1a20b1SVineet Gupta#endif
2396d1a20b1SVineet Gupta
2406d1a20b1SVineet Gupta	bl.d  @arch_do_IRQ
2416d1a20b1SVineet Gupta	mov r1, sp
2426d1a20b1SVineet Gupta
2436d1a20b1SVineet Gupta	mov r8,0x1
2446d1a20b1SVineet Gupta	sr r8, [AUX_IRQ_LV12]       ; clear bit in Sticky Status Reg
2456d1a20b1SVineet Gupta
2466d1a20b1SVineet Gupta	b   ret_from_exception
2476d1a20b1SVineet GuptaEND(handle_interrupt_level1)
2486d1a20b1SVineet Gupta
2496d1a20b1SVineet Gupta;################### Non TLB Exception Handling #############################
2506d1a20b1SVineet Gupta
2516d1a20b1SVineet Gupta; ---------------------------------------------
2526d1a20b1SVineet Gupta; Protection Violation Exception Handler
2536d1a20b1SVineet Gupta; ---------------------------------------------
2546d1a20b1SVineet Gupta
2556d1a20b1SVineet GuptaENTRY(EV_TLBProtV)
2566d1a20b1SVineet Gupta
2576d1a20b1SVineet Gupta	EXCEPTION_PROLOGUE
2586d1a20b1SVineet Gupta
2596d1a20b1SVineet Gupta	lr  r2, [ecr]
2606d1a20b1SVineet Gupta	lr  r0, [efa]	; Faulting Data address (not part of pt_regs saved above)
2616d1a20b1SVineet Gupta
2626d1a20b1SVineet Gupta	; Exception auto-disables further Intr/exceptions.
2636d1a20b1SVineet Gupta	; Re-enable them by pretending to return from exception
2646d1a20b1SVineet Gupta	; (so rest of handler executes in pure K mode)
2656d1a20b1SVineet Gupta
2666d1a20b1SVineet Gupta	FAKE_RET_FROM_EXCPN
2676d1a20b1SVineet Gupta
2686d1a20b1SVineet Gupta	mov   r1, sp	; Handle to pt_regs
2696d1a20b1SVineet Gupta
2706d1a20b1SVineet Gupta	;------ (5) Type of Protection Violation? ----------
2716d1a20b1SVineet Gupta	;
2726d1a20b1SVineet Gupta	; ProtV Hardware Exception is triggered for Access Faults of 2 types
2736d1a20b1SVineet Gupta	;   -Access Violaton	: 00_23_(00|01|02|03)_00
2746d1a20b1SVineet Gupta	;			         x  r  w  r+w
2756d1a20b1SVineet Gupta	;   -Unaligned Access	: 00_23_04_00
2766d1a20b1SVineet Gupta	;
2776d1a20b1SVineet Gupta	bbit1 r2, ECR_C_BIT_PROTV_MISALIG_DATA, 4f
2786d1a20b1SVineet Gupta
2796d1a20b1SVineet Gupta	;========= (6a) Access Violation Processing ========
2806d1a20b1SVineet Gupta	bl  do_page_fault
2816d1a20b1SVineet Gupta	b   ret_from_exception
2826d1a20b1SVineet Gupta
2836d1a20b1SVineet Gupta	;========== (6b) Non aligned access ============
2846d1a20b1SVineet Gupta4:
2856d1a20b1SVineet Gupta
2866d1a20b1SVineet Gupta	SAVE_CALLEE_SAVED_USER
2876d1a20b1SVineet Gupta	mov r2, sp              ; callee_regs
2886d1a20b1SVineet Gupta
2896d1a20b1SVineet Gupta	bl  do_misaligned_access
2906d1a20b1SVineet Gupta
2916d1a20b1SVineet Gupta	; TBD: optimize - do this only if a callee reg was involved
2926d1a20b1SVineet Gupta	; either a dst of emulated LD/ST or src with address-writeback
2936d1a20b1SVineet Gupta	RESTORE_CALLEE_SAVED_USER
2946d1a20b1SVineet Gupta
2956d1a20b1SVineet Gupta	b   ret_from_exception
2966d1a20b1SVineet Gupta
2976d1a20b1SVineet GuptaEND(EV_TLBProtV)
2986d1a20b1SVineet Gupta
2996d1a20b1SVineet Gupta; Wrapper for Linux page fault handler called from EV_TLBMiss*
3006d1a20b1SVineet Gupta; Very similar to ProtV handler case (6a) above, but avoids the extra checks
3016d1a20b1SVineet Gupta; for Misaligned access
3026d1a20b1SVineet Gupta;
3036d1a20b1SVineet GuptaENTRY(call_do_page_fault)
3046d1a20b1SVineet Gupta
3056d1a20b1SVineet Gupta	EXCEPTION_PROLOGUE
3066d1a20b1SVineet Gupta	lr  r0, [efa]	; Faulting Data address
3076d1a20b1SVineet Gupta	mov   r1, sp
3086d1a20b1SVineet Gupta	FAKE_RET_FROM_EXCPN
3096d1a20b1SVineet Gupta
3106d1a20b1SVineet Gupta	mov blink, ret_from_exception
3116d1a20b1SVineet Gupta	b  do_page_fault
3126d1a20b1SVineet Gupta
3136d1a20b1SVineet GuptaEND(call_do_page_fault)
3146d1a20b1SVineet Gupta
3156d1a20b1SVineet Gupta;############# Common Handlers for ARCompact and ARCv2 ##############
3166d1a20b1SVineet Gupta
3176d1a20b1SVineet Gupta#include "entry.S"
3186d1a20b1SVineet Gupta
3196d1a20b1SVineet Gupta;############# Return from Intr/Excp/Trap (ARC Specifics) ##############
3206d1a20b1SVineet Gupta;
3216d1a20b1SVineet Gupta; Restore the saved sys context (common exit-path for EXCPN/IRQ/Trap)
3226d1a20b1SVineet Gupta; IRQ shd definitely not happen between now and rtie
3236d1a20b1SVineet Gupta; All 2 entry points to here already disable interrupts
3246d1a20b1SVineet Gupta
3256d1a20b1SVineet Gupta.Lrestore_regs:
3266d1a20b1SVineet Gupta
3276d1a20b1SVineet Gupta	TRACE_ASM_IRQ_ENABLE
3286d1a20b1SVineet Gupta
3296d1a20b1SVineet Gupta	lr	r10, [status32]
3306d1a20b1SVineet Gupta
3316d1a20b1SVineet Gupta	; Restore REG File. In case multiple Events outstanding,
3326d1a20b1SVineet Gupta	; use the same priorty as rtie: EXCPN, L2 IRQ, L1 IRQ, None
3336d1a20b1SVineet Gupta	; Note that we use realtime STATUS32 (not pt_regs->status32) to
3346d1a20b1SVineet Gupta	; decide that.
3356d1a20b1SVineet Gupta
3366d1a20b1SVineet Gupta	; if Returning from Exception
337c80417b6SVineet Gupta	btst   r10, STATUS_AE_BIT
338c80417b6SVineet Gupta	bnz    .Lexcep_ret
3396d1a20b1SVineet Gupta
3406d1a20b1SVineet Gupta	; Not Exception so maybe Interrupts (Level 1 or 2)
3416d1a20b1SVineet Gupta
3426d1a20b1SVineet Gupta#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
3436d1a20b1SVineet Gupta
3446d1a20b1SVineet Gupta	; Level 2 interrupt return Path - from hardware standpoint
3456d1a20b1SVineet Gupta	bbit0  r10, STATUS_A2_BIT, not_level2_interrupt
3466d1a20b1SVineet Gupta
3476d1a20b1SVineet Gupta	;------------------------------------------------------------------
3486d1a20b1SVineet Gupta	; However the context returning might not have taken L2 intr itself
3496d1a20b1SVineet Gupta	; e.g. Task'A' user-code -> L2 intr -> schedule -> 'B' user-code ret
3506d1a20b1SVineet Gupta	; Special considerations needed for the context which took L2 intr
3516d1a20b1SVineet Gupta
3526d1a20b1SVineet Gupta	ld   r9, [sp, PT_event]        ; Ensure this is L2 intr context
3536d1a20b1SVineet Gupta	brne r9, event_IRQ2, 149f
3546d1a20b1SVineet Gupta
3556d1a20b1SVineet Gupta	;------------------------------------------------------------------
3566d1a20b1SVineet Gupta	; if L2 IRQ interrupted an L1 ISR,  we'd disabled preemption earlier
3576d1a20b1SVineet Gupta	; so that sched doesn't move to new task, causing L1 to be delayed
3586d1a20b1SVineet Gupta	; undeterministically. Now that we've achieved that, let's reset
3596d1a20b1SVineet Gupta	; things to what they were, before returning from L2 context
3606d1a20b1SVineet Gupta	;----------------------------------------------------------------
3616d1a20b1SVineet Gupta
3626d1a20b1SVineet Gupta	ld r9, [sp, PT_status32]       ; get statu32_l2 (saved in pt_regs)
3636d1a20b1SVineet Gupta	bbit0 r9, STATUS_A1_BIT, 149f  ; L1 not active when L2 IRQ, so normal
3646d1a20b1SVineet Gupta
3656d1a20b1SVineet Gupta	; decrement thread_info->preempt_count (re-enable preemption)
3666d1a20b1SVineet Gupta	GET_CURR_THR_INFO_FROM_SP   r10
3676d1a20b1SVineet Gupta	ld      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
3686d1a20b1SVineet Gupta
3696d1a20b1SVineet Gupta	; paranoid check, given A1 was active when A2 happened, preempt count
3706d1a20b1SVineet Gupta	; must not be 0 because we would have incremented it.
3716d1a20b1SVineet Gupta	; If this does happen we simply HALT as it means a BUG !!!
3726d1a20b1SVineet Gupta	cmp     r9, 0
3736d1a20b1SVineet Gupta	bnz     2f
3746d1a20b1SVineet Gupta	flag 1
3756d1a20b1SVineet Gupta
3766d1a20b1SVineet Gupta2:
3776d1a20b1SVineet Gupta	sub     r9, r9, 1
3786d1a20b1SVineet Gupta	st      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
3796d1a20b1SVineet Gupta
3806d1a20b1SVineet Gupta149:
3816d1a20b1SVineet Gupta	;return from level 2
3826d1a20b1SVineet Gupta	INTERRUPT_EPILOGUE 2
3836d1a20b1SVineet Guptadebug_marker_l2:
3846d1a20b1SVineet Gupta	rtie
3856d1a20b1SVineet Gupta
3866d1a20b1SVineet Guptanot_level2_interrupt:
3876d1a20b1SVineet Gupta
3886d1a20b1SVineet Gupta#endif
3896d1a20b1SVineet Gupta
390c80417b6SVineet Gupta	bbit0  r10, STATUS_A1_BIT, .Lpure_k_mode_ret
3916d1a20b1SVineet Gupta
3926d1a20b1SVineet Gupta	;return from level 1
3936d1a20b1SVineet Gupta	INTERRUPT_EPILOGUE 1
3946d1a20b1SVineet Guptadebug_marker_l1:
3956d1a20b1SVineet Gupta	rtie
3966d1a20b1SVineet Gupta
397c80417b6SVineet Gupta.Lexcep_ret:
398c80417b6SVineet Gupta.Lpure_k_mode_ret:
3996d1a20b1SVineet Gupta
400c80417b6SVineet Gupta	;this case is for syscalls or Exceptions or pure kernel mode
4016d1a20b1SVineet Gupta
4026d1a20b1SVineet Gupta	EXCEPTION_EPILOGUE
4036d1a20b1SVineet Guptadebug_marker_syscall:
4046d1a20b1SVineet Gupta	rtie
405c7e6d792SVineet Gupta
406c7e6d792SVineet GuptaEND(ret_from_exception)
407