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

Daniel Hellstrom daniel at gaisler.com
Mon Oct 6 12:53:56 UTC 2014


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.
---
 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 |   87 +++++++++++++++++++++++
 c/src/lib/libbsp/sparc/leon3/startup/bspreset.c |   62 ----------------
 4 files changed, 90 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 fa297ac..c5c9b77 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 8ace8a3..c29dc52 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_POWER_DOWN_AT_FATAL_HALT],
 [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..0d7d855
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/leon3/startup/bspclean.c
@@ -0,0 +1,87 @@
+/**
+ * @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>
+#include <rtems/score/schedulerimpl.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) {
+        const Scheduler_Assignment *assignment = _Scheduler_Get_assignment( i );
+
+        if ( (i != self_cpu) &&
+            _Scheduler_Should_start_processor( assignment ) ) {
+          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 */
-- 
1.7.0.4



More information about the devel mailing list