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:
Wayne Ren 2017-11-29 17:24:09 +08:00 committed by Anas Nashif
parent 52e4c197f3
commit 528c960ae7
8 changed files with 96 additions and 4 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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