arch: arc: add initial support of ARC TEE
* it's based on ARC SecureShield * add basic secure service in arch/arc/core/secureshield * necesssary changes in arch level * thread switch * irq/exception handling * initialization * add secure time support Signed-off-by: Wayne Ren <wei.ren@synopsys.com>
This commit is contained in:
parent
ee92cf4d68
commit
cca39204c2
25 changed files with 880 additions and 122 deletions
|
|
@ -177,12 +177,6 @@ config CODE_DENSITY
|
|||
help
|
||||
Enable code density option to get better code density
|
||||
|
||||
config ARC_HAS_SECURE
|
||||
bool
|
||||
# a hidden option
|
||||
help
|
||||
This option is enabled when ARC core supports secure mode
|
||||
|
||||
config ARC_HAS_ACCL_REGS
|
||||
bool "Reg Pair ACCL:ACCH (FPU and/or MPY > 6)"
|
||||
default y if FLOAT
|
||||
|
|
@ -191,6 +185,60 @@ config ARC_HAS_ACCL_REGS
|
|||
(also referred to as r58:r59). These can also be used by gcc as GPR so
|
||||
kernel needs to save/restore per process
|
||||
|
||||
config ARC_HAS_SECURE
|
||||
bool "ARC has SecureShield"
|
||||
select CPU_HAS_TEE
|
||||
select ARCH_HAS_TRUSTED_EXECUTION
|
||||
help
|
||||
This option is enabled when ARC core supports secure mode
|
||||
|
||||
config SJLI_TABLE_SIZE
|
||||
int "SJLI table size"
|
||||
depends on ARC_SECURE_FIRMWARE
|
||||
default 8
|
||||
help
|
||||
The size of sjli (Secure Jump and Link Indexed) table. The
|
||||
code in normal mode call secure services in secure mode through
|
||||
sjli instruction.
|
||||
|
||||
config ARC_SECURE_FIRMWARE
|
||||
prompt "Generate Secure Firmware"
|
||||
bool
|
||||
depends on ARC_HAS_SECURE
|
||||
default y if TRUSTED_EXECUTION_SECURE
|
||||
help
|
||||
This option indicates that we are building a Zephyr image that
|
||||
is intended to execute in secure mode. The option is only
|
||||
applicable to ARC processors that implement the SecureShield.
|
||||
|
||||
This option enables Zephyr to include code that executes in
|
||||
secure mode, as well as to exclude code that is designed to
|
||||
execute only in normal mode.
|
||||
|
||||
Code executing in secure mode has access to both the secure
|
||||
and normal resources of the ARC processors.
|
||||
|
||||
config ARC_NORMAL_FIRMWARE
|
||||
prompt "Generate Normal Firmware"
|
||||
bool
|
||||
depends on !ARC_SECURE_FIRMWARE
|
||||
depends on ARC_HAS_SECURE
|
||||
default y if TRUSTED_EXECUTION_NONSECURE
|
||||
help
|
||||
This option indicates that we are building a Zephyr image that
|
||||
is intended to execute in normal mode. Execution of this
|
||||
image is triggered by secure firmware that executes in secure
|
||||
mode. The option is only applicable to ARC processors that
|
||||
implement the SecureShield.
|
||||
|
||||
This option enables Zephyr to include code that executes in
|
||||
normal mode only, as well as to exclude code that is
|
||||
designed to execute only in secure mode.
|
||||
|
||||
Code executing in normal mode has no access to secure
|
||||
resources of the ARC processors, and, therefore, it shall avoid
|
||||
accessing them.
|
||||
|
||||
menu "ARC MPU Options"
|
||||
depends on CPU_HAS_MPU
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ zephyr_library_sources_ifdef(CONFIG_ARC_FIRQ fast_irq.S)
|
|||
|
||||
zephyr_library_sources_if_kconfig(irq_offload.c)
|
||||
add_subdirectory_ifdef(CONFIG_ARC_CORE_MPU mpu)
|
||||
add_subdirectory_ifdef(CONFIG_ARC_SECURE_FIRMWARE secureshield)
|
||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE userspace.S)
|
||||
zephyr_library_sources_ifdef(CONFIG_ARC_CONNECT arc_connect.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SMP arc_smp.c)
|
||||
|
|
|
|||
|
|
@ -53,12 +53,10 @@ SECTION_FUNC(TEXT, _firq_enter)
|
|||
* This has already been done by _isr_wrapper.
|
||||
*/
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
lr r2, [_ARC_V2_SEC_STAT]
|
||||
bclr r2, r2, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
/* sflag r2 */
|
||||
/* sflag instruction is not supported in current ARC GNU */
|
||||
.long 0x00bf302f
|
||||
sflag r2
|
||||
#else
|
||||
/* disable stack checking */
|
||||
lr r2, [_ARC_V2_STATUS32]
|
||||
|
|
|
|||
|
|
@ -81,6 +81,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
|
||||
|
|
@ -121,7 +122,7 @@ _exc_return:
|
|||
st_s r2, [r1, _kernel_offset_to_current]
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
/*
|
||||
* sync up the ERSEC_STAT.ERM and SEC_STAT.IRM.
|
||||
* use a fake interrupt return to simulate an exception turn.
|
||||
|
|
@ -130,11 +131,9 @@ _exc_return:
|
|||
*/
|
||||
lr r3,[_ARC_V2_ERSEC_STAT]
|
||||
btst r3, 31
|
||||
bset.nz r3, r3, 3
|
||||
bclr.z r3, r3, 3
|
||||
/* sflag r3 */
|
||||
/* sflag instruction is not supported in current ARC GNU */
|
||||
.long 0x00ff302f
|
||||
bset.nz r3, r3, _ARC_V2_SEC_STAT_IRM_BIT
|
||||
bclr.z r3, r3, _ARC_V2_SEC_STAT_IRM_BIT
|
||||
sflag r3
|
||||
#endif
|
||||
/* clear AE bit to forget this was an exception, and go to
|
||||
* register bank0 (if exception is raised in firq with 2 reg
|
||||
|
|
@ -155,8 +154,23 @@ _exc_return:
|
|||
* raise exception again. The ignored interrupts will be re-triggered
|
||||
* if not cleared, or re-triggered by interrupt sources, or just missed
|
||||
*/
|
||||
mov r3,(1 << (CONFIG_NUM_IRQ_PRIO_LEVELS - 1)) /* use lowest */
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
mov r3, (1 << (ARC_N_IRQ_START_LEVEL - 1))
|
||||
#else
|
||||
mov r3, (1 << (CONFIG_NUM_IRQ_PRIO_LEVELS - 1))
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
push r2
|
||||
mov r0, _ARC_V2_AUX_IRQ_ACT
|
||||
mov r1, r3
|
||||
mov r6, ARC_S_CALL_AUX_WRITE
|
||||
sjli SJLI_CALL_ARC_SECURE
|
||||
pop r2
|
||||
#else
|
||||
sr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ARC_FIRQ) && CONFIG_RGF_NUM_BANKS != 1
|
||||
mov r2, ilink
|
||||
|
|
@ -191,7 +205,7 @@ SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_trap)
|
|||
mov r6, K_SYSCALL_BAD
|
||||
|
||||
valid_syscall_id:
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
lr ilink, [_ARC_V2_ERSEC_STAT]
|
||||
push ilink
|
||||
#endif
|
||||
|
|
@ -268,17 +282,8 @@ exc_nest_handle:
|
|||
/* check if the current thread needs to be rescheduled */
|
||||
ld_s r0, [r1, _kernel_offset_to_ready_q_cache]
|
||||
breq r0, r2, _exc_return_from_irqoffload_trap
|
||||
|
||||
_save_callee_saved_regs
|
||||
|
||||
st _CAUSE_RIRQ, [r2, _thread_offset_to_relinquish_cause]
|
||||
/* note: Ok to use _CAUSE_RIRQ since everything is saved */
|
||||
|
||||
ld_s r2, [r1, _kernel_offset_to_ready_q_cache]
|
||||
st_s r2, [r1, _kernel_offset_to_current]
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
/*
|
||||
* sync up the ERSEC_STAT.ERM and SEC_STAT.IRM.
|
||||
* use a fake interrupt return to simulate an exception turn.
|
||||
|
|
@ -287,21 +292,42 @@ exc_nest_handle:
|
|||
*/
|
||||
lr r3,[_ARC_V2_ERSEC_STAT]
|
||||
btst r3, 31
|
||||
bset.nz r3, r3, 3
|
||||
bclr.z r3, r3, 3
|
||||
/* sflag r3 */
|
||||
/* sflag instruction is not supported in current ARC GNU */
|
||||
.long 0x00ff302f
|
||||
bset.nz r3, r3, _ARC_V2_SEC_STAT_IRM_BIT
|
||||
bclr.z r3, r3, _ARC_V2_SEC_STAT_IRM_BIT
|
||||
sflag r3
|
||||
#endif
|
||||
|
||||
_save_callee_saved_regs
|
||||
|
||||
st _CAUSE_RIRQ, [r2, _thread_offset_to_relinquish_cause]
|
||||
/* note: Ok to use _CAUSE_RIRQ since everything is saved */
|
||||
|
||||
ld_s r2, [r1, _kernel_offset_to_ready_q_cache]
|
||||
st_s r2, [r1, _kernel_offset_to_current]
|
||||
|
||||
/* clear AE bit to forget this was an exception */
|
||||
lr r3, [_ARC_V2_STATUS32]
|
||||
and r3,r3,(~_ARC_V2_STATUS32_AE)
|
||||
kflag r3
|
||||
/* pretend lowest priority interrupt happened to use common handler */
|
||||
lr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
or r3,r3,(1<<(CONFIG_NUM_IRQ_PRIO_LEVELS-1)) /* use lowest */
|
||||
sr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
or r3, r3, (1 << (ARC_N_IRQ_START_LEVEL - 1))
|
||||
#else
|
||||
or r3, r3, (1 << (CONFIG_NUM_IRQ_PRIO_LEVELS - 1))
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
push_s r2
|
||||
mov r0, _ARC_V2_AUX_IRQ_ACT
|
||||
mov r1, r3
|
||||
mov r6, ARC_S_CALL_AUX_WRITE
|
||||
sjli SJLI_CALL_ARC_SECURE
|
||||
pop_s r2
|
||||
#else
|
||||
sr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
/* Assumption: r2 has current thread */
|
||||
b _rirq_common_interrupt_swap
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -83,6 +83,16 @@ void z_irq_priority_set(unsigned int irq, unsigned int prio, u32_t flags)
|
|||
|
||||
__ASSERT(prio < CONFIG_NUM_IRQ_PRIO_LEVELS,
|
||||
"invalid priority %d for irq %d", prio, irq);
|
||||
/* 0 -> CONFIG_NUM_IRQ_PRIO_LEVELS allocted to secure world
|
||||
* left prio levels allocated to normal world
|
||||
*/
|
||||
#if defined(CONFIG_ARC_SECURE_FIRMWARE)
|
||||
prio = prio < ARC_N_IRQ_START_LEVEL ?
|
||||
prio : (ARC_N_IRQ_START_LEVEL - 1);
|
||||
#elif defined(CONFIG_ARC_NORMAL_FIRMWARE)
|
||||
prio = prio < ARC_N_IRQ_START_LEVEL ?
|
||||
ARC_N_IRQ_START_LEVEL : prio;
|
||||
#endif
|
||||
z_arc_v2_irq_unit_prio_set(irq, prio);
|
||||
irq_unlock(key);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,68 @@ static u8_t dynamic_region_index;
|
|||
*/
|
||||
static struct dynamic_region_info dyn_reg_info[MPU_DYNAMIC_REGION_AREAS_NUM];
|
||||
|
||||
#ifdef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
/* \todo through secure service to access mpu */
|
||||
static inline void _region_init(u32_t index, u32_t region_addr, u32_t size,
|
||||
u32_t region_attr)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void _region_set_attr(u32_t index, u32_t attr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static inline u32_t _region_get_attr(u32_t index)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u32_t _region_get_start(u32_t index)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void _region_set_start(u32_t index, u32_t start)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static inline u32_t _region_get_end(u32_t index)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void _region_set_end(u32_t index, u32_t end)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function probes the given addr's MPU index.if not
|
||||
* in MPU, returns error
|
||||
*/
|
||||
static inline int _mpu_probe(u32_t addr)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function checks if MPU region is enabled or not
|
||||
*/
|
||||
static inline bool _is_enabled_region(u32_t r_index)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function check if the region is user accessible or not
|
||||
*/
|
||||
static inline bool _is_user_accessible_region(u32_t r_index, int write)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#else /* CONFIG_ARC_NORMAL_FIRMWARE */
|
||||
/* the following functions are prepared for SECURE_FRIMWARE */
|
||||
static inline void _region_init(u32_t index, u32_t region_addr, u32_t size,
|
||||
u32_t region_attr)
|
||||
{
|
||||
|
|
@ -77,7 +139,7 @@ static inline void _region_init(u32_t index, u32_t region_addr, u32_t size,
|
|||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_INDEX, index);
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_RSTART, region_addr);
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_REND,
|
||||
CALC_REGION_END_ADDR(region_addr, size));
|
||||
CALC_REGION_END_ADDR(region_addr, size));
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_RPER, region_attr);
|
||||
}
|
||||
|
||||
|
|
@ -142,20 +204,6 @@ static inline int _mpu_probe(u32_t addr)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function allocates a dynamic MPU region and returns
|
||||
* the index or error
|
||||
*/
|
||||
static inline int _dynamic_region_allocate_index(void)
|
||||
{
|
||||
if (dynamic_region_index >= get_num_regions()) {
|
||||
LOG_ERR("no enough mpu entries %d", dynamic_region_index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return dynamic_region_index++;
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function checks if MPU region is enabled or not
|
||||
*/
|
||||
|
|
@ -166,21 +214,6 @@ static inline bool _is_enabled_region(u32_t r_index)
|
|||
AUX_MPU_RPER_VALID_MASK) == AUX_MPU_RPER_VALID_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function checks the area given by (start, size)
|
||||
* and returns the index if the area match one MPU entry
|
||||
*/
|
||||
static inline int _get_region_index(u32_t start, u32_t size)
|
||||
{
|
||||
int index = _mpu_probe(start);
|
||||
|
||||
if (index > 0 && index == _mpu_probe(start + size - 1)) {
|
||||
return index;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function check if the region is user accessible or not
|
||||
*/
|
||||
|
|
@ -201,6 +234,37 @@ static inline bool _is_user_accessible_region(u32_t r_index, int write)
|
|||
(AUX_MPU_ATTR_UR | AUX_MPU_ATTR_KR));
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARC_NORMAL_FIRMWARE */
|
||||
|
||||
/**
|
||||
* This internal function allocates a dynamic MPU region and returns
|
||||
* the index or error
|
||||
*/
|
||||
static inline int _dynamic_region_allocate_index(void)
|
||||
{
|
||||
if (dynamic_region_index >= get_num_regions()) {
|
||||
LOG_ERR("no enough mpu entries %d", dynamic_region_index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return dynamic_region_index++;
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function checks the area given by (start, size)
|
||||
* and returns the index if the area match one MPU entry
|
||||
*/
|
||||
static inline int _get_region_index(u32_t start, u32_t size)
|
||||
{
|
||||
int index = _mpu_probe(start);
|
||||
|
||||
if (index > 0 && index == _mpu_probe(start + size - 1)) {
|
||||
return index;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* @brief allocate and init a dynamic MPU region
|
||||
*
|
||||
* This internal function performs the allocation and initialization of
|
||||
|
|
@ -353,7 +417,14 @@ static inline int _mpu_configure(u8_t type, u32_t base, u32_t size)
|
|||
*/
|
||||
void arc_core_mpu_enable(void)
|
||||
{
|
||||
#define MPU_ENABLE_ATTR 0
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
/* the default region:
|
||||
* normal:0x000, SID:0x10000, KW:0x100 KR:0x80, KE:0x4 0
|
||||
*/
|
||||
#define MPU_ENABLE_ATTR 0x101c0
|
||||
#else
|
||||
#define MPU_ENABLE_ATTR 0
|
||||
#endif
|
||||
arc_core_mpu_default(MPU_ENABLE_ATTR);
|
||||
}
|
||||
|
||||
|
|
@ -365,7 +436,8 @@ void arc_core_mpu_disable(void)
|
|||
/* MPU is always enabled, use default region to
|
||||
* simulate MPU disable
|
||||
*/
|
||||
arc_core_mpu_default(REGION_ALL_ATTR);
|
||||
arc_core_mpu_default(REGION_ALL_ATTR | AUX_MPU_ATTR_S |
|
||||
AUX_MPU_RPER_SID1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -474,12 +546,11 @@ void arc_core_mpu_configure_thread(struct k_thread *thread)
|
|||
*/
|
||||
void arc_core_mpu_default(u32_t region_attr)
|
||||
{
|
||||
u32_t val = z_arc_v2_aux_reg_read(_ARC_V2_MPU_EN) &
|
||||
(~AUX_MPU_RPER_ATTR_MASK);
|
||||
|
||||
region_attr &= AUX_MPU_RPER_ATTR_MASK;
|
||||
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_EN, region_attr | val);
|
||||
#ifdef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
/* \todo through secure service to access mpu */
|
||||
#else
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_EN, region_attr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -85,6 +85,9 @@ GEN_OFFSET_SYM(_callee_saved_stack_t, r24);
|
|||
GEN_OFFSET_SYM(_callee_saved_stack_t, r25);
|
||||
GEN_OFFSET_SYM(_callee_saved_stack_t, r26);
|
||||
GEN_OFFSET_SYM(_callee_saved_stack_t, fp);
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
GEN_OFFSET_SYM(_callee_saved_stack_t, sec_stat);
|
||||
#endif
|
||||
#ifdef CONFIG_USERSPACE
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
GEN_OFFSET_SYM(_callee_saved_stack_t, kernel_sp);
|
||||
|
|
|
|||
|
|
@ -53,12 +53,11 @@ SECTION_FUNC(TEXT, _rirq_enter)
|
|||
|
||||
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
lr r2, [_ARC_V2_SEC_STAT]
|
||||
bclr r2, r2, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
/* sflag r2 */
|
||||
/* sflag instruction is not supported in current ARC GNU */
|
||||
.long 0x00bf302f
|
||||
sflag r2
|
||||
|
||||
#else
|
||||
/* disable stack checking */
|
||||
lr r2, [_ARC_V2_STATUS32]
|
||||
|
|
@ -199,6 +198,12 @@ _rirq_common_interrupt_swap:
|
|||
.balign 4
|
||||
_rirq_return_from_coop:
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
/* must return to secure mode, so set IRM bit to 1 */
|
||||
lr r0, [_ARC_V2_SEC_STAT]
|
||||
bset r0, r0, _ARC_V2_SEC_STAT_IRM_BIT
|
||||
sflag r0
|
||||
#endif
|
||||
/* carve fake stack */
|
||||
sub sp, sp, ___isf_t_pc_OFFSET
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ GTEXT(__start)
|
|||
|
||||
SECTION_FUNC(TEXT,__reset)
|
||||
SECTION_FUNC(TEXT,__start)
|
||||
|
||||
/* lock interrupts: will get unlocked when switch to main task
|
||||
* also make sure the processor in the correct status
|
||||
*/
|
||||
|
|
@ -62,8 +61,11 @@ SECTION_FUNC(TEXT,__start)
|
|||
sr r0, [_ARC_V2_TMR0_COUNT]
|
||||
#endif
|
||||
/* interrupt related init */
|
||||
#ifndef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
/* IRQ_ACT and IRQ_CTRL should be initialized and set in secure mode */
|
||||
sr r0, [_ARC_V2_AUX_IRQ_ACT]
|
||||
sr r0, [_ARC_V2_AUX_IRQ_CTRL]
|
||||
#endif
|
||||
sr r0, [_ARC_V2_AUX_IRQ_HINT]
|
||||
|
||||
/* \todo: MPU init, gp for small data? */
|
||||
|
|
@ -72,7 +74,7 @@ SECTION_FUNC(TEXT,__start)
|
|||
* so that exception vectors can be handled.
|
||||
*/
|
||||
mov r0, _VectorTable
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
sr r0, [_ARC_V2_IRQ_VECT_BASE_S]
|
||||
#else
|
||||
sr r0, [_ARC_V2_IRQ_VECT_BASE]
|
||||
|
|
|
|||
12
arch/arc/core/secureshield/CMakeLists.txt
Normal file
12
arch/arc/core/secureshield/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#
|
||||
# Copyright (c) 2018 Synopsys, Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources(
|
||||
arc_sjli.c
|
||||
arc_secure.S
|
||||
secure_sys_services.c
|
||||
)
|
||||
122
arch/arc/core/secureshield/arc_secure.S
Normal file
122
arch/arc/core/secureshield/arc_secure.S
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Synopsys.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <arch/cpu.h>
|
||||
|
||||
.macro clear_scratch_regs
|
||||
mov r1, 0
|
||||
mov r2, 0
|
||||
mov r3, 0
|
||||
mov r4, 0
|
||||
mov r5, 0
|
||||
mov r6, 0
|
||||
mov r7, 0
|
||||
mov r8, 0
|
||||
mov r9, 0
|
||||
mov r10, 0
|
||||
mov r11, 0
|
||||
mov r12, 0
|
||||
.endm
|
||||
|
||||
.macro clear_callee_regs
|
||||
mov r25, 0
|
||||
mov r24, 0
|
||||
mov r23, 0
|
||||
mov r22, 0
|
||||
mov r21, 0
|
||||
mov r20, 0
|
||||
mov r19, 0
|
||||
mov r18, 0
|
||||
mov r17, 0
|
||||
mov r16, 0
|
||||
|
||||
mov r15, 0
|
||||
mov r14, 0
|
||||
mov r13, 0
|
||||
.endm
|
||||
|
||||
GTEXT(arc_go_to_normal)
|
||||
GTEXT(_arc_do_secure_call)
|
||||
GDATA(arc_s_call_table)
|
||||
|
||||
|
||||
SECTION_FUNC(TEXT, _arc_do_secure_call)
|
||||
/* r0-r5: arg1-arg6, r6 is call id */
|
||||
/* the call id should be checked */
|
||||
/* disable normal interrupt happened when processor in secure mode ? */
|
||||
/* seti (0x30 | (ARC_N_IRQ_START_LEVEL-1)) */
|
||||
breq r6, ARC_S_CALL_CLRI, _s_clri
|
||||
breq r6, ARC_S_CALL_SETI, _s_seti
|
||||
push_s blink
|
||||
mov blink, arc_s_call_table
|
||||
ld.as r6, [blink, r6]
|
||||
|
||||
jl [r6]
|
||||
|
||||
/*
|
||||
* no need to clear callee regs, as they will be saved and restored
|
||||
* automatically
|
||||
*/
|
||||
clear_scratch_regs
|
||||
|
||||
mov r29, 0
|
||||
mov r30, 0
|
||||
|
||||
|
||||
_arc_do_secure_call_exit:
|
||||
pop_s blink
|
||||
|
||||
j [blink]
|
||||
/* enable normal interrupt */
|
||||
/*
|
||||
* j.d [blink]
|
||||
* seti (0x30 | (CONFIG_NUM_IRQ_PRIO_LEVELS - 1))
|
||||
*/
|
||||
|
||||
_s_clri:
|
||||
lr r0, [_ARC_V2_STATUS32]
|
||||
and r0, r0, 0x1e
|
||||
asr r0, r0
|
||||
or r0, r0, 0x30
|
||||
mov r6, (0x30 | (ARC_N_IRQ_START_LEVEL-1))
|
||||
|
||||
j.d [blink]
|
||||
seti r6
|
||||
|
||||
_s_seti:
|
||||
btst r0, 4
|
||||
jnz __seti_0
|
||||
mov r0, (CONFIG_NUM_IRQ_PRIO_LEVELS - 1)
|
||||
lr r6, [_ARC_V2_STATUS32]
|
||||
and r6, r6, 0x1e
|
||||
asr r6, r6
|
||||
cmp r0, r6
|
||||
mov.hs r0, r6
|
||||
__seti_0:
|
||||
and r0, r0, 0xf
|
||||
brhs r0, ARC_N_IRQ_START_LEVEL, __seti_1
|
||||
mov r0, ARC_N_IRQ_START_LEVEL
|
||||
__seti_1:
|
||||
or r0, r0, 0x30
|
||||
|
||||
j.d [blink]
|
||||
seti r0
|
||||
|
||||
|
||||
SECTION_FUNC(TEXT, arc_go_to_normal)
|
||||
clear_callee_regs
|
||||
clear_scratch_regs
|
||||
|
||||
mov fp, 0
|
||||
mov r29, 0
|
||||
mov r30, 0
|
||||
mov blink, 0
|
||||
|
||||
jl [r0]
|
||||
/* should not come here */
|
||||
kflag 1
|
||||
|
||||
68
arch/arc/core/secureshield/arc_sjli.c
Normal file
68
arch/arc/core/secureshield/arc_sjli.c
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Synopsys, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <device.h>
|
||||
#include <kernel.h>
|
||||
#include <errno.h>
|
||||
#include <zephyr/types.h>
|
||||
#include <init.h>
|
||||
#include <toolchain.h>
|
||||
|
||||
#include <arch/arc/v2/secureshield/arc_secure.h>
|
||||
|
||||
static void _default_sjli_entry(void);
|
||||
/*
|
||||
* sjli vector table must be in instruction space
|
||||
* \todo: how to let user to install customized sjli entry easily, e.g.
|
||||
* through macros or with the help of compiler?
|
||||
*/
|
||||
const static u32_t _sjli_vector_table[CONFIG_SJLI_TABLE_SIZE] = {
|
||||
[0] = (u32_t)_arc_do_secure_call,
|
||||
[1 ... (CONFIG_SJLI_TABLE_SIZE - 1)] = (u32_t)_default_sjli_entry,
|
||||
};
|
||||
|
||||
/*
|
||||
* @brief default entry of sjli call
|
||||
*
|
||||
*/
|
||||
static void _default_sjli_entry(void)
|
||||
{
|
||||
printk("default sjli entry\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief initializaiton of sjli related functions
|
||||
*
|
||||
*/
|
||||
static void sjli_table_init(void)
|
||||
{
|
||||
/* install SJLI table */
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_NSC_TABLE_BASE, _sjli_vector_table);
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_NSC_TABLE_TOP,
|
||||
(_sjli_vector_table + CONFIG_SJLI_TABLE_SIZE));
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief initializaiton of secureshield related functions.
|
||||
*/
|
||||
static int arc_secureshield_init(struct device *arg)
|
||||
{
|
||||
sjli_table_init();
|
||||
|
||||
/* set nic bit to enable seti/clri and
|
||||
* sleep/wevt in normal mode.
|
||||
* If not set, direct call of seti/clri etc. will raise exception.
|
||||
* Then, these seti/clri instructions should be replaced with secure
|
||||
* secure services (sjli call)
|
||||
*
|
||||
*/
|
||||
__asm__ volatile("sflag 0x20");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(arc_secureshield_init, PRE_KERNEL_1,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
89
arch/arc/core/secureshield/secure_sys_services.c
Normal file
89
arch/arc/core/secureshield/secure_sys_services.c
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Synopsys, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <kernel.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <zephyr/types.h>
|
||||
#include <soc.h>
|
||||
#include <toolchain.h>
|
||||
|
||||
#include <arch/arc/v2/secureshield/arc_secure.h>
|
||||
|
||||
#define IRQ_PRIO_MASK (0xffff << ARC_N_IRQ_START_LEVEL)
|
||||
/*
|
||||
* @brief read secure auxiliary regs on behalf of normal mode
|
||||
*
|
||||
* @param aux_reg address of aux reg
|
||||
*
|
||||
* Some aux regs require secure privilege, this function implements
|
||||
* an secure service to access secure aux regs. Check should be done
|
||||
* to decide whether the access is valid.
|
||||
*/
|
||||
static s32_t arc_s_aux_read(u32_t aux_reg)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief write secure auxiliary regs on behalf of normal mode
|
||||
*
|
||||
* @param aux_reg address of aux reg
|
||||
* @param val, the val to write
|
||||
*
|
||||
* Some aux regs require secure privilege, this function implements
|
||||
* an secure service to access secure aux regs. Check should be done
|
||||
* to decide whether the access is valid.
|
||||
*/
|
||||
static s32_t arc_s_aux_write(u32_t aux_reg, u32_t val)
|
||||
{
|
||||
if (aux_reg == _ARC_V2_AUX_IRQ_ACT) {
|
||||
/* 0 -> CONFIG_NUM_IRQ_PRIO_LEVELS allocated to secure world
|
||||
* left prio levels allocated to normal world
|
||||
*/
|
||||
val &= IRQ_PRIO_MASK;
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_AUX_IRQ_ACT, val |
|
||||
(z_arc_v2_aux_reg_read(_ARC_V2_AUX_IRQ_ACT) &
|
||||
(~IRQ_PRIO_MASK)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief allocate interrupt for normal world
|
||||
*
|
||||
* @param intno, the interrupt to be allocated to normal world
|
||||
*
|
||||
* By default, most interrupts are configured to be secure in initialization.
|
||||
* If normal world wants to use an interrupt, through this secure service to
|
||||
* apply one. Necessary check should be done to decide whether the apply is
|
||||
* valid
|
||||
*/
|
||||
static s32_t arc_s_irq_alloc(u32_t intno)
|
||||
{
|
||||
z_arc_v2_irq_uinit_secure_set(intno, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* \todo, to access MPU from normal mode, secure mpu service should be
|
||||
* created. In the secure mpu service, the parameters should be checked
|
||||
* (e.g., not overwrite the mpu regions for secure world)that operations
|
||||
* are valid
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* \todo, how to add secure service easily
|
||||
*/
|
||||
const _arc_s_call_handler_t arc_s_call_table[ARC_S_CALL_LIMIT] = {
|
||||
[ARC_S_CALL_AUX_READ] = (_arc_s_call_handler_t)arc_s_aux_read,
|
||||
[ARC_S_CALL_AUX_WRITE] = (_arc_s_call_handler_t)arc_s_aux_write,
|
||||
[ARC_S_CALL_IRQ_ALLOC] = (_arc_s_call_handler_t)arc_s_irq_alloc,
|
||||
};
|
||||
|
|
@ -86,7 +86,11 @@ SECTION_FUNC(TEXT, z_arch_switch)
|
|||
push_s r3
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
lr r3, [_ARC_V2_SEC_STAT]
|
||||
#else
|
||||
mov r3, 0
|
||||
#endif
|
||||
push_s r3
|
||||
#endif
|
||||
|
||||
|
|
@ -98,11 +102,9 @@ SECTION_FUNC(TEXT, z_arch_switch)
|
|||
/* disable stack checking here, as sp will be changed to target
|
||||
* thread'sp
|
||||
*/
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#if defined(CONFIG_ARC_HAS_SECURE) && defined(CONFIG_ARC_SECURE_FIRMWARE)
|
||||
bclr r3, r3, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
/* sflag r3 */
|
||||
/* sflag instruction is not supported in current ARC GNU */
|
||||
.long 0x00ff302f
|
||||
sflag r3
|
||||
#else
|
||||
bclr r3, r3, _ARC_V2_STATUS32_SC_BIT
|
||||
kflag r3
|
||||
|
|
@ -144,9 +146,9 @@ _switch_return_from_coop:
|
|||
pop_s blink /* pc into blink */
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
pop_s r3 /* pop SEC_STAT */
|
||||
/* sflag r3 */
|
||||
/* sflag instruction is not supported in current ARC GNU */
|
||||
.long 0x00ff302f
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
sflag r3
|
||||
#endif
|
||||
#endif
|
||||
pop_s r3 /* status32 into r3 */
|
||||
kflag r3 /* write status32 */
|
||||
|
|
@ -166,22 +168,19 @@ _switch_return_from_firq:
|
|||
bbit1 r3, _ARC_V2_STATUS32_AE_BIT, _return_from_exc_irq
|
||||
|
||||
/* pretend interrupt happened to use rtie instruction */
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
lr r3, [_ARC_V2_SEC_STAT]
|
||||
/* set SEC_STAT.IRM = SECURE for interrupt return */
|
||||
bset r3, r3, 3
|
||||
/* sflag r3 */
|
||||
/* sflag instruction is not supported in current ARC GNU */
|
||||
.long 0x00ff302f
|
||||
#endif
|
||||
|
||||
lr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
brne r3, 0, _switch_already_in_irq
|
||||
|
||||
/* use lowest interrupt priority */
|
||||
or r3, r3, (1 << (CONFIG_NUM_IRQ_PRIO_LEVELS-1))
|
||||
#ifdef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
mov r0, _ARC_V2_AUX_IRQ_ACT
|
||||
mov r1, r3
|
||||
mov r6, ARC_S_CALL_AUX_WRITE
|
||||
sjli SJLI_CALL_ARC_SECURE
|
||||
#else
|
||||
sr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
|
||||
_switch_already_in_irq:
|
||||
rtie
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ void z_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
|||
pInitCtx->pc = ((u32_t)z_thread_entry_wrapper);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
pInitCtx->sec_stat = z_arc_v2_aux_reg_read(_ARC_V2_SEC_STAT);
|
||||
#endif
|
||||
|
||||
|
|
@ -188,7 +188,7 @@ void z_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
|||
|
||||
/* stack check configuration */
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
pInitCtx->sec_stat |= _ARC_V2_SEC_STAT_SSC;
|
||||
#else
|
||||
pInitCtx->status32 |= _ARC_V2_STATUS32_SC;
|
||||
|
|
|
|||
|
|
@ -95,12 +95,10 @@ SECTION_FUNC(TEXT, z_arc_userspace_enter)
|
|||
*/
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
/* disable stack checking as the stack should be initialized */
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
lr blink, [_ARC_V2_SEC_STAT]
|
||||
bclr blink, blink, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
/* sflag blink */
|
||||
/* sflag instruction is not supported in current ARC GNU */
|
||||
.long 0x07ff302f
|
||||
sflag blink
|
||||
#else
|
||||
lr blink, [_ARC_V2_STATUS32]
|
||||
bclr blink, blink, _ARC_V2_STATUS32_SC_BIT
|
||||
|
|
@ -136,12 +134,10 @@ _clear_user_stack:
|
|||
|
||||
_load_stack_check_regs
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
lr r0, [_ARC_V2_SEC_STAT]
|
||||
bset r0, r0, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
/* sflag r0 */
|
||||
/* sflag instruction is not supported in current ARC GNU */
|
||||
.long 0x003f302f
|
||||
sflag r0
|
||||
#else
|
||||
lr r0, [_ARC_V2_STATUS32]
|
||||
bset r0, r0, _ARC_V2_STATUS32_SC_BIT
|
||||
|
|
@ -163,16 +159,16 @@ _arc_go_to_user_space:
|
|||
bclr r0, r0, _ARC_V2_STATUS32_AE_BIT
|
||||
kflag r0
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
/* when exception returns from kernel to user, sp and _ARC_V2_USER_SP
|
||||
* /_ARC_V2_SECU_SP will be switched
|
||||
*/
|
||||
#if defined(CONFIG_ARC_HAS_SECURE) && defined(CONFIG_ARC_SECURE_FIRMWARE)
|
||||
lr r0, [_ARC_V2_SEC_STAT]
|
||||
/* the mode returns from exception return is secure mode */
|
||||
bset r0, r0, 31
|
||||
sr r0, [_ARC_V2_ERSEC_STAT]
|
||||
sr r5, [_ARC_V2_SEC_U_SP]
|
||||
#else
|
||||
/* when exception returns from kernel to user, sp and _ARC_V2_USER_SP
|
||||
* will be switched
|
||||
*/
|
||||
sr r5, [_ARC_V2_USER_SP]
|
||||
#endif
|
||||
mov sp, blink
|
||||
|
|
@ -236,7 +232,7 @@ SECTION_FUNC(TEXT, _arc_do_syscall)
|
|||
sr r6, [_ARC_V2_ERSTATUS]
|
||||
pop r6
|
||||
sr r6, [_ARC_V2_ERET]
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
pop r6
|
||||
sr r6, [_ARC_V2_ERSEC_STAT]
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -130,6 +130,10 @@ struct _callee_saved_stack {
|
|||
u32_t r26;
|
||||
u32_t fp; /* r27 */
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
u32_t sec_stat;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
u32_t user_sp;
|
||||
|
|
|
|||
|
|
@ -42,12 +42,24 @@ extern "C" {
|
|||
st r26, [sp, ___callee_saved_stack_t_r26_OFFSET]
|
||||
st fp, [sp, ___callee_saved_stack_t_fp_OFFSET]
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
lr r13, [_ARC_V2_SEC_STAT]
|
||||
st_s r13, [sp, ___callee_saved_stack_t_sec_stat_OFFSET]
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
lr r13, [_ARC_V2_SEC_U_SP]
|
||||
st r13, [sp, ___callee_saved_stack_t_user_sp_OFFSET]
|
||||
lr r13, [_ARC_V2_SEC_K_SP]
|
||||
st r13, [sp, ___callee_saved_stack_t_kernel_sp_OFFSET]
|
||||
#else
|
||||
lr r13, [_ARC_V2_USER_SP]
|
||||
st r13, [sp, ___callee_saved_stack_t_user_sp_OFFSET]
|
||||
lr r13, [_ARC_V2_KERNEL_SP]
|
||||
st r13, [sp, ___callee_saved_stack_t_kernel_sp_OFFSET]
|
||||
#endif /* CONFIG_ARC_SECURE_FIRMWARE */
|
||||
#else
|
||||
lr r13, [_ARC_V2_USER_SP]
|
||||
st r13, [sp, ___callee_saved_stack_t_user_sp_OFFSET]
|
||||
|
|
@ -121,6 +133,7 @@ extern "C" {
|
|||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
ld r13, [sp, ___callee_saved_stack_t_user_sp_OFFSET]
|
||||
sr r13, [_ARC_V2_SEC_U_SP]
|
||||
ld r13, [sp, ___callee_saved_stack_t_kernel_sp_OFFSET]
|
||||
|
|
@ -128,9 +141,21 @@ extern "C" {
|
|||
#else
|
||||
ld_s r13, [sp, ___callee_saved_stack_t_user_sp_OFFSET]
|
||||
sr r13, [_ARC_V2_USER_SP]
|
||||
ld r13, [sp, ___callee_saved_stack_t_kernel_sp_OFFSET]
|
||||
sr r13, [_ARC_V2_KERNEL_SP]
|
||||
#endif /* CONFIG_ARC_SECURE_FIRMWARE */
|
||||
#else
|
||||
ld r13, [sp, ___callee_saved_stack_t_user_sp_OFFSET]
|
||||
sr r13, [_ARC_V2_USER_SP]
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
ld r13, [sp, ___callee_saved_stack_t_sec_stat_OFFSET]
|
||||
|
||||
sflag r13
|
||||
#endif
|
||||
|
||||
ld_s r13, [sp, ___callee_saved_stack_t_r13_OFFSET]
|
||||
ld_s r14, [sp, ___callee_saved_stack_t_r14_OFFSET]
|
||||
ld_s r15, [sp, ___callee_saved_stack_t_r15_OFFSET]
|
||||
|
|
@ -259,7 +284,7 @@ extern "C" {
|
|||
* _kernel.current. r3 is a scratch reg.
|
||||
*/
|
||||
.macro _load_stack_check_regs
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#if defined(CONFIG_ARC_SECURE_FIRMWARE)
|
||||
ld r3, [r2, _thread_offset_to_k_stack_base]
|
||||
sr r3, [_ARC_V2_S_KSTACK_BASE]
|
||||
ld r3, [r2, _thread_offset_to_k_stack_top]
|
||||
|
|
@ -281,7 +306,7 @@ extern "C" {
|
|||
ld r3, [r2, _thread_offset_to_u_stack_top]
|
||||
sr r3, [_ARC_V2_USTACK_TOP]
|
||||
#endif
|
||||
#endif /* CONFIG_ARC_HAS_SECURE */
|
||||
#endif /* CONFIG_ARC_SECURE_FIRMWARE */
|
||||
.endm
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
#ifndef ZEPHYR_ARCH_ARC_INCLUDE_V2_IRQ_H_
|
||||
#define ZEPHYR_ARCH_ARC_INCLUDE_V2_IRQ_H_
|
||||
|
||||
#include <arch/cpu.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
@ -28,7 +30,12 @@ extern "C" {
|
|||
#define _ARC_V2_AUX_IRQ_CTRL_32_REGS 16
|
||||
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
#define _ARC_V2_DEF_IRQ_LEVEL (ARC_N_IRQ_START_LEVEL - 1)
|
||||
#else
|
||||
#define _ARC_V2_DEF_IRQ_LEVEL (CONFIG_NUM_IRQ_PRIO_LEVELS - 1)
|
||||
#endif
|
||||
|
||||
#define _ARC_V2_WAKE_IRQ_LEVEL _ARC_V2_DEF_IRQ_LEVEL
|
||||
|
||||
/*
|
||||
|
|
@ -59,7 +66,13 @@ static ALWAYS_INLINE void z_irq_setup(void)
|
|||
);
|
||||
|
||||
k_cpu_sleep_mode = _ARC_V2_WAKE_IRQ_LEVEL;
|
||||
|
||||
#ifdef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
/* normal mode cannot write irq_ctrl, ignore it */
|
||||
aux_irq_ctrl_value = aux_irq_ctrl_value;
|
||||
#else
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_AUX_IRQ_CTRL, aux_irq_ctrl_value);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ extern void *_VectorTable;
|
|||
#include <kernel_structs.h>
|
||||
#include <v2/irq.h>
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
#undef _ARC_V2_IRQ_VECT_BASE
|
||||
#define _ARC_V2_IRQ_VECT_BASE _ARC_V2_IRQ_VECT_BASE_S
|
||||
#endif
|
||||
|
|
@ -71,8 +71,9 @@ static int arc_v2_irq_unit_init(struct device *unused)
|
|||
* values in this loop.
|
||||
*/
|
||||
for (irq = 16; irq < CONFIG_NUM_IRQS; irq++) {
|
||||
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq);
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY,
|
||||
(CONFIG_NUM_IRQ_PRIO_LEVELS-1) |
|
||||
_ARC_V2_IRQ_PRIORITY_SECURE); /* lowest priority */
|
||||
|
|
@ -148,7 +149,7 @@ static int arc_v2_irq_unit_resume(struct device *dev)
|
|||
*/
|
||||
for (irq = 16U; irq < CONFIG_NUM_IRQS; irq++) {
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq);
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY,
|
||||
ctx.irq_config[irq - 16] >> 2 |
|
||||
_ARC_V2_IRQ_PRIORITY_SECURE);
|
||||
|
|
@ -162,7 +163,11 @@ static int arc_v2_irq_unit_resume(struct device *dev)
|
|||
ctx.irq_config[irq - 16] & BIT(0));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
/* \todo use sjli instruction to access irq_ctrl */
|
||||
#else
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_AUX_IRQ_CTRL, ctx.irq_ctrl);
|
||||
#endif
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_IRQ_VECT_BASE, ctx.irq_vect_base);
|
||||
|
||||
status32 = z_arc_v2_aux_reg_read(_ARC_V2_STATUS32);
|
||||
|
|
|
|||
|
|
@ -13,8 +13,24 @@
|
|||
/*
|
||||
* note: This implementation assumes Timer0 is present. Be sure
|
||||
* to build the ARC CPU with Timer0.
|
||||
*
|
||||
* If secureshield is present and secure firmware is configured,
|
||||
* use secure Timer 0
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
|
||||
#undef _ARC_V2_TMR0_COUNT
|
||||
#undef _ARC_V2_TMR0_CONTROL
|
||||
#undef _ARC_V2_TMR0_LIMIT
|
||||
#undef IRQ_TIMER0
|
||||
|
||||
#define _ARC_V2_TMR0_COUNT _ARC_V2_S_TMR0_COUNT
|
||||
#define _ARC_V2_TMR0_CONTROL _ARC_V2_S_TMR0_CONTROL
|
||||
#define _ARC_V2_TMR0_LIMIT _ARC_V2_S_TMR0_LIMIT
|
||||
#define IRQ_TIMER0 IRQ_SEC_TIMER0
|
||||
|
||||
#endif
|
||||
|
||||
#define _ARC_V2_TMR_CTRL_IE 0x1 /* interrupt enable */
|
||||
#define _ARC_V2_TMR_CTRL_NH 0x2 /* count only while not halted */
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@
|
|||
#ifdef CONFIG_ARC_CONNECT
|
||||
#include <arch/arc/v2/arc_connect.h>
|
||||
#endif
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#include <arch/arc/v2/secureshield/arc_secure.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
/* configuration flags for interrupt unit */
|
||||
|
||||
#define _ARC_V2_INT_PRIO_MASK 0xf
|
||||
#define _ARC_V2_INT_DISABLE 0
|
||||
#define _ARC_V2_INT_ENABLE 1
|
||||
|
||||
|
|
@ -97,16 +97,35 @@ void z_arc_v2_irq_unit_int_disable(int irq)
|
|||
static ALWAYS_INLINE
|
||||
void z_arc_v2_irq_unit_prio_set(int irq, unsigned char prio)
|
||||
{
|
||||
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq);
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
/* if ARC has secure mode, all interrupt should be secure */
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY, prio |
|
||||
_ARC_V2_IRQ_PRIORITY_SECURE);
|
||||
#if defined(CONFIG_ARC_SECURE_FIRMWARE)
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY,
|
||||
(z_arc_v2_aux_reg_read(_ARC_V2_IRQ_PRIORITY) & (~_ARC_V2_INT_PRIO_MASK))
|
||||
| prio);
|
||||
#else
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY, prio);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARC_SECURE_FIRMWARE)
|
||||
static ALWAYS_INLINE
|
||||
void z_arc_v2_irq_uinit_secure_set(int irq, bool secure)
|
||||
{
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq);
|
||||
|
||||
if (secure) {
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY,
|
||||
z_arc_v2_aux_reg_read(_ARC_V2_IRQ_PRIORITY) |
|
||||
_ARC_V2_IRQ_PRIORITY_SECURE);
|
||||
} else {
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY,
|
||||
z_arc_v2_aux_reg_read(_ARC_V2_IRQ_PRIORITY) &
|
||||
_ARC_V2_INT_PRIO_MASK);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* @brief Set interrupt sensitivity
|
||||
*
|
||||
|
|
@ -119,7 +138,7 @@ void z_arc_v2_irq_unit_prio_set(int irq, unsigned char prio)
|
|||
*/
|
||||
|
||||
static ALWAYS_INLINE
|
||||
void _arc_v2_irq_unit_sensitivity_set(int irq, int s)
|
||||
void z_arc_v2_irq_unit_sensitivity_set(int irq, int s)
|
||||
{
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq);
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_IRQ_TRIGGER, s);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ extern "C" {
|
|||
#define _ARC_V2_TMR0_LIMIT 0x023
|
||||
#define _ARC_V2_IRQ_VECT_BASE 0x025
|
||||
#define _ARC_V2_IRQ_VECT_BASE_S 0x26
|
||||
#define _ARC_V2_KERNEL_SP 0x38
|
||||
#define _ARC_V2_SEC_U_SP 0x39
|
||||
#define _ARC_V2_SEC_K_SP 0x3a
|
||||
#define _ARC_V2_AUX_IRQ_ACT 0x043
|
||||
|
|
@ -73,6 +74,12 @@ extern "C" {
|
|||
#define _ARC_V2_TMR1_COUNT 0x100
|
||||
#define _ARC_V2_TMR1_CONTROL 0x101
|
||||
#define _ARC_V2_TMR1_LIMIT 0x102
|
||||
#define _ARC_V2_S_TMR0_COUNT 0x106
|
||||
#define _ARC_V2_S_TMR0_CONTROL 0x107
|
||||
#define _ARC_V2_S_TMR0_LIMIT 0x108
|
||||
#define _ARC_V2_S_TMR1_COUNT 0x109
|
||||
#define _ARC_V2_S_TMR1_CONTROL 0x10a
|
||||
#define _ARC_V2_S_TMR1_LIMIT 0x10b
|
||||
#define _ARC_V2_IRQ_PRIO_PEND 0x200
|
||||
#define _ARC_V2_AUX_IRQ_HINT 0x201
|
||||
#define _ARC_V2_IRQ_PRIORITY 0x206
|
||||
|
|
@ -84,6 +91,8 @@ extern "C" {
|
|||
#define _ARC_V2_KSTACK_BASE 0x265
|
||||
#define _ARC_V2_S_KSTACK_TOP 0x266
|
||||
#define _ARC_V2_S_KSTACK_BASE 0x267
|
||||
#define _ARC_V2_NSC_TABLE_TOP 0x268
|
||||
#define _ARC_V2_NSC_TABLE_BASE 0x269
|
||||
#define _ARC_V2_JLI_BASE 0x290
|
||||
#define _ARC_V2_LDI_BASE 0x291
|
||||
#define _ARC_V2_EI_BASE 0x292
|
||||
|
|
@ -128,6 +137,8 @@ extern "C" {
|
|||
#define _ARC_V2_STATUS32_AD (1 << _ARC_V2_STATUS32_AD_BIT)
|
||||
#define _ARC_V2_STATUS32_US_BIT 20
|
||||
#define _ARC_V2_STATUS32_US (1 << _ARC_V2_STATUS32_US_BIT)
|
||||
#define _ARC_V2_STATUS32_S_BIT 21
|
||||
#define _ARC_V2_STATUS32_S (1 << _ARC_V2_STATUS32_US_BIT)
|
||||
#define _ARC_V2_STATUS32_IE (1 << 31)
|
||||
|
||||
/* SEC_STAT bits */
|
||||
|
|
|
|||
212
include/arch/arc/v2/secureshield/arc_secure.h
Normal file
212
include/arch/arc/v2/secureshield/arc_secure.h
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Synopsys, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_ARCH_ARC_V2_SJLI_H
|
||||
#define ZEPHYR_INCLUDE_ARCH_ARC_V2_SJLI_H
|
||||
|
||||
#define SJLI_CALL_ARC_SECURE 0
|
||||
|
||||
#define ARC_S_CALL_AUX_READ 0
|
||||
#define ARC_S_CALL_AUX_WRITE 1
|
||||
#define ARC_S_CALL_IRQ_ALLOC 2
|
||||
#define ARC_S_CALL_CLRI 3
|
||||
#define ARC_S_CALL_SETI 4
|
||||
#define ARC_S_CALL_LIMIT 5
|
||||
|
||||
|
||||
|
||||
#define ARC_N_IRQ_START_LEVEL ((CONFIG_NUM_IRQ_PRIO_LEVELS + 1) / 2)
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <arch/arc/v2/aux_regs.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define arc_sjli(id) \
|
||||
(__asm__ volatile("sjli %[sjli_id]\n" :: [sjli_id] "i" (id)))
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
typedef u32_t (*_arc_s_call_handler_t)(u32_t arg1, u32_t arg2, u32_t arg3,
|
||||
u32_t arg4, u32_t arg5, u32_t arg6);
|
||||
|
||||
|
||||
extern void arc_go_to_normal(u32_t addr);
|
||||
extern void _arc_do_secure_call(void);
|
||||
extern const _arc_s_call_handler_t arc_s_call_table[ARC_S_CALL_LIMIT];
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
|
||||
static inline u32_t _arc_s_call_invoke6(u32_t arg1, u32_t arg2, u32_t arg3,
|
||||
u32_t arg4, u32_t arg5, u32_t arg6,
|
||||
u32_t call_id)
|
||||
{
|
||||
register u32_t ret __asm__("r0") = arg1;
|
||||
register u32_t r1 __asm__("r1") = arg2;
|
||||
register u32_t r2 __asm__("r2") = arg3;
|
||||
register u32_t r3 __asm__("r3") = arg4;
|
||||
register u32_t r4 __asm__("r4") = arg5;
|
||||
register u32_t r5 __asm__("r5") = arg6;
|
||||
register u32_t r6 __asm__("r6") = call_id;
|
||||
|
||||
compiler_barrier();
|
||||
|
||||
__asm__ volatile(
|
||||
"sjli %[id]\n"
|
||||
: "=r"(ret)
|
||||
: [id] "i" (SJLI_CALL_ARC_SECURE),
|
||||
"r" (ret), "r" (r1), "r" (r2), "r" (r3),
|
||||
"r" (r4), "r" (r5), "r" (r6));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline u32_t _arc_s_call_invoke5(u32_t arg1, u32_t arg2, u32_t arg3,
|
||||
u32_t arg4, u32_t arg5, u32_t call_id)
|
||||
{
|
||||
register u32_t ret __asm__("r0") = arg1;
|
||||
register u32_t r1 __asm__("r1") = arg2;
|
||||
register u32_t r2 __asm__("r2") = arg3;
|
||||
register u32_t r3 __asm__("r3") = arg4;
|
||||
register u32_t r4 __asm__("r4") = arg5;
|
||||
register u32_t r6 __asm__("r6") = call_id;
|
||||
|
||||
compiler_barrier();
|
||||
|
||||
__asm__ volatile(
|
||||
"sjli %[id]\n"
|
||||
: "=r"(ret)
|
||||
: [id] "i" (SJLI_CALL_ARC_SECURE),
|
||||
"r" (ret), "r" (r1), "r" (r2), "r" (r3),
|
||||
"r" (r4), "r" (r6));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline u32_t _arc_s_call_invoke4(u32_t arg1, u32_t arg2, u32_t arg3,
|
||||
u32_t arg4, u32_t call_id)
|
||||
{
|
||||
register u32_t ret __asm__("r0") = arg1;
|
||||
register u32_t r1 __asm__("r1") = arg2;
|
||||
register u32_t r2 __asm__("r2") = arg3;
|
||||
register u32_t r3 __asm__("r3") = arg4;
|
||||
register u32_t r6 __asm__("r6") = call_id;
|
||||
|
||||
compiler_barrier();
|
||||
|
||||
__asm__ volatile(
|
||||
"sjli %[id]\n"
|
||||
: "=r"(ret)
|
||||
: [id] "i" (SJLI_CALL_ARC_SECURE),
|
||||
"r" (ret), "r" (r1), "r" (r2), "r" (r3),
|
||||
"r" (r6));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline u32_t _arc_s_call_invoke3(u32_t arg1, u32_t arg2, u32_t arg3,
|
||||
u32_t call_id)
|
||||
{
|
||||
register u32_t ret __asm__("r0") = arg1;
|
||||
register u32_t r1 __asm__("r1") = arg2;
|
||||
register u32_t r2 __asm__("r2") = arg3;
|
||||
register u32_t r6 __asm__("r6") = call_id;
|
||||
|
||||
compiler_barrier();
|
||||
|
||||
__asm__ volatile(
|
||||
"sjli %[id]\n"
|
||||
: "=r"(ret)
|
||||
: [id] "i" (SJLI_CALL_ARC_SECURE),
|
||||
"r" (ret), "r" (r1), "r" (r2), "r" (r6));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline u32_t _arc_s_call_invoke2(u32_t arg1, u32_t arg2, u32_t call_id)
|
||||
{
|
||||
register u32_t ret __asm__("r0") = arg1;
|
||||
register u32_t r1 __asm__("r1") = arg2;
|
||||
register u32_t r6 __asm__("r6") = call_id;
|
||||
|
||||
compiler_barrier();
|
||||
|
||||
__asm__ volatile(
|
||||
"sjli %[id]\n"
|
||||
: "=r"(ret)
|
||||
: [id] "i" (SJLI_CALL_ARC_SECURE),
|
||||
"r" (ret), "r" (r1), "r" (r6));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline u32_t _arc_s_call_invoke1(u32_t arg1, u32_t call_id)
|
||||
{
|
||||
register u32_t ret __asm__("r0") = arg1;
|
||||
register u32_t r6 __asm__("r6") = call_id;
|
||||
|
||||
compiler_barrier();
|
||||
|
||||
__asm__ volatile(
|
||||
"sjli %[id]\n"
|
||||
: "=r"(ret)
|
||||
: [id] "i" (SJLI_CALL_ARC_SECURE),
|
||||
"r" (ret), "r" (r6));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline u32_t _arc_s_call_invoke0(u32_t call_id)
|
||||
{
|
||||
register u32_t ret __asm__("r0");
|
||||
register u32_t r6 __asm__("r6") = call_id;
|
||||
|
||||
compiler_barrier();
|
||||
|
||||
__asm__ volatile(
|
||||
"sjli %[id]\n"
|
||||
: "=r"(ret)
|
||||
: [id] "i" (SJLI_CALL_ARC_SECURE),
|
||||
"r" (ret), "r" (r6));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline bool _arch_is_user_context(void)
|
||||
{
|
||||
u32_t status;
|
||||
|
||||
compiler_barrier();
|
||||
|
||||
__asm__ volatile("lr %0, [%[status32]]\n"
|
||||
: "=r"(status)
|
||||
: [status32] "i" (_ARC_V2_STATUS32));
|
||||
|
||||
return !(status & _ARC_V2_STATUS32_US) ? true : false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* CONFIG_ARC_NORMAL_FIRMWARE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ASMLANGUAGE */
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_ARCH_ARC_V2_SECURE_H */
|
||||
Loading…
Reference in a new issue