Add and use _CPU_SMP_Finalize_initialization(). Move the processor start loop to the high-level _SMP_Handler_initialize() function. This can simplify the CPU port. The CPU port has the ability to signal a processor start failure. With the support for clustered/partitioned scheduling the presence of particular processors can be configured to be optional or mandatory. There will be a fatal error only in case mandatory processors are not present. --- c/src/lib/libbsp/arm/shared/arm-a9mpcore-smp.c | 18 +++++++++- c/src/lib/libbsp/i386/shared/smp/smp-imps.c | 28 +++++++-------- c/src/lib/libbsp/powerpc/qoriq/startup/smp.c | 20 ++++++++++- c/src/lib/libbsp/shared/smp/smp_stub.c | 11 +++++- c/src/lib/libbsp/sparc/leon3/smp/smp_leon3.c | 22 +++++++----- cpukit/score/cpu/arm/rtems/score/cpu.h | 6 +++- cpukit/score/cpu/i386/rtems/score/cpu.h | 6 +++- cpukit/score/cpu/no_cpu/rtems/score/cpu.h | 43 ++++++++++++++++++++---- cpukit/score/cpu/powerpc/rtems/score/cpu.h | 6 +++- cpukit/score/cpu/sparc/rtems/score/cpu.h | 6 +++- cpukit/score/include/rtems/score/smpimpl.h | 3 +- cpukit/score/src/smp.c | 23 ++++++++++++- 12 files changed, 151 insertions(+), 41 deletions(-)
diff --git a/c/src/lib/libbsp/arm/shared/arm-a9mpcore-smp.c b/c/src/lib/libbsp/arm/shared/arm-a9mpcore-smp.c index c9c9936..321e89e 100644 --- a/c/src/lib/libbsp/arm/shared/arm-a9mpcore-smp.c +++ b/c/src/lib/libbsp/arm/shared/arm-a9mpcore-smp.c @@ -25,7 +25,12 @@ static void bsp_inter_processor_interrupt(void *arg) _SMP_Inter_processor_interrupt_handler(); } -void _CPU_SMP_Initialize(uint32_t cpu_count) +void _CPU_SMP_Initialize(void) +{ + /* Nothing to do */ +} + +void _CPU_SMP_Finalize_initialization(uint32_t cpu_count) { if (cpu_count > 0) { rtems_status_code sc; @@ -41,6 +46,15 @@ void _CPU_SMP_Initialize(uint32_t cpu_count) } } +bool _CPU_SMP_Start_processor(uint32_t cpu_index) +{ + (void) cpu_index; + + /* Nothing to do */ + + return true; +} + uint32_t _CPU_SMP_Get_processor_count( void ) { return arm_gic_irq_processor_count(); @@ -48,7 +62,7 @@ uint32_t _CPU_SMP_Get_processor_count( void ) void _CPU_SMP_Send_interrupt( uint32_t target_processor_index ) { - rtems_status_code sc = arm_gic_irq_generate_software_irq( + arm_gic_irq_generate_software_irq( ARM_GIC_IRQ_SGI_0, ARM_GIC_IRQ_SOFTWARE_IRQ_TO_ALL_IN_LIST, (uint8_t) (1U << target_processor_index) diff --git a/c/src/lib/libbsp/i386/shared/smp/smp-imps.c b/c/src/lib/libbsp/i386/shared/smp/smp-imps.c index 2882953..296f0e7 100644 --- a/c/src/lib/libbsp/i386/shared/smp/smp-imps.c +++ b/c/src/lib/libbsp/i386/shared/smp/smp-imps.c @@ -684,8 +684,6 @@ imps_force(int ncpus) static int imps_probe(void) { - static bool probe_done; - /* * Determine possible address of the EBDA */ @@ -703,10 +701,6 @@ imps_probe(void) unsigned mem_lower = ((CMOS_READ_BYTE(CMOS_BASE_MEMORY+1) << 8) | CMOS_READ_BYTE(CMOS_BASE_MEMORY)) << 10; - if (probe_done) { - return imps_num_cpus; - } - #ifdef IMPS_DEBUG imps_enabled = 0; imps_num_cpus = 1; @@ -729,8 +723,6 @@ imps_probe(void) if (((ebda_addr && imps_scan(ebda_addr, 1024)) || (!ebda_addr && imps_scan(mem_lower - 1024, 1024)) || imps_scan(0xF0000, 0x10000)) && imps_enabled) { - probe_done = true; - return imps_num_cpus; } @@ -794,22 +786,28 @@ static void secondary_cpu_initialize(void) _SMP_Start_multitasking_on_secondary_processor(); } -void _CPU_SMP_Initialize( uint32_t cpu_count ) +void _CPU_SMP_Initialize( void ) { - int cores; /* XXX need to deal with finding too many cores */ - cores = imps_probe(); + imps_probe(); +} - if ( cores > 1 ) +void _CPU_SMP_Finalize_initialization( uint32_t cpu_count ) +{ + if ( cpu_count > 1 ) ipi_install_irq(); - return cores; } -uint32_t _CPU_SMP_Get_processor_count( void ) +bool _CPU_SMP_Start_processor( uint32_t cpu_index ) { - imps_probe(); + (void) cpu_index; + return true; +} + +uint32_t _CPU_SMP_Get_processor_count( void ) +{ return imps_num_cpus; } diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/smp.c b/c/src/lib/libbsp/powerpc/qoriq/startup/smp.c index 205e84d..ca01663 100644 --- a/c/src/lib/libbsp/powerpc/qoriq/startup/smp.c +++ b/c/src/lib/libbsp/powerpc/qoriq/startup/smp.c @@ -141,7 +141,12 @@ static void bsp_inter_processor_interrupt(void *arg) _SMP_Inter_processor_interrupt_handler(); } -void _CPU_SMP_Initialize(uint32_t cpu_count) +void _CPU_SMP_Initialize(void) +{ + /* Nothing to do */ +} + +void _CPU_SMP_Finalize_initialization(uint32_t cpu_count) { if (cpu_count > 1) { rtems_status_code sc; @@ -154,9 +159,22 @@ void _CPU_SMP_Initialize(uint32_t cpu_count) NULL ); assert(sc == RTEMS_SUCCESSFUL); + } +} +bool _CPU_SMP_Start_processor(uint32_t cpu_index) +{ + bool ok; + + if (cpu_index == 1) { release_core_1(); + + ok = true; + } else { + ok = false; } + + return ok; } uint32_t _CPU_SMP_Get_processor_count(void) diff --git a/c/src/lib/libbsp/shared/smp/smp_stub.c b/c/src/lib/libbsp/shared/smp/smp_stub.c index fa46076..c398ac9 100644 --- a/c/src/lib/libbsp/shared/smp/smp_stub.c +++ b/c/src/lib/libbsp/shared/smp/smp_stub.c @@ -11,10 +11,19 @@ #include <rtems/score/cpu.h> -void _CPU_SMP_Initialize( uint32_t cpu_count ) +void _CPU_SMP_Initialize( void ) { } +void _CPU_SMP_Finalize_initialization( uint32_t cpu_count ) +{ +} + +bool _CPU_SMP_Start_processor( uint32_t cpu_index ) +{ + return cpu_index == 1; +} + uint32_t _CPU_SMP_Get_processor_count( void ) { return 1; diff --git a/c/src/lib/libbsp/sparc/leon3/smp/smp_leon3.c b/c/src/lib/libbsp/sparc/leon3/smp/smp_leon3.c index bfc801a..e1c1715 100644 --- a/c/src/lib/libbsp/sparc/leon3/smp/smp_leon3.c +++ b/c/src/lib/libbsp/sparc/leon3/smp/smp_leon3.c @@ -35,24 +35,28 @@ void leon3_secondary_cpu_initialize(uint32_t cpu_index) _SMP_Start_multitasking_on_secondary_processor(); } -void _CPU_SMP_Initialize( uint32_t cpu_count ) +void _CPU_SMP_Initialize( void ) { - uint32_t cpu_index; - leon3_set_cache_control_register(0x80000F); +} +void _CPU_SMP_Finalize_initialization( uint32_t cpu_count ) +{ if ( cpu_count > 1 ) { LEON_Unmask_interrupt(LEON3_MP_IRQ); set_vector(bsp_inter_processor_interrupt, LEON_TRAP_TYPE(LEON3_MP_IRQ), 1); } +} - for ( cpu_index = 1 ; cpu_index < cpu_count ; ++cpu_index ) { - #if defined(RTEMS_DEBUG) - printk( "Waking CPU %d\n", cpu_index ); - #endif +bool _CPU_SMP_Start_processor( uint32_t cpu_index ) +{ + #if defined(RTEMS_DEBUG) + printk( "Waking CPU %d\n", cpu_index ); + #endif - LEON3_IrqCtrl_Regs->mpstat = 1U << cpu_index; - } + LEON3_IrqCtrl_Regs->mpstat = 1U << cpu_index; + + return true; } uint32_t _CPU_SMP_Get_processor_count( void ) diff --git a/cpukit/score/cpu/arm/rtems/score/cpu.h b/cpukit/score/cpu/arm/rtems/score/cpu.h index acf82c6..b770599 100644 --- a/cpukit/score/cpu/arm/rtems/score/cpu.h +++ b/cpukit/score/cpu/arm/rtems/score/cpu.h @@ -467,7 +467,11 @@ void _CPU_Context_volatile_clobber( uintptr_t pattern ); void _CPU_Context_validate( uintptr_t pattern ); #ifdef RTEMS_SMP - void _CPU_SMP_Initialize( uint32_t cpu_count ); + void _CPU_SMP_Initialize( void ); + + void _CPU_SMP_Finalize_initialization( uint32_t cpu_count ); + + bool _CPU_SMP_Start_processor( uint32_t cpu_index ); uint32_t _CPU_SMP_Get_processor_count( void ); diff --git a/cpukit/score/cpu/i386/rtems/score/cpu.h b/cpukit/score/cpu/i386/rtems/score/cpu.h index 92afa59..b831038 100644 --- a/cpukit/score/cpu/i386/rtems/score/cpu.h +++ b/cpukit/score/cpu/i386/rtems/score/cpu.h @@ -462,7 +462,11 @@ uint32_t _CPU_ISR_Get_level( void ); _CPU_Context_restore( (_the_context) ); #if defined(RTEMS_SMP) - void _CPU_SMP_Initialize( uint32_t cpu_count ); + void _CPU_SMP_Initialize( void ); + + void _CPU_SMP_Finalize_initialization( uint32_t cpu_count ); + + bool _CPU_SMP_Start_processor( uint32_t cpu_index ); uint32_t _CPU_SMP_Get_processor_count( void ); diff --git a/cpukit/score/cpu/no_cpu/rtems/score/cpu.h b/cpukit/score/cpu/no_cpu/rtems/score/cpu.h index 7d43185..393d5ed 100644 --- a/cpukit/score/cpu/no_cpu/rtems/score/cpu.h +++ b/cpukit/score/cpu/no_cpu/rtems/score/cpu.h @@ -1467,24 +1467,53 @@ CPU_Counter_ticks _CPU_Counter_difference( * @brief Performs CPU specific SMP initialization in the context of the boot * processor. * - * This function is invoked on the boot processor by RTEMS during + * This function is invoked on the boot processor during system * initialization. All interrupt stacks are allocated at this point in case - * the CPU port allocates the interrupt stacks. + * the CPU port allocates the interrupt stacks. This function is called + * before _CPU_SMP_Get_processor_count() or _CPU_SMP_Start_processor() is + * used. + */ + void _CPU_SMP_Initialize( void ); + + /** + * @brief Performs final steps of CPU specific SMP initialization in the + * context of the boot processor. * - * The CPU port should start secondary processors now. + * This function is invoked on the boot processor during system + * initialization. + * + * This function will be called after all processors requested by the + * application have been started. * * @param[in] cpu_count The minimum value of the count of processors * requested by the application configuration and the count of physically or * virtually available processors. */ - void _CPU_SMP_Initialize( uint32_t cpu_count ); + void _CPU_SMP_Finalize_initialization( uint32_t cpu_count ); + + /** + * @brief Starts a processor specified by its index. + * + * This function is invoked on the boot processor during system + * initialization. + * + * This function will be called after _CPU_SMP_Initialize(). + * + * @param[in] cpu_index The processor index. + * + * @retval true Successful operation. + * @retval false Unable to start this processor. + */ + bool _CPU_SMP_Start_processor( uint32_t cpu_index ); /** * @brief Returns the count of physically or virtually available processors. * - * This function is used during system initialization and is not performance - * critical. Depending on the configuration the application may use less - * processors. + * This function is invoked on the boot processor during system + * initialization. Depending on the configuration the application may use + * less processors. + * + * This function will be called after _CPU_SMP_Initialize(). * * @return The count of physically or virtually available processors. */ diff --git a/cpukit/score/cpu/powerpc/rtems/score/cpu.h b/cpukit/score/cpu/powerpc/rtems/score/cpu.h index ffc5c18..35e3c36 100644 --- a/cpukit/score/cpu/powerpc/rtems/score/cpu.h +++ b/cpukit/score/cpu/powerpc/rtems/score/cpu.h @@ -1034,7 +1034,11 @@ void _CPU_Context_volatile_clobber( uintptr_t pattern ); void _CPU_Context_validate( uintptr_t pattern ); #ifdef RTEMS_SMP - void _CPU_SMP_Initialize( uint32_t cpu_count ); + void _CPU_SMP_Initialize( void ); + + void _CPU_SMP_Finalize_initialization( uint32_t cpu_count ); + + bool _CPU_SMP_Start_processor( uint32_t cpu_index ); uint32_t _CPU_SMP_Get_processor_count( void ); diff --git a/cpukit/score/cpu/sparc/rtems/score/cpu.h b/cpukit/score/cpu/sparc/rtems/score/cpu.h index cbc9cf9..cfb6132 100644 --- a/cpukit/score/cpu/sparc/rtems/score/cpu.h +++ b/cpukit/score/cpu/sparc/rtems/score/cpu.h @@ -1161,7 +1161,11 @@ void _CPU_Context_restore( ) RTEMS_COMPILER_NO_RETURN_ATTRIBUTE; #if defined(RTEMS_SMP) - void _CPU_SMP_Initialize( uint32_t cpu_count ); + void _CPU_SMP_Initialize( void ); + + void _CPU_SMP_Finalize_initialization( uint32_t cpu_count ); + + bool _CPU_SMP_Start_processor( uint32_t cpu_index ); uint32_t _CPU_SMP_Get_processor_count( void ); diff --git a/cpukit/score/include/rtems/score/smpimpl.h b/cpukit/score/include/rtems/score/smpimpl.h index c32d4a2..962c7f2 100644 --- a/cpukit/score/include/rtems/score/smpimpl.h +++ b/cpukit/score/include/rtems/score/smpimpl.h @@ -48,7 +48,8 @@ extern "C" { */ typedef enum { SMP_FATAL_SHUTDOWN, - SMP_FATAL_SHUTDOWN_EARLY + SMP_FATAL_SHUTDOWN_EARLY, + SMP_FATAL_UNABLE_TO_START_PROCESSOR } SMP_Fatal_code; /** diff --git a/cpukit/score/src/smp.c b/cpukit/score/src/smp.c index d635a19..107b121 100644 --- a/cpukit/score/src/smp.c +++ b/cpukit/score/src/smp.c @@ -27,6 +27,7 @@ void _SMP_Handler_initialize( void ) { uint32_t cpu_max = rtems_configuration_get_maximum_processors(); + uint32_t cpu_self; uint32_t cpu_count; uint32_t cpu_index; @@ -39,10 +40,30 @@ void _SMP_Handler_initialize( void ) /* * Discover and initialize the secondary cores in an SMP system. */ + + _CPU_SMP_Initialize(); + cpu_count = _CPU_SMP_Get_processor_count(); cpu_count = cpu_count < cpu_max ? cpu_count : cpu_max; _SMP_Processor_count = cpu_count; - _CPU_SMP_Initialize( cpu_count ); + + cpu_self = _SMP_Get_current_processor(); + + for ( cpu_index = 0 ; cpu_index < cpu_count; ++cpu_index ) { + if ( cpu_index != cpu_self ) { + bool ok = _CPU_SMP_Start_processor( cpu_index ); + + if ( !ok ) { + _Terminate( + RTEMS_FATAL_SOURCE_SMP, + false, + SMP_FATAL_UNABLE_TO_START_PROCESSOR + ); + } + } + } + + _CPU_SMP_Finalize_initialization( cpu_count ); } void _SMP_Request_start_multitasking( void ) -- 1.7.7 _______________________________________________ rtems-devel mailing list rtems-devel@rtems.org http://www.rtems.org/mailman/listinfo/rtems-devel