[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