xref: /openbmc/linux/arch/arc/kernel/entry-compact.S (revision 94055304690acfa256c39e36d0eb80294d1a7d65)
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() no longer 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
33*94055304SLiav Rehana *   out. Since we don't do FAKE RTIE for Priv-V, CPU exception 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>
62*94055304SLiav Rehana#include <linux/linkage.h>	/* {ENTRY,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
83*94055304SLiav Rehana * across sections (.vector to .text) we are guaranteed that 'j somewhere'
84*94055304SLiav Rehana * will use the 'j limm' form of the instruction as long as somewhere is in
856d1a20b1SVineet Gupta * a section other than .vector.
866d1a20b1SVineet Gupta */
876d1a20b1SVineet Gupta
886d1a20b1SVineet Gupta; ********* Critical System Events **********************
893971cdc2SVineet GuptaVECTOR   res_service             ; 0x0, Reset Vector	(0x0)
906d1a20b1SVineet GuptaVECTOR   mem_service             ; 0x8, Mem exception   (0x1)
916d1a20b1SVineet GuptaVECTOR   instr_service           ; 0x10, Instrn Error   (0x2)
926d1a20b1SVineet Gupta
936d1a20b1SVineet Gupta; ******************** Device ISRs **********************
9460f2b4b8SVineet Gupta#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
956d1a20b1SVineet GuptaVECTOR   handle_interrupt_level2
966d1a20b1SVineet Gupta#else
976d1a20b1SVineet GuptaVECTOR   handle_interrupt_level1
986d1a20b1SVineet Gupta#endif
996d1a20b1SVineet Gupta
10060f2b4b8SVineet Gupta.rept   28
1016d1a20b1SVineet GuptaVECTOR   handle_interrupt_level1 ; Other devices
1026d1a20b1SVineet Gupta.endr
1036d1a20b1SVineet Gupta
1046d1a20b1SVineet Gupta/* FOR ARC600: timer = 0x3, uart = 0x8, emac = 0x10 */
1056d1a20b1SVineet Gupta
1066d1a20b1SVineet Gupta; ******************** Exceptions **********************
1076d1a20b1SVineet GuptaVECTOR   EV_MachineCheck         ; 0x100, Fatal Machine check   (0x20)
108*94055304SLiav RehanaVECTOR   EV_TLBMissI             ; 0x108, Instruction TLB miss  (0x21)
1096d1a20b1SVineet GuptaVECTOR   EV_TLBMissD             ; 0x110, Data TLB miss         (0x22)
1106d1a20b1SVineet GuptaVECTOR   EV_TLBProtV             ; 0x118, Protection Violation  (0x23)
1116d1a20b1SVineet Gupta				 ;         or Misaligned Access
1126d1a20b1SVineet GuptaVECTOR   EV_PrivilegeV           ; 0x120, Privilege Violation   (0x24)
1136d1a20b1SVineet GuptaVECTOR   EV_Trap                 ; 0x128, Trap exception        (0x25)
114*94055304SLiav RehanaVECTOR   EV_Extension            ; 0x130, Extn Instruction Excp (0x26)
1156d1a20b1SVineet Gupta
1166d1a20b1SVineet Gupta.rept   24
1176d1a20b1SVineet GuptaVECTOR   reserved                ; Reserved Exceptions
1186d1a20b1SVineet Gupta.endr
1196d1a20b1SVineet Gupta
1206d1a20b1SVineet Gupta
1216d1a20b1SVineet Gupta;##################### Scratch Mem for IRQ stack switching #############
1226d1a20b1SVineet Gupta
1236d1a20b1SVineet GuptaARCFP_DATA int1_saved_reg
1246d1a20b1SVineet Gupta	.align 32
1256d1a20b1SVineet Gupta	.type   int1_saved_reg, @object
1266d1a20b1SVineet Gupta	.size   int1_saved_reg, 4
1276d1a20b1SVineet Guptaint1_saved_reg:
1286d1a20b1SVineet Gupta	.zero 4
1296d1a20b1SVineet Gupta
1306d1a20b1SVineet Gupta/* Each Interrupt level needs its own scratch */
1316d1a20b1SVineet GuptaARCFP_DATA int2_saved_reg
1326d1a20b1SVineet Gupta	.type   int2_saved_reg, @object
1336d1a20b1SVineet Gupta	.size   int2_saved_reg, 4
1346d1a20b1SVineet Guptaint2_saved_reg:
1356d1a20b1SVineet Gupta	.zero 4
1366d1a20b1SVineet Gupta
1376d1a20b1SVineet Gupta; ---------------------------------------------
1386d1a20b1SVineet Gupta	.section .text, "ax",@progbits
1396d1a20b1SVineet Gupta
1406d1a20b1SVineet Gupta
1413971cdc2SVineet Guptareserved:
1423971cdc2SVineet Gupta	flag 1		; Unexpected event, halt
1436d1a20b1SVineet Gupta
1446d1a20b1SVineet Gupta;##################### Interrupt Handling ##############################
1456d1a20b1SVineet Gupta
1466d1a20b1SVineet Gupta#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
1476d1a20b1SVineet Gupta; ---------------------------------------------
1486d1a20b1SVineet Gupta;  Level 2 ISR: Can interrupt a Level 1 ISR
1496d1a20b1SVineet Gupta; ---------------------------------------------
1506d1a20b1SVineet GuptaENTRY(handle_interrupt_level2)
1516d1a20b1SVineet Gupta
1526d1a20b1SVineet Gupta	INTERRUPT_PROLOGUE 2
1536d1a20b1SVineet Gupta
1546d1a20b1SVineet Gupta	;------------------------------------------------------
1556d1a20b1SVineet Gupta	; if L2 IRQ interrupted a L1 ISR, disable preemption
1565f888087SVineet Gupta	;
1575f888087SVineet Gupta	; This is to avoid a potential L1-L2-L1 scenario
1585f888087SVineet Gupta	;  -L1 IRQ taken
1595f888087SVineet Gupta	;  -L2 interrupts L1 (before L1 ISR could run)
1605f888087SVineet Gupta	;  -preemption off IRQ, user task in syscall picked to run
1615f888087SVineet Gupta	;  -RTIE to userspace
1625f888087SVineet Gupta	;	Returns from L2 context fine
1635f888087SVineet Gupta	;	But both L1 and L2 re-enabled, so another L1 can be taken
1645f888087SVineet Gupta	;	while prev L1 is still unserviced
1655f888087SVineet Gupta	;
1666d1a20b1SVineet Gupta	;------------------------------------------------------
1676d1a20b1SVineet Gupta
1685f888087SVineet Gupta	; L2 interrupting L1 implies both L2 and L1 active
1695f888087SVineet Gupta	; However both A2 and A1 are NOT set in STATUS32, thus
1705f888087SVineet Gupta	; need to check STATUS32_L2 to determine if L1 was active
1715f888087SVineet Gupta
1726d1a20b1SVineet Gupta	ld r9, [sp, PT_status32]        ; get statu32_l2 (saved in pt_regs)
1736d1a20b1SVineet Gupta	bbit0 r9, STATUS_A1_BIT, 1f     ; L1 not active when L2 IRQ, so normal
1746d1a20b1SVineet Gupta
1756d1a20b1SVineet Gupta	; bump thread_info->preempt_count (Disable preemption)
1766d1a20b1SVineet Gupta	GET_CURR_THR_INFO_FROM_SP   r10
1776d1a20b1SVineet Gupta	ld      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
1786d1a20b1SVineet Gupta	add     r9, r9, 1
1796d1a20b1SVineet Gupta	st      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
1806d1a20b1SVineet Gupta
1816d1a20b1SVineet Gupta1:
1826d1a20b1SVineet Gupta	;------------------------------------------------------
1836d1a20b1SVineet Gupta	; setup params for Linux common ISR and invoke it
1846d1a20b1SVineet Gupta	;------------------------------------------------------
1856d1a20b1SVineet Gupta	lr  r0, [icause2]
1866d1a20b1SVineet Gupta	and r0, r0, 0x1f
1876d1a20b1SVineet Gupta
1886d1a20b1SVineet Gupta	bl.d  @arch_do_IRQ
1896d1a20b1SVineet Gupta	mov r1, sp
1906d1a20b1SVineet Gupta
1916d1a20b1SVineet Gupta	mov r8,0x2
1926d1a20b1SVineet Gupta	sr r8, [AUX_IRQ_LV12]       ; clear bit in Sticky Status Reg
1936d1a20b1SVineet Gupta
1946d1a20b1SVineet Gupta	b   ret_from_exception
1956d1a20b1SVineet Gupta
1966d1a20b1SVineet GuptaEND(handle_interrupt_level2)
1976d1a20b1SVineet Gupta
1986d1a20b1SVineet Gupta#endif
1996d1a20b1SVineet Gupta
2006d1a20b1SVineet Gupta; ---------------------------------------------
201541366daSVineet Gupta; User Mode Memory Bus Error Interrupt Handler
202*94055304SLiav Rehana; (Kernel mode memory errors handled via separate exception vectors)
203541366daSVineet Gupta; ---------------------------------------------
204541366daSVineet GuptaENTRY(mem_service)
205541366daSVineet Gupta
206541366daSVineet Gupta	INTERRUPT_PROLOGUE 2
207541366daSVineet Gupta
208541366daSVineet Gupta	mov r0, ilink2
209541366daSVineet Gupta	mov r1, sp
210541366daSVineet Gupta
211541366daSVineet Gupta	; User process needs to be killed with SIGBUS, but first need to get
212541366daSVineet Gupta	; out of the L2 interrupt context (drop to pure kernel mode) and jump
213541366daSVineet Gupta	; off to "C" code where SIGBUS in enqueued
214541366daSVineet Gupta	lr  r3, [status32]
215541366daSVineet Gupta	bclr r3, r3, STATUS_A2_BIT
216541366daSVineet Gupta	or  r3, r3, (STATUS_E1_MASK|STATUS_E2_MASK)
217541366daSVineet Gupta	sr  r3, [status32_l2]
218541366daSVineet Gupta	mov ilink2, 1f
219541366daSVineet Gupta	rtie
220541366daSVineet Gupta1:
221541366daSVineet Gupta	bl  do_memory_error
222541366daSVineet Gupta	b   ret_from_exception
223541366daSVineet GuptaEND(mem_service)
224541366daSVineet Gupta
225541366daSVineet Gupta; ---------------------------------------------
2266d1a20b1SVineet Gupta;  Level 1 ISR
2276d1a20b1SVineet Gupta; ---------------------------------------------
2286d1a20b1SVineet GuptaENTRY(handle_interrupt_level1)
2296d1a20b1SVineet Gupta
2306d1a20b1SVineet Gupta	INTERRUPT_PROLOGUE 1
2316d1a20b1SVineet Gupta
2326d1a20b1SVineet Gupta	lr  r0, [icause1]
2336d1a20b1SVineet Gupta	and r0, r0, 0x1f
2346d1a20b1SVineet Gupta
2356d1a20b1SVineet Gupta#ifdef CONFIG_TRACE_IRQFLAGS
2366d1a20b1SVineet Gupta	; icause1 needs to be read early, before calling tracing, which
2376d1a20b1SVineet Gupta	; can clobber scratch regs, hence use of stack to stash it
2386d1a20b1SVineet Gupta	push r0
2396d1a20b1SVineet Gupta	TRACE_ASM_IRQ_DISABLE
2406d1a20b1SVineet Gupta	pop  r0
2416d1a20b1SVineet Gupta#endif
2426d1a20b1SVineet Gupta
2436d1a20b1SVineet Gupta	bl.d  @arch_do_IRQ
2446d1a20b1SVineet Gupta	mov r1, sp
2456d1a20b1SVineet Gupta
2466d1a20b1SVineet Gupta	mov r8,0x1
2476d1a20b1SVineet Gupta	sr r8, [AUX_IRQ_LV12]       ; clear bit in Sticky Status Reg
2486d1a20b1SVineet Gupta
2496d1a20b1SVineet Gupta	b   ret_from_exception
2506d1a20b1SVineet GuptaEND(handle_interrupt_level1)
2516d1a20b1SVineet Gupta
2526d1a20b1SVineet Gupta;################### Non TLB Exception Handling #############################
2536d1a20b1SVineet Gupta
2546d1a20b1SVineet Gupta; ---------------------------------------------
2556d1a20b1SVineet Gupta; Protection Violation Exception Handler
2566d1a20b1SVineet Gupta; ---------------------------------------------
2576d1a20b1SVineet Gupta
2586d1a20b1SVineet GuptaENTRY(EV_TLBProtV)
2596d1a20b1SVineet Gupta
2606d1a20b1SVineet Gupta	EXCEPTION_PROLOGUE
2616d1a20b1SVineet Gupta
262f5f3bde4SVineet Gupta	mov r2, r9	; ECR set into r9 already
2636d1a20b1SVineet Gupta	lr  r0, [efa]	; Faulting Data address (not part of pt_regs saved above)
2646d1a20b1SVineet Gupta
2656d1a20b1SVineet Gupta	; Exception auto-disables further Intr/exceptions.
2666d1a20b1SVineet Gupta	; Re-enable them by pretending to return from exception
2676d1a20b1SVineet Gupta	; (so rest of handler executes in pure K mode)
2686d1a20b1SVineet Gupta
2696d1a20b1SVineet Gupta	FAKE_RET_FROM_EXCPN
2706d1a20b1SVineet Gupta
2716d1a20b1SVineet Gupta	mov   r1, sp	; Handle to pt_regs
2726d1a20b1SVineet Gupta
2736d1a20b1SVineet Gupta	;------ (5) Type of Protection Violation? ----------
2746d1a20b1SVineet Gupta	;
2756d1a20b1SVineet Gupta	; ProtV Hardware Exception is triggered for Access Faults of 2 types
276*94055304SLiav Rehana	;   -Access Violation	: 00_23_(00|01|02|03)_00
2776d1a20b1SVineet Gupta	;			         x  r  w  r+w
2786d1a20b1SVineet Gupta	;   -Unaligned Access	: 00_23_04_00
2796d1a20b1SVineet Gupta	;
2806d1a20b1SVineet Gupta	bbit1 r2, ECR_C_BIT_PROTV_MISALIG_DATA, 4f
2816d1a20b1SVineet Gupta
2826d1a20b1SVineet Gupta	;========= (6a) Access Violation Processing ========
2836d1a20b1SVineet Gupta	bl  do_page_fault
2846d1a20b1SVineet Gupta	b   ret_from_exception
2856d1a20b1SVineet Gupta
2866d1a20b1SVineet Gupta	;========== (6b) Non aligned access ============
2876d1a20b1SVineet Gupta4:
2886d1a20b1SVineet Gupta
2896d1a20b1SVineet Gupta	SAVE_CALLEE_SAVED_USER
2906d1a20b1SVineet Gupta	mov r2, sp              ; callee_regs
2916d1a20b1SVineet Gupta
2926d1a20b1SVineet Gupta	bl  do_misaligned_access
2936d1a20b1SVineet Gupta
2946d1a20b1SVineet Gupta	; TBD: optimize - do this only if a callee reg was involved
2956d1a20b1SVineet Gupta	; either a dst of emulated LD/ST or src with address-writeback
2966d1a20b1SVineet Gupta	RESTORE_CALLEE_SAVED_USER
2976d1a20b1SVineet Gupta
2986d1a20b1SVineet Gupta	b   ret_from_exception
2996d1a20b1SVineet Gupta
3006d1a20b1SVineet GuptaEND(EV_TLBProtV)
3016d1a20b1SVineet Gupta
3026d1a20b1SVineet Gupta; Wrapper for Linux page fault handler called from EV_TLBMiss*
3036d1a20b1SVineet Gupta; Very similar to ProtV handler case (6a) above, but avoids the extra checks
3046d1a20b1SVineet Gupta; for Misaligned access
3056d1a20b1SVineet Gupta;
3066d1a20b1SVineet GuptaENTRY(call_do_page_fault)
3076d1a20b1SVineet Gupta
3086d1a20b1SVineet Gupta	EXCEPTION_PROLOGUE
3096d1a20b1SVineet Gupta	lr  r0, [efa]	; Faulting Data address
3106d1a20b1SVineet Gupta	mov   r1, sp
3116d1a20b1SVineet Gupta	FAKE_RET_FROM_EXCPN
3126d1a20b1SVineet Gupta
3136d1a20b1SVineet Gupta	mov blink, ret_from_exception
3146d1a20b1SVineet Gupta	b  do_page_fault
3156d1a20b1SVineet Gupta
3166d1a20b1SVineet GuptaEND(call_do_page_fault)
3176d1a20b1SVineet Gupta
3186d1a20b1SVineet Gupta;############# Common Handlers for ARCompact and ARCv2 ##############
3196d1a20b1SVineet Gupta
3206d1a20b1SVineet Gupta#include "entry.S"
3216d1a20b1SVineet Gupta
3226d1a20b1SVineet Gupta;############# Return from Intr/Excp/Trap (ARC Specifics) ##############
3236d1a20b1SVineet Gupta;
3246d1a20b1SVineet Gupta; Restore the saved sys context (common exit-path for EXCPN/IRQ/Trap)
3256d1a20b1SVineet Gupta; IRQ shd definitely not happen between now and rtie
3266d1a20b1SVineet Gupta; All 2 entry points to here already disable interrupts
3276d1a20b1SVineet Gupta
3286d1a20b1SVineet Gupta.Lrestore_regs:
3296d1a20b1SVineet Gupta
330*94055304SLiav Rehana	# Interrupts are actually disabled from this point on, but will get
331d9676fa1SEvgeny Voevodin	# reenabled after we return from interrupt/exception.
332d9676fa1SEvgeny Voevodin	# But irq tracer needs to be told now...
3336d1a20b1SVineet Gupta	TRACE_ASM_IRQ_ENABLE
3346d1a20b1SVineet Gupta
3356d1a20b1SVineet Gupta	lr	r10, [status32]
3366d1a20b1SVineet Gupta
3376d1a20b1SVineet Gupta	; Restore REG File. In case multiple Events outstanding,
338*94055304SLiav Rehana	; use the same priority as rtie: EXCPN, L2 IRQ, L1 IRQ, None
3396d1a20b1SVineet Gupta	; Note that we use realtime STATUS32 (not pt_regs->status32) to
3406d1a20b1SVineet Gupta	; decide that.
3416d1a20b1SVineet Gupta
3429fabcc63SVineet Gupta	and.f	0, r10, (STATUS_A1_MASK|STATUS_A2_MASK)
3439fabcc63SVineet Gupta	bz	.Lexcep_or_pure_K_ret
3446d1a20b1SVineet Gupta
3459fabcc63SVineet Gupta	; Returning from Interrupts (Level 1 or 2)
3466d1a20b1SVineet Gupta
3476d1a20b1SVineet Gupta#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
3486d1a20b1SVineet Gupta
3496d1a20b1SVineet Gupta	; Level 2 interrupt return Path - from hardware standpoint
3506d1a20b1SVineet Gupta	bbit0  r10, STATUS_A2_BIT, not_level2_interrupt
3516d1a20b1SVineet Gupta
3526d1a20b1SVineet Gupta	;------------------------------------------------------------------
3536d1a20b1SVineet Gupta	; However the context returning might not have taken L2 intr itself
3546d1a20b1SVineet Gupta	; e.g. Task'A' user-code -> L2 intr -> schedule -> 'B' user-code ret
3556d1a20b1SVineet Gupta	; Special considerations needed for the context which took L2 intr
3566d1a20b1SVineet Gupta
3576d1a20b1SVineet Gupta	ld   r9, [sp, PT_event]        ; Ensure this is L2 intr context
3586d1a20b1SVineet Gupta	brne r9, event_IRQ2, 149f
3596d1a20b1SVineet Gupta
3606d1a20b1SVineet Gupta	;------------------------------------------------------------------
3616d1a20b1SVineet Gupta	; if L2 IRQ interrupted an L1 ISR,  we'd disabled preemption earlier
3626d1a20b1SVineet Gupta	; so that sched doesn't move to new task, causing L1 to be delayed
3636d1a20b1SVineet Gupta	; undeterministically. Now that we've achieved that, let's reset
3646d1a20b1SVineet Gupta	; things to what they were, before returning from L2 context
3656d1a20b1SVineet Gupta	;----------------------------------------------------------------
3666d1a20b1SVineet Gupta
3676d1a20b1SVineet Gupta	ld r9, [sp, PT_status32]       ; get statu32_l2 (saved in pt_regs)
3686d1a20b1SVineet Gupta	bbit0 r9, STATUS_A1_BIT, 149f  ; L1 not active when L2 IRQ, so normal
3696d1a20b1SVineet Gupta
3706d1a20b1SVineet Gupta	; decrement thread_info->preempt_count (re-enable preemption)
3716d1a20b1SVineet Gupta	GET_CURR_THR_INFO_FROM_SP   r10
3726d1a20b1SVineet Gupta	ld      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
3736d1a20b1SVineet Gupta
3746d1a20b1SVineet Gupta	; paranoid check, given A1 was active when A2 happened, preempt count
3756d1a20b1SVineet Gupta	; must not be 0 because we would have incremented it.
3766d1a20b1SVineet Gupta	; If this does happen we simply HALT as it means a BUG !!!
3776d1a20b1SVineet Gupta	cmp     r9, 0
3786d1a20b1SVineet Gupta	bnz     2f
3796d1a20b1SVineet Gupta	flag 1
3806d1a20b1SVineet Gupta
3816d1a20b1SVineet Gupta2:
3826d1a20b1SVineet Gupta	sub     r9, r9, 1
3836d1a20b1SVineet Gupta	st      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
3846d1a20b1SVineet Gupta
3856d1a20b1SVineet Gupta149:
3869fabcc63SVineet Gupta	INTERRUPT_EPILOGUE 2	; return from level 2 interrupt
3876d1a20b1SVineet Guptadebug_marker_l2:
3886d1a20b1SVineet Gupta	rtie
3896d1a20b1SVineet Gupta
3906d1a20b1SVineet Guptanot_level2_interrupt:
3916d1a20b1SVineet Gupta
3926d1a20b1SVineet Gupta#endif
3936d1a20b1SVineet Gupta
3949fabcc63SVineet Gupta	INTERRUPT_EPILOGUE 1	; return from level 1 interrupt
3956d1a20b1SVineet Guptadebug_marker_l1:
3966d1a20b1SVineet Gupta	rtie
3976d1a20b1SVineet Gupta
3989fabcc63SVineet Gupta.Lexcep_or_pure_K_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