diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index d050d327e5..720654d028 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -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 diff --git a/arch/arc/core/prep_c.c b/arch/arc/core/prep_c.c index a5b5a9d9a1..c40ea9e44e 100644 --- a/arch/arc/core/prep_c.c +++ b/arch/arc/core/prep_c.c @@ -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 diff --git a/arch/arc/core/regular_irq.S b/arch/arc/core/regular_irq.S index 0c1919a8fa..ad7dc708ba 100644 --- a/arch/arc/core/regular_irq.S +++ b/arch/arc/core/regular_irq.S @@ -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 diff --git a/arch/arc/core/swap.S b/arch/arc/core/swap.S index 88954c3eb8..13aa360147 100644 --- a/arch/arc/core/swap.S +++ b/arch/arc/core/swap.S @@ -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 diff --git a/arch/arc/include/kernel_arch_data.h b/arch/arc/include/kernel_arch_data.h index 3d02af5e19..548fc67a0b 100644 --- a/arch/arc/include/kernel_arch_data.h +++ b/arch/arc/include/kernel_arch_data.h @@ -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; diff --git a/drivers/interrupt_controller/arcv2_irq_unit.c b/drivers/interrupt_controller/arcv2_irq_unit.c index 769de7f409..71915590ab 100644 --- a/drivers/interrupt_controller/arcv2_irq_unit.c +++ b/drivers/interrupt_controller/arcv2_irq_unit.c @@ -28,6 +28,11 @@ extern void *_VectorTable; #include #include +#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, diff --git a/include/arch/arc/v2/arcv2_irq_unit.h b/include/arch/arc/v2/arcv2_irq_unit.h index 10de5ceacc..45ac897826 100644 --- a/include/arch/arc/v2/arcv2_irq_unit.h +++ b/include/arch/arc/v2/arcv2_irq_unit.h @@ -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 } /* diff --git a/include/arch/arc/v2/aux_regs.h b/include/arch/arc/v2/aux_regs.h index fd2583a20d..70f7f85c57 100644 --- a/include/arch/arc/v2/aux_regs.h +++ b/include/arch/arc/v2/aux_regs.h @@ -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)