summaryrefslogtreecommitdiffstats
path: root/cpukit/score/include
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2011-03-16 20:05:06 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2011-03-16 20:05:06 +0000
commit06dcaf09e6c0eae0b3a3c8d84adb663d03a53a4b (patch)
tree931cf314d5a87d1d3dcd6e5c366b5ce58270a6aa /cpukit/score/include
parent2011-03-16 Joel Sherrill <joel.sherrill@oarcorp.com> (diff)
downloadrtems-06dcaf09e6c0eae0b3a3c8d84adb663d03a53a4b.tar.bz2
2011-03-16 Jennifer Averett <jennifer.averett@OARcorp.com>
PR 1729/cpukit * configure.ac, sapi/include/confdefs.h, sapi/src/exinit.c, score/Makefile.am, score/preinstall.am, score/cpu/i386/rtems/score/cpu.h, score/cpu/sparc/cpu_asm.S, score/cpu/sparc/rtems/score/cpu.h, score/include/rtems/score/basedefs.h, score/include/rtems/score/context.h, score/include/rtems/score/percpu.h, score/src/percpu.c, score/src/thread.c, score/src/threadcreateidle.c: Add next step in SMP support. This adds an allocated array of the Per_CPU structures to support multiple cpus vs a single instance of the structure which is still used if SMP support is disabled. Configuration support is also added to explicitly enable or disable SMP. But SMP can only be enabled for the CPUs which will support it initially -- SPARC and i386. With the stub BSP support, a BSP can be run as a single core SMP system from an RTEMS data structure standpoint. * aclocal/check-smp.m4, aclocal/enable-smp.m4, score/include/rtems/bspsmp.h, score/include/rtems/score/smplock.h, score/src/smp.c, score/src/smplock.c: New files.
Diffstat (limited to 'cpukit/score/include')
-rw-r--r--cpukit/score/include/rtems/bspsmp.h233
-rw-r--r--cpukit/score/include/rtems/score/basedefs.h13
-rw-r--r--cpukit/score/include/rtems/score/context.h17
-rw-r--r--cpukit/score/include/rtems/score/percpu.h131
-rw-r--r--cpukit/score/include/rtems/score/smplock.h95
5 files changed, 465 insertions, 24 deletions
diff --git a/cpukit/score/include/rtems/bspsmp.h b/cpukit/score/include/rtems/bspsmp.h
new file mode 100644
index 0000000000..26da0a7614
--- /dev/null
+++ b/cpukit/score/include/rtems/bspsmp.h
@@ -0,0 +1,233 @@
+/**
+ * @file rtems/bspsmp.h
+ *
+ * This include file defines the interface between RTEMS and an
+ * SMP aware BSP. These methods will only be used when RTEMS
+ * is configured with SMP support enabled.
+ */
+
+/*
+ * 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_BSPSMP_H
+#define _RTEMS_BSPSMP_H
+
+#if defined (RTEMS_SMP)
+#include <rtems/score/percpu.h>
+
+/**
+ * @defgroup RTEMS BSP SMP Interface
+ *
+ * This defines the interface between RTEMS and the BSP for
+ * SMP support. The interface uses the term primary
+ * to refer to the "boot" processor and secondary to refer
+ * to the "application" processors. Different architectures
+ * use different terminology.
+ *
+ * It is assumed that when the processor is reset and thus
+ * when RTEMS is initialized, that the primary processor is
+ * the only one executing. The others are assumed to be in
+ * a quiescent or reset state awaiting a command to come online.
+ */
+
+/**@{*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * This defines the bit which indicates the interprocessor interrupt
+ * has been requested so that RTEMS will reschedule on this CPU
+ * because the currently executing thread needs to be switched out.
+ */
+#define RTEMS_BSP_SMP_CONTEXT_SWITCH_NECESSARY 0x01
+
+/**
+ * This defines the bit which indicates the interprocessor interrupt
+ * has been requested so that RTEMS will reschedule on this CPU
+ * because the currently executing thread has been sent a signal.
+ */
+#define RTEMS_BSP_SMP_SIGNAL_TO_SELF 0x02
+
+/**
+ * This defines the bit which indicates the interprocessor interrupt
+ * has been requested so that this CPU will be shutdown. This is done
+ * as part of rtems_executive_shutdown().
+ */
+#define RTEMS_BSP_SMP_SHUTDOWN 0x04
+
+/**
+ * This defines the bit which indicates the interprocessor interrupt
+ * has been requested that the receiving CPU needs to perform a context
+ * switch to the first task.
+ */
+#define RTEMS_BSP_SMP_FIRST_TASK 0x08
+
+#ifndef ASM
+/**
+ * @brief Number of CPUs in SMP System
+ *
+ * This variable is set during the SMP initialization sequence to
+ * indicate the number of CPUs in this system.
+ */
+SCORE_EXTERN uint32_t _SMP_Processor_count;
+
+/**
+ * @brief Maximum Number of CPUs in SMP System
+ *
+ * This variable is set during the SMP initialization sequence to
+ * indicate the Maximum number of CPUs in this system.
+ */
+extern uint32_t rtems_smp_maximum_processors;
+
+/**
+ * @brief Initialize Secondary CPUs
+ *
+ * This method is invoked by RTEMS during initialization to bring the
+ * secondary CPUs out of reset.
+ *
+ * @param [in] maximum is the maximum number of CPU cores that RTEMS
+ * can handle
+ *
+ * @return This method returns the number of cores available in the
+ * system.
+ */
+int bsp_smp_initialize(
+ int maximum
+);
+
+/**
+ * @brief Obtain Current CPU Index
+ *
+ * This method is invoked by RTEMS when it needs to know the index
+ * of the CPU it is executing on.
+ *
+ * @return This method returns the current CPU index.
+ */
+int bsp_smp_processor_id(void) RTEMS_COMPILER_PURE_ATTRIBUTE;
+
+/**
+ * @brief Make Request of Another CPU
+ *
+ * This method is invoked by RTEMS when it needs to make a request
+ * of another CPU. It should be implemented using some type of
+ * interprocessor interrupt.
+ *
+ * @param [in] cpu is the target CPU for this request.
+ * @param [in] message is message to send
+ */
+void bsp_smp_send_message(
+ int cpu,
+ uint32_t message
+);
+
+/**
+ * @brief Make Request of Others CPUs
+ *
+ * This method is invoked by RTEMS when it needs to make a request
+ * of the other CPUs. It should be implemented using some type of
+ * interprocessor interrupt. CPUs not including the originating
+ * CPU should receive the message.
+ *
+ * @param [in] message is message to send
+ */
+void bsp_smp_broadcast_message(
+ uint32_t message
+);
+
+/**
+ * @brief Generate a Interprocessor Broadcast Interrupt
+ *
+ * This method is invoked when RTEMS wants to let all of the other
+ * CPUs know that it has sent them message. CPUs not including
+ * the originating CPU should receive the interrupt.
+
+ *
+ * @note On CPUs without the capability to generate a broadcast
+ * to all other CPUs interrupt, this can be implemented by
+ * a loop of sending interrupts to specific CPUs.
+ */
+void bsp_smp_broadcast_interrupt(void);
+
+/**
+ * @brief Generate a Interprocessor Interrupt
+ *
+ * This method is invoked by RTEMS to let @a cpu know that it
+ * has sent it a message.
+ *
+ * @param [in] cpu is the recipient CPU
+ */
+void bsp_smp_interrupt_cpu(
+ int cpu
+);
+
+/**
+ * @brief Obtain CPU Core Number
+ *
+ * This method is invoked by RTEMS when it needs to know which core
+ * number it is executing on. This is used when it needs to perform
+ * some action or bookkeeping and needs to distinguish itself from
+ * the other cores. For example, it may need to realize it needs to
+ * preempt a thread on another node.
+ *
+ * @return This method returns the Id of the current CPU core.
+ */
+int bsp_smp_processor_id( void );
+
+/**
+ * This method is invoked by @ref rtems_smp_secondary_cpu_initialize
+ * to allow the BSP to perform some intialization. The @a cpu
+ * parameter indicates the secondary CPU that the code is executing on
+ * and is currently being initialized.
+ *
+ * @note This is called by @ref rtems_smp_secondary_cpu_initialize.
+ */
+void bsp_smp_secondary_cpu_initialize(int cpu);
+
+/**
+ * This method is the C entry point which secondary CPUs should
+ * arrange to call. It performs OS initialization for the secondary
+ * CPU and coordinates bring it to a useful state.
+ *
+ * @note This is provided by RTEMS.
+ */
+void rtems_smp_secondary_cpu_initialize(void);
+
+/**
+ * This method is invoked by the BSP to initialize the per CPU structure
+ * for the specified @a cpu while it is bringing the secondary CPUs
+ * out of their reset state and into a useful state.
+ *
+ * @param [in] cpu indicates the CPU whose per cpu structure is to
+ * be initialized.
+ */
+void rtems_smp_initialize_per_cpu(int cpu);
+
+/**
+ * This is the method called by the BSP's interrupt handler
+ * to process the incoming interprocessor request.
+ */
+void rtems_smp_process_interrupt(void);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#else
+ #define bsp_smp_processor_id() 0
+#endif
+
+#endif
+
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/basedefs.h b/cpukit/score/include/rtems/score/basedefs.h
index 6bb03459e6..b956806313 100644
--- a/cpukit/score/include/rtems/score/basedefs.h
+++ b/cpukit/score/include/rtems/score/basedefs.h
@@ -136,6 +136,19 @@
#endif
/**
+ * The following defines a compiler specific attribute which informs
+ * the compiler that the method has no effect except the return value
+ * and that the return value depends only on parameters and/or global
+ * variables.
+ */
+#ifdef __GNUC__
+ #define RTEMS_COMPILER_PURE_ATTRIBUTE \
+ __attribute__ ((pure))
+#else
+ #define RTEMS_COMPILER_PURE_ATTRIBUTE
+#endif
+
+/**
* Instructs the compiler to issue a warning whenever a variable or function
* with this attribute will be used.
*/
diff --git a/cpukit/score/include/rtems/score/context.h b/cpukit/score/include/rtems/score/context.h
index cdef1d3fa5..34baf32669 100644
--- a/cpukit/score/include/rtems/score/context.h
+++ b/cpukit/score/include/rtems/score/context.h
@@ -101,6 +101,23 @@ extern "C" {
#define _Context_Restart_self( _the_context ) \
_CPU_Context_Restart_self( _the_context )
+#if defined(RTEMS_SMP)
+/*
+ * @brief Switch to First Task on Secondary Core
+ *
+ * This routine is only used to switch to the first task on a
+ * secondary core in an SMP configuration. Since the switch
+ * to the first task is done from an interrupt handler, this
+ * may be different from simply restarting the currently running
+ * task.
+ *
+ * @param[in] _the_context is the context of the first thread to
+ * run on this core
+ */
+#define _Context_Switch_to_first_task_smp( _the_context ) \
+ _CPU_Context_switch_to_first_task_smp( _the_context )
+#endif
+
/**
* @brief Return Starting Address of Floating Point Context
*
diff --git a/cpukit/score/include/rtems/score/percpu.h b/cpukit/score/include/rtems/score/percpu.h
index 2778573481..0c48b50570 100644
--- a/cpukit/score/include/rtems/score/percpu.h
+++ b/cpukit/score/include/rtems/score/percpu.h
@@ -6,14 +6,14 @@
*/
/*
- * COPYRIGHT (c) 1989-2010.
+ * 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$
+ * $Id$
*/
#ifndef _RTEMS_PERCPU_H
@@ -23,6 +23,11 @@
#ifdef ASM
#include <rtems/asm.h>
+#else
+ #if defined(RTEMS_SMP)
+ #include <rtems/score/smplock.h>
+ #endif
+ #include <rtems/bspsmp.h>
#endif
/**
@@ -41,11 +46,35 @@ extern "C" {
#endif
#ifndef ASM
-
-/**
- * This forward defines the Thread Control Block structure.
- */
+#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
@@ -53,6 +82,22 @@ typedef struct Thread_Control_struct Thread_Control;
* 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)
/**
@@ -69,7 +114,6 @@ typedef struct {
#endif
/**
- *
* This contains the current interrupt nesting level on this
* CPU.
*/
@@ -91,6 +135,14 @@ typedef struct {
#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)
@@ -98,14 +150,13 @@ typedef struct {
* 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 0
- #define PER_CPU_INTERRUPT_STACK_HIGH (1 * __RTEMS_SIZEOF_VOID_P__)
- #define PER_CPU_END_STACK (2 * __RTEMS_SIZEOF_VOID_P__)
+ #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
- /*
- * Otherwise, there are no interrupt stack addresses in the per CPU table.
- */
- #define PER_CPU_END_STACK 0
+ #define PER_CPU_END_STACK PER_CPU_END_SMP
#endif
/*
@@ -147,20 +198,52 @@ typedef struct {
*
* This is an array of per CPU core information.
*/
-extern Per_CPU_Control _Per_CPU_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 an SMP system, these macros dereference the CPU core number.
- * But on a non-SMP system, these macros are simple references.
+ * 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.heir
-#define _Thread_Executing _Per_CPU_Information.executing
-#define _Thread_Idle _Per_CPU_Information.idle
-#define _ISR_Nest_level _Per_CPU_Information.isr_nest_level
-#define _CPU_Interrupt_stack_low _Per_CPU_Information.interrupt_stack_low
-#define _CPU_Interrupt_stack_high _Per_CPU_Information.interrupt_stack_high
-#define _Thread_Dispatch_necessary _Per_CPU_Information.dispatch_necessary
+#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 */
diff --git a/cpukit/score/include/rtems/score/smplock.h b/cpukit/score/include/rtems/score/smplock.h
new file mode 100644
index 0000000000..a20d9260a4
--- /dev/null
+++ b/cpukit/score/include/rtems/score/smplock.h
@@ -0,0 +1,95 @@
+/**
+ * @file rtems/score/smplock.h
+ *
+ * This include file defines the interface for atomic locks
+ * which can be used in multiprocessor configurations.
+ */
+
+/*
+ * 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_LOCK_H
+#define _RTEMS_LOCK_H
+
+#include <rtems/score/isr.h>
+
+/**
+ * @defgroup RTEMS Lock Interface
+ *
+ */
+
+/**@{*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * This type is used to lock elements for atomic access.
+ *
+ * @note This type may move to RTEMS.
+ */
+typedef volatile uint32_t SMP_lock_Control;
+
+/**
+ * @brief Initialize a Lock
+ *
+ * This method is used to initialize the lock at @a lock.
+ *
+ * @param [in] lock is the address of the lock to obtain.
+ *
+ * @note This lock may be "too low" here. It may need to move
+ * out of the BSP area.
+ */
+void _SMP_lock_Spinlock_Initialize(
+ SMP_lock_Control *lock
+);
+
+/**
+ * @brief Obtain a Lock
+ *
+ * This method is used to obtain the lock at @a lock.
+ *
+ * @param [in] lock is the address of the lock to obtain.
+ *
+ * @return This method returns with processor interrupts disabled.
+ * The previous level is returned.
+ *
+ * @note This lock may be "too low" here. It may need to move
+ * out of the BSP area.
+ */
+ISR_Level _SMP_lock_Spinlock_Obtain(
+ SMP_lock_Control *lock
+);
+
+/**
+ * @brief Release a Lock
+ *
+ * This method is used to release the lock at @a lock.
+ *
+ * @param [in] lock is the address of the lock to obtain.
+ *
+ * @note This lock may be "too low" here. It may need to move
+ * out of the BSP area.
+ */
+void _SMP_lock_Spinlock_Release(
+ SMP_lock_Control *lock,
+ ISR_Level level
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**@}*/
+
+#endif
+/* end of include file */