[PATCH 2/2] score: Add and use _CPU_SMP_Start_processor()

Sebastian Huber sebastian.huber at embedded-brains.de
Thu Apr 10 14:47:04 UTC 2014


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




More information about the devel mailing list