[6ca4f6a] | 1 | /** |
---|
| 2 | * @file |
---|
| 3 | * |
---|
| 4 | * @ingroup ScoreSMPImpl |
---|
| 5 | * |
---|
| 6 | * @brief SuperCore SMP Implementation |
---|
| 7 | */ |
---|
| 8 | |
---|
| 9 | /* |
---|
| 10 | * COPYRIGHT (c) 1989-2011. |
---|
| 11 | * On-Line Applications Research Corporation (OAR). |
---|
| 12 | * |
---|
| 13 | * The license and distribution terms for this file may be |
---|
| 14 | * found in the file LICENSE in this distribution or at |
---|
[c499856] | 15 | * http://www.rtems.org/license/LICENSE. |
---|
[6ca4f6a] | 16 | */ |
---|
| 17 | |
---|
| 18 | #ifndef _RTEMS_SCORE_SMPIMPL_H |
---|
| 19 | #define _RTEMS_SCORE_SMPIMPL_H |
---|
| 20 | |
---|
| 21 | #include <rtems/score/smp.h> |
---|
[8a65a960] | 22 | #include <rtems/score/percpu.h> |
---|
[b3a4c48e] | 23 | #include <rtems/score/processormask.h> |
---|
[8a65a960] | 24 | #include <rtems/fatal.h> |
---|
[ddbc3f8d] | 25 | #include <rtems/rtems/cache.h> |
---|
[6ca4f6a] | 26 | |
---|
| 27 | #ifdef __cplusplus |
---|
| 28 | extern "C" { |
---|
| 29 | #endif |
---|
| 30 | |
---|
| 31 | /** |
---|
| 32 | * @defgroup ScoreSMP SMP Support |
---|
| 33 | * |
---|
| 34 | * @ingroup Score |
---|
| 35 | * |
---|
| 36 | * This defines the interface of the SuperCore SMP support. |
---|
| 37 | * |
---|
| 38 | * @{ |
---|
| 39 | */ |
---|
| 40 | |
---|
| 41 | /** |
---|
| 42 | * @brief SMP message to request a processor shutdown. |
---|
| 43 | * |
---|
| 44 | * @see _SMP_Send_message(). |
---|
| 45 | */ |
---|
[4d906bda] | 46 | #define SMP_MESSAGE_SHUTDOWN 0x1UL |
---|
[6ca4f6a] | 47 | |
---|
[145becf] | 48 | /** |
---|
| 49 | * @brief SMP message to request a test handler invocation. |
---|
| 50 | * |
---|
| 51 | * @see _SMP_Send_message(). |
---|
| 52 | */ |
---|
[4d906bda] | 53 | #define SMP_MESSAGE_TEST 0x2UL |
---|
[145becf] | 54 | |
---|
[ddbc3f8d] | 55 | /** |
---|
[26c142e5] | 56 | * @brief SMP message to request a multicast action. |
---|
[ddbc3f8d] | 57 | * |
---|
| 58 | * @see _SMP_Send_message(). |
---|
| 59 | */ |
---|
[26c142e5] | 60 | #define SMP_MESSAGE_MULTICAST_ACTION 0x4UL |
---|
[ddbc3f8d] | 61 | |
---|
[90d8567] | 62 | /** |
---|
| 63 | * @brief SMP message to request a clock tick. |
---|
| 64 | * |
---|
| 65 | * This message is provided for systems without a proper interrupt affinity |
---|
| 66 | * support and may be used by the clock driver. |
---|
| 67 | * |
---|
| 68 | * @see _SMP_Send_message(). |
---|
| 69 | */ |
---|
| 70 | #define SMP_MESSAGE_CLOCK_TICK 0x8UL |
---|
| 71 | |
---|
[6ca4f6a] | 72 | /** |
---|
| 73 | * @brief SMP fatal codes. |
---|
| 74 | */ |
---|
| 75 | typedef enum { |
---|
[c5831a3f] | 76 | SMP_FATAL_BOOT_PROCESSOR_NOT_ASSIGNED_TO_SCHEDULER, |
---|
| 77 | SMP_FATAL_MANDATORY_PROCESSOR_NOT_PRESENT, |
---|
[c952ecab] | 78 | SMP_FATAL_MULTITASKING_START_ON_INVALID_PROCESSOR, |
---|
[c5831a3f] | 79 | SMP_FATAL_MULTITASKING_START_ON_UNASSIGNED_PROCESSOR, |
---|
[c952ecab] | 80 | SMP_FATAL_SHUTDOWN, |
---|
[d134adeb] | 81 | SMP_FATAL_SHUTDOWN_RESPONSE, |
---|
[c952ecab] | 82 | SMP_FATAL_START_OF_MANDATORY_PROCESSOR_FAILED |
---|
[6ca4f6a] | 83 | } SMP_Fatal_code; |
---|
| 84 | |
---|
[c5831a3f] | 85 | static inline void _SMP_Fatal( SMP_Fatal_code code ) |
---|
| 86 | { |
---|
[b6606e8] | 87 | _Terminate( RTEMS_FATAL_SOURCE_SMP, code ); |
---|
[c5831a3f] | 88 | } |
---|
| 89 | |
---|
[6ca4f6a] | 90 | /** |
---|
| 91 | * @brief Initialize SMP Handler |
---|
| 92 | * |
---|
| 93 | * This method initialize the SMP Handler. |
---|
| 94 | */ |
---|
| 95 | #if defined( RTEMS_SMP ) |
---|
| 96 | void _SMP_Handler_initialize( void ); |
---|
| 97 | #else |
---|
| 98 | #define _SMP_Handler_initialize() \ |
---|
| 99 | do { } while ( 0 ) |
---|
| 100 | #endif |
---|
| 101 | |
---|
| 102 | #if defined( RTEMS_SMP ) |
---|
| 103 | |
---|
[b3a4c48e] | 104 | /** |
---|
| 105 | * @brief Set of online processors. |
---|
| 106 | * |
---|
| 107 | * A processor is online if was started during system initialization. In this |
---|
| 108 | * case its corresponding bit in the mask is set. |
---|
| 109 | * |
---|
| 110 | * @see _SMP_Handler_initialize(). |
---|
| 111 | */ |
---|
| 112 | extern Processor_mask _SMP_Online_processors; |
---|
| 113 | |
---|
[911b1d2] | 114 | /** |
---|
| 115 | * @brief Performs high-level initialization of a secondary processor and runs |
---|
| 116 | * the application threads. |
---|
| 117 | * |
---|
| 118 | * The low-level initialization code must call this function to hand over the |
---|
| 119 | * control of this processor to RTEMS. Interrupts must be disabled. It must |
---|
| 120 | * be possible to send inter-processor interrupts to this processor. Since |
---|
| 121 | * interrupts are disabled the inter-processor interrupt delivery is postponed |
---|
| 122 | * until interrupts are enabled the first time. Interrupts are enabled during |
---|
| 123 | * the execution begin of threads in case they have interrupt level zero (this |
---|
| 124 | * is the default). |
---|
| 125 | * |
---|
| 126 | * The pre-requisites for the call to this function are |
---|
| 127 | * - disabled interrupts, |
---|
| 128 | * - delivery of inter-processor interrupts is possible, |
---|
| 129 | * - a valid stack pointer and enough stack space, |
---|
| 130 | * - a valid code memory, and |
---|
| 131 | * - a valid BSS section. |
---|
| 132 | * |
---|
| 133 | * This function must not be called by the main processor. The main processor |
---|
| 134 | * uses _Thread_Start_multitasking() instead. |
---|
| 135 | * |
---|
| 136 | * This function does not return to the caller. |
---|
| 137 | */ |
---|
| 138 | void _SMP_Start_multitasking_on_secondary_processor( void ) |
---|
[143696a] | 139 | RTEMS_NO_RETURN; |
---|
[911b1d2] | 140 | |
---|
[145becf] | 141 | typedef void ( *SMP_Test_message_handler )( Per_CPU_Control *cpu_self ); |
---|
| 142 | |
---|
| 143 | extern SMP_Test_message_handler _SMP_Test_message_handler; |
---|
| 144 | |
---|
| 145 | /** |
---|
| 146 | * @brief Sets the handler for test messages. |
---|
| 147 | * |
---|
| 148 | * This handler can be used to test the inter-processor interrupt |
---|
| 149 | * implementation. |
---|
| 150 | */ |
---|
| 151 | static inline void _SMP_Set_test_message_handler( |
---|
| 152 | SMP_Test_message_handler handler |
---|
| 153 | ) |
---|
| 154 | { |
---|
| 155 | _SMP_Test_message_handler = handler; |
---|
| 156 | } |
---|
| 157 | |
---|
[ddbc3f8d] | 158 | /** |
---|
[26c142e5] | 159 | * @brief Processes all pending multicast actions. |
---|
[ddbc3f8d] | 160 | */ |
---|
[26c142e5] | 161 | void _SMP_Multicast_actions_process( void ); |
---|
[ddbc3f8d] | 162 | |
---|
[4d9bd56] | 163 | /** |
---|
| 164 | * @brief Interrupt handler for inter-processor interrupts. |
---|
[90d8567] | 165 | * |
---|
| 166 | * @return The received message. |
---|
[4d9bd56] | 167 | */ |
---|
[90d8567] | 168 | static inline long unsigned _SMP_Inter_processor_interrupt_handler( void ) |
---|
[8a65a960] | 169 | { |
---|
[9bb3ce39] | 170 | Per_CPU_Control *cpu_self; |
---|
| 171 | unsigned long message; |
---|
| 172 | |
---|
| 173 | cpu_self = _Per_CPU_Get(); |
---|
[8a65a960] | 174 | |
---|
[258ad71] | 175 | /* |
---|
| 176 | * In the common case the inter-processor interrupt is issued to carry out a |
---|
| 177 | * thread dispatch. |
---|
| 178 | */ |
---|
| 179 | cpu_self->dispatch_necessary = true; |
---|
| 180 | |
---|
[9bb3ce39] | 181 | message = _Atomic_Exchange_ulong( |
---|
| 182 | &cpu_self->message, |
---|
| 183 | 0, |
---|
| 184 | ATOMIC_ORDER_ACQUIRE |
---|
| 185 | ); |
---|
[8a65a960] | 186 | |
---|
[9bb3ce39] | 187 | if ( message != 0 ) { |
---|
[8a65a960] | 188 | if ( ( message & SMP_MESSAGE_SHUTDOWN ) != 0 ) { |
---|
[b3049a1d] | 189 | _SMP_Fatal( SMP_FATAL_SHUTDOWN_RESPONSE ); |
---|
[8a65a960] | 190 | /* does not continue past here */ |
---|
| 191 | } |
---|
[145becf] | 192 | |
---|
| 193 | if ( ( message & SMP_MESSAGE_TEST ) != 0 ) { |
---|
| 194 | ( *_SMP_Test_message_handler )( cpu_self ); |
---|
| 195 | } |
---|
[ddbc3f8d] | 196 | |
---|
[26c142e5] | 197 | if ( ( message & SMP_MESSAGE_MULTICAST_ACTION ) != 0 ) { |
---|
| 198 | _SMP_Multicast_actions_process(); |
---|
[ddbc3f8d] | 199 | } |
---|
[8a65a960] | 200 | } |
---|
[90d8567] | 201 | |
---|
| 202 | return message; |
---|
[8a65a960] | 203 | } |
---|
[4d9bd56] | 204 | |
---|
[2a4f9d7] | 205 | /** |
---|
| 206 | * @brief Returns true, if the processor with the specified index should be |
---|
| 207 | * started. |
---|
| 208 | * |
---|
| 209 | * @param[in] cpu_index The processor index. |
---|
| 210 | * |
---|
| 211 | * @retval true The processor should be started. |
---|
| 212 | * @retval false Otherwise. |
---|
| 213 | */ |
---|
| 214 | bool _SMP_Should_start_processor( uint32_t cpu_index ); |
---|
| 215 | |
---|
[6ca4f6a] | 216 | /** |
---|
[90d8567] | 217 | * @brief Sends an SMP message to a processor. |
---|
[6ca4f6a] | 218 | * |
---|
| 219 | * The target processor may be the sending processor. |
---|
| 220 | * |
---|
[3380ee8] | 221 | * @param[in] cpu_index The target processor of the message. |
---|
[6ca4f6a] | 222 | * @param[in] message The message. |
---|
| 223 | */ |
---|
[4d906bda] | 224 | void _SMP_Send_message( uint32_t cpu_index, unsigned long message ); |
---|
[6ca4f6a] | 225 | |
---|
| 226 | /** |
---|
[90d8567] | 227 | * @brief Sends an SMP message to all other online processors. |
---|
[6ca4f6a] | 228 | * |
---|
[90d8567] | 229 | * @param[in] message The message. |
---|
[6ca4f6a] | 230 | */ |
---|
[aed38189] | 231 | void _SMP_Send_message_broadcast( |
---|
| 232 | unsigned long message |
---|
[6ca4f6a] | 233 | ); |
---|
| 234 | |
---|
[a68cc1b] | 235 | /** |
---|
[90d8567] | 236 | * @brief Sends an SMP message to a set of processors. |
---|
[a68cc1b] | 237 | * |
---|
| 238 | * The sending processor may be part of the set. |
---|
| 239 | * |
---|
| 240 | * @param[in] setsize The size of the set of target processors of the message. |
---|
| 241 | * @param[in] cpus The set of target processors of the message. |
---|
| 242 | * @param[in] message The message. |
---|
| 243 | */ |
---|
| 244 | void _SMP_Send_message_multicast( |
---|
| 245 | const size_t setsize, |
---|
| 246 | const cpu_set_t *cpus, |
---|
| 247 | unsigned long message |
---|
| 248 | ); |
---|
| 249 | |
---|
[5b0d2c1] | 250 | typedef void ( *SMP_Action_handler )( void *arg ); |
---|
[26c142e5] | 251 | |
---|
| 252 | /** |
---|
[90d8567] | 253 | * @brief Initiates an SMP multicast action to a set of processors. |
---|
[26c142e5] | 254 | * |
---|
| 255 | * The current processor may be part of the set. |
---|
| 256 | * |
---|
| 257 | * @param[in] setsize The size of the set of target processors of the message. |
---|
| 258 | * @param[in] cpus The set of target processors of the message. |
---|
| 259 | * @param[in] handler The multicast action handler. |
---|
| 260 | * @param[in] arg The multicast action argument. |
---|
| 261 | */ |
---|
| 262 | void _SMP_Multicast_action( |
---|
| 263 | const size_t setsize, |
---|
| 264 | const cpu_set_t *cpus, |
---|
[5b0d2c1] | 265 | SMP_Action_handler handler, |
---|
[26c142e5] | 266 | void *arg |
---|
| 267 | ); |
---|
| 268 | |
---|
[5b0d2c1] | 269 | /** |
---|
| 270 | * @brief Executes a handler with argument on the specified processor on behalf |
---|
| 271 | * of the boot processor. |
---|
| 272 | * |
---|
| 273 | * The calling processor must be the boot processor. In case the specified |
---|
| 274 | * processor is not online or not in the |
---|
| 275 | * PER_CPU_STATE_READY_TO_START_MULTITASKING state, then no action is |
---|
| 276 | * performed. |
---|
| 277 | * |
---|
| 278 | * @param cpu The processor to execute the action. |
---|
| 279 | * @param handler The handler of the action. |
---|
| 280 | * @param arg The argument of the action. |
---|
| 281 | * |
---|
| 282 | * @retval true The handler executed on the specified processor. |
---|
| 283 | * @retval false Otherwise. |
---|
| 284 | * |
---|
| 285 | * @see _SMP_Before_multitasking_action_broadcast(). |
---|
| 286 | */ |
---|
| 287 | bool _SMP_Before_multitasking_action( |
---|
| 288 | Per_CPU_Control *cpu, |
---|
| 289 | SMP_Action_handler handler, |
---|
| 290 | void *arg |
---|
| 291 | ); |
---|
| 292 | |
---|
| 293 | /** |
---|
| 294 | * @brief Executes a handler with argument on all online processors except the |
---|
| 295 | * boot processor on behalf of the boot processor. |
---|
| 296 | * |
---|
| 297 | * The calling processor must be the boot processor. |
---|
| 298 | * |
---|
| 299 | * @param handler The handler of the action. |
---|
| 300 | * @param arg The argument of the action. |
---|
| 301 | * |
---|
| 302 | * @retval true The handler executed on all online processors except the boot |
---|
| 303 | * processor. |
---|
| 304 | * @retval false Otherwise. |
---|
| 305 | * |
---|
| 306 | * @see _SMP_Before_multitasking_action(). |
---|
| 307 | */ |
---|
| 308 | bool _SMP_Before_multitasking_action_broadcast( |
---|
| 309 | SMP_Action_handler handler, |
---|
| 310 | void *arg |
---|
| 311 | ); |
---|
| 312 | |
---|
[6ca4f6a] | 313 | #endif /* defined( RTEMS_SMP ) */ |
---|
| 314 | |
---|
| 315 | /** |
---|
[7336be9d] | 316 | * @brief Requests a multitasking start on all configured and available |
---|
| 317 | * processors. |
---|
[6ca4f6a] | 318 | */ |
---|
| 319 | #if defined( RTEMS_SMP ) |
---|
[7336be9d] | 320 | void _SMP_Request_start_multitasking( void ); |
---|
[6ca4f6a] | 321 | #else |
---|
[7336be9d] | 322 | #define _SMP_Request_start_multitasking() \ |
---|
[6ca4f6a] | 323 | do { } while ( 0 ) |
---|
| 324 | #endif |
---|
| 325 | |
---|
| 326 | /** |
---|
[7336be9d] | 327 | * @brief Requests a shutdown of all processors. |
---|
| 328 | * |
---|
| 329 | * This function is a part of the system termination procedure. |
---|
[6ca4f6a] | 330 | * |
---|
[7336be9d] | 331 | * @see _Terminate(). |
---|
[6ca4f6a] | 332 | */ |
---|
| 333 | #if defined( RTEMS_SMP ) |
---|
[7336be9d] | 334 | void _SMP_Request_shutdown( void ); |
---|
[6ca4f6a] | 335 | #else |
---|
[7336be9d] | 336 | #define _SMP_Request_shutdown() \ |
---|
[6ca4f6a] | 337 | do { } while ( 0 ) |
---|
| 338 | #endif |
---|
| 339 | |
---|
| 340 | /** @} */ |
---|
| 341 | |
---|
| 342 | #ifdef __cplusplus |
---|
| 343 | } |
---|
| 344 | #endif |
---|
| 345 | |
---|
| 346 | #endif |
---|
| 347 | /* end of include file */ |
---|