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:
Wayne Ren 2019-08-01 12:39:35 +08:00 committed by Ioannis Glaropoulos
parent ee92cf4d68
commit cca39204c2
25 changed files with 880 additions and 122 deletions

View file

@ -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

View file

@ -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)

View file

@ -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]

View file

@ -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

View file

@ -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);
}

View file

@ -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
}
/**

View file

@ -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);

View file

@ -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

View file

@ -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]

View 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
)

View 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

View 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);

View 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,
};

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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 */

View file

@ -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);

View file

@ -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 */

View file

@ -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

View file

@ -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);

View file

@ -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 */

View 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 */