[e655f7e] | 1 | /** |
---|
| 2 | * @file |
---|
| 3 | * |
---|
| 4 | * @brief SMP Support |
---|
| 5 | * @ingroup Score |
---|
| 6 | */ |
---|
| 7 | |
---|
[06dcaf0] | 8 | /* |
---|
| 9 | * COPYRIGHT (c) 1989-2011. |
---|
| 10 | * On-Line Applications Research Corporation (OAR). |
---|
| 11 | * |
---|
| 12 | * The license and distribution terms for this file may be |
---|
| 13 | * found in the file LICENSE in this distribution or at |
---|
| 14 | * http://www.rtems.com/license/LICENSE. |
---|
| 15 | */ |
---|
| 16 | |
---|
| 17 | #if HAVE_CONFIG_H |
---|
| 18 | #include "config.h" |
---|
| 19 | #endif |
---|
| 20 | |
---|
| 21 | #include <rtems/system.h> |
---|
| 22 | #include <rtems/bspsmp.h> |
---|
[0d5a9f1] | 23 | #include <rtems/score/smp.h> |
---|
[06dcaf0] | 24 | #include <rtems/score/thread.h> |
---|
[4fc370e] | 25 | #include <rtems/score/threaddispatch.h> |
---|
[06dcaf0] | 26 | |
---|
[d4dc7c8] | 27 | #if defined(RTEMS_DEBUG) |
---|
[06dcaf0] | 28 | #include <rtems/bspIo.h> |
---|
| 29 | #endif |
---|
| 30 | |
---|
[2f6108f9] | 31 | void rtems_smp_secondary_cpu_initialize( void ) |
---|
[06dcaf0] | 32 | { |
---|
[2f6108f9] | 33 | int self = bsp_smp_processor_id(); |
---|
| 34 | Per_CPU_Control *per_cpu = &_Per_CPU_Information[ self ]; |
---|
| 35 | Thread_Control *heir; |
---|
| 36 | |
---|
| 37 | #if defined(RTEMS_DEBUG) |
---|
| 38 | printk( "Made it to %d -- ", self ); |
---|
| 39 | #endif |
---|
| 40 | |
---|
| 41 | _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING ); |
---|
| 42 | |
---|
| 43 | _Per_CPU_Wait_for_state( per_cpu, PER_CPU_STATE_BEGIN_MULTITASKING ); |
---|
[dad36c52] | 44 | |
---|
[2f6108f9] | 45 | _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_UP ); |
---|
[06dcaf0] | 46 | |
---|
| 47 | /* |
---|
[d4dc7c8] | 48 | * The Scheduler will have selected the heir thread for each CPU core. |
---|
| 49 | * Now we have been requested to perform the first context switch. So |
---|
[2f6108f9] | 50 | * force a switch to the designated heir and make it executing on |
---|
[d4dc7c8] | 51 | * THIS core. |
---|
[06dcaf0] | 52 | */ |
---|
[2f6108f9] | 53 | heir = per_cpu->heir; |
---|
| 54 | per_cpu->executing = heir; |
---|
[06dcaf0] | 55 | |
---|
| 56 | /* |
---|
[2f6108f9] | 57 | * Threads begin execution in the _Thread_Handler() function. This function |
---|
| 58 | * will call _Thread_Enable_dispatch(). |
---|
[06dcaf0] | 59 | */ |
---|
[2f6108f9] | 60 | _Thread_Disable_dispatch(); |
---|
[dad36c52] | 61 | |
---|
[2f6108f9] | 62 | _CPU_Context_switch_to_first_task_smp( &heir->Registers ); |
---|
[06dcaf0] | 63 | } |
---|
| 64 | |
---|
[2f6108f9] | 65 | void rtems_smp_process_interrupt( void ) |
---|
[06dcaf0] | 66 | { |
---|
[2f6108f9] | 67 | int self = bsp_smp_processor_id(); |
---|
| 68 | Per_CPU_Control *per_cpu = &_Per_CPU_Information[ self ]; |
---|
| 69 | uint32_t message; |
---|
| 70 | ISR_Level level; |
---|
[06dcaf0] | 71 | |
---|
| 72 | |
---|
[a8ef3bf0] | 73 | _Per_CPU_Lock_acquire( per_cpu, level ); |
---|
[2f6108f9] | 74 | message = per_cpu->message; |
---|
| 75 | per_cpu->message = 0; |
---|
[a8ef3bf0] | 76 | _Per_CPU_Lock_release( per_cpu, level ); |
---|
[06dcaf0] | 77 | |
---|
[d4dc7c8] | 78 | #if defined(RTEMS_DEBUG) |
---|
[06dcaf0] | 79 | { |
---|
| 80 | void *sp = __builtin_frame_address(0); |
---|
[d4dc7c8] | 81 | if ( !(message & RTEMS_BSP_SMP_SHUTDOWN) ) { |
---|
[2f6108f9] | 82 | printk( "ISR on CPU %d -- (0x%02x) (0x%p)\n", self, message, sp ); |
---|
[d4dc7c8] | 83 | if ( message & RTEMS_BSP_SMP_CONTEXT_SWITCH_NECESSARY ) |
---|
| 84 | printk( "context switch necessary\n" ); |
---|
| 85 | if ( message & RTEMS_BSP_SMP_SIGNAL_TO_SELF ) |
---|
| 86 | printk( "signal to self\n" ); |
---|
| 87 | if ( message & RTEMS_BSP_SMP_SHUTDOWN ) |
---|
| 88 | printk( "shutdown\n" ); |
---|
| 89 | } |
---|
| 90 | |
---|
| 91 | printk( "Dispatch level %d\n", _Thread_Dispatch_get_disable_level() ); |
---|
[06dcaf0] | 92 | } |
---|
| 93 | #endif |
---|
| 94 | |
---|
| 95 | if ( message & RTEMS_BSP_SMP_SHUTDOWN ) { |
---|
[2f6108f9] | 96 | _ISR_Disable_on_this_core( level ); |
---|
[d4dc7c8] | 97 | |
---|
[2f6108f9] | 98 | while ( _Thread_Dispatch_decrement_disable_level() != 0 ) { |
---|
| 99 | /* Release completely */ |
---|
| 100 | } |
---|
[dad36c52] | 101 | |
---|
[2f6108f9] | 102 | _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_SHUTDOWN ); |
---|
[3148438] | 103 | |
---|
| 104 | _CPU_Fatal_halt( self ); |
---|
[06dcaf0] | 105 | /* does not continue past here */ |
---|
| 106 | } |
---|
| 107 | } |
---|
| 108 | |
---|
[2f6108f9] | 109 | void _SMP_Send_message( int cpu, uint32_t message ) |
---|
[06dcaf0] | 110 | { |
---|
[2f6108f9] | 111 | Per_CPU_Control *per_cpu = &_Per_CPU_Information[ cpu ]; |
---|
[06dcaf0] | 112 | ISR_Level level; |
---|
| 113 | |
---|
[dad36c52] | 114 | #if defined(RTEMS_DEBUG) |
---|
| 115 | if ( message & RTEMS_BSP_SMP_SIGNAL_TO_SELF ) |
---|
| 116 | printk( "Send 0x%x to %d\n", message, cpu ); |
---|
| 117 | #endif |
---|
| 118 | |
---|
[a8ef3bf0] | 119 | _Per_CPU_Lock_acquire( per_cpu, level ); |
---|
[2f6108f9] | 120 | per_cpu->message |= message; |
---|
[a8ef3bf0] | 121 | _Per_CPU_Lock_release( per_cpu, level ); |
---|
[2f6108f9] | 122 | |
---|
[06dcaf0] | 123 | bsp_smp_interrupt_cpu( cpu ); |
---|
| 124 | } |
---|
| 125 | |
---|
[2f6108f9] | 126 | void _SMP_Broadcast_message( uint32_t message ) |
---|
[06dcaf0] | 127 | { |
---|
[2f6108f9] | 128 | int self = bsp_smp_processor_id(); |
---|
[edde99b] | 129 | int ncpus = _SMP_Get_processor_count(); |
---|
[2f6108f9] | 130 | int cpu; |
---|
| 131 | |
---|
| 132 | for ( cpu = 0 ; cpu < ncpus ; ++cpu ) { |
---|
| 133 | if ( cpu != self ) { |
---|
| 134 | Per_CPU_Control *per_cpu = &_Per_CPU_Information[ cpu ]; |
---|
[e358088] | 135 | ISR_Level level; |
---|
| 136 | |
---|
[a8ef3bf0] | 137 | _Per_CPU_Lock_acquire( per_cpu, level ); |
---|
[2f6108f9] | 138 | per_cpu->message |= message; |
---|
[a8ef3bf0] | 139 | _Per_CPU_Lock_release( per_cpu, level ); |
---|
[2f6108f9] | 140 | } |
---|
[06dcaf0] | 141 | } |
---|
[2f6108f9] | 142 | |
---|
[06dcaf0] | 143 | bsp_smp_broadcast_interrupt(); |
---|
| 144 | } |
---|
[d4dc7c8] | 145 | |
---|
[2f6108f9] | 146 | void _SMP_Request_other_cores_to_perform_first_context_switch( void ) |
---|
[d4dc7c8] | 147 | { |
---|
[2f6108f9] | 148 | int self = bsp_smp_processor_id(); |
---|
[edde99b] | 149 | int ncpus = _SMP_Get_processor_count(); |
---|
[2f6108f9] | 150 | int cpu; |
---|
[d4dc7c8] | 151 | |
---|
[2f6108f9] | 152 | for ( cpu = 0 ; cpu < ncpus ; ++cpu ) { |
---|
[7cf2ec6f] | 153 | Per_CPU_Control *per_cpu = &_Per_CPU_Information[ cpu ]; |
---|
| 154 | |
---|
[2f6108f9] | 155 | if ( cpu != self ) { |
---|
[7cf2ec6f] | 156 | _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_BEGIN_MULTITASKING ); |
---|
| 157 | } else { |
---|
| 158 | |
---|
| 159 | _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_UP ); |
---|
[2f6108f9] | 160 | } |
---|
[d4dc7c8] | 161 | } |
---|
| 162 | } |
---|
| 163 | |
---|
[2f6108f9] | 164 | void _SMP_Request_other_cores_to_dispatch( void ) |
---|
[d4dc7c8] | 165 | { |
---|
[2f6108f9] | 166 | if ( _System_state_Is_up( _System_state_Get() ) ) { |
---|
| 167 | int self = bsp_smp_processor_id(); |
---|
[edde99b] | 168 | int ncpus = _SMP_Get_processor_count(); |
---|
[2f6108f9] | 169 | int cpu; |
---|
| 170 | |
---|
| 171 | for ( cpu = 0 ; cpu < ncpus ; ++cpu ) { |
---|
| 172 | const Per_CPU_Control *per_cpu = &_Per_CPU_Information[ cpu ]; |
---|
| 173 | |
---|
| 174 | if ( |
---|
| 175 | cpu != self |
---|
| 176 | && per_cpu->state == PER_CPU_STATE_UP |
---|
| 177 | && per_cpu->dispatch_necessary |
---|
| 178 | ) { |
---|
| 179 | _SMP_Send_message( cpu, RTEMS_BSP_SMP_CONTEXT_SWITCH_NECESSARY ); |
---|
| 180 | } |
---|
| 181 | } |
---|
[d4dc7c8] | 182 | } |
---|
| 183 | } |
---|
| 184 | |
---|
[2f6108f9] | 185 | void _SMP_Request_other_cores_to_shutdown( void ) |
---|
[d4dc7c8] | 186 | { |
---|
[2f6108f9] | 187 | int self = bsp_smp_processor_id(); |
---|
[edde99b] | 188 | int ncpus = _SMP_Get_processor_count(); |
---|
[2f6108f9] | 189 | int cpu; |
---|
[d4dc7c8] | 190 | |
---|
| 191 | _SMP_Broadcast_message( RTEMS_BSP_SMP_SHUTDOWN ); |
---|
| 192 | |
---|
[2f6108f9] | 193 | for ( cpu = 0 ; cpu < ncpus ; ++cpu ) { |
---|
| 194 | if ( cpu != self ) { |
---|
| 195 | _Per_CPU_Wait_for_state( |
---|
| 196 | &_Per_CPU_Information[ cpu ], |
---|
| 197 | PER_CPU_STATE_SHUTDOWN |
---|
| 198 | ); |
---|
| 199 | } |
---|
[d4dc7c8] | 200 | } |
---|
| 201 | } |
---|