arch : arc: clean up of assembly codes
* update comments to match latest codes * add extra comments for some assembly, macros * use macro to replace duplcated codes * remove unused codes, lables, symobols Signed-off-by: Wayne Ren <wei.ren@synopsys.com>
This commit is contained in:
parent
3f88ddd549
commit
84cdfa271d
6 changed files with 196 additions and 213 deletions
|
@ -19,7 +19,6 @@
|
|||
#include <syscall.h>
|
||||
|
||||
GTEXT(_Fault)
|
||||
GTEXT(z_do_kernel_oops)
|
||||
GTEXT(__reset)
|
||||
GTEXT(__memory_error)
|
||||
GTEXT(__instruction_error)
|
||||
|
@ -38,6 +37,17 @@ GTEXT(__ev_maligned)
|
|||
GTEXT(z_irq_do_offload);
|
||||
#endif
|
||||
|
||||
.macro _save_exc_regs_into_stack
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
/* ERSEC_STAT is IOW/RAZ in normal mode */
|
||||
lr r0,[_ARC_V2_ERSEC_STAT]
|
||||
st_s r0, [sp, ___isf_t_sec_stat_OFFSET]
|
||||
#endif
|
||||
lr r0,[_ARC_V2_ERET]
|
||||
st_s r0, [sp, ___isf_t_pc_OFFSET]
|
||||
lr r0,[_ARC_V2_ERSTATUS]
|
||||
st_s r0, [sp, ___isf_t_status32_OFFSET]
|
||||
.endm
|
||||
|
||||
/*
|
||||
* The exception handling will use top part of interrupt stack to
|
||||
|
@ -89,15 +99,7 @@ _exc_entry:
|
|||
*/
|
||||
_create_irq_stack_frame
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
/* ERSEC_STAT is IOW/RAZ in normal mode */
|
||||
lr r0,[_ARC_V2_ERSEC_STAT]
|
||||
st_s r0, [sp, ___isf_t_sec_stat_OFFSET]
|
||||
#endif
|
||||
lr r0,[_ARC_V2_ERSTATUS]
|
||||
st_s r0, [sp, ___isf_t_status32_OFFSET]
|
||||
lr r0,[_ARC_V2_ERET]
|
||||
st_s r0, [sp, ___isf_t_pc_OFFSET] /* eret into pc */
|
||||
_save_exc_regs_into_stack
|
||||
|
||||
/* sp is parameter of _Fault */
|
||||
mov_s r0, sp
|
||||
|
@ -174,10 +176,13 @@ _exc_return:
|
|||
mov r2, ilink
|
||||
#endif
|
||||
|
||||
/* Assumption: r2 has next thread */
|
||||
/* Assumption: r2 has next thread */
|
||||
b _rirq_newthread_switch
|
||||
|
||||
_exc_return_from_exc:
|
||||
/* exception handler may change return address.
|
||||
* reload it
|
||||
*/
|
||||
ld_s r0, [sp, ___isf_t_pc_OFFSET]
|
||||
sr r0, [_ARC_V2_ERET]
|
||||
|
||||
|
@ -185,7 +190,7 @@ _exc_return_from_exc:
|
|||
mov_s sp, ilink
|
||||
rtie
|
||||
|
||||
|
||||
/* separated entry for trap which may be used by irq_offload, USERPSACE */
|
||||
SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_trap)
|
||||
/* get the id of trap_s */
|
||||
lr ilink, [_ARC_V2_ECR]
|
||||
|
@ -208,15 +213,12 @@ valid_syscall_id:
|
|||
*/
|
||||
_create_irq_stack_frame
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
/* ERSEC_STAT is IOW/RAZ in normal mode */
|
||||
lr r0, [_ARC_V2_ERSEC_STAT]
|
||||
st_s r0, [sp, ___isf_t_sec_stat_OFFSET]
|
||||
#endif
|
||||
lr r0,[_ARC_V2_ERET]
|
||||
st_s r0, [sp, ___isf_t_pc_OFFSET] /* eret into pc */
|
||||
lr r0,[_ARC_V2_ERSTATUS]
|
||||
st_s r0, [sp, ___isf_t_status32_OFFSET]
|
||||
_save_exc_regs_into_stack
|
||||
|
||||
/* exc return and do sys call in kernel mode,
|
||||
* so need to clear U bit, r0 is already loaded
|
||||
* with ERSTATUS in _save_exc_regs_into_stack
|
||||
*/
|
||||
|
||||
bclr r0, r0, _ARC_V2_STATUS32_U_BIT
|
||||
sr r0, [_ARC_V2_ERSTATUS]
|
||||
|
@ -239,15 +241,7 @@ _do_non_syscall_trap:
|
|||
/* save caller saved registers */
|
||||
_create_irq_stack_frame
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
lr r0,[_ARC_V2_ERSEC_STAT]
|
||||
st_s r0, [sp, ___isf_t_sec_stat_OFFSET]
|
||||
#endif
|
||||
lr r0,[_ARC_V2_ERSTATUS]
|
||||
st_s r0, [sp, ___isf_t_status32_OFFSET]
|
||||
lr r0,[_ARC_V2_ERET]
|
||||
st_s r0, [sp, ___isf_t_pc_OFFSET] /* eret into pc */
|
||||
|
||||
_save_exc_regs_into_stack
|
||||
|
||||
/* check whether irq stack is used */
|
||||
_check_and_inc_int_nest_counter r0, r1
|
||||
|
@ -266,6 +260,8 @@ exc_nest_handle:
|
|||
_dec_int_nest_counter r0, r1
|
||||
|
||||
_pop_irq_stack_frame
|
||||
|
||||
/* ERSTATUS, ERET are not changed, so ok to rtie */
|
||||
rtie
|
||||
#endif /* CONFIG_IRQ_OFFLOAD */
|
||||
b _exc_entry
|
||||
|
|
|
@ -35,37 +35,35 @@ _rirq_enter/_firq_enter: they are jump points.
|
|||
The flow is the following:
|
||||
|
||||
ISR -> _isr_wrapper -- + -> _rirq_enter -> _isr_demux -> ISR -> _rirq_exit
|
||||
|
|
||||
+ -> _firq_enter -> _isr_demux -> ISR -> _firq_exit
|
||||
|
|
||||
+ -> _firq_enter -> _isr_demux -> ISR -> _firq_exit
|
||||
|
||||
Context switch explanation:
|
||||
|
||||
The context switch code is spread in these files:
|
||||
|
||||
isr_wrapper.s, switch.s, swap_macros.s, fast_irq.s, regular_irq.s
|
||||
isr_wrapper.s, switch.s, swap_macros.h, fast_irq.s, regular_irq.s
|
||||
|
||||
IRQ stack frame layout:
|
||||
|
||||
high address
|
||||
high address
|
||||
|
||||
status32
|
||||
pc
|
||||
lp_count
|
||||
lp_start
|
||||
lp_end
|
||||
blink
|
||||
r13
|
||||
...
|
||||
sp -> r0
|
||||
status32
|
||||
pc
|
||||
lp_count
|
||||
lp_start
|
||||
lp_end
|
||||
blink
|
||||
r13
|
||||
...
|
||||
sp -> r0
|
||||
|
||||
low address
|
||||
low address
|
||||
|
||||
The context switch code adopts this standard so that it is easier to follow:
|
||||
|
||||
- r1 contains _kernel ASAP and is not overwritten over the lifespan of
|
||||
the functions.
|
||||
- r2 contains _kernel.current ASAP, and the incoming thread when we
|
||||
transition from outgoing thread to incoming thread
|
||||
- r2 contains _kernel.current ASAP, and the incoming thread when we
|
||||
transition from outgoing thread to incoming thread
|
||||
|
||||
Not loading _kernel into r0 allows loading _kernel without stomping on
|
||||
the parameter in r0 in arch_switch().
|
||||
|
@ -100,47 +98,49 @@ done upfront, and the rest is done when needed:
|
|||
|
||||
o RIRQ
|
||||
|
||||
All needed registers to run C code in the ISR are saved automatically
|
||||
on the outgoing thread's stack: loop, status32, pc, and the caller-
|
||||
saved GPRs. That stack frame layout is pre-determined. If returning
|
||||
to a thread, the stack is popped and no registers have to be saved by
|
||||
the kernel. If a context switch is required, the callee-saved GPRs
|
||||
are then saved in the thread control structure (TCS).
|
||||
All needed registers to run C code in the ISR are saved automatically
|
||||
on the outgoing thread's stack: loop, status32, pc, and the caller-
|
||||
saved GPRs. That stack frame layout is pre-determined. If returning
|
||||
to a thread, the stack is popped and no registers have to be saved by
|
||||
the kernel. If a context switch is required, the callee-saved GPRs
|
||||
are then saved in the thread's stack.
|
||||
|
||||
o FIRQ
|
||||
|
||||
First, a FIRQ can be interrupting a lower-priority RIRQ: if this is the case,
|
||||
the FIRQ does not take a scheduling decision and leaves it the RIRQ to
|
||||
handle. This limits the amount of code that has to run at interrupt-level.
|
||||
First, a FIRQ can be interrupting a lower-priority RIRQ: if this is
|
||||
the case, the FIRQ does not take a scheduling decision and leaves it
|
||||
the RIRQ to handle. This limits the amount of code that has to run at
|
||||
interrupt-level.
|
||||
|
||||
CONFIG_RGF_NUM_BANKS==1 case:
|
||||
Registers are saved on the stack frame just as they are for RIRQ.
|
||||
Context switch can happen just as it does in the RIRQ case, however,
|
||||
if the FIRQ interrupted a RIRQ, the FIRQ will return from interrupt and
|
||||
let the RIRQ do the context switch. At entry, one register is needed in order
|
||||
to have code to save other registers. r0 is saved first in a global called
|
||||
saved_r0.
|
||||
CONFIG_RGF_NUM_BANKS==1 case:
|
||||
Registers are saved on the stack frame just as they are for RIRQ.
|
||||
Context switch can happen just as it does in the RIRQ case, however,
|
||||
if the FIRQ interrupted a RIRQ, the FIRQ will return from interrupt
|
||||
and let the RIRQ do the context switch. At entry, one register is
|
||||
needed in order to have code to save other registers. r0 is saved
|
||||
first in the stack and restored later
|
||||
|
||||
CONFIG_RGF_NUM_BANKS!=1 case:
|
||||
During early initialization, the sp in the 2nd register bank is made to
|
||||
refer to _firq_stack. This allows for the FIRQ handler to use its own stack.
|
||||
GPRs are banked, loop registers are saved in unused callee saved regs upon
|
||||
interrupt entry. If returning to a thread, loop registers are restored and the
|
||||
CPU switches back to bank 0 for the GPRs. If a context switch is
|
||||
needed, at this point only are all the registers saved. First, a
|
||||
stack frame with the same layout as the automatic RIRQ one is created
|
||||
and then the callee-saved GPRs are saved in the TCS. status32_p0 and
|
||||
ilink are saved in this case, not status32 and pc.
|
||||
To create the stack frame, the FIRQ handling code must first go back to using
|
||||
bank0 of registers, since that is where the registers containing the exiting
|
||||
thread are saved. Care must be taken not to touch any register before saving
|
||||
them: the only one usable at that point is the stack pointer.
|
||||
CONFIG_RGF_NUM_BANKS!=1 case:
|
||||
During early initialization, the sp in the 2nd register bank is made to
|
||||
refer to _firq_stack. This allows for the FIRQ handler to use its own
|
||||
stack. GPRs are banked, loop registers are saved in unused callee saved
|
||||
regs upon interrupt entry. If returning to a thread, loop registers are
|
||||
restored and the CPU switches back to bank 0 for the GPRs. If a context
|
||||
switch is needed, at this point only are all the registers saved.
|
||||
First, a stack frame with the same layout as the automatic RIRQ one is
|
||||
created and then the callee-saved GPRs are saved in the stack.
|
||||
status32_p0 and ilink are saved in this case, not status32 and pc.
|
||||
To create the stack frame, the FIRQ handling code must first go back to
|
||||
using bank0 of registers, since that is where the registers containing
|
||||
the exiting thread are saved. Care must be taken not to touch any
|
||||
register before saving them: the only one usable at that point is the
|
||||
stack pointer.
|
||||
|
||||
o coop
|
||||
|
||||
When a coop context switch is done, the callee-saved registers are
|
||||
saved in the TCS. The other GPRs do not need to be saved, since the
|
||||
compiler has already placed them on the stack.
|
||||
When a coop context switch is done, the callee-saved registers are
|
||||
saved in the stack. The other GPRs do not need to be saved, since the
|
||||
compiler has already placed them on the stack.
|
||||
|
||||
For restoring the contexts, there are six cases. In all cases, the
|
||||
callee-saved registers of the incoming thread have to be restored. Then, there
|
||||
|
@ -148,57 +148,56 @@ are specifics for each case:
|
|||
|
||||
From coop:
|
||||
|
||||
o to coop
|
||||
o to coop
|
||||
|
||||
Do a normal function call return.
|
||||
Do a normal function call return.
|
||||
|
||||
o to any irq
|
||||
o to any irq
|
||||
|
||||
The incoming interrupted thread has an IRQ stack frame containing the
|
||||
caller-saved registers that has to be popped. status32 has to be restored,
|
||||
then we jump to the interrupted instruction.
|
||||
The incoming interrupted thread has an IRQ stack frame containing the
|
||||
caller-saved registers that has to be popped. status32 has to be
|
||||
restored, then we jump to the interrupted instruction.
|
||||
|
||||
From FIRQ:
|
||||
|
||||
When CONFIG_RGF_NUM_BANKS==1, context switch is done as it is for RIRQ.
|
||||
When CONFIG_RGF_NUM_BANKS!=1, the processor is put back to using bank0,
|
||||
not bank1 anymore, because it had to save the outgoing context from bank0,
|
||||
and now has to load the incoming one
|
||||
into bank0.
|
||||
When CONFIG_RGF_NUM_BANKS==1, context switch is done as it is for RIRQ.
|
||||
When CONFIG_RGF_NUM_BANKS!=1, the processor is put back to using bank0,
|
||||
not bank1 anymore, because it had to save the outgoing context from
|
||||
bank0, and now has to load the incoming one into bank0.
|
||||
|
||||
o to coop
|
||||
o to coop
|
||||
|
||||
The address of the returning instruction from arch_switch() is loaded
|
||||
in ilink and the saved status32 in status32_p0.
|
||||
The address of the returning instruction from arch_switch() is loaded
|
||||
in ilink and the saved status32 in status32_p0.
|
||||
|
||||
o to any irq
|
||||
o to any irq
|
||||
|
||||
The IRQ has saved the caller-saved registers in a stack frame, which must be
|
||||
popped, and status32 and pc loaded in status32_p0 and ilink.
|
||||
The IRQ has saved the caller-saved registers in a stack frame, which
|
||||
must be popped, and status32 and pc loaded in status32_p0 and ilink.
|
||||
|
||||
From RIRQ:
|
||||
|
||||
o to coop
|
||||
o to coop
|
||||
|
||||
The interrupt return mechanism in the processor expects a stack frame, but
|
||||
the outgoing context did not create one. A fake one is created here, with
|
||||
only the relevant values filled in: pc, status32.
|
||||
The interrupt return mechanism in the processor expects a stack frame,
|
||||
but the outgoing context did not create one. A fake one is created
|
||||
here, with only the relevant values filled in: pc, status32.
|
||||
|
||||
There is a discrepancy between the ABI from the ARCv2 docs, including the
|
||||
way the processor pushes GPRs in pairs in the IRQ stack frame, and the ABI
|
||||
GCC uses. r13 should be a callee-saved register, but GCC treats it as
|
||||
caller-saved. This means that the processor pushes it in the stack frame
|
||||
along with r12, but the compiler does not save it before entering a
|
||||
function. So, it is saved as part of the callee-saved registers, and
|
||||
restored there, but the processor restores it _a second time_ when popping
|
||||
the IRQ stack frame. Thus, the correct value must also be put in the fake
|
||||
stack frame when returning to a thread that context switched out
|
||||
cooperatively.
|
||||
There is a discrepancy between the ABI from the ARCv2 docs,
|
||||
including the way the processor pushes GPRs in pairs in the IRQ stack
|
||||
frame, and the ABI GCC uses. r13 should be a callee-saved register,
|
||||
but GCC treats it as caller-saved. This means that the processor pushes
|
||||
it in the stack frame along with r12, but the compiler does not save it
|
||||
before entering a function. So, it is saved as part of the callee-saved
|
||||
registers, and restored there, but the processor restores it _a second
|
||||
time_ when popping the IRQ stack frame. Thus, the correct value must
|
||||
also be put in the fake stack frame when returning to a thread that
|
||||
context switched out cooperatively.
|
||||
|
||||
o to any irq
|
||||
o to any irq
|
||||
|
||||
Both types of IRQs already have an IRQ stack frame: simply return from
|
||||
interrupt.
|
||||
Both types of IRQs already have an IRQ stack frame: simply return from
|
||||
interrupt.
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, _isr_wrapper)
|
||||
|
@ -251,8 +250,6 @@ GTEXT(sys_trace_isr_enter)
|
|||
#if defined(CONFIG_SYS_POWER_MANAGEMENT)
|
||||
.macro exit_tickless_idle
|
||||
clri r0 /* do not interrupt exiting tickless idle operations */
|
||||
push_s r1
|
||||
push_s r0
|
||||
mov_s r1, _kernel
|
||||
ld_s r0, [r1, _kernel_offset_to_idle] /* requested idle duration */
|
||||
breq r0, 0, _skip_sys_power_save_idle_exit
|
||||
|
@ -263,8 +260,6 @@ GTEXT(sys_trace_isr_enter)
|
|||
pop_s blink
|
||||
|
||||
_skip_sys_power_save_idle_exit:
|
||||
pop_s r0
|
||||
pop_s r1
|
||||
seti r0
|
||||
.endm
|
||||
#else
|
||||
|
|
|
@ -25,17 +25,6 @@ GTEXT(_rirq_enter)
|
|||
GTEXT(_rirq_exit)
|
||||
GTEXT(_rirq_newthread_switch)
|
||||
|
||||
|
||||
#if 0 /* TODO: when FIRQ is not present, all would be regular */
|
||||
#define NUM_REGULAR_IRQ_PRIO_LEVELS CONFIG_NUM_IRQ_PRIO_LEVELS
|
||||
#else
|
||||
#define NUM_REGULAR_IRQ_PRIO_LEVELS (CONFIG_NUM_IRQ_PRIO_LEVELS-1)
|
||||
#endif
|
||||
/* note: the above define assumes that prio 0 IRQ is for FIRQ, and
|
||||
* that all others are regular interrupts.
|
||||
* TODO: Revist this if FIRQ becomes configurable.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
===========================================================
|
||||
|
@ -214,23 +203,16 @@ will be corrupted.
|
|||
|
||||
SECTION_FUNC(TEXT, _rirq_enter)
|
||||
|
||||
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
lr r2, [_ARC_V2_SEC_STAT]
|
||||
bclr r2, r2, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
sflag r2
|
||||
|
||||
#else
|
||||
/* disable stack checking */
|
||||
lr r2, [_ARC_V2_STATUS32]
|
||||
bclr r2, r2, _ARC_V2_STATUS32_SC_BIT
|
||||
kflag r2
|
||||
#endif
|
||||
#endif
|
||||
/* the ISR will be handled in separate interrupt stack,
|
||||
* so stack checking must be diabled, or exception will
|
||||
* be caused
|
||||
*/
|
||||
_disable_stack_checking r2
|
||||
clri
|
||||
|
||||
/* check whether irq stack is used */
|
||||
/* check whether irq stack is used, if
|
||||
* not switch to isr stack
|
||||
*/
|
||||
_check_and_inc_int_nest_counter r0, r1
|
||||
|
||||
bne.d rirq_nest
|
||||
|
@ -302,6 +284,9 @@ _rirq_newthread_switch:
|
|||
.balign 4
|
||||
_rirq_switch_from_coop:
|
||||
|
||||
/* for a cooperative switch, it's not in irq, so
|
||||
* need to set some regs for irq return
|
||||
*/
|
||||
_set_misc_regs_irq_switch_from_coop
|
||||
|
||||
/*
|
||||
|
|
|
@ -96,18 +96,10 @@ SECTION_FUNC(TEXT, arch_switch)
|
|||
|
||||
_store_old_thread_callee_regs
|
||||
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
/* disable stack checking here, as sp will be changed to target
|
||||
* thread'sp
|
||||
*/
|
||||
#if defined(CONFIG_ARC_HAS_SECURE) && defined(CONFIG_ARC_SECURE_FIRMWARE)
|
||||
bclr r3, r3, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
sflag r3
|
||||
#else
|
||||
bclr r3, r3, _ARC_V2_STATUS32_SC_BIT
|
||||
kflag r3
|
||||
#endif
|
||||
#endif
|
||||
_disable_stack_checking r3
|
||||
|
||||
mov_s r2, r0
|
||||
|
||||
|
@ -134,9 +126,12 @@ _switch_return_from_coop:
|
|||
kflag r3 /* write status32 */
|
||||
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
b _capture_value_for_benchmarking
|
||||
#endif
|
||||
return_loc:
|
||||
push_s blink
|
||||
|
||||
bl read_timer_end_of_swap
|
||||
|
||||
pop_s blink
|
||||
#endif /* CONFIG_EXECUTION_BENCHMARKING */
|
||||
j_s [blink]
|
||||
|
||||
|
||||
|
@ -167,14 +162,3 @@ _switch_return_from_firq:
|
|||
sr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
rtie
|
||||
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
.balign 4
|
||||
_capture_value_for_benchmarking:
|
||||
push_s blink
|
||||
|
||||
bl read_timer_end_of_swap
|
||||
|
||||
pop_s blink
|
||||
b return_loc
|
||||
#endif /* CONFIG_EXECUTION_BENCHMARKING */
|
||||
|
|
|
@ -93,22 +93,13 @@ SECTION_FUNC(TEXT, z_arc_userspace_enter)
|
|||
/*
|
||||
* In ARCv2, the U bit can only be set through exception return
|
||||
*/
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
/* disable stack checking as the stack should be initialized */
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
lr blink, [_ARC_V2_SEC_STAT]
|
||||
bclr blink, blink, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
sflag blink
|
||||
#else
|
||||
lr blink, [_ARC_V2_STATUS32]
|
||||
bclr blink, blink, _ARC_V2_STATUS32_SC_BIT
|
||||
kflag blink
|
||||
#endif
|
||||
#endif
|
||||
_disable_stack_checking blink
|
||||
|
||||
/* the end of user stack in r5 */
|
||||
add r5, r4, r5
|
||||
/* start of privilege stack */
|
||||
add blink, r5, CONFIG_PRIVILEGED_STACK_SIZE+STACK_GUARD_SIZE
|
||||
add blink, r5, CONFIG_PRIVILEGED_STACK_SIZE + STACK_GUARD_SIZE
|
||||
mov_s sp, r5
|
||||
|
||||
push_s r0
|
||||
|
@ -118,6 +109,9 @@ SECTION_FUNC(TEXT, z_arc_userspace_enter)
|
|||
|
||||
mov r5, sp /* skip r0, r1, r2, r3 */
|
||||
|
||||
/* to avoid the leakage of kernel info, the thread stack needs to be
|
||||
* re-initialized
|
||||
*/
|
||||
#ifdef CONFIG_INIT_STACKS
|
||||
mov_s r0, 0xaaaaaaaa
|
||||
#else
|
||||
|
@ -128,23 +122,22 @@ _clear_user_stack:
|
|||
cmp r4, r5
|
||||
jlt _clear_user_stack
|
||||
|
||||
/* reload the stack checking regs as the original kernel stack
|
||||
* becomess user stack
|
||||
*/
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
mov_s r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
|
||||
_load_stack_check_regs
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
lr r0, [_ARC_V2_SEC_STAT]
|
||||
bset r0, r0, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
sflag r0
|
||||
#else
|
||||
lr r0, [_ARC_V2_STATUS32]
|
||||
bset r0, r0, _ARC_V2_STATUS32_SC_BIT
|
||||
kflag r0
|
||||
#endif
|
||||
_enable_stack_checking r0
|
||||
#endif
|
||||
|
||||
/* the following codes are used to switch from kernel mode
|
||||
* to user mode by fake exception, because U bit can only be set
|
||||
* by exception
|
||||
*/
|
||||
_arc_go_to_user_space:
|
||||
lr r0, [_ARC_V2_STATUS32]
|
||||
bset r0, r0, _ARC_V2_STATUS32_U_BIT
|
||||
|
@ -185,9 +178,8 @@ _arc_go_to_user_space:
|
|||
mov_s blink, 0
|
||||
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
b _capture_value_for_benchmarking_userspace
|
||||
return_loc_userspace_enter:
|
||||
#endif /* CONFIG_EXECUTION_BENCHMARKING */
|
||||
bl read_timer_end_of_userspace_enter
|
||||
#endif
|
||||
|
||||
rtie
|
||||
|
||||
|
@ -298,20 +290,3 @@ inc_len:
|
|||
/* increment length measurement, loop again */
|
||||
add_s r0, r0, 1
|
||||
b_s strlen_loop
|
||||
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
.balign 4
|
||||
_capture_value_for_benchmarking_userspace:
|
||||
mov r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
_save_callee_saved_regs
|
||||
push_s blink
|
||||
|
||||
bl read_timer_end_of_userspace_enter
|
||||
|
||||
pop_s blink
|
||||
mov r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
_load_callee_saved_regs
|
||||
b return_loc_userspace_enter
|
||||
#endif
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#ifdef _ASMLANGUAGE
|
||||
|
||||
/* entering this macro, current is in r2 */
|
||||
/* save callee regs of current thread in r2 */
|
||||
.macro _save_callee_saved_regs
|
||||
|
||||
sub_s sp, sp, ___callee_saved_stack_t_SIZEOF
|
||||
|
@ -89,7 +89,7 @@
|
|||
st sp, [r2, _thread_offset_to_sp]
|
||||
.endm
|
||||
|
||||
/* entering this macro, current is in r2 */
|
||||
/* load the callee regs of thread (in r2)*/
|
||||
.macro _load_callee_saved_regs
|
||||
/* restore stack pointer from struct k_thread */
|
||||
ld sp, [r2, _thread_offset_to_sp]
|
||||
|
@ -162,6 +162,7 @@
|
|||
|
||||
.endm
|
||||
|
||||
/* discard callee regs */
|
||||
.macro _discard_callee_saved_regs
|
||||
add_s sp, sp, ___callee_saved_stack_t_SIZEOF
|
||||
.endm
|
||||
|
@ -265,7 +266,7 @@
|
|||
.endm
|
||||
|
||||
/*
|
||||
* To use this macor, r2 should have the value of thread struct pointer to
|
||||
* To use this macro, r2 should have the value of thread struct pointer to
|
||||
* _kernel.current. r3 is a scratch reg.
|
||||
*/
|
||||
.macro _load_stack_check_regs
|
||||
|
@ -297,6 +298,7 @@
|
|||
/* check and increase the interrupt nest counter
|
||||
* after increase, check whether nest counter == 1
|
||||
* the result will be EQ bit of status32
|
||||
* two temp regs are needed
|
||||
*/
|
||||
.macro _check_and_inc_int_nest_counter reg1 reg2
|
||||
#ifdef CONFIG_SMP
|
||||
|
@ -316,7 +318,10 @@
|
|||
cmp \reg2, 1
|
||||
.endm
|
||||
|
||||
/* decrease interrupt nest counter */
|
||||
/* decrease interrupt stack nest counter
|
||||
* the counter > 0, interrupt stack is used, or
|
||||
* not used
|
||||
*/
|
||||
.macro _dec_int_nest_counter reg1 reg2
|
||||
#ifdef CONFIG_SMP
|
||||
_get_cpu_id \reg1
|
||||
|
@ -336,6 +341,7 @@
|
|||
|
||||
/* If multi bits in IRQ_ACT are set, i.e. last bit != fist bit, it's
|
||||
* in nest interrupt. The result will be EQ bit of status32
|
||||
* need two temp reg to do this
|
||||
*/
|
||||
.macro _check_nest_int_by_irq_act reg1, reg2
|
||||
lr \reg1, [_ARC_V2_AUX_IRQ_ACT]
|
||||
|
@ -349,11 +355,18 @@
|
|||
cmp \reg1, \reg2
|
||||
.endm
|
||||
|
||||
|
||||
/* macro to get id of current cpu
|
||||
* the result will be in reg (a reg)
|
||||
*/
|
||||
.macro _get_cpu_id reg
|
||||
lr \reg, [_ARC_V2_IDENTITY]
|
||||
xbfu \reg, \reg, 0xe8
|
||||
.endm
|
||||
|
||||
/* macro to get the interrupt stack of current cpu
|
||||
* the result will be in irq_sp (a reg)
|
||||
*/
|
||||
.macro _get_curr_cpu_irq_stack irq_sp
|
||||
#ifdef CONFIG_SMP
|
||||
_get_cpu_id \irq_sp
|
||||
|
@ -478,6 +491,41 @@
|
|||
pop_s r2
|
||||
.endm
|
||||
|
||||
/* macro to disable stack checking in assembly, need a GPR
|
||||
* to do this
|
||||
*/
|
||||
.macro _disable_stack_checking reg
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
lr \reg, [_ARC_V2_SEC_STAT]
|
||||
bclr \reg, \reg, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
sflag \reg
|
||||
|
||||
#else
|
||||
lr \reg, [_ARC_V2_STATUS32]
|
||||
bclr \reg, \reg, _ARC_V2_STATUS32_SC_BIT
|
||||
kflag \reg
|
||||
#endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
/* macro to enable stack checking in assembly, need a GPR
|
||||
* to do this
|
||||
*/
|
||||
.macro _enable_stack_checking reg
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
lr \reg, [_ARC_V2_SEC_STAT]
|
||||
bset \reg, \reg, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
sflag \reg
|
||||
#else
|
||||
lr \reg, [_ARC_V2_STATUS32]
|
||||
bset \reg, \reg, _ARC_V2_STATUS32_SC_BIT
|
||||
kflag \reg
|
||||
#endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#endif /* ZEPHYR_ARCH_ARC_INCLUDE_SWAP_MACROS_H_ */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue