arch: arc: Add the support of secure mode for em
In ARC's SecureShield, a new secure mode (currently only em) is added. The secure/normal mode is orthogonal to kernel/user mode. The differences between secure mode and normal mode are following: * different irq stack frame. so need to change the definition of _irq_stack_frame, assembly code. * new aux regs, e.g, secure status(SEC_STAT), secure vector base (VECT_BASE_S) * interrupts and exceptions, secure mode has its own vector base; interrupt can be configured as secure or normal through the interrupt priority aux reg. * secure timers. Two secure timers (secure timer 0 and timer 1) are added.Here, for simplicity and backwards compatibility original internal timers (timer 0 and timer1) are used as sys clock of zephyr * on reset, the processor is in secure mode and secure vector base is used. Note: the mix of secure and normal mode is not supported, i.e. it's assumed that the processor is always in secure mode. Signed-off-by: Wayne Ren <wei.ren@synopsys.com>
This commit is contained in:
parent
52e4c197f3
commit
528c960ae7
|
@ -149,6 +149,13 @@ config CODE_DENSITY
|
|||
help
|
||||
Enable code density option to get better code density
|
||||
|
||||
config ARC_HAS_SECURE
|
||||
bool
|
||||
# a hidden option
|
||||
default n
|
||||
help
|
||||
This opiton is enabled when ARC core supports secure mode
|
||||
|
||||
menu "ARC MPU Options"
|
||||
depends on CPU_HAS_MPU
|
||||
|
||||
|
|
|
@ -87,6 +87,10 @@ static void invalidate_dcache(void)
|
|||
|
||||
static void adjust_vector_table_base(void)
|
||||
{
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#undef _ARC_V2_IRQ_VECT_BASE
|
||||
#define _ARC_V2_IRQ_VECT_BASE _ARC_V2_IRQ_VECT_BASE_S
|
||||
#endif
|
||||
extern struct vector_table _VectorTable;
|
||||
unsigned int vbr;
|
||||
/* if the compiled-in vector table is different
|
||||
|
|
|
@ -192,12 +192,29 @@ _rirq_return_from_coop:
|
|||
|
||||
/* carve fake stack */
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
/* a) status32/pc are already on the stack
|
||||
* pc
|
||||
* status
|
||||
* b) make a space for sec_stat
|
||||
* c) adjust the right place for sec_stat and pc
|
||||
* pc
|
||||
* sec_stat
|
||||
* status
|
||||
* d) a real value will be pushed in r0
|
||||
*/
|
||||
ld_s r0, [sp]
|
||||
push_s r0
|
||||
lr r0, [_ARC_V2_SEC_STAT]
|
||||
st_s r0, [sp, 4]
|
||||
sub sp, sp, (___isf_t_SIZEOF - 16)
|
||||
#else
|
||||
/*
|
||||
* a) status32/pc are already on the stack
|
||||
* b) a real value will be pushed in r0
|
||||
*/
|
||||
sub sp, sp, (___isf_t_SIZEOF - 12)
|
||||
|
||||
#endif
|
||||
/* push return value on stack */
|
||||
ld_s r0, [r2, _thread_offset_to_return_value]
|
||||
push_s r0
|
||||
|
|
|
@ -164,7 +164,7 @@ _swap_already_in_irq:
|
|||
.balign 4
|
||||
_return_from_exc_irq:
|
||||
_pop_irq_stack_frame
|
||||
sub_s sp, sp, 8
|
||||
sub_s sp, sp, ___isf_t_status32_OFFSET - ___isf_t_pc_OFFSET + 4
|
||||
|
||||
_return_from_exc:
|
||||
|
||||
|
@ -173,7 +173,7 @@ _return_from_exc:
|
|||
sr ilink, [_ARC_V2_ERET]
|
||||
|
||||
/* put status32 into estatus */
|
||||
ld ilink, [sp, 4] /* status32 into ilink */
|
||||
ld ilink, [sp, ___isf_t_status32_OFFSET - ___isf_t_pc_OFFSET] /* status32 into ilink */
|
||||
sr ilink, [_ARC_V2_ERSTATUS]
|
||||
add_s sp, sp, 8
|
||||
add_s sp, sp, ___isf_t_status32_OFFSET - ___isf_t_pc_OFFSET + 4
|
||||
rtie
|
||||
|
|
|
@ -39,6 +39,41 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#ifndef _ASMLANGUAGE
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
struct _irq_stack_frame {
|
||||
u32_t lp_end;
|
||||
u32_t lp_start;
|
||||
u32_t lp_count;
|
||||
#ifdef CONFIG_CODE_DENSITY
|
||||
/*
|
||||
* Currently unsupported. This is where those registers are
|
||||
* automatically pushed on the stack by the CPU when taking a regular
|
||||
* IRQ.
|
||||
*/
|
||||
u32_t ei_base;
|
||||
u32_t ldi_base;
|
||||
u32_t jli_base;
|
||||
#endif
|
||||
u32_t r0;
|
||||
u32_t r1;
|
||||
u32_t r2;
|
||||
u32_t r3;
|
||||
u32_t r4;
|
||||
u32_t r5;
|
||||
u32_t r6;
|
||||
u32_t r7;
|
||||
u32_t r8;
|
||||
u32_t r9;
|
||||
u32_t r10;
|
||||
u32_t r11;
|
||||
u32_t r12;
|
||||
u32_t r13;
|
||||
u32_t blink;
|
||||
u32_t pc;
|
||||
u32_t sec_stat;
|
||||
u32_t status32;
|
||||
};
|
||||
#else
|
||||
struct _irq_stack_frame {
|
||||
u32_t r0;
|
||||
u32_t r1;
|
||||
|
@ -71,6 +106,7 @@ struct _irq_stack_frame {
|
|||
u32_t pc;
|
||||
u32_t status32;
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef struct _irq_stack_frame _isf_t;
|
||||
|
||||
|
|
|
@ -28,6 +28,11 @@ extern void *_VectorTable;
|
|||
#include <kernel_structs.h>
|
||||
#include <v2/irq.h>
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#undef _ARC_V2_IRQ_VECT_BASE
|
||||
#define _ARC_V2_IRQ_VECT_BASE _ARC_V2_IRQ_VECT_BASE_S
|
||||
#endif
|
||||
|
||||
static u32_t _arc_v2_irq_unit_device_power_state = DEVICE_PM_ACTIVE_STATE;
|
||||
struct arc_v2_irq_unit_ctx {
|
||||
u32_t irq_ctrl; /* Interrupt Context Saving Control Register. */
|
||||
|
@ -68,8 +73,14 @@ static int _arc_v2_irq_unit_init(struct device *unused)
|
|||
*/
|
||||
for (irq = 16; irq < CONFIG_NUM_IRQS; irq++) {
|
||||
_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq);
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY,
|
||||
(CONFIG_NUM_IRQ_PRIO_LEVELS-1) |
|
||||
_ARC_V2_IRQ_PRIORITY_SECURE); /* lowest priority */
|
||||
#else
|
||||
_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY,
|
||||
(CONFIG_NUM_IRQ_PRIO_LEVELS-1)); /* lowest priority */
|
||||
#endif
|
||||
_arc_v2_aux_reg_write(_ARC_V2_IRQ_ENABLE, _ARC_V2_INT_DISABLE);
|
||||
_arc_v2_aux_reg_write(_ARC_V2_IRQ_TRIGGER, _ARC_V2_INT_LEVEL);
|
||||
}
|
||||
|
@ -138,8 +149,14 @@ static int _arc_v2_irq_unit_resume(struct device *dev)
|
|||
*/
|
||||
for (irq = 16; irq < CONFIG_NUM_IRQS; irq++) {
|
||||
_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq);
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY,
|
||||
ctx.irq_config[irq - 16] >> 2 |
|
||||
_ARC_V2_IRQ_PRIORITY_SECURE);
|
||||
#else
|
||||
_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY,
|
||||
ctx.irq_config[irq - 16] >> 2);
|
||||
#endif
|
||||
_arc_v2_aux_reg_write(_ARC_V2_IRQ_TRIGGER,
|
||||
(ctx.irq_config[irq - 16] >> 1) & BIT(0));
|
||||
_arc_v2_aux_reg_write(_ARC_V2_IRQ_ENABLE,
|
||||
|
|
|
@ -94,7 +94,13 @@ static inline void _arc_v2_irq_unit_int_disable(int irq)
|
|||
static inline void _arc_v2_irq_unit_prio_set(int irq, unsigned char prio)
|
||||
{
|
||||
_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 */
|
||||
_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY, prio |
|
||||
_ARC_V2_IRQ_PRIORITY_SECURE);
|
||||
#else
|
||||
_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY, prio);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -22,6 +22,7 @@ extern "C" {
|
|||
#define _ARC_V2_LP_START 0x002
|
||||
#define _ARC_V2_LP_END 0x003
|
||||
#define _ARC_V2_IDENTITY 0x004
|
||||
#define _ARC_V2_SEC_STAT 0x09
|
||||
#define _ARC_V2_STATUS32 0x00a
|
||||
#define _ARC_V2_STATUS32_P0 0x00b
|
||||
#define _ARC_V2_AUX_IRQ_CTRL 0x00e
|
||||
|
@ -34,6 +35,7 @@ extern "C" {
|
|||
#define _ARC_V2_TMR0_CONTROL 0x022
|
||||
#define _ARC_V2_TMR0_LIMIT 0x023
|
||||
#define _ARC_V2_IRQ_VECT_BASE 0x025
|
||||
#define _ARC_V2_IRQ_VECT_BASE_S 0x26
|
||||
#define _ARC_V2_AUX_IRQ_ACT 0x043
|
||||
#define _ARC_V2_DC_IVDC 0x047
|
||||
#define _ARC_V2_DC_CTRL 0x048
|
||||
|
@ -113,6 +115,9 @@ extern "C" {
|
|||
#define _ARC_V2_STATUS32_RB(x) ((x) << 16)
|
||||
#define _ARC_V2_STATUS32_IE (1 << 31)
|
||||
|
||||
/* interrupt related bits */
|
||||
#define _ARC_V2_IRQ_PRIORITY_SECURE 0x100
|
||||
|
||||
/* exception cause register masks */
|
||||
#define _ARC_V2_ECR_VECTOR(X) ((X & 0xff0000) >> 16)
|
||||
#define _ARC_V2_ECR_CODE(X) ((X & 0xff00) >> 8)
|
||||
|
|
Loading…
Reference in a new issue