From 53e008b6fda8ccd1cdcf0f000bbccf1d3788206b Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 10 Apr 2014 15:48:05 +0200 Subject: score: SMP initialization changes Add and use _CPU_SMP_Start_processor(). Add and use _CPU_SMP_Finalize_initialization(). This makes most _CPU_SMP_Initialize() functions a bit simpler since we can calculate the minimum value of the count of processors requested by the application configuration and the count of physically or virtually available processors in the high-level code. The CPU port has now 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. The CPU port may use a timeout to monitor the start of a processor. --- c/src/lib/libbsp/arm/shared/arm-a9mpcore-smp.c | 41 +++++++++++++-------- c/src/lib/libbsp/i386/shared/smp/smp-imps.c | 18 +++++++--- c/src/lib/libbsp/powerpc/qoriq/startup/smp.c | 42 +++++++++++++--------- c/src/lib/libbsp/shared/smp/smp_stub.c | 11 +++++- c/src/lib/libbsp/sparc/leon3/smp/smp_leon3.c | 50 +++++++++++--------------- 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 | 44 ++++++++++++++++++----- 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 | 33 +++++++++++++---- 12 files changed, 179 insertions(+), 87 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 17d6498804..6f4af46343 100644 --- a/c/src/lib/libbsp/arm/shared/arm-a9mpcore-smp.c +++ b/c/src/lib/libbsp/arm/shared/arm-a9mpcore-smp.c @@ -25,28 +25,39 @@ static void bsp_inter_processor_interrupt(void *arg) _SMP_Inter_processor_interrupt_handler(); } -uint32_t _CPU_SMP_Initialize(uint32_t configured_cpu_count) +uint32_t _CPU_SMP_Initialize(void) { - rtems_status_code sc; - uint32_t max_cpu_count = arm_gic_irq_processor_count(); - uint32_t used_cpu_count = configured_cpu_count < max_cpu_count ? - configured_cpu_count : max_cpu_count; + return arm_gic_irq_processor_count(); +} - sc = rtems_interrupt_handler_install( - ARM_GIC_IRQ_SGI_0, - "IPI", - RTEMS_INTERRUPT_UNIQUE, - bsp_inter_processor_interrupt, - NULL - ); - assert(sc == RTEMS_SUCCESSFUL); +bool _CPU_SMP_Start_processor(uint32_t cpu_index) +{ + (void) cpu_index; + + /* Nothing to do */ + + return true; +} + +void _CPU_SMP_Finalize_initialization(uint32_t cpu_count) +{ + if (cpu_count > 0) { + rtems_status_code sc; - return used_cpu_count; + sc = rtems_interrupt_handler_install( + ARM_GIC_IRQ_SGI_0, + "IPI", + RTEMS_INTERRUPT_UNIQUE, + bsp_inter_processor_interrupt, + NULL + ); + assert(sc == RTEMS_SUCCESSFUL); + } } 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 1e5faeb644..19b23e2631 100644 --- a/c/src/lib/libbsp/i386/shared/smp/smp-imps.c +++ b/c/src/lib/libbsp/i386/shared/smp/smp-imps.c @@ -786,16 +786,24 @@ static void secondary_cpu_initialize(void) _SMP_Start_multitasking_on_secondary_processor(); } -uint32_t _CPU_SMP_Initialize( uint32_t configured_cpu_count ) +uint32_t _CPU_SMP_Initialize( void ) { - int cores; /* XXX need to deal with finding too many cores */ - cores = imps_probe(); + return (uint32_t) imps_probe(); +} + +bool _CPU_SMP_Start_processor( uint32_t cpu_index ) +{ + (void) cpu_index; - if ( cores > 1 ) + return true; +} + +void _CPU_SMP_Finalize_initialization( uint32_t cpu_count ) +{ + if ( cpu_count > 1 ) ipi_install_irq(); - return cores; } void _CPU_SMP_Send_interrupt( uint32_t target_processor_index ) diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/smp.c b/c/src/lib/libbsp/powerpc/qoriq/startup/smp.c index 2ce0ba75ad..5b4c12a2db 100644 --- a/c/src/lib/libbsp/powerpc/qoriq/startup/smp.c +++ b/c/src/lib/libbsp/powerpc/qoriq/startup/smp.c @@ -141,26 +141,34 @@ static void bsp_inter_processor_interrupt(void *arg) _SMP_Inter_processor_interrupt_handler(); } -uint32_t _CPU_SMP_Initialize(uint32_t configured_cpu_count) +uint32_t _CPU_SMP_Initialize(void) { - rtems_status_code sc; - uint32_t cores = configured_cpu_count < CORE_COUNT ? - configured_cpu_count : CORE_COUNT; - - sc = rtems_interrupt_handler_install( - QORIQ_IRQ_IPI_0, - "IPI", - RTEMS_INTERRUPT_UNIQUE, - bsp_inter_processor_interrupt, - NULL - ); - assert(sc == RTEMS_SUCCESSFUL); + return CORE_COUNT; +} - if (cores > 1) { - release_core_1(); - } +bool _CPU_SMP_Start_processor(uint32_t cpu_index) +{ + (void) cpu_index; + + release_core_1(); - return cores; + return true; +} + +void _CPU_SMP_Finalize_initialization(uint32_t cpu_count) +{ + if (cpu_count > 1) { + rtems_status_code sc; + + sc = rtems_interrupt_handler_install( + QORIQ_IRQ_IPI_0, + "IPI", + RTEMS_INTERRUPT_UNIQUE, + bsp_inter_processor_interrupt, + NULL + ); + assert(sc == RTEMS_SUCCESSFUL); + } } void _CPU_SMP_Send_interrupt(uint32_t target_processor_index) diff --git a/c/src/lib/libbsp/shared/smp/smp_stub.c b/c/src/lib/libbsp/shared/smp/smp_stub.c index 8165363d3b..3dc44b1d3a 100644 --- a/c/src/lib/libbsp/shared/smp/smp_stub.c +++ b/c/src/lib/libbsp/shared/smp/smp_stub.c @@ -11,12 +11,21 @@ #include -uint32_t _CPU_SMP_Initialize( uint32_t configured_cpu_count ) +uint32_t _CPU_SMP_Initialize( void ) { /* return the number of CPUs */ return 1; } +bool _CPU_SMP_Start_processor( uint32_t cpu_index ) +{ + return true; +} + +void _CPU_SMP_Finalize_initialization( uint32_t cpu_count ) +{ +} + void _CPU_SMP_Send_interrupt( uint32_t target_processor_index ) { } 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 2470e76fce..6681525861 100644 --- a/c/src/lib/libbsp/sparc/leon3/smp/smp_leon3.c +++ b/c/src/lib/libbsp/sparc/leon3/smp/smp_leon3.c @@ -26,53 +26,43 @@ static rtems_isr bsp_inter_processor_interrupt( _SMP_Inter_processor_interrupt_handler(); } -void leon3_secondary_cpu_initialize(uint32_t cpu) +void leon3_secondary_cpu_initialize(uint32_t cpu_index) { leon3_set_cache_control_register(0x80000F); /* Unmask IPI interrupts at Interrupt controller for this CPU */ - LEON3_IrqCtrl_Regs->mask[cpu] |= 1 << LEON3_MP_IRQ; + LEON3_IrqCtrl_Regs->mask[cpu_index] |= 1U << LEON3_MP_IRQ; _SMP_Start_multitasking_on_secondary_processor(); } -uint32_t _CPU_SMP_Initialize( uint32_t configured_cpu_count ) +uint32_t _CPU_SMP_Initialize( void ) { - uint32_t max_cpu_count; - uint32_t used_cpu_count; - uint32_t cpu; - leon3_set_cache_control_register(0x80000F); - max_cpu_count = leon3_get_cpu_count(LEON3_IrqCtrl_Regs); - used_cpu_count = configured_cpu_count < max_cpu_count ? - configured_cpu_count : max_cpu_count; + if ( rtems_configuration_get_maximum_processors() > 1 ) { + LEON_Unmask_interrupt(LEON3_MP_IRQ); + set_vector(bsp_inter_processor_interrupt, LEON_TRAP_TYPE(LEON3_MP_IRQ), 1); + } - #if defined(RTEMS_DEBUG) - printk( "Found %d CPUs\n", max_cpu_count ); + return leon3_get_cpu_count(LEON3_IrqCtrl_Regs); +} - if ( max_cpu_count > configured_cpu_count ) { - printk( - "%d CPUs IS MORE THAN CONFIGURED -- ONLY USING %d\n", - max_cpu_count, - configured_cpu_count - ); - } +bool _CPU_SMP_Start_processor( uint32_t cpu_index ) +{ + #if defined(RTEMS_DEBUG) + printk( "Waking CPU %d\n", cpu_index ); #endif - if ( used_cpu_count > 1 ) { - LEON_Unmask_interrupt(LEON3_MP_IRQ); - set_vector(bsp_inter_processor_interrupt, LEON_TRAP_TYPE(LEON3_MP_IRQ), 1); - } + LEON3_IrqCtrl_Regs->mpstat = 1U << cpu_index; - for ( cpu = 1 ; cpu < used_cpu_count ; ++cpu ) { - #if defined(RTEMS_DEBUG) - printk( "Waking CPU %d\n", cpu ); - #endif + return true; +} - LEON3_IrqCtrl_Regs->mpstat = 1 << cpu; - } +void _CPU_SMP_Finalize_initialization( uint32_t cpu_count ) +{ + (void) cpu_count; - return used_cpu_count; + /* Nothing to do */ } void _CPU_SMP_Send_interrupt(uint32_t target_processor_index) diff --git a/cpukit/score/cpu/arm/rtems/score/cpu.h b/cpukit/score/cpu/arm/rtems/score/cpu.h index dc2bbddcaf..ccf8c9a834 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 - uint32_t _CPU_SMP_Initialize( uint32_t configured_cpu_count ); + uint32_t _CPU_SMP_Initialize( void ); + + bool _CPU_SMP_Start_processor( uint32_t cpu_index ); + + void _CPU_SMP_Finalize_initialization( uint32_t cpu_count ); static inline uint32_t _CPU_SMP_Get_current_processor( void ) { diff --git a/cpukit/score/cpu/i386/rtems/score/cpu.h b/cpukit/score/cpu/i386/rtems/score/cpu.h index 296ad8ba47..be22d9e217 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) - uint32_t _CPU_SMP_Initialize( uint32_t configured_cpu_count ); + uint32_t _CPU_SMP_Initialize( void ); + + bool _CPU_SMP_Start_processor( uint32_t cpu_index ); + + void _CPU_SMP_Finalize_initialization( uint32_t cpu_count ); uint32_t _CPU_SMP_Get_current_processor( void ); diff --git a/cpukit/score/cpu/no_cpu/rtems/score/cpu.h b/cpukit/score/cpu/no_cpu/rtems/score/cpu.h index c864164667..5241b5ba5d 100644 --- a/cpukit/score/cpu/no_cpu/rtems/score/cpu.h +++ b/cpukit/score/cpu/no_cpu/rtems/score/cpu.h @@ -1467,19 +1467,47 @@ 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_Start_processor() or _CPU_SMP_Finalize_initialization() is + * used. * - * The CPU port should start secondary processors now. + * @return The count of physically or virtually available processors. + * Depending on the configuration the application may use not all processors. + */ + uint32_t _CPU_SMP_Initialize( void ); + + /** + * @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 Performs final steps of CPU specific SMP initialization in the + * context of the boot processor. + * + * This function is invoked on the boot processor during system + * initialization. * - * @param[in] configured_cpu_count The count of processors requested by the - * application configuration. + * This function will be called after all processors requested by the + * application have been started. * - * @return The count of processors available for the application in the system. - * This value is less than or equal to the configured count of processors. + * @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. */ - uint32_t _CPU_SMP_Initialize( uint32_t configured_cpu_count ); + void _CPU_SMP_Finalize_initialization( uint32_t cpu_count ); /** * @brief Returns the index of the current processor. diff --git a/cpukit/score/cpu/powerpc/rtems/score/cpu.h b/cpukit/score/cpu/powerpc/rtems/score/cpu.h index a7cad2e402..3130b3535e 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 - uint32_t _CPU_SMP_Initialize( uint32_t configured_cpu_count ); + uint32_t _CPU_SMP_Initialize( void ); + + bool _CPU_SMP_Start_processor( uint32_t cpu_index ); + + void _CPU_SMP_Finalize_initialization( uint32_t cpu_count ); static inline uint32_t _CPU_SMP_Get_current_processor( void ) { diff --git a/cpukit/score/cpu/sparc/rtems/score/cpu.h b/cpukit/score/cpu/sparc/rtems/score/cpu.h index e43b3bee5e..1b5dbcae73 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) - uint32_t _CPU_SMP_Initialize( uint32_t configured_cpu_count ); + uint32_t _CPU_SMP_Initialize( void ); + + bool _CPU_SMP_Start_processor( uint32_t cpu_index ); + + void _CPU_SMP_Finalize_initialization( uint32_t cpu_count ); #if defined(__leon__) static inline uint32_t _CPU_SMP_Get_current_processor( void ) diff --git a/cpukit/score/include/rtems/score/smpimpl.h b/cpukit/score/include/rtems/score/smpimpl.h index c32d4a2001..3e808600d3 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_START_OF_MANDATORY_PROCESSOR_FAILED } SMP_Fatal_code; /** diff --git a/cpukit/score/src/smp.c b/cpukit/score/src/smp.c index bfb09dd783..08677d83c7 100644 --- a/cpukit/score/src/smp.c +++ b/cpukit/score/src/smp.c @@ -26,11 +26,13 @@ void _SMP_Handler_initialize( void ) { - uint32_t max_cpus = rtems_configuration_get_maximum_processors(); - uint32_t cpu; + uint32_t cpu_max = rtems_configuration_get_maximum_processors(); + uint32_t cpu_self; + uint32_t cpu_count; + uint32_t cpu_index; - for ( cpu = 0 ; cpu < max_cpus; ++cpu ) { - Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu ); + for ( cpu_index = 0 ; cpu_index < cpu_max; ++cpu_index ) { + Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu_index ); _SMP_ticket_lock_Initialize( &per_cpu->Lock, "per-CPU" ); } @@ -38,9 +40,28 @@ void _SMP_Handler_initialize( void ) /* * Discover and initialize the secondary cores in an SMP system. */ - max_cpus = _CPU_SMP_Initialize( max_cpus ); - _SMP_Processor_count = max_cpus; + cpu_count = _CPU_SMP_Initialize(); + cpu_count = cpu_count < cpu_max ? cpu_count : cpu_max; + _SMP_Processor_count = 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_START_OF_MANDATORY_PROCESSOR_FAILED + ); + } + } + } + + _CPU_SMP_Finalize_initialization( cpu_count ); } void _SMP_Request_start_multitasking( void ) -- cgit v1.2.3