diff options
Diffstat (limited to 'cpukit/score/include/rtems/score/percpu.h')
-rw-r--r-- | cpukit/score/include/rtems/score/percpu.h | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/cpukit/score/include/rtems/score/percpu.h b/cpukit/score/include/rtems/score/percpu.h new file mode 100644 index 0000000000..0c48b50570 --- /dev/null +++ b/cpukit/score/include/rtems/score/percpu.h @@ -0,0 +1,257 @@ +/** + * @file rtems/score/percpu.h + * + * This include file defines the per CPU information required + * by RTEMS. + */ + +/* + * COPYRIGHT (c) 1989-2011. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_PERCPU_H +#define _RTEMS_PERCPU_H + +#include <rtems/score/cpu.h> + +#ifdef ASM + #include <rtems/asm.h> +#else + #if defined(RTEMS_SMP) + #include <rtems/score/smplock.h> + #endif + #include <rtems/bspsmp.h> +#endif + +/** + * @defgroup PerCPU RTEMS Per CPU Information + * + * This defines the per CPU state information required by RTEMS + * and the BSP. In an SMP configuration, there will be multiple + * instances of this data structure -- one per CPU -- and the + * current CPU number will be used as the index. + */ + +/**@{*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ASM +#ifndef __THREAD_CONTROL_DEFINED__ +#define __THREAD_CONTROL_DEFINED__ +typedef struct Thread_Control_struct Thread_Control; +#endif + +#if (CPU_ALLOCATE_INTERRUPT_STACK == FALSE) && defined(RTEMS_SMP) + #error "RTEMS must allocate per CPU interrupt stack for SMP" +#endif + +typedef enum { + + /** + * This defines the constant used to indicate that the cpu code is in + * its initial powered up start. + */ + RTEMS_BSP_SMP_CPU_INITIAL_STATE = 1, + + /** + * This defines the constant used to indicate that the cpu code has + * completed basic initialization and awaits further commands. + */ + RTEMS_BSP_SMP_CPU_INITIALIZED = 2, + + /** + * This defines the constant used to indicate that the cpu code has + * shut itself down. + */ + RTEMS_BSP_SMP_CPU_SHUTDOWN = 3 +} bsp_smp_cpu_state; + +/** + * @brief Per CPU Core Structure + * + * This structure is used to hold per core state information. + */ +typedef struct { + #if defined(RTEMS_SMP) + /** This element is used to lock this structure */ + SMP_lock_Control lock; + + /** This indicates that the CPU is online. */ + uint32_t state; + + /** + * This is the request for the interrupt. + * + * @note This may become a chain protected by atomic instructions. + */ + uint32_t message; + + #endif + +#if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE) || \ + (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + /** + * This contains a pointer to the lower range of the interrupt stack for + * this CPU. This is the address allocated and freed. + */ + void *interrupt_stack_low; + + /** + * This contains a pointer to the interrupt stack pointer for this CPU. + * It will be loaded at the beginning on an ISR. + */ + void *interrupt_stack_high; +#endif + + /** + * This contains the current interrupt nesting level on this + * CPU. + */ + uint32_t isr_nest_level; + + /** This is the thread executing on this CPU. */ + Thread_Control *executing; + + /** This is the heir thread for this this CPU. */ + Thread_Control *heir; + + /** This is the idle thread for this CPU. */ + Thread_Control *idle; + + /** This is set to true when this CPU needs to run the dispatcher. */ + volatile bool dispatch_necessary; + +} Per_CPU_Control; +#endif + +#ifdef ASM +#if defined(RTEMS_SMP) + #define PER_CPU_LOCK 0 + #define PER_CPU_STATE (1 * __RTEMS_SIZEOF_VOID_P__) + #define PER_CPU_MESSAGE (2 * __RTEMS_SIZEOF_VOID_P__) + #define PER_CPU_END_SMP (3 * __RTEMS_SIZEOF_VOID_P__) +#else + #define PER_CPU_END_SMP 0 +#endif + +#if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE) || \ + (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + /* + * If this CPU target lets RTEMS allocates the interrupt stack, then + * we need to have places in the per cpu table to hold them. + */ + #define PER_CPU_INTERRUPT_STACK_LOW PER_CPU_END_SMP + #define PER_CPU_INTERRUPT_STACK_HIGH \ + PER_CPU_INTERRUPT_STACK_LOW + (1 * __RTEMS_SIZEOF_VOID_P__) + #define PER_CPU_END_STACK \ + PER_CPU_INTERRUPT_STACK_HIGH + (1 * __RTEMS_SIZEOF_VOID_P__) +#else + #define PER_CPU_END_STACK PER_CPU_END_SMP +#endif + +/* + * These are the offsets of the required elements in the per CPU table. + */ +#define PER_CPU_ISR_NEST_LEVEL \ + PER_CPU_END_STACK + 0 +#define PER_CPU_EXECUTING \ + PER_CPU_END_STACK + (1 * __RTEMS_SIZEOF_VOID_P__) +#define PER_CPU_HEIR \ + PER_CPU_END_STACK + (2 * __RTEMS_SIZEOF_VOID_P__) +#define PER_CPU_IDLE \ + PER_CPU_END_STACK + (3 * __RTEMS_SIZEOF_VOID_P__) +#define PER_CPU_DISPATCH_NEEDED \ + PER_CPU_END_STACK + (4 * __RTEMS_SIZEOF_VOID_P__) + +#define ISR_NEST_LEVEL \ + (SYM(_Per_CPU_Information) + PER_CPU_ISR_NEST_LEVEL) +#define DISPATCH_NEEDED \ + (SYM(_Per_CPU_Information) + PER_CPU_DISPATCH_NEEDED) + +/* + * Do not define these offsets if they are not in the table. + */ +#if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE) || \ + (CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE) + #define INTERRUPT_STACK_LOW \ + (SYM(_Per_CPU_Information) + PER_CPU_INTERRUPT_STACK_LOW) + #define INTERRUPT_STACK_HIGH \ + (SYM(_Per_CPU_Information) + PER_CPU_INTERRUPT_STACK_HIGH) +#endif + +#endif + +#ifndef ASM + +/** + * @brief Set of Per CPU Core Information + * + * This is an array of per CPU core information. + */ +extern Per_CPU_Control _Per_CPU_Information[]; + +#if defined(RTEMS_SMP) +/** + * @brief Set of Pointers to Per CPU Core Information + * + * This is an array of pointers to each CPU's per CPU data structure. + * It should be simpler to retrieve this pointer in assembly language + * that to calculate the array offset. + */ +extern Per_CPU_Control *_Per_CPU_Information_p[]; + +/** + * @brief Initialize SMP Handler + * + * This method initialize the SMP Handler. + */ +void _SMP_Handler_initialize(void); + +/** + * @brief Allocate and Initialize Per CPU Structures + * + * This method allocates and initialize the per CPU structure. + */ +void _Per_CPU_Initialize(void); + +#endif + +/* + * On a non SMP system, the bsp_smp_processor_id is defined to 0. + * Thus when built for non-SMP, there should be no performance penalty. + */ +#define _Thread_Heir \ + _Per_CPU_Information[bsp_smp_processor_id()].heir +#define _Thread_Executing \ + _Per_CPU_Information[bsp_smp_processor_id()].executing +#define _Thread_Idle \ + _Per_CPU_Information[bsp_smp_processor_id()].idle +#define _ISR_Nest_level \ + _Per_CPU_Information[bsp_smp_processor_id()].isr_nest_level +#define _CPU_Interrupt_stack_low \ + _Per_CPU_Information[bsp_smp_processor_id()].interrupt_stack_low +#define _CPU_Interrupt_stack_high \ + _Per_CPU_Information[bsp_smp_processor_id()].interrupt_stack_high +#define _Thread_Dispatch_necessary \ + _Per_CPU_Information[bsp_smp_processor_id()].dispatch_necessary + +#endif /* ASM */ + +#ifdef __cplusplus +} +#endif + +/**@}*/ + +#endif +/* end of include file */ |