xref: /openbmc/linux/arch/arc/kernel/entry-compact.S (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1d2912cb1SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */
26d1a20b1SVineet Gupta/*
36d1a20b1SVineet Gupta * Low Level Interrupts/Traps/Exceptions(non-TLB) Handling for ARCompact ISA
46d1a20b1SVineet Gupta *
56d1a20b1SVineet Gupta * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
66d1a20b1SVineet Gupta * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
76d1a20b1SVineet Gupta *
86d1a20b1SVineet Gupta * vineetg: May 2011
96d1a20b1SVineet Gupta *  -Userspace unaligned access emulation
106d1a20b1SVineet Gupta *
116d1a20b1SVineet Gupta * vineetg: Feb 2011 (ptrace low level code fixes)
126d1a20b1SVineet Gupta *  -traced syscall return code (r0) was not saved into pt_regs for restoring
136d1a20b1SVineet Gupta *   into user reg-file when traded task rets to user space.
146d1a20b1SVineet Gupta *  -syscalls needing arch-wrappers (mainly for passing sp as pt_regs)
156d1a20b1SVineet Gupta *   were not invoking post-syscall trace hook (jumping directly into
166d1a20b1SVineet Gupta *   ret_from_system_call)
176d1a20b1SVineet Gupta *
186d1a20b1SVineet Gupta * vineetg: Nov 2010:
196d1a20b1SVineet Gupta *  -Vector table jumps (@8 bytes) converted into branches (@4 bytes)
206d1a20b1SVineet Gupta *  -To maintain the slot size of 8 bytes/vector, added nop, which is
216d1a20b1SVineet Gupta *   not executed at runtime.
226d1a20b1SVineet Gupta *
236d1a20b1SVineet Gupta * vineetg: Nov 2009 (Everything needed for TIF_RESTORE_SIGMASK)
246d1a20b1SVineet Gupta *  -do_signal()invoked upon TIF_RESTORE_SIGMASK as well
256d1a20b1SVineet Gupta *  -Wrappers for sys_{,rt_}sigsuspend() no longer needed as they don't
266d1a20b1SVineet Gupta *   need ptregs anymore
276d1a20b1SVineet Gupta *
286d1a20b1SVineet Gupta * Vineetg: Oct 2009
296d1a20b1SVineet Gupta *  -In a rare scenario, Process gets a Priv-V exception and gets scheduled
3094055304SLiav Rehana *   out. Since we don't do FAKE RTIE for Priv-V, CPU exception state remains
316d1a20b1SVineet Gupta *   active (AE bit enabled).  This causes a double fault for a subseq valid
326d1a20b1SVineet Gupta *   exception. Thus FAKE RTIE needed in low level Priv-Violation handler.
336d1a20b1SVineet Gupta *   Instr Error could also cause similar scenario, so same there as well.
346d1a20b1SVineet Gupta *
356d1a20b1SVineet Gupta * Vineetg: March 2009 (Supporting 2 levels of Interrupts)
366d1a20b1SVineet Gupta *
376d1a20b1SVineet Gupta * Vineetg: Aug 28th 2008: Bug #94984
386d1a20b1SVineet Gupta *  -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap
396d1a20b1SVineet Gupta *   Normally CPU does this automatically, however when doing FAKE rtie,
406d1a20b1SVineet Gupta *   we need to explicitly do this. The problem in macros
416d1a20b1SVineet Gupta *   FAKE_RET_FROM_EXCPN and FAKE_RET_FROM_EXCPN_LOCK_IRQ was that this bit
426d1a20b1SVineet Gupta *   was being "CLEARED" rather then "SET". Since it is Loop INHIBIT Bit,
436d1a20b1SVineet Gupta *   setting it and not clearing it clears ZOL context
446d1a20b1SVineet Gupta *
456d1a20b1SVineet Gupta * Vineetg: May 16th, 2008
466d1a20b1SVineet Gupta *  - r25 now contains the Current Task when in kernel
476d1a20b1SVineet Gupta *
486d1a20b1SVineet Gupta * Vineetg: Dec 22, 2007
496d1a20b1SVineet Gupta *    Minor Surgery of Low Level ISR to make it SMP safe
506d1a20b1SVineet Gupta *    - MMU_SCRATCH0 Reg used for freeing up r9 in Level 1 ISR
516d1a20b1SVineet Gupta *    - _current_task is made an array of NR_CPUS
526d1a20b1SVineet Gupta *    - Access of _current_task wrapped inside a macro so that if hardware
536d1a20b1SVineet Gupta *       team agrees for a dedicated reg, no other code is touched
546d1a20b1SVineet Gupta *
556d1a20b1SVineet Gupta * Amit Bhor, Rahul Trivedi, Kanika Nema, Sameer Dhavale : Codito Tech 2004
566d1a20b1SVineet Gupta */
576d1a20b1SVineet Gupta
586d1a20b1SVineet Gupta#include <linux/errno.h>
5994055304SLiav Rehana#include <linux/linkage.h>	/* {ENTRY,EXIT} */
606d1a20b1SVineet Gupta#include <asm/entry.h>
616d1a20b1SVineet Gupta#include <asm/irqflags.h>
626d1a20b1SVineet Gupta
636d1a20b1SVineet Gupta	.cpu A7
646d1a20b1SVineet Gupta
656d1a20b1SVineet Gupta;############################ Vector Table #################################
666d1a20b1SVineet Gupta
676d1a20b1SVineet Gupta.macro VECTOR  lbl
686d1a20b1SVineet Gupta#if 1   /* Just in case, build breaks */
696d1a20b1SVineet Gupta	j   \lbl
706d1a20b1SVineet Gupta#else
716d1a20b1SVineet Gupta	b   \lbl
726d1a20b1SVineet Gupta	nop
736d1a20b1SVineet Gupta#endif
746d1a20b1SVineet Gupta.endm
756d1a20b1SVineet Gupta
766d1a20b1SVineet Gupta	.section .vector, "ax",@progbits
776d1a20b1SVineet Gupta	.align 4
786d1a20b1SVineet Gupta
796d1a20b1SVineet Gupta/* Each entry in the vector table must occupy 2 words. Since it is a jump
8094055304SLiav Rehana * across sections (.vector to .text) we are guaranteed that 'j somewhere'
8194055304SLiav Rehana * will use the 'j limm' form of the instruction as long as somewhere is in
826d1a20b1SVineet Gupta * a section other than .vector.
836d1a20b1SVineet Gupta */
846d1a20b1SVineet Gupta
856d1a20b1SVineet Gupta; ********* Critical System Events **********************
863971cdc2SVineet GuptaVECTOR   res_service             ; 0x0, Reset Vector	(0x0)
876d1a20b1SVineet GuptaVECTOR   mem_service             ; 0x8, Mem exception   (0x1)
886d1a20b1SVineet GuptaVECTOR   instr_service           ; 0x10, Instrn Error   (0x2)
896d1a20b1SVineet Gupta
906d1a20b1SVineet Gupta; ******************** Device ISRs **********************
9160f2b4b8SVineet Gupta#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
926d1a20b1SVineet GuptaVECTOR   handle_interrupt_level2
936d1a20b1SVineet Gupta#else
946d1a20b1SVineet GuptaVECTOR   handle_interrupt_level1
956d1a20b1SVineet Gupta#endif
966d1a20b1SVineet Gupta
9760f2b4b8SVineet Gupta.rept   28
986d1a20b1SVineet GuptaVECTOR   handle_interrupt_level1 ; Other devices
996d1a20b1SVineet Gupta.endr
1006d1a20b1SVineet Gupta
1016d1a20b1SVineet Gupta/* FOR ARC600: timer = 0x3, uart = 0x8, emac = 0x10 */
1026d1a20b1SVineet Gupta
1036d1a20b1SVineet Gupta; ******************** Exceptions **********************
1046d1a20b1SVineet GuptaVECTOR   EV_MachineCheck         ; 0x100, Fatal Machine check   (0x20)
10594055304SLiav RehanaVECTOR   EV_TLBMissI             ; 0x108, Instruction TLB miss  (0x21)
1066d1a20b1SVineet GuptaVECTOR   EV_TLBMissD             ; 0x110, Data TLB miss         (0x22)
1076d1a20b1SVineet GuptaVECTOR   EV_TLBProtV             ; 0x118, Protection Violation  (0x23)
1086d1a20b1SVineet Gupta				 ;         or Misaligned Access
1096d1a20b1SVineet GuptaVECTOR   EV_PrivilegeV           ; 0x120, Privilege Violation   (0x24)
1106d1a20b1SVineet GuptaVECTOR   EV_Trap                 ; 0x128, Trap exception        (0x25)
11194055304SLiav RehanaVECTOR   EV_Extension            ; 0x130, Extn Instruction Excp (0x26)
1126d1a20b1SVineet Gupta
1136d1a20b1SVineet Gupta.rept   24
1146d1a20b1SVineet GuptaVECTOR   reserved                ; Reserved Exceptions
1156d1a20b1SVineet Gupta.endr
1166d1a20b1SVineet Gupta
1176d1a20b1SVineet Gupta
1186d1a20b1SVineet Gupta;##################### Scratch Mem for IRQ stack switching #############
1196d1a20b1SVineet Gupta
1206d1a20b1SVineet GuptaARCFP_DATA int1_saved_reg
1216d1a20b1SVineet Gupta	.align 32
1226d1a20b1SVineet Gupta	.type   int1_saved_reg, @object
1236d1a20b1SVineet Gupta	.size   int1_saved_reg, 4
1246d1a20b1SVineet Guptaint1_saved_reg:
1256d1a20b1SVineet Gupta	.zero 4
1266d1a20b1SVineet Gupta
1276d1a20b1SVineet Gupta/* Each Interrupt level needs its own scratch */
1286d1a20b1SVineet GuptaARCFP_DATA int2_saved_reg
1296d1a20b1SVineet Gupta	.type   int2_saved_reg, @object
1306d1a20b1SVineet Gupta	.size   int2_saved_reg, 4
1316d1a20b1SVineet Guptaint2_saved_reg:
1326d1a20b1SVineet Gupta	.zero 4
1336d1a20b1SVineet Gupta
1346d1a20b1SVineet Gupta; ---------------------------------------------
1356d1a20b1SVineet Gupta	.section .text, "ax",@progbits
1366d1a20b1SVineet Gupta
1376d1a20b1SVineet Gupta
1383971cdc2SVineet Guptareserved:
1393971cdc2SVineet Gupta	flag 1		; Unexpected event, halt
1406d1a20b1SVineet Gupta
1416d1a20b1SVineet Gupta;##################### Interrupt Handling ##############################
1426d1a20b1SVineet Gupta
1436d1a20b1SVineet Gupta#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
1446d1a20b1SVineet Gupta; ---------------------------------------------
1456d1a20b1SVineet Gupta;  Level 2 ISR: Can interrupt a Level 1 ISR
1466d1a20b1SVineet Gupta; ---------------------------------------------
1476d1a20b1SVineet GuptaENTRY(handle_interrupt_level2)
1486d1a20b1SVineet Gupta
1496d1a20b1SVineet Gupta	INTERRUPT_PROLOGUE 2
1506d1a20b1SVineet Gupta
1516d1a20b1SVineet Gupta	;------------------------------------------------------
1526d1a20b1SVineet Gupta	; if L2 IRQ interrupted a L1 ISR, disable preemption
1535f888087SVineet Gupta	;
1545f888087SVineet Gupta	; This is to avoid a potential L1-L2-L1 scenario
1555f888087SVineet Gupta	;  -L1 IRQ taken
1565f888087SVineet Gupta	;  -L2 interrupts L1 (before L1 ISR could run)
1575f888087SVineet Gupta	;  -preemption off IRQ, user task in syscall picked to run
1585f888087SVineet Gupta	;  -RTIE to userspace
1595f888087SVineet Gupta	;	Returns from L2 context fine
1605f888087SVineet Gupta	;	But both L1 and L2 re-enabled, so another L1 can be taken
1615f888087SVineet Gupta	;	while prev L1 is still unserviced
1625f888087SVineet Gupta	;
1636d1a20b1SVineet Gupta	;------------------------------------------------------
1646d1a20b1SVineet Gupta
1655f888087SVineet Gupta	; L2 interrupting L1 implies both L2 and L1 active
1665f888087SVineet Gupta	; However both A2 and A1 are NOT set in STATUS32, thus
1675f888087SVineet Gupta	; need to check STATUS32_L2 to determine if L1 was active
1685f888087SVineet Gupta
1696d1a20b1SVineet Gupta	ld r9, [sp, PT_status32]        ; get statu32_l2 (saved in pt_regs)
1706d1a20b1SVineet Gupta	bbit0 r9, STATUS_A1_BIT, 1f     ; L1 not active when L2 IRQ, so normal
1716d1a20b1SVineet Gupta
1726d1a20b1SVineet Gupta	; bump thread_info->preempt_count (Disable preemption)
1736d1a20b1SVineet Gupta	GET_CURR_THR_INFO_FROM_SP   r10
1746d1a20b1SVineet Gupta	ld      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
1756d1a20b1SVineet Gupta	add     r9, r9, 1
1766d1a20b1SVineet Gupta	st      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
1776d1a20b1SVineet Gupta
1786d1a20b1SVineet Gupta1:
1796d1a20b1SVineet Gupta	;------------------------------------------------------
1806d1a20b1SVineet Gupta	; setup params for Linux common ISR and invoke it
1816d1a20b1SVineet Gupta	;------------------------------------------------------
1826d1a20b1SVineet Gupta	lr  r0, [icause2]
1836d1a20b1SVineet Gupta	and r0, r0, 0x1f
1846d1a20b1SVineet Gupta
1856d1a20b1SVineet Gupta	bl.d  @arch_do_IRQ
1866d1a20b1SVineet Gupta	mov r1, sp
1876d1a20b1SVineet Gupta
1886d1a20b1SVineet Gupta	mov r8,0x2
1896d1a20b1SVineet Gupta	sr r8, [AUX_IRQ_LV12]       ; clear bit in Sticky Status Reg
1906d1a20b1SVineet Gupta
1916d1a20b1SVineet Gupta	b   ret_from_exception
1926d1a20b1SVineet Gupta
1936d1a20b1SVineet GuptaEND(handle_interrupt_level2)
1946d1a20b1SVineet Gupta
1956d1a20b1SVineet Gupta#endif
1966d1a20b1SVineet Gupta
1976d1a20b1SVineet Gupta; ---------------------------------------------
198541366daSVineet Gupta; User Mode Memory Bus Error Interrupt Handler
19994055304SLiav Rehana; (Kernel mode memory errors handled via separate exception vectors)
200541366daSVineet Gupta; ---------------------------------------------
201541366daSVineet GuptaENTRY(mem_service)
202541366daSVineet Gupta
203541366daSVineet Gupta	INTERRUPT_PROLOGUE 2
204541366daSVineet Gupta
205541366daSVineet Gupta	mov r0, ilink2
206541366daSVineet Gupta	mov r1, sp
207541366daSVineet Gupta
208541366daSVineet Gupta	; User process needs to be killed with SIGBUS, but first need to get
209541366daSVineet Gupta	; out of the L2 interrupt context (drop to pure kernel mode) and jump
210541366daSVineet Gupta	; off to "C" code where SIGBUS in enqueued
211541366daSVineet Gupta	lr  r3, [status32]
212541366daSVineet Gupta	bclr r3, r3, STATUS_A2_BIT
213541366daSVineet Gupta	or  r3, r3, (STATUS_E1_MASK|STATUS_E2_MASK)
214541366daSVineet Gupta	sr  r3, [status32_l2]
215541366daSVineet Gupta	mov ilink2, 1f
216541366daSVineet Gupta	rtie
217541366daSVineet Gupta1:
218541366daSVineet Gupta	bl  do_memory_error
219541366daSVineet Gupta	b   ret_from_exception
220541366daSVineet GuptaEND(mem_service)
221541366daSVineet Gupta
222541366daSVineet 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
257*6b606c8dSVineet Gupta	EXCEPTION_PROLOGUE	; ECR returned in r10
2586d1a20b1SVineet Gupta
2596d1a20b1SVineet Gupta	;------ (5) Type of Protection Violation? ----------
2606d1a20b1SVineet Gupta	;
2616d1a20b1SVineet Gupta	; ProtV Hardware Exception is triggered for Access Faults of 2 types
26294055304SLiav Rehana	;   -Access Violation	: 00_23_(00|01|02|03)_00
2636d1a20b1SVineet Gupta	;			         x  r  w  r+w
2646d1a20b1SVineet Gupta	;   -Unaligned Access	: 00_23_04_00
265*6b606c8dSVineet Gupta	bbit1 r10, ECR_C_BIT_PROTV_MISALIG_DATA, 4f
2666d1a20b1SVineet Gupta
2676d1a20b1SVineet Gupta	;========= (6a) Access Violation Processing ========
2686d1a20b1SVineet Gupta	bl  do_page_fault
2696d1a20b1SVineet Gupta	b   ret_from_exception
2706d1a20b1SVineet Gupta
2716d1a20b1SVineet Gupta	;========== (6b) Non aligned access ============
2726d1a20b1SVineet Gupta4:
2736d1a20b1SVineet Gupta
2746d1a20b1SVineet Gupta	SAVE_CALLEE_SAVED_USER
2756d1a20b1SVineet Gupta	mov r2, sp              ; callee_regs
2766d1a20b1SVineet Gupta
2776d1a20b1SVineet Gupta	bl  do_misaligned_access
2786d1a20b1SVineet Gupta
2796d1a20b1SVineet Gupta	; TBD: optimize - do this only if a callee reg was involved
2806d1a20b1SVineet Gupta	; either a dst of emulated LD/ST or src with address-writeback
2816d1a20b1SVineet Gupta	RESTORE_CALLEE_SAVED_USER
2826d1a20b1SVineet Gupta
2836d1a20b1SVineet Gupta	b   ret_from_exception
2846d1a20b1SVineet Gupta
2856d1a20b1SVineet GuptaEND(EV_TLBProtV)
2866d1a20b1SVineet Gupta
2876d1a20b1SVineet Gupta; Wrapper for Linux page fault handler called from EV_TLBMiss*
2886d1a20b1SVineet Gupta; Very similar to ProtV handler case (6a) above, but avoids the extra checks
2896d1a20b1SVineet Gupta; for Misaligned access
2906d1a20b1SVineet Gupta;
2916d1a20b1SVineet GuptaENTRY(call_do_page_fault)
2926d1a20b1SVineet Gupta
2936d1a20b1SVineet Gupta	EXCEPTION_PROLOGUE
2946d1a20b1SVineet Gupta
2956d1a20b1SVineet Gupta	mov blink, ret_from_exception
2966d1a20b1SVineet Gupta	b  do_page_fault
2976d1a20b1SVineet Gupta
2986d1a20b1SVineet GuptaEND(call_do_page_fault)
2996d1a20b1SVineet Gupta
3006d1a20b1SVineet Gupta;############# Common Handlers for ARCompact and ARCv2 ##############
3016d1a20b1SVineet Gupta
3026d1a20b1SVineet Gupta#include "entry.S"
3036d1a20b1SVineet Gupta
3046d1a20b1SVineet Gupta;############# Return from Intr/Excp/Trap (ARC Specifics) ##############
3056d1a20b1SVineet Gupta;
3066d1a20b1SVineet Gupta; Restore the saved sys context (common exit-path for EXCPN/IRQ/Trap)
3076d1a20b1SVineet Gupta; IRQ shd definitely not happen between now and rtie
3086d1a20b1SVineet Gupta; All 2 entry points to here already disable interrupts
3096d1a20b1SVineet Gupta
3106d1a20b1SVineet Gupta.Lrestore_regs:
3116d1a20b1SVineet Gupta
31294055304SLiav Rehana	# Interrupts are actually disabled from this point on, but will get
313d9676fa1SEvgeny Voevodin	# reenabled after we return from interrupt/exception.
314d9676fa1SEvgeny Voevodin	# But irq tracer needs to be told now...
3156d1a20b1SVineet Gupta	TRACE_ASM_IRQ_ENABLE
3166d1a20b1SVineet Gupta
3176d1a20b1SVineet Gupta	lr	r10, [status32]
3186d1a20b1SVineet Gupta
3196d1a20b1SVineet Gupta	; Restore REG File. In case multiple Events outstanding,
32094055304SLiav Rehana	; use the same priority as rtie: EXCPN, L2 IRQ, L1 IRQ, None
3216d1a20b1SVineet Gupta	; Note that we use realtime STATUS32 (not pt_regs->status32) to
3226d1a20b1SVineet Gupta	; decide that.
3236d1a20b1SVineet Gupta
3249fabcc63SVineet Gupta	and.f	0, r10, (STATUS_A1_MASK|STATUS_A2_MASK)
3259fabcc63SVineet Gupta	bz	.Lexcep_or_pure_K_ret
3266d1a20b1SVineet Gupta
3279fabcc63SVineet Gupta	; Returning from Interrupts (Level 1 or 2)
3286d1a20b1SVineet Gupta
3296d1a20b1SVineet Gupta#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
3306d1a20b1SVineet Gupta
3316d1a20b1SVineet Gupta	; Level 2 interrupt return Path - from hardware standpoint
3326d1a20b1SVineet Gupta	bbit0  r10, STATUS_A2_BIT, not_level2_interrupt
3336d1a20b1SVineet Gupta
3346d1a20b1SVineet Gupta	;------------------------------------------------------------------
3356d1a20b1SVineet Gupta	; However the context returning might not have taken L2 intr itself
3366d1a20b1SVineet Gupta	; e.g. Task'A' user-code -> L2 intr -> schedule -> 'B' user-code ret
3376d1a20b1SVineet Gupta	; Special considerations needed for the context which took L2 intr
3386d1a20b1SVineet Gupta
3396d1a20b1SVineet Gupta	ld   r9, [sp, PT_event]        ; Ensure this is L2 intr context
3406d1a20b1SVineet Gupta	brne r9, event_IRQ2, 149f
3416d1a20b1SVineet Gupta
3426d1a20b1SVineet Gupta	;------------------------------------------------------------------
3436d1a20b1SVineet Gupta	; if L2 IRQ interrupted an L1 ISR,  we'd disabled preemption earlier
3446d1a20b1SVineet Gupta	; so that sched doesn't move to new task, causing L1 to be delayed
3456d1a20b1SVineet Gupta	; undeterministically. Now that we've achieved that, let's reset
3466d1a20b1SVineet Gupta	; things to what they were, before returning from L2 context
3476d1a20b1SVineet Gupta	;----------------------------------------------------------------
3486d1a20b1SVineet Gupta
3496d1a20b1SVineet Gupta	ld r9, [sp, PT_status32]       ; get statu32_l2 (saved in pt_regs)
3506d1a20b1SVineet Gupta	bbit0 r9, STATUS_A1_BIT, 149f  ; L1 not active when L2 IRQ, so normal
3516d1a20b1SVineet Gupta
3526d1a20b1SVineet Gupta	; decrement thread_info->preempt_count (re-enable preemption)
3536d1a20b1SVineet Gupta	GET_CURR_THR_INFO_FROM_SP   r10
3546d1a20b1SVineet Gupta	ld      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
3556d1a20b1SVineet Gupta
3566d1a20b1SVineet Gupta	; paranoid check, given A1 was active when A2 happened, preempt count
3576d1a20b1SVineet Gupta	; must not be 0 because we would have incremented it.
3586d1a20b1SVineet Gupta	; If this does happen we simply HALT as it means a BUG !!!
3596d1a20b1SVineet Gupta	cmp     r9, 0
3606d1a20b1SVineet Gupta	bnz     2f
3616d1a20b1SVineet Gupta	flag 1
3626d1a20b1SVineet Gupta
3636d1a20b1SVineet Gupta2:
3646d1a20b1SVineet Gupta	sub     r9, r9, 1
3656d1a20b1SVineet Gupta	st      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
3666d1a20b1SVineet Gupta
3676d1a20b1SVineet Gupta149:
3689fabcc63SVineet Gupta	INTERRUPT_EPILOGUE 2	; return from level 2 interrupt
3696d1a20b1SVineet Guptadebug_marker_l2:
3706d1a20b1SVineet Gupta	rtie
3716d1a20b1SVineet Gupta
3726d1a20b1SVineet Guptanot_level2_interrupt:
3736d1a20b1SVineet Gupta
3746d1a20b1SVineet Gupta#endif
3756d1a20b1SVineet Gupta
3769fabcc63SVineet Gupta	INTERRUPT_EPILOGUE 1	; return from level 1 interrupt
3776d1a20b1SVineet Guptadebug_marker_l1:
3786d1a20b1SVineet Gupta	rtie
3796d1a20b1SVineet Gupta
3809fabcc63SVineet Gupta.Lexcep_or_pure_K_ret:
3816d1a20b1SVineet Gupta
382c80417b6SVineet Gupta	;this case is for syscalls or Exceptions or pure kernel mode
3836d1a20b1SVineet Gupta
3846d1a20b1SVineet Gupta	EXCEPTION_EPILOGUE
3856d1a20b1SVineet Guptadebug_marker_syscall:
3866d1a20b1SVineet Gupta	rtie
387c7e6d792SVineet Gupta
388c7e6d792SVineet GuptaEND(ret_from_exception)
389