Skip to content
Permalink
Browse files

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>
  • Loading branch information...
vonhust authored and ioannisg committed Aug 1, 2019
1 parent ee92cf4 commit cca39204c2fb76642251fcc2c835115abaab0eef
@@ -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);
}

0 comments on commit cca3920

Please sign in to comment.
You can’t perform that action at this time.