2015-04-11 01:44:37 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2014 Wind River Systems, Inc.
|
|
|
|
*
|
2017-01-19 02:01:01 +01:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
2015-04-11 01:44:37 +02:00
|
|
|
*/
|
|
|
|
|
2015-12-04 16:09:39 +01:00
|
|
|
/**
|
|
|
|
* @file
|
|
|
|
* @brief Handling of transitions to-and-from fast IRQs (FIRQ)
|
|
|
|
*
|
|
|
|
* This module implements the code for handling entry to and exit from Fast IRQs.
|
|
|
|
*
|
|
|
|
* See isr_wrapper.S for details.
|
2015-07-01 23:22:39 +02:00
|
|
|
*/
|
2015-04-11 01:44:37 +02:00
|
|
|
|
2016-11-08 16:36:50 +01:00
|
|
|
#include <kernel_structs.h>
|
|
|
|
#include <offsets_short.h>
|
2015-04-11 01:44:37 +02:00
|
|
|
#include <toolchain.h>
|
2019-10-24 17:08:21 +02:00
|
|
|
#include <linker/sections.h>
|
2015-05-28 19:56:47 +02:00
|
|
|
#include <arch/cpu.h>
|
2016-11-01 14:07:34 +01:00
|
|
|
#include <swap_macros.h>
|
2015-04-11 01:44:37 +02:00
|
|
|
|
|
|
|
GTEXT(_firq_enter)
|
|
|
|
GTEXT(_firq_exit)
|
arc: Support FIRQ handling when CONFIG_RGF_NUM_BANKS==1
For the EM Starterkit, one SOC I will soon be adding is EM7D.
This SOC has FIRQ, but only has one register bank.
Thus the interrupt handling for FIRQ needs to be different
when CONFIG_RGF_NUM_BANKS==1. The handler must instead push
registers onto the stack in the same stack frame layout that RIRQ uses.
This allows for context switch to be easily done since its compatible.
The common interrupt entry point _isr_enter must save r0 before using
it, because in the FIRQ 1-bank case, it would be destroyed otherwise.
So a global variable named saved_r0 has been added for this reason.
The stack cannot be used to save r0, because it first has to determine
whether its FIRQ or RIRQ here. This change has been tested on the
EM Starterkit with EM7D SOC changes -- coming soon. To make the review
easier, these 3 files are submitted first.
Also, exceptions will no longer use the _firq_stack.
This stack is not needed in the 1-bank case, but an exception stack
is needed. I've added a new stack called _exception_stack,
and made it be 512B, which should be enough for one exception.
See ZEP-966
Change-Id: I6f228b840da7c4db440dd1cfef4ae25336c87f0d
Signed-off-by: Chuck Jordan <cjordan@synopsys.com>
2016-10-15 18:50:27 +02:00
|
|
|
|
2015-07-01 23:22:39 +02:00
|
|
|
/**
|
|
|
|
*
|
2015-07-01 23:51:40 +02:00
|
|
|
* @brief Work to be done before handing control to a FIRQ ISR
|
2015-07-01 23:22:39 +02:00
|
|
|
*
|
|
|
|
* The processor switches to a second register bank so registers from the
|
|
|
|
* current bank do not have to be preserved yet. The only issue is the LP_START/
|
arc: improved saving of lp_<count,start,end> using GPRs
Since firq utilizes a 2nd register bank, and since all of those
many GPRs can be used, the strategy here is to save extra registers,
such as lp_count, lp_start, lp_end into callee saved registers.
These registers are safe to use because the C-ABI followed by the
compiler will cause these to be spilled to the stack if a C function
wants to use them. By selecting upper GPRs, r23-r25, it is very unlikely
the compiler will spill them. This improvement, therefore, can avoid a
d-cache miss since we are avoding memory altogether when saving these.
The struct firq_regs is no longer needed.
Change-Id: I7c0d061908a90376da7a0101b62e804647a20443
Signed-off-by: Chuck Jordan <cjordan@synopsys.com>
2016-05-27 21:25:00 +02:00
|
|
|
* LP_COUNT/LP_END registers, which are not banked. These can be saved
|
|
|
|
* in available callee saved registers.
|
2015-07-01 23:22:39 +02:00
|
|
|
*
|
|
|
|
* If all FIRQ ISRs are programmed such that there are no use of the LP
|
2016-03-11 18:29:14 +01:00
|
|
|
* registers (ie. no LPcc instruction), and CONFIG_ARC_STACK_CHECKING is
|
arc: improved saving of lp_<count,start,end> using GPRs
Since firq utilizes a 2nd register bank, and since all of those
many GPRs can be used, the strategy here is to save extra registers,
such as lp_count, lp_start, lp_end into callee saved registers.
These registers are safe to use because the C-ABI followed by the
compiler will cause these to be spilled to the stack if a C function
wants to use them. By selecting upper GPRs, r23-r25, it is very unlikely
the compiler will spill them. This improvement, therefore, can avoid a
d-cache miss since we are avoding memory altogether when saving these.
The struct firq_regs is no longer needed.
Change-Id: I7c0d061908a90376da7a0101b62e804647a20443
Signed-off-by: Chuck Jordan <cjordan@synopsys.com>
2016-05-27 21:25:00 +02:00
|
|
|
* not set, then the kernel can be configured to not save and restore them.
|
2015-07-01 23:22:39 +02:00
|
|
|
*
|
|
|
|
* When entering a FIRQ, interrupts might as well be locked: the processor is
|
arc: improved saving of lp_<count,start,end> using GPRs
Since firq utilizes a 2nd register bank, and since all of those
many GPRs can be used, the strategy here is to save extra registers,
such as lp_count, lp_start, lp_end into callee saved registers.
These registers are safe to use because the C-ABI followed by the
compiler will cause these to be spilled to the stack if a C function
wants to use them. By selecting upper GPRs, r23-r25, it is very unlikely
the compiler will spill them. This improvement, therefore, can avoid a
d-cache miss since we are avoding memory altogether when saving these.
The struct firq_regs is no longer needed.
Change-Id: I7c0d061908a90376da7a0101b62e804647a20443
Signed-off-by: Chuck Jordan <cjordan@synopsys.com>
2016-05-27 21:25:00 +02:00
|
|
|
* running at its highest priority, and cannot be interrupted by any other
|
|
|
|
* interrupt. An exception, however, can be taken.
|
2015-07-01 23:22:39 +02:00
|
|
|
*
|
|
|
|
* Assumption by _isr_demux: r3 is untouched by _firq_enter.
|
|
|
|
*
|
2015-07-01 23:29:04 +02:00
|
|
|
* @return N/A
|
2015-07-01 23:22:39 +02:00
|
|
|
*/
|
2015-04-11 01:44:37 +02:00
|
|
|
|
|
|
|
SECTION_FUNC(TEXT, _firq_enter)
|
arc: Support FIRQ handling when CONFIG_RGF_NUM_BANKS==1
For the EM Starterkit, one SOC I will soon be adding is EM7D.
This SOC has FIRQ, but only has one register bank.
Thus the interrupt handling for FIRQ needs to be different
when CONFIG_RGF_NUM_BANKS==1. The handler must instead push
registers onto the stack in the same stack frame layout that RIRQ uses.
This allows for context switch to be easily done since its compatible.
The common interrupt entry point _isr_enter must save r0 before using
it, because in the FIRQ 1-bank case, it would be destroyed otherwise.
So a global variable named saved_r0 has been added for this reason.
The stack cannot be used to save r0, because it first has to determine
whether its FIRQ or RIRQ here. This change has been tested on the
EM Starterkit with EM7D SOC changes -- coming soon. To make the review
easier, these 3 files are submitted first.
Also, exceptions will no longer use the _firq_stack.
This stack is not needed in the 1-bank case, but an exception stack
is needed. I've added a new stack called _exception_stack,
and made it be 512B, which should be enough for one exception.
See ZEP-966
Change-Id: I6f228b840da7c4db440dd1cfef4ae25336c87f0d
Signed-off-by: Chuck Jordan <cjordan@synopsys.com>
2016-10-15 18:50:27 +02:00
|
|
|
/*
|
|
|
|
* ATTENTION:
|
|
|
|
* If CONFIG_RGF_NUM_BANKS>1, firq uses a 2nd register bank so GPRs do
|
|
|
|
* not need to be saved.
|
|
|
|
* If CONFIG_RGF_NUM_BANKS==1, firq must use the stack to save registers.
|
2017-02-13 18:36:32 +01:00
|
|
|
* This has already been done by _isr_wrapper.
|
arc: Support FIRQ handling when CONFIG_RGF_NUM_BANKS==1
For the EM Starterkit, one SOC I will soon be adding is EM7D.
This SOC has FIRQ, but only has one register bank.
Thus the interrupt handling for FIRQ needs to be different
when CONFIG_RGF_NUM_BANKS==1. The handler must instead push
registers onto the stack in the same stack frame layout that RIRQ uses.
This allows for context switch to be easily done since its compatible.
The common interrupt entry point _isr_enter must save r0 before using
it, because in the FIRQ 1-bank case, it would be destroyed otherwise.
So a global variable named saved_r0 has been added for this reason.
The stack cannot be used to save r0, because it first has to determine
whether its FIRQ or RIRQ here. This change has been tested on the
EM Starterkit with EM7D SOC changes -- coming soon. To make the review
easier, these 3 files are submitted first.
Also, exceptions will no longer use the _firq_stack.
This stack is not needed in the 1-bank case, but an exception stack
is needed. I've added a new stack called _exception_stack,
and made it be 512B, which should be enough for one exception.
See ZEP-966
Change-Id: I6f228b840da7c4db440dd1cfef4ae25336c87f0d
Signed-off-by: Chuck Jordan <cjordan@synopsys.com>
2016-10-15 18:50:27 +02:00
|
|
|
*/
|
2016-03-11 18:29:14 +01:00
|
|
|
#ifdef CONFIG_ARC_STACK_CHECKING
|
2019-08-01 06:39:35 +02:00
|
|
|
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
2018-07-19 10:59:21 +02:00
|
|
|
lr r2, [_ARC_V2_SEC_STAT]
|
|
|
|
bclr r2, r2, _ARC_V2_SEC_STAT_SSC_BIT
|
2019-08-01 06:39:35 +02:00
|
|
|
sflag r2
|
2018-07-19 10:59:21 +02:00
|
|
|
#else
|
2016-03-11 18:29:14 +01:00
|
|
|
/* disable stack checking */
|
|
|
|
lr r2, [_ARC_V2_STATUS32]
|
|
|
|
bclr r2, r2, _ARC_V2_STATUS32_SC_BIT
|
|
|
|
kflag r2
|
|
|
|
#endif
|
2018-07-19 10:59:21 +02:00
|
|
|
#endif
|
2016-03-11 18:29:14 +01:00
|
|
|
|
arc: Support FIRQ handling when CONFIG_RGF_NUM_BANKS==1
For the EM Starterkit, one SOC I will soon be adding is EM7D.
This SOC has FIRQ, but only has one register bank.
Thus the interrupt handling for FIRQ needs to be different
when CONFIG_RGF_NUM_BANKS==1. The handler must instead push
registers onto the stack in the same stack frame layout that RIRQ uses.
This allows for context switch to be easily done since its compatible.
The common interrupt entry point _isr_enter must save r0 before using
it, because in the FIRQ 1-bank case, it would be destroyed otherwise.
So a global variable named saved_r0 has been added for this reason.
The stack cannot be used to save r0, because it first has to determine
whether its FIRQ or RIRQ here. This change has been tested on the
EM Starterkit with EM7D SOC changes -- coming soon. To make the review
easier, these 3 files are submitted first.
Also, exceptions will no longer use the _firq_stack.
This stack is not needed in the 1-bank case, but an exception stack
is needed. I've added a new stack called _exception_stack,
and made it be 512B, which should be enough for one exception.
See ZEP-966
Change-Id: I6f228b840da7c4db440dd1cfef4ae25336c87f0d
Signed-off-by: Chuck Jordan <cjordan@synopsys.com>
2016-10-15 18:50:27 +02:00
|
|
|
#if CONFIG_RGF_NUM_BANKS != 1
|
2015-04-11 01:44:37 +02:00
|
|
|
/*
|
arc: improved saving of lp_<count,start,end> using GPRs
Since firq utilizes a 2nd register bank, and since all of those
many GPRs can be used, the strategy here is to save extra registers,
such as lp_count, lp_start, lp_end into callee saved registers.
These registers are safe to use because the C-ABI followed by the
compiler will cause these to be spilled to the stack if a C function
wants to use them. By selecting upper GPRs, r23-r25, it is very unlikely
the compiler will spill them. This improvement, therefore, can avoid a
d-cache miss since we are avoding memory altogether when saving these.
The struct firq_regs is no longer needed.
Change-Id: I7c0d061908a90376da7a0101b62e804647a20443
Signed-off-by: Chuck Jordan <cjordan@synopsys.com>
2016-05-27 21:25:00 +02:00
|
|
|
* Save LP_START/LP_COUNT/LP_END because called handler might use.
|
|
|
|
* Save these in callee saved registers to avoid using memory.
|
|
|
|
* These will be saved by the compiler if it needs to spill them.
|
2015-04-11 01:44:37 +02:00
|
|
|
*/
|
arc: improved saving of lp_<count,start,end> using GPRs
Since firq utilizes a 2nd register bank, and since all of those
many GPRs can be used, the strategy here is to save extra registers,
such as lp_count, lp_start, lp_end into callee saved registers.
These registers are safe to use because the C-ABI followed by the
compiler will cause these to be spilled to the stack if a C function
wants to use them. By selecting upper GPRs, r23-r25, it is very unlikely
the compiler will spill them. This improvement, therefore, can avoid a
d-cache miss since we are avoding memory altogether when saving these.
The struct firq_regs is no longer needed.
Change-Id: I7c0d061908a90376da7a0101b62e804647a20443
Signed-off-by: Chuck Jordan <cjordan@synopsys.com>
2016-05-27 21:25:00 +02:00
|
|
|
mov r23,lp_count
|
|
|
|
lr r24, [_ARC_V2_LP_START]
|
|
|
|
lr r25, [_ARC_V2_LP_END]
|
2015-04-11 01:44:37 +02:00
|
|
|
#endif
|
|
|
|
|
2019-08-13 18:45:13 +02:00
|
|
|
/* check whether irq stack is used */
|
|
|
|
_check_and_inc_int_nest_counter r0, r1
|
2017-07-11 04:39:54 +02:00
|
|
|
|
2019-07-03 17:43:31 +02:00
|
|
|
bne.d firq_nest
|
2019-08-29 12:52:04 +02:00
|
|
|
mov_s r0, sp
|
2017-07-11 04:39:54 +02:00
|
|
|
|
2019-07-25 06:13:13 +02:00
|
|
|
_get_curr_cpu_irq_stack sp
|
2017-07-11 04:39:54 +02:00
|
|
|
#if CONFIG_RGF_NUM_BANKS != 1
|
|
|
|
b firq_nest_1
|
|
|
|
firq_nest:
|
2019-07-03 13:46:13 +02:00
|
|
|
/*
|
|
|
|
* because firq and rirq share the same interrupt stack,
|
|
|
|
* switch back to original register bank to get correct sp.
|
|
|
|
* to get better firq latency, an approach is to prepare
|
|
|
|
* separate interrupt stack for firq and do not do thread
|
|
|
|
* switch in firq.
|
|
|
|
*/
|
|
|
|
lr r1, [_ARC_V2_STATUS32]
|
|
|
|
and r1, r1, ~_ARC_V2_STATUS32_RB(7)
|
|
|
|
kflag r1
|
2017-07-11 04:39:54 +02:00
|
|
|
|
2019-07-03 13:46:13 +02:00
|
|
|
/* here use _ARC_V2_USER_SP and ilink to exchange sp
|
|
|
|
* save original value of _ARC_V2_USER_SP and ilink into
|
|
|
|
* the stack of interrupted context first, then restore them later
|
|
|
|
*/
|
2019-09-25 10:21:45 +02:00
|
|
|
push ilink
|
|
|
|
PUSHAX ilink, _ARC_V2_USER_SP
|
|
|
|
|
2019-07-03 13:46:13 +02:00
|
|
|
/* sp here is the sp of interrupted context */
|
|
|
|
sr sp, [_ARC_V2_USER_SP]
|
2019-09-25 10:21:45 +02:00
|
|
|
/* here, bank 0 sp must go back to the value before push and
|
|
|
|
* PUSHAX as we will switch to bank1, the pop and POPAX later will
|
|
|
|
* change bank1's sp, not bank0's sp
|
|
|
|
*/
|
|
|
|
add sp, sp, 8
|
2017-07-11 04:39:54 +02:00
|
|
|
|
2019-07-03 13:46:13 +02:00
|
|
|
/* switch back to banked reg, only ilink can be used */
|
2017-07-11 04:39:54 +02:00
|
|
|
lr ilink, [_ARC_V2_STATUS32]
|
|
|
|
or ilink, ilink, _ARC_V2_STATUS32_RB(1)
|
|
|
|
kflag ilink
|
2019-07-03 13:46:13 +02:00
|
|
|
lr sp, [_ARC_V2_USER_SP]
|
2019-09-25 10:21:45 +02:00
|
|
|
|
|
|
|
POPAX ilink, _ARC_V2_USER_SP
|
|
|
|
pop ilink
|
2017-07-11 04:39:54 +02:00
|
|
|
firq_nest_1:
|
|
|
|
#else
|
|
|
|
firq_nest:
|
|
|
|
#endif
|
|
|
|
push_s r0
|
2015-04-11 01:44:37 +02:00
|
|
|
j @_isr_demux
|
|
|
|
|
2017-07-11 04:39:54 +02:00
|
|
|
|
|
|
|
|
2015-07-01 23:22:39 +02:00
|
|
|
/**
|
|
|
|
*
|
2015-07-01 23:51:40 +02:00
|
|
|
* @brief Work to be done exiting a FIRQ
|
2015-07-01 23:22:39 +02:00
|
|
|
*
|
2015-07-01 23:29:04 +02:00
|
|
|
* @return N/A
|
2015-07-01 23:22:39 +02:00
|
|
|
*/
|
2015-04-11 01:44:37 +02:00
|
|
|
|
|
|
|
SECTION_FUNC(TEXT, _firq_exit)
|
|
|
|
|
arc: Support FIRQ handling when CONFIG_RGF_NUM_BANKS==1
For the EM Starterkit, one SOC I will soon be adding is EM7D.
This SOC has FIRQ, but only has one register bank.
Thus the interrupt handling for FIRQ needs to be different
when CONFIG_RGF_NUM_BANKS==1. The handler must instead push
registers onto the stack in the same stack frame layout that RIRQ uses.
This allows for context switch to be easily done since its compatible.
The common interrupt entry point _isr_enter must save r0 before using
it, because in the FIRQ 1-bank case, it would be destroyed otherwise.
So a global variable named saved_r0 has been added for this reason.
The stack cannot be used to save r0, because it first has to determine
whether its FIRQ or RIRQ here. This change has been tested on the
EM Starterkit with EM7D SOC changes -- coming soon. To make the review
easier, these 3 files are submitted first.
Also, exceptions will no longer use the _firq_stack.
This stack is not needed in the 1-bank case, but an exception stack
is needed. I've added a new stack called _exception_stack,
and made it be 512B, which should be enough for one exception.
See ZEP-966
Change-Id: I6f228b840da7c4db440dd1cfef4ae25336c87f0d
Signed-off-by: Chuck Jordan <cjordan@synopsys.com>
2016-10-15 18:50:27 +02:00
|
|
|
#if CONFIG_RGF_NUM_BANKS != 1
|
arc: improved saving of lp_<count,start,end> using GPRs
Since firq utilizes a 2nd register bank, and since all of those
many GPRs can be used, the strategy here is to save extra registers,
such as lp_count, lp_start, lp_end into callee saved registers.
These registers are safe to use because the C-ABI followed by the
compiler will cause these to be spilled to the stack if a C function
wants to use them. By selecting upper GPRs, r23-r25, it is very unlikely
the compiler will spill them. This improvement, therefore, can avoid a
d-cache miss since we are avoding memory altogether when saving these.
The struct firq_regs is no longer needed.
Change-Id: I7c0d061908a90376da7a0101b62e804647a20443
Signed-off-by: Chuck Jordan <cjordan@synopsys.com>
2016-05-27 21:25:00 +02:00
|
|
|
/* restore lp_count, lp_start, lp_end from r23-r25 */
|
|
|
|
mov lp_count,r23
|
|
|
|
sr r24, [_ARC_V2_LP_START]
|
|
|
|
sr r25, [_ARC_V2_LP_END]
|
2015-04-11 01:44:37 +02:00
|
|
|
#endif
|
2019-08-13 18:45:13 +02:00
|
|
|
_dec_int_nest_counter r0, r1
|
2019-07-03 17:43:31 +02:00
|
|
|
|
|
|
|
_check_nest_int_by_irq_act r0, r1
|
|
|
|
|
2020-02-03 14:07:19 +01:00
|
|
|
jne _firq_no_switch
|
2015-04-11 01:44:37 +02:00
|
|
|
|
2020-02-03 14:07:19 +01:00
|
|
|
/* sp is struct k_thread **old of z_arc_switch_in_isr
|
|
|
|
* which is a wrapper of z_get_next_switch_handle.
|
|
|
|
* r0 contains the 1st thread in ready queue. if
|
|
|
|
* it equals _current(r2) ,then do swap, or no swap.
|
|
|
|
*/
|
|
|
|
_get_next_switch_handle
|
2018-04-16 12:14:03 +02:00
|
|
|
|
2020-02-03 14:07:19 +01:00
|
|
|
cmp r0, r2
|
|
|
|
bne _firq_switch
|
2015-04-11 01:44:37 +02:00
|
|
|
|
2020-02-03 14:07:19 +01:00
|
|
|
/* fall to no switch */
|
2018-04-16 12:14:03 +02:00
|
|
|
|
2020-02-03 14:07:19 +01:00
|
|
|
.balign 4
|
|
|
|
_firq_no_switch:
|
2020-07-06 10:37:07 +02:00
|
|
|
/* restore interrupted context' sp */
|
|
|
|
pop sp
|
2016-10-27 17:49:48 +02:00
|
|
|
/*
|
|
|
|
* Keeping this code block close to those that use it allows using brxx
|
|
|
|
* instruction instead of a pair of cmp and bxx
|
|
|
|
*/
|
|
|
|
#if CONFIG_RGF_NUM_BANKS == 1
|
2019-03-15 07:24:43 +01:00
|
|
|
_pop_irq_stack_frame
|
2016-10-27 17:49:48 +02:00
|
|
|
#endif
|
|
|
|
rtie
|
|
|
|
|
2015-04-11 01:44:37 +02:00
|
|
|
.balign 4
|
2020-02-03 14:07:19 +01:00
|
|
|
_firq_switch:
|
2020-07-06 10:37:07 +02:00
|
|
|
/* restore interrupted context' sp */
|
|
|
|
pop sp
|
2015-04-11 01:44:37 +02:00
|
|
|
|
arc: Support FIRQ handling when CONFIG_RGF_NUM_BANKS==1
For the EM Starterkit, one SOC I will soon be adding is EM7D.
This SOC has FIRQ, but only has one register bank.
Thus the interrupt handling for FIRQ needs to be different
when CONFIG_RGF_NUM_BANKS==1. The handler must instead push
registers onto the stack in the same stack frame layout that RIRQ uses.
This allows for context switch to be easily done since its compatible.
The common interrupt entry point _isr_enter must save r0 before using
it, because in the FIRQ 1-bank case, it would be destroyed otherwise.
So a global variable named saved_r0 has been added for this reason.
The stack cannot be used to save r0, because it first has to determine
whether its FIRQ or RIRQ here. This change has been tested on the
EM Starterkit with EM7D SOC changes -- coming soon. To make the review
easier, these 3 files are submitted first.
Also, exceptions will no longer use the _firq_stack.
This stack is not needed in the 1-bank case, but an exception stack
is needed. I've added a new stack called _exception_stack,
and made it be 512B, which should be enough for one exception.
See ZEP-966
Change-Id: I6f228b840da7c4db440dd1cfef4ae25336c87f0d
Signed-off-by: Chuck Jordan <cjordan@synopsys.com>
2016-10-15 18:50:27 +02:00
|
|
|
#if CONFIG_RGF_NUM_BANKS != 1
|
2019-07-25 06:13:13 +02:00
|
|
|
/*
|
2020-02-03 14:07:19 +01:00
|
|
|
* save r0, r2 in irq stack for a while, as they will be changed by register
|
2019-07-25 06:13:13 +02:00
|
|
|
* bank switch
|
|
|
|
*/
|
2020-02-03 14:07:19 +01:00
|
|
|
_get_curr_cpu_irq_stack r1
|
|
|
|
st r0, [r1, -4]
|
|
|
|
st r2, [r1, -8]
|
|
|
|
|
2015-04-11 01:44:37 +02:00
|
|
|
/*
|
|
|
|
* We know there is no interrupted interrupt of lower priority at this
|
|
|
|
* point, so when switching back to register bank 0, it will contain the
|
|
|
|
* registers from the interrupted thread.
|
|
|
|
*/
|
2020-02-01 12:44:00 +01:00
|
|
|
#if defined(CONFIG_USERSPACE)
|
|
|
|
/* when USERSPACE is configured, here need to consider the case where firq comes
|
|
|
|
* out in user mode, according to ARCv2 ISA and nsim, the following micro ops
|
|
|
|
* will be executed:
|
|
|
|
* sp<-reg bank1'sp
|
|
|
|
* switch between sp and _ARC_V2_USER_SP
|
|
|
|
* then:
|
|
|
|
* sp is the sp of kernel stack of interrupted thread
|
|
|
|
* _ARC_V2_USER_SP is reg bank1'sp
|
|
|
|
* the sp of user stack of interrupted thread is reg bank0'sp
|
|
|
|
* if firq comes out in kernel mode, the following micro ops will be executed:
|
|
|
|
* sp<-reg bank'sp
|
|
|
|
* so, sw needs to do necessary handling to set up the correct sp
|
|
|
|
*/
|
|
|
|
lr r0, [_ARC_V2_AUX_IRQ_ACT]
|
|
|
|
bbit0 r0, 31, _firq_from_kernel
|
|
|
|
aex sp, [_ARC_V2_USER_SP]
|
|
|
|
lr r0, [_ARC_V2_STATUS32]
|
|
|
|
and r0, r0, ~_ARC_V2_STATUS32_RB(7)
|
|
|
|
kflag r0
|
|
|
|
aex sp, [_ARC_V2_USER_SP]
|
|
|
|
b _firq_create_irq_stack_frame
|
|
|
|
_firq_from_kernel:
|
|
|
|
#endif
|
2015-04-11 01:44:37 +02:00
|
|
|
/* chose register bank #0 */
|
|
|
|
lr r0, [_ARC_V2_STATUS32]
|
|
|
|
and r0, r0, ~_ARC_V2_STATUS32_RB(7)
|
|
|
|
kflag r0
|
|
|
|
|
2020-02-01 12:44:00 +01:00
|
|
|
_firq_create_irq_stack_frame:
|
2015-04-11 01:44:37 +02:00
|
|
|
/* we're back on the outgoing thread's stack */
|
|
|
|
_create_irq_stack_frame
|
|
|
|
|
|
|
|
/*
|
|
|
|
* In a FIRQ, STATUS32 of the outgoing thread is in STATUS32_P0 and the
|
|
|
|
* PC in ILINK: save them in status32/pc respectively.
|
|
|
|
*/
|
|
|
|
|
|
|
|
lr r0, [_ARC_V2_STATUS32_P0]
|
2016-11-08 16:36:50 +01:00
|
|
|
st_s r0, [sp, ___isf_t_status32_OFFSET]
|
2015-04-11 01:44:37 +02:00
|
|
|
|
2016-11-08 16:36:50 +01:00
|
|
|
st ilink, [sp, ___isf_t_pc_OFFSET] /* ilink into pc */
|
2020-02-01 12:44:00 +01:00
|
|
|
/*
|
2020-02-03 14:07:19 +01:00
|
|
|
* load r0, r2 from irq stack
|
2020-02-01 12:44:00 +01:00
|
|
|
*/
|
2020-02-03 14:07:19 +01:00
|
|
|
_get_curr_cpu_irq_stack r1
|
|
|
|
ld r0, [r1, -4]
|
|
|
|
ld r2, [r1, -8]
|
2019-07-25 06:13:13 +02:00
|
|
|
#endif
|
2020-02-03 14:07:19 +01:00
|
|
|
/* r2 is old thread */
|
|
|
|
_irq_store_old_thread_callee_regs
|
2015-04-11 01:44:37 +02:00
|
|
|
|
2016-11-08 16:36:50 +01:00
|
|
|
st _CAUSE_FIRQ, [r2, _thread_offset_to_relinquish_cause]
|
2015-04-11 01:44:37 +02:00
|
|
|
|
2020-02-03 14:07:19 +01:00
|
|
|
/* mov new thread (r0) to r2 */
|
2015-04-11 01:44:37 +02:00
|
|
|
|
2020-02-03 14:07:19 +01:00
|
|
|
mov r2, r0
|
|
|
|
_load_new_thread_callee_regs
|
2015-04-11 01:44:37 +02:00
|
|
|
|
2020-02-03 14:07:19 +01:00
|
|
|
breq r3, _CAUSE_RIRQ, _firq_switch_from_rirq
|
2019-08-29 12:52:04 +02:00
|
|
|
nop_s
|
2020-02-03 14:07:19 +01:00
|
|
|
breq r3, _CAUSE_FIRQ, _firq_switch_from_firq
|
2019-08-29 12:52:04 +02:00
|
|
|
nop_s
|
2015-04-11 01:44:37 +02:00
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
|
|
|
.balign 4
|
2020-02-03 14:07:19 +01:00
|
|
|
_firq_switch_from_coop:
|
|
|
|
|
|
|
|
_set_misc_regs_irq_switch_from_coop
|
|
|
|
|
2015-04-11 01:44:37 +02:00
|
|
|
/* pc into ilink */
|
|
|
|
pop_s r0
|
2019-08-29 12:52:04 +02:00
|
|
|
mov_s ilink, r0
|
2015-04-11 01:44:37 +02:00
|
|
|
|
|
|
|
pop_s r0 /* status32 into r0 */
|
|
|
|
sr r0, [_ARC_V2_STATUS32_P0]
|
|
|
|
|
|
|
|
rtie
|
|
|
|
|
|
|
|
.balign 4
|
2020-02-03 14:07:19 +01:00
|
|
|
_firq_switch_from_rirq:
|
|
|
|
_firq_switch_from_firq:
|
2015-04-11 01:44:37 +02:00
|
|
|
|
2020-02-03 14:07:19 +01:00
|
|
|
_set_misc_regs_irq_switch_from_irq
|
2020-02-01 12:44:00 +01:00
|
|
|
|
2015-04-11 01:44:37 +02:00
|
|
|
_pop_irq_stack_frame
|
|
|
|
|
|
|
|
ld ilink, [sp, -4] /* status32 into ilink */
|
|
|
|
sr ilink, [_ARC_V2_STATUS32_P0]
|
|
|
|
ld ilink, [sp, -8] /* pc into ilink */
|
|
|
|
|
|
|
|
/* LP registers are already restored, just switch back to bank 0 */
|
|
|
|
rtie
|