[PATCH 5/5] LEON3: use CPU_Fatal_halt for halt

Daniel Hellstrom daniel at gaisler.com
Fri Jul 4 08:49:59 UTC 2014


On 07/03/2014 05:00 PM, Joel Sherrill wrote:
> On 7/3/2014 2:29 AM, Daniel Hellstrom wrote:
>> By removing the bsp_reset() mechanism and instead relying on the
>> CPU_Fatal_halt() routine SMP and single-core can halt by updating
>> the _Internal_errors_What_happened structure and set the state to
>> SYSTEM_STATE_TERMINATED (the generic way). This will be better
>> for test scripts and debugger that can generically look into why
>> the OS stopped.
>>
>> For SMP systems, only the fatal-reporting CPU waits until all other
>> CPUs are powered down (with a time out of one clock tick). The
>> reason why a fatal stop happend may be because CPU0 was soft-locked
>> up so we can never trust that CPU0 should do the halt for us.
> And in the last patch, the reason for this series. :)

Please see previous responses, I hope that explains some of it at least :)

>
> Do we need a generic call to bsp_fatal_halt() before
> _CPU_Fatal_halt() in interr.c?

According to the calling convention the registers can be destroyed at function call, so the exit-code must be prepared in the last code executing.

> And move setting _Internal_errors_What_happened
> up to just after disable interrupts?
That is not possible as commented before, could be if we change more things, please see below.
>
> I am more comfortable adding a cross-architecture
> solution than hacking on _CPU_Fatal_halt() and
> introducing architecture specific differences. Sebastian
> did a nice job cleaning this path up. If there is a case
> missing, then we need to address it in a cross-BSP way.
Returning to a hypervisor with an exist code must be architecture and/or BSP specific in my mind. Relying on memory for exit-codes might prove complicated. We could try solving the SMP BSP fatal 
handling in a generic way in _Terminate(), to through all other CPUs in the a special BSP_fatal_halt_secondary() perhaps?

again, thanks for your comments!

>
> Hopefully Sebastian will pipe up soon.
>
>> ---
>>   c/src/lib/libbsp/sparc/leon3/Makefile.am        |    4 +-
>>   c/src/lib/libbsp/sparc/leon3/configure.ac       |    2 +-
>>   c/src/lib/libbsp/sparc/leon3/startup/bspclean.c |   84 +++++++++++++++++++++++
>>   c/src/lib/libbsp/sparc/leon3/startup/bspreset.c |   62 -----------------
>>   4 files changed, 87 insertions(+), 65 deletions(-)
>>   create mode 100644 c/src/lib/libbsp/sparc/leon3/startup/bspclean.c
>>   delete mode 100644 c/src/lib/libbsp/sparc/leon3/startup/bspreset.c
>>
>> diff --git a/c/src/lib/libbsp/sparc/leon3/Makefile.am b/c/src/lib/libbsp/sparc/leon3/Makefile.am
>> index d1f07a7..9e60046 100644
>> --- a/c/src/lib/libbsp/sparc/leon3/Makefile.am
>> +++ b/c/src/lib/libbsp/sparc/leon3/Makefile.am
>> @@ -32,14 +32,14 @@ noinst_LIBRARIES += libbsp.a
>>   libbsp_a_SOURCES =
>>   
>>   # startup
>> -libbsp_a_SOURCES += ../../shared/bspclean.c ../../shared/bsplibc.c \
>> +libbsp_a_SOURCES += startup/bspclean.c
>> +libbsp_a_SOURCES += ../../shared/bsplibc.c \
>>       ../../shared/bsppost.c ../../shared/bootcard.c startup/bspstart.c \
>>       ../../sparc/shared/bsppretaskinghook.c startup/bsppredriver.c \
>>       ../../sparc/shared/startup/bspgetworkarea.c ../../shared/sbrk.c \
>>       startup/setvec.c \
>>       startup/spurious.c startup/bspidle.S startup/bspdelay.c \
>>       ../../shared/bspinit.c ../../sparc/shared/startup/early_malloc.c
>> -libbsp_a_SOURCES += startup/bspreset.c
>>   libbsp_a_SOURCES += startup/cpucounter.c
>>   libbsp_a_SOURCES += ../../sparc/shared/startup/bsp_fatal_exit.c
>>   libbsp_a_SOURCES += startup/bsp_fatal_halt.c
>> diff --git a/c/src/lib/libbsp/sparc/leon3/configure.ac b/c/src/lib/libbsp/sparc/leon3/configure.ac
>> index 206a662..90e3b2b 100644
>> --- a/c/src/lib/libbsp/sparc/leon3/configure.ac
>> +++ b/c/src/lib/libbsp/sparc/leon3/configure.ac
>> @@ -43,7 +43,7 @@ RTEMS_BSPOPTS_HELP([BSP_HALT_AT_FATAL_EXIT],
>>   [If defined, CPU is powered down on fatal exit. Otherwise generate system
>>    error which will hand over to debugger, simulator, etc.])
>>   
>> -RTEMS_BSP_CLEANUP_OPTIONS(0, 1, 1)
>> +RTEMS_BSP_CLEANUP_OPTIONS(0, 0, 1)
>>   RTEMS_BSP_LINKCMDS
>>   
>>   # Explicitly list all Makefiles here
>> diff --git a/c/src/lib/libbsp/sparc/leon3/startup/bspclean.c b/c/src/lib/libbsp/sparc/leon3/startup/bspclean.c
>> new file mode 100644
>> index 0000000..3a036a0
>> --- /dev/null
>> +++ b/c/src/lib/libbsp/sparc/leon3/startup/bspclean.c
>> @@ -0,0 +1,84 @@
>> +/**
>> + * @file
>> + * @ingroup sparc_leon3
>> + * @brief LEON3 BSP fatal extension
>> + *
>> + *  Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
>> + *
>> + *  embedded brains GmbH
>> + *  Dornierstr. 4
>> + *  82178 Puchheim
>> + *  Germany
>> + *  <rtems at embedded-brains.de>
>> + *
>> + *  COPYRIGHT (c) 2014
>> + *  Aeroflex Gaisler
>> + *
>> + *  The license and distribution terms for this file may be
>> + *  found in the file LICENSE in this distribution or at
>> + *  http://www.rtems.org/license/LICENSE.
>> + */
>> +
>> +#include <bsp.h>
>> +#include <bsp/bootcard.h>
>> +#include <rtems/bspIo.h>
>> +#include <rtems/score/smpimpl.h>
>> +
>> +void bsp_fatal_extension(
>> +  rtems_fatal_source source,
>> +  bool is_internal,
>> +  rtems_fatal_code code
>> +)
>> +{
>> +  /* On SMP we must wait for all other CPUs not requesting a fatal halt, they
>> +   * are responding to another CPU's fatal request. These CPUs goes into
>> +   * power-down. The CPU requesting fatal halt waits for the others and then
>> +   * handles the system shutdown via the normal procedure.
>> +   */
>> +  #ifdef RTEMS_SMP
>> +  if ((source == RTEMS_FATAL_SOURCE_SMP) &&
>> +      (code == SMP_FATAL_SHUTDOWN_RESPONSE)) {
>> +    leon3_power_down_loop(); /* CPU didn't start shutdown sequence .. */
>> +  } else {
>> +    volatile struct irqmp_regs *irqmp = LEON3_IrqCtrl_Regs;
>> +
>> +    if (irqmp != NULL) {
>> +      /*
>> +       * Value was choosen to get something in the magnitude of 1ms on a 200MHz
>> +       * processor.
>> +       */
>> +      uint32_t max_wait = 1234567;
>> +      uint32_t self_cpu = rtems_get_current_processor();
>> +
>> +      uint32_t cpu_count = rtems_get_processor_count();
>> +      uint32_t halt_mask = 0;
>> +      uint32_t i;
>> +
>> +      for (i = 0; i < cpu_count; ++i) {
>> +        if (i != self_cpu) {
>> +          halt_mask |= UINT32_C(1) << i;
>> +        }
>> +      }
>> +
>> +      /* Wait some time for secondary processors to halt */
>> +      i = 0;
>> +      while ((irqmp->mpstat & halt_mask) != halt_mask && i < max_wait) {
>> +        ++i;
>> +      }
>> +    }
>> +  }
>> +  #endif
>> +
>> +  #if (BSP_PRINT_EXCEPTION_CONTEXT)
>> +    if ( source == RTEMS_FATAL_SOURCE_EXCEPTION ) {
>> +      rtems_exception_frame_print( (const rtems_exception_frame *) code );
>> +    }
>> +  #endif
>> +
>> +  /*
>> +   *  If user wants to implement custom reset/reboot it can be done here
>> +   */
>> +  #if (BSP_RESET_BOARD_AT_EXIT)
>> +    bsp_reset();
>> +  #endif
>> +}
>> diff --git a/c/src/lib/libbsp/sparc/leon3/startup/bspreset.c b/c/src/lib/libbsp/sparc/leon3/startup/bspreset.c
>> deleted file mode 100644
>> index c642a75..0000000
>> --- a/c/src/lib/libbsp/sparc/leon3/startup/bspreset.c
>> +++ /dev/null
>> @@ -1,62 +0,0 @@
>> -/*
>> - * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
>> - *
>> - *  embedded brains GmbH
>> - *  Dornierstr. 4
>> - *  82178 Puchheim
>> - *  Germany
>> - *  <rtems at embedded-brains.de>
>> - *
>> - * The license and distribution terms for this file may be
>> - * found in the file LICENSE in this distribution or at
>> - * http://www.rtems.org/license/LICENSE.
>> - */
>> -
>> -#include <bsp.h>
>> -#include <bsp/bootcard.h>
>> -#include <leon.h>
>> -
>> -#ifdef RTEMS_SMP
>> -
>> -void bsp_reset(void)
>> -{
>> -  uint32_t self_cpu = rtems_get_current_processor();
>> -
>> -  if (self_cpu == 0) {
>> -    volatile struct irqmp_regs *irqmp = LEON3_IrqCtrl_Regs;
>> -
>> -    if (irqmp != NULL) {
>> -      /*
>> -       * Value was choosen to get something in the magnitude of 1ms on a 200MHz
>> -       * processor.
>> -       */
>> -      uint32_t max_wait = 1234567;
>> -
>> -      uint32_t cpu_count = rtems_get_processor_count();
>> -      uint32_t halt_mask = 0;
>> -      uint32_t i;
>> -
>> -      for (i = 0; i < cpu_count; ++i) {
>> -        if (i != self_cpu) {
>> -          halt_mask |= UINT32_C(1) << i;
>> -        }
>> -      }
>> -
>> -      /* Wait some time for secondary processors to halt */
>> -      i = 0;
>> -      while ((irqmp->mpstat & halt_mask) != halt_mask && i < max_wait) {
>> -        ++i;
>> -      }
>> -    }
>> -
>> -    __asm__ volatile (
>> -      "mov 1, %g1\n"
>> -      "ta 0\n"
>> -      "nop"
>> -    );
>> -  }
>> -
>> -  leon3_power_down_loop();
>> -}
>> -
>> -#endif /* RTEMS_SMP */



More information about the devel mailing list