From 3773a63b2ac208b9e1d4ae743ceedd8e679cd156 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 30 Jul 2021 11:09:10 +0200 Subject: bsp/leon3: Simplify fatal error handling --- bsps/sparc/leon3/include/bsp/leon3.h | 12 +++++ bsps/sparc/leon3/start/bspclean.c | 89 +++++++++++++++++++++++++----------- bsps/sparc/leon3/start/bspsmp.c | 16 ++----- 3 files changed, 77 insertions(+), 40 deletions(-) diff --git a/bsps/sparc/leon3/include/bsp/leon3.h b/bsps/sparc/leon3/include/bsp/leon3.h index 1394dd1c1c..476ed73647 100644 --- a/bsps/sparc/leon3/include/bsp/leon3.h +++ b/bsps/sparc/leon3/include/bsp/leon3.h @@ -161,6 +161,18 @@ static inline uint32_t leon3_get_data_cache_config_register( void ) return leon3_get_system_register( 0xc ); } +/** + * @brief Gets the processor count. + * + * @param[in] regs is the IRQ(A)MP register block address. + * + * @return Returns the processor count. + */ +static inline uint32_t leon3_get_cpu_count( const irqamp *regs ) +{ + return IRQAMP_MPSTAT_NCPU_GET( grlib_load_32( ®s->mpstat ) ) + 1; +} + /** * @brief This constant defines the index of the GPTIMER timer used by the * clock driver. diff --git a/bsps/sparc/leon3/start/bspclean.c b/bsps/sparc/leon3/start/bspclean.c index acb2d6093c..4c9b385b43 100644 --- a/bsps/sparc/leon3/start/bspclean.c +++ b/bsps/sparc/leon3/start/bspclean.c @@ -35,14 +35,62 @@ #include #include #include +#include #include +#if defined(RTEMS_SMP) +static void leon3_wait_for_power_down(irqamp *regs) +{ + uint32_t max_wait; + uint32_t cpu_self; + uint32_t cpu_count; + uint32_t halt_mask; + uint32_t i; + + cpu_count = leon3_get_cpu_count(regs); + + if (cpu_count > rtems_configuration_get_maximum_processors()) { + cpu_count = rtems_configuration_get_maximum_processors(); + } + + cpu_self = rtems_scheduler_get_processor(); + halt_mask = 0; + + for (i = 0; i < cpu_count; ++i) { + if (i != cpu_self && _SMP_Should_start_processor(i)) { + halt_mask |= UINT32_C(1) << i; + } + } + + /* + * Wait some time for secondary processors to halt. + * + * The value was chosen to get something in the magnitude of 1ms on a 200MHz + * processor. + */ + + max_wait = 1234567; + i = 0; + + while ( + (grlib_load_32(®s->mpstat) & halt_mask) != halt_mask && i < max_wait + ) { + ++i; + } +} +#endif + void bsp_fatal_extension( rtems_fatal_source source, bool always_set_to_false, rtems_fatal_code code ) { + rtems_interrupt_level level; + + rtems_interrupt_local_disable(level); + (void) level; + #if defined(RTEMS_SMP) /* * On SMP we must wait for all other CPUs not requesting a fatal halt, they @@ -54,34 +102,18 @@ void bsp_fatal_extension( (code == SMP_FATAL_SHUTDOWN_RESPONSE)) { leon3_power_down_loop(); /* CPU didn't start shutdown sequence .. */ } else { - irqamp *regs = LEON3_IrqCtrl_Regs; + irqamp *regs; + + _SMP_Request_shutdown(); + regs = LEON3_IrqCtrl_Regs; +#if defined(LEON3_IRQAMP_BASE) + leon3_wait_for_power_down(regs); +#else if (regs != NULL) { - /* - * Value was chosen to get something in the magnitude of 1ms on a 200MHz - * processor. - */ - uint32_t max_wait = 1234567; - uint32_t self_cpu = rtems_scheduler_get_processor(); - uint32_t cpu_count = rtems_scheduler_get_processor_maximum(); - uint32_t halt_mask = 0; - uint32_t i; - - for (i = 0; i < cpu_count; ++i) { - if ( (i != self_cpu) && _SMP_Should_start_processor( i ) ) { - halt_mask |= UINT32_C(1) << i; - } - } - - /* Wait some time for secondary processors to halt */ - i = 0; - while ( - (grlib_load_32(®s->mpstat) & halt_mask) != halt_mask && - i < max_wait - ) { - ++i; - } + leon3_wait_for_power_down(regs); } +#endif } #endif @@ -92,7 +124,10 @@ void bsp_fatal_extension( #endif #if BSP_RESET_BOARD_AT_EXIT - /* If user wants to implement custom reset/reboot it can be done here */ - bsp_reset(); + /* + * Stop the system termination right now. This skips the dynamically + * installed fatal error extensions and the generics shutdown procedure. + */ + _CPU_Fatal_halt( source, code ); #endif } diff --git a/bsps/sparc/leon3/start/bspsmp.c b/bsps/sparc/leon3/start/bspsmp.c index 7f8496289a..dc4065450a 100644 --- a/bsps/sparc/leon3/start/bspsmp.c +++ b/bsps/sparc/leon3/start/bspsmp.c @@ -39,14 +39,9 @@ static void bsp_inter_processor_interrupt( void *arg ) void bsp_start_on_secondary_processor(Per_CPU_Control *cpu_self) { - /* - * If data cache snooping is not enabled we terminate using BSP_fatal_exit() - * instead of bsp_fatal(). This is done since the latter function tries to - * acquire a ticket lock, an operation which requires data cache snooping to - * be enabled. - */ - if ( !leon3_data_cache_snooping_enabled() ) - BSP_fatal_exit( LEON3_FATAL_INVALID_CACHE_CONFIG_SECONDARY_PROCESSOR ); + if ( !leon3_data_cache_snooping_enabled() ) { + bsp_fatal( LEON3_FATAL_INVALID_CACHE_CONFIG_SECONDARY_PROCESSOR ); + } _SMP_Start_multitasking_on_secondary_processor(cpu_self); } @@ -75,11 +70,6 @@ static void leon3_install_inter_processor_interrupt( void ) _Assert_Unused_variable_equals( sc, RTEMS_SUCCESSFUL ); } -static uint32_t leon3_get_cpu_count( const irqamp *regs ) -{ - return IRQAMP_MPSTAT_NCPU_GET( grlib_load_32( ®s->mpstat ) ) + 1; -} - uint32_t _CPU_SMP_Initialize( void ) { if ( !leon3_data_cache_snooping_enabled() ) -- cgit v1.2.3