- This is the complete set of changes for strict isolation of thread stacks. - There needs to be a confiuration operation,(#if defined(USE_THREAD_STACK_PROTECTION) for simple configuration can be used) - The stack attributes are allocated through malloc, this needs to be done through score unlimited objects. --- bsps/arm/headers.am | 1 + .../include/bsp/arm-cp15-set-ttb-entries.h | 7 + .../shared/cp15/arm-cp15-set-ttb-entries.c | 3 + bsps/arm/xilinx-zynq/mmu/bsp-set-mmu-attr.c | 72 +++++++++ bsps/shared/start/stackalloc.c | 20 ++- c/src/lib/libbsp/arm/xilinx-zynq/Makefile.am | 5 +- cpukit/Makefile.am | 1 + cpukit/headers.am | 2 + cpukit/include/rtems/score/memorymanagement.h | 22 +++ cpukit/include/rtems/score/stackmanagement.h | 49 ++++++ cpukit/score/cpu/arm/cpu.c | 3 + cpukit/score/cpu/arm/cpu_asm.S | 22 ++- .../score/cpu/arm/include/rtems/score/cpu.h | 20 +++ cpukit/score/src/stackmanagement.c | 143 ++++++++++++++++++ 14 files changed, 365 insertions(+), 5 deletions(-) create mode 100644 bsps/arm/include/bsp/arm-cp15-set-ttb-entries.h create mode 100644 bsps/arm/xilinx-zynq/mmu/bsp-set-mmu-attr.c create mode 100644 cpukit/include/rtems/score/memorymanagement.h create mode 100644 cpukit/include/rtems/score/stackmanagement.h create mode 100644 cpukit/score/src/stackmanagement.c
diff --git a/bsps/arm/headers.am b/bsps/arm/headers.am index 3d2b09effa..b1e86f3385 100644 --- a/bsps/arm/headers.am +++ b/bsps/arm/headers.am @@ -15,6 +15,7 @@ include_bsp_HEADERS += ../../../../../bsps/arm/include/bsp/arm-a9mpcore-clock.h include_bsp_HEADERS += ../../../../../bsps/arm/include/bsp/arm-a9mpcore-irq.h include_bsp_HEADERS += ../../../../../bsps/arm/include/bsp/arm-a9mpcore-regs.h include_bsp_HEADERS += ../../../../../bsps/arm/include/bsp/arm-a9mpcore-start.h +include_bsp_HEADERS += ../../../../../bsps/arm/include/bsp/arm-cp15-set-ttb-entries.h include_bsp_HEADERS += ../../../../../bsps/arm/include/bsp/arm-cp15-start.h include_bsp_HEADERS += ../../../../../bsps/arm/include/bsp/arm-errata.h include_bsp_HEADERS += ../../../../../bsps/arm/include/bsp/arm-gic-irq.h diff --git a/bsps/arm/include/bsp/arm-cp15-set-ttb-entries.h b/bsps/arm/include/bsp/arm-cp15-set-ttb-entries.h new file mode 100644 index 0000000000..39170927da --- /dev/null +++ b/bsps/arm/include/bsp/arm-cp15-set-ttb-entries.h @@ -0,0 +1,7 @@ +#include<bsp/arm-cp15-start.h> + +uint32_t arm_cp15_set_translation_table_entries( + const void *begin, + const void *end, + uint32_t section_flags +); \ No newline at end of file diff --git a/bsps/arm/shared/cp15/arm-cp15-set-ttb-entries.c b/bsps/arm/shared/cp15/arm-cp15-set-ttb-entries.c index 507277dca1..f5d0494167 100644 --- a/bsps/arm/shared/cp15/arm-cp15-set-ttb-entries.c +++ b/bsps/arm/shared/cp15/arm-cp15-set-ttb-entries.c @@ -14,6 +14,7 @@ #include <rtems.h> #include <libcpu/arm-cp15.h> +#include <bsp/arm-cp15-set-ttb-entries.h> #include <bspopts.h> /* @@ -30,6 +31,8 @@ * ARM DDI 0406C.b (ID072512) */ +#define ARM_MMU_USE_SMALL_PAGES + static uint32_t set_translation_table_entries( const void *begin, const void *end, diff --git a/bsps/arm/xilinx-zynq/mmu/bsp-set-mmu-attr.c b/bsps/arm/xilinx-zynq/mmu/bsp-set-mmu-attr.c new file mode 100644 index 0000000000..978e35b86c --- /dev/null +++ b/bsps/arm/xilinx-zynq/mmu/bsp-set-mmu-attr.c @@ -0,0 +1,72 @@ +#include <bsp/arm-cp15-start.h> +#include <bsp/arm-cp15-set-ttb-entries.h> +#include <rtems/score/memorymanagement.h> +#include <libcpu/arm-cp15.h> +#include <rtems.h> + +#ifdef USE_THREAD_STACK_PROTECTION + #define ARM_MMU_USE_SMALL_PAGES +#endif + +void memory_entries_set(uintptr_t begin, size_t size, memory_flags flags) +{ + + uintptr_t end; + rtems_interrupt_level irq_level; + uint32_t access_flags; + + end = begin + size; + access_flags = memory_translate_flags(flags); + + rtems_interrupt_local_disable(irq_level); + arm_cp15_set_translation_table_entries(begin, end, access_flags); + rtems_interrupt_local_enable(irq_level); +} + +void memory_entries_unset(uintptr_t begin, size_t size) +{ + uint32_t access_flags; + uintptr_t end; + rtems_interrupt_level irq_level; + + end = begin + size; + access_flags = memory_translate_flags(NO_ACCESS); + + rtems_interrupt_local_disable(irq_level); + arm_cp15_set_translation_table_entries(begin, end, access_flags); + rtems_interrupt_local_enable(irq_level); +} + + +uint32_t memory_translate_flags(memory_flags attr_flags) +{ + uint32_t flags; + switch (attr_flags) + { + case READ_WRITE: + flags = ARMV7_MMU_READ_WRITE; + break; + + case READ_WRITE_CACHED: + flags = ARMV7_MMU_DATA_READ_WRITE_CACHED; + break; + + case READ_ONLY: + flags = ARMV7_MMU_READ_ONLY; + break; + + case READ_ONLY_CACHED: + flags = ARMV7_MMU_READ_ONLY_CACHED; + break; + + case NO_ACCESS: + flags = 0; + break; + + default: + return -1; + break; + } + + return flags; +} \ No newline at end of file diff --git a/bsps/shared/start/stackalloc.c b/bsps/shared/start/stackalloc.c index f7cf7be0f1..2ce0d6573b 100644 --- a/bsps/shared/start/stackalloc.c +++ b/bsps/shared/start/stackalloc.c @@ -25,6 +25,7 @@ #include <rtems.h> #include <rtems/score/heapimpl.h> #include <rtems/score/wkspace.h> +#include <rtems/score/stackmanagement.h> #include <bsp/linker-symbols.h> @@ -42,7 +43,8 @@ void bsp_stack_allocate_init(size_t stack_space_size) void *bsp_stack_allocate(size_t size) { - void *stack = NULL; + void *stack = NULL; + uintptr_t page_table_base; if (bsp_stack_heap.area_begin != 0) { stack = _Heap_Allocate(&bsp_stack_heap, size); @@ -51,11 +53,23 @@ void *bsp_stack_allocate(size_t size) if (stack == NULL) { stack = _Workspace_Allocate(size); } - + +#ifdef USE_THREAD_STACK_PROTECTION + /* + This is a hard coded address, assigned just for the + purpose of consistency + */ + page_table_base = (uintptr_t)0x1000; + /* + The current way to allocate protected stack is to assign memory attributes + to the allocated memory and remove memory-entry of every other stack + */ + prot_stack_allocate( (uintptr_t)stack, size, page_table_base ); +#endif return stack; } -void bsp_stack_free(void *stack) +void bsp_stack_free(void *stack) { bool ok = _Heap_Free(&bsp_stack_heap, stack); diff --git a/c/src/lib/libbsp/arm/xilinx-zynq/Makefile.am b/c/src/lib/libbsp/arm/xilinx-zynq/Makefile.am index cfd59475c2..490f99792e 100644 --- a/c/src/lib/libbsp/arm/xilinx-zynq/Makefile.am +++ b/c/src/lib/libbsp/arm/xilinx-zynq/Makefile.am @@ -74,6 +74,9 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/xilinx-zynq/i2c/cadence-i2c. # Cache librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/shared/cache/cache-l2c-310.c +#MMU +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/xilinx-zynq/mmu/bsp-set-mmu-attr.c + # Start hooks librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/xilinx-zynq/start/bspstarthooks.c librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/xilinx-zynq/start/bspstartmmu.c @@ -85,4 +88,4 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/xilinx-zynq/start/bspstartmm include $(srcdir)/../../../../../../bsps/shared/irq-sources.am include $(srcdir)/../../../../../../bsps/shared/shared-sources.am -include $(srcdir)/../../../../../../bsps/arm/xilinx-zynq/headers.am +include $(srcdir)/../../../../../../bsps/arm/xilinx-zynq/headers.am \ No newline at end of file diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am index 51f38c84c7..f3b373376b 100644 --- a/cpukit/Makefile.am +++ b/cpukit/Makefile.am @@ -929,6 +929,7 @@ librtemscpu_a_SOURCES += score/src/schedulercbsgetserverid.c librtemscpu_a_SOURCES += score/src/schedulercbssetparameters.c librtemscpu_a_SOURCES += score/src/schedulercbsreleasejob.c librtemscpu_a_SOURCES += score/src/schedulercbsunblock.c +librtemscpu_a_SOURCES += score/src/stackmanagement.c librtemscpu_a_SOURCES += score/src/stackallocator.c librtemscpu_a_SOURCES += score/src/pheapallocate.c librtemscpu_a_SOURCES += score/src/pheapextend.c diff --git a/cpukit/headers.am b/cpukit/headers.am index fcf679f09d..9388aa0c8c 100644 --- a/cpukit/headers.am +++ b/cpukit/headers.am @@ -352,6 +352,7 @@ include_rtems_score_HEADERS += include/rtems/score/isr.h include_rtems_score_HEADERS += include/rtems/score/isrlevel.h include_rtems_score_HEADERS += include/rtems/score/isrlock.h include_rtems_score_HEADERS += include/rtems/score/memory.h +include_rtems_score_HEADERS += include/rtems/score/memorymanagement.h include_rtems_score_HEADERS += include/rtems/score/mpci.h include_rtems_score_HEADERS += include/rtems/score/mpciimpl.h include_rtems_score_HEADERS += include/rtems/score/mppkt.h @@ -405,6 +406,7 @@ include_rtems_score_HEADERS += include/rtems/score/smplockstats.h include_rtems_score_HEADERS += include/rtems/score/smplockticket.h include_rtems_score_HEADERS += include/rtems/score/stack.h include_rtems_score_HEADERS += include/rtems/score/stackimpl.h +include_rtems_score_HEADERS += include/rtems/score/stackmanagement.h include_rtems_score_HEADERS += include/rtems/score/states.h include_rtems_score_HEADERS += include/rtems/score/statesimpl.h include_rtems_score_HEADERS += include/rtems/score/status.h diff --git a/cpukit/include/rtems/score/memorymanagement.h b/cpukit/include/rtems/score/memorymanagement.h new file mode 100644 index 0000000000..c712e7301a --- /dev/null +++ b/cpukit/include/rtems/score/memorymanagement.h @@ -0,0 +1,22 @@ +#ifndef _RTEMS_SCORE_MEMORYMANAGEMENT_H +#define _RTEMS_SCORE_MEMORYMANAGEMENT_H + +#include <stdlib.h> +#include <stdint.h> + +typedef enum +{ + READ_WRITE, + READ_WRITE_CACHED, + READ_ONLY, + READ_ONLY_CACHED, + NO_ACCESS +} memory_flags; + +void memory_entries_set(uintptr_t begin_addr, size_t size, memory_flags flags); + +void memory_entries_unset(uintptr_t begin_addr, size_t size); + +uint32_t memory_translate_flags(memory_flags flags); + +#endif \ No newline at end of file diff --git a/cpukit/include/rtems/score/stackmanagement.h b/cpukit/include/rtems/score/stackmanagement.h new file mode 100644 index 0000000000..53b6a23af0 --- /dev/null +++ b/cpukit/include/rtems/score/stackmanagement.h @@ -0,0 +1,49 @@ +#ifndef _RTEMS_SCORE_STACKMANAGEMENT_H +#define _RTEMS_SCORE_STACKMANAGEMENT_H + +#if defined (ASM) +#include <rtems/asm.h> +#else + +#include <stdint.h> +#include <stdbool.h> +#include <rtems/score/memorymanagement.h> +#include <rtems/score/chainimpl.h> + +typedef struct stack_attr +{ + Chain_Node node; + uintptr_t stack_address; + size_t size; + uint32_t page_table_base; + memory_flags access_flags; +}stack_attr; + +typedef struct stack_attr_shared +{ + stack_attr Base; + Chain_Control shared_node_control; +}stack_attr_shared; + +typedef struct stack_attr_prot +{ + stack_attr_shared *shared_stacks; + stack_attr Base; + bool current_stack; +} stack_attr_prot; + + +void prot_stack_allocate(uintptr_t stack_address, size_t size, uintptr_t page_table_base); + + +void prot_stack_share(stack_attr_shared *shared, stack_attr_prot prot_stack); + +stack_attr_prot *prot_stack_context_initialize(void); + +void prot_stack_context_switch(stack_attr_prot *stack_attr); + +void prot_stack_context_restore(stack_attr_prot *stack_attr); + +#endif + +#endif \ No newline at end of file diff --git a/cpukit/score/cpu/arm/cpu.c b/cpukit/score/cpu/arm/cpu.c index 07b9588afd..aa3626965a 100644 --- a/cpukit/score/cpu/arm/cpu.c +++ b/cpukit/score/cpu/arm/cpu.c @@ -97,6 +97,9 @@ void _CPU_Context_Initialize( { (void) new_level; + #if defined (USE_THREAD_STACK_PROTECTION) + the_context->stack_attr = prot_stack_context_initialize(); + #endif the_context->register_sp = (uint32_t) stack_area_begin + stack_area_size; the_context->register_lr = (uint32_t) entry_point; the_context->isr_dispatch_disable = 0; diff --git a/cpukit/score/cpu/arm/cpu_asm.S b/cpukit/score/cpu/arm/cpu_asm.S index 66f8ba6032..0133746b82 100644 --- a/cpukit/score/cpu/arm/cpu_asm.S +++ b/cpukit/score/cpu/arm/cpu_asm.S @@ -36,7 +36,6 @@ #ifdef ARM_MULTILIB_ARCH_V4 .text - /* * void _CPU_Context_switch( run_context, heir_context ) * void _CPU_Context_restore( run_context, heir_context ) @@ -65,6 +64,16 @@ DEFINE_FUNCTION_ARM(_CPU_Context_switch) #endif str r3, [r0, #ARM_CONTEXT_CONTROL_ISR_DISPATCH_DISABLE] +#ifdef USE_THREAD_STACK_PROTECTION + mov r8, r0 + mov r9, r1 + mov r10, r2 + ldr r0, [r0, #112] + bl prot_stack_context_switch + mov r0, r8 + mov r1, r9 + mov r2, r10 +#endif #ifdef RTEMS_SMP /* @@ -133,6 +142,17 @@ DEFINE_FUNCTION_ARM(_CPU_Context_switch) */ DEFINE_FUNCTION_ARM(_CPU_Context_restore) mov r1, r0 +#if defined( USE_THREAD_STACK_PROTECTION ) + mov r8, r0 + mov r9, r1 + mov r10, r2 + ldr r0, [r0, #ARM_STACK_PROT_ATTR_OFFSET] + bl prot_stack_context_restore + ldr lr, [r2] + mov r0, r8 + mov r1, r9 + mov r2, r10 +#endif GET_SELF_CPU_CONTROL r2 b .L_restore diff --git a/cpukit/score/cpu/arm/include/rtems/score/cpu.h b/cpukit/score/cpu/arm/include/rtems/score/cpu.h index b7b48a3ac3..fb91142f35 100644 --- a/cpukit/score/cpu/arm/include/rtems/score/cpu.h +++ b/cpukit/score/cpu/arm/include/rtems/score/cpu.h @@ -34,6 +34,7 @@ #include <rtems/score/paravirt.h> #endif #include <rtems/score/arm.h> +#include <rtems/score/stackmanagement.h> /** * @addtogroup RTEMSScoreCPUARM @@ -157,6 +158,21 @@ #ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER #define ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET 44 + #ifdef ARM_MULITLIB_VFP + #define ARM_STACK_PROT_ATTR_OFFSET 112 + #else + #define ARM_STACK_PROT_ATTR_OFFSET 48 + #endif +#endif + +#ifdef USE_THREAD_STACK_PROTECTION + #if defined ARM_MULITLIB_VFP + #define ARM_CONTEXT_CONTROL_STACK_ATTR_OFFSET 112 + #elif ARM_MULTILIB_HAS_THREAD_ID_REGISTER + #define ARM_CONTEXT_CONTROL_STACK_ATTR_OFFSET 48 + #else + #define ARM_CONTEXT_CONTROL_STACK_ATTR_OFFSET 44 + #endif #endif #ifdef ARM_MULTILIB_VFP @@ -185,6 +201,7 @@ #define ARM_VFP_CONTEXT_SIZE 264 + #ifndef ASM #ifdef __cplusplus @@ -235,6 +252,9 @@ typedef struct { #ifdef RTEMS_SMP volatile bool is_executing; #endif +#ifdef USE_THREAD_STACK_PROTECTION +stack_attr_prot *stack_attr; +#endif } Context_Control; static inline void _ARM_Data_memory_barrier( void ) diff --git a/cpukit/score/src/stackmanagement.c b/cpukit/score/src/stackmanagement.c new file mode 100644 index 0000000000..ae66099b14 --- /dev/null +++ b/cpukit/score/src/stackmanagement.c @@ -0,0 +1,143 @@ +#include <rtems/score/stackmanagement.h> +#include <rtems/score/chainimpl.h> +#include <rtems/score/basedefs.h> + +Chain_Control prot_node_control = CHAIN_INITIALIZER_EMPTY(prot_node_control); + +Chain_Control *shared_node_control; + +static void prot_stack_prev_entry_remove(void) +{ + + Chain_Node *node; + stack_attr_prot *stack_attr; + + if( _Chain_Is_empty(&prot_node_control) == true ) { + _Chain_Initialize_empty(&prot_node_control); + } + node = _Chain_First( &prot_node_control ); + + while(_Chain_Is_tail(&prot_node_control, node) == false) { + + stack_attr = RTEMS_CONTAINER_OF(node,stack_attr_prot, Base.node); + + if( stack_attr->current_stack == false ) { + memory_entries_unset(stack_attr->Base.stack_address, stack_attr->Base.size); + // shared_stack_entry_remove(stack_attr->shared_stacks); + + } + node = _Chain_Immutable_next( node ); + } + +} + +/* +Iterate to the end of the chain and mark all the 'currnet' stack as false +Append the current stack attribute to the end of the chain +*/ +static void prot_stack_chain_append (Chain_Control *control, stack_attr_prot *stack_append_attr) +{ + Chain_Node *node; + stack_attr_prot *present_stacks_attr; + + if(_Chain_Is_empty(&prot_node_control) == true ) { + + _Chain_Initialize_one(&prot_node_control, &stack_append_attr->Base.node); + } else { + node = _Chain_First(&prot_node_control); + + while(_Chain_Is_tail(&prot_node_control,node) == false) { + + present_stacks_attr = RTEMS_CONTAINER_OF(node, stack_attr_prot, Base.node); + present_stacks_attr->current_stack = false; + node = _Chain_Immutable_next( node ); + } + _Chain_Append_unprotected(&prot_node_control, &stack_append_attr->Base.node); + } + +} + +void prot_stack_allocate(uintptr_t stack_address, size_t size, uintptr_t page_table_base) +{ + stack_attr_prot *stack_attr; + +/*This field will be refactored and score objects will be used for dynamic allocation*/ + stack_attr = malloc(sizeof(stack_attr_prot)); + + if(stack_attr != NULL) { + stack_attr->Base.stack_address = stack_address; + stack_attr->Base.size = size; + stack_attr->Base.page_table_base = page_table_base; + stack_attr->Base.access_flags = READ_WRITE_CACHED; + stack_attr->current_stack = true; + } + + /* + Add the attribute field to the end of the chain, remove the memory entries of + previously allocated stack and set the memory entry of the currnet stack. + */ + prot_stack_chain_append(&prot_node_control, stack_attr ); + prot_stack_prev_entry_remove(); + memory_entries_set(stack_address, size, READ_WRITE_CACHED); + +} + +stack_attr_prot *prot_stack_context_initialize(void) +{ + Chain_Node *node; + stack_attr_prot *stack_attr; + + if( _Chain_Is_empty(&prot_node_control) == false ) { + node = _Chain_First( &prot_node_control ); + + while( _Chain_Is_tail(&prot_node_control, node ) == false) { + stack_attr = RTEMS_CONTAINER_OF( node, stack_attr_prot, Base.node); + + if(stack_attr->current_stack == true) { + return stack_attr; + } else { + node = _Chain_Immutable_next( node ); + } + } + } + + return stack_attr; +} + +void prot_stack_context_switch(stack_attr_prot *stack_attr) +{ + void *stack_address; + size_t size; + Chain_Node *node; + Chain_Control *shared_node_control; + + /* + Remove the stacks shared with the current stack by iterating the chain + */ + if( stack_attr != NULL) { + + stack_address = stack_attr->Base.stack_address; + size = stack_attr->Base.size; + + if(stack_attr->current_stack == true) { + memory_entries_unset(stack_address, size); + stack_attr->current_stack = false; + } + + shared_node_control = &stack_attr->shared_stacks->shared_node_control; + } +} + +void prot_stack_context_restore(stack_attr_prot *stack_attr) +{ + void *stack_address; + size_t size; + Chain_Node *node; + Chain_Control *shared_node_control; + memory_flags flags; + + if(stack_attr->current_stack == true) { + memory_entries_set(stack_address, size, READ_WRITE_CACHED); + } + +} -- 2.17.1 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel