[PATCH v1 2/5] cpukit: Add Exception Manager

Kinsey Moore kinsey.moore at oarcorp.com
Mon Aug 23 23:50:42 UTC 2021


This adds the framework necessary to allow more generic handling of
machine exceptions. This initial patch offers the ability to get the
class of exception from the CPU_Exception_frame provided. Future
extensions of the Exception Manager could include the ability to get
the address of the exception if applicable or to resume execution at
the next instruction or an arbitrary location.
---
 cpukit/include/rtems/exception.h          | 159 ++++++++++++++++++++++
 cpukit/include/rtems/score/userext.h      |  18 +++
 cpukit/include/rtems/score/userextimpl.h  |  41 ++++++
 cpukit/score/src/userextiterate.c         |  18 ++-
 spec/build/cpukit/cpuopts.yml             |   2 +
 spec/build/cpukit/librtemscpu.yml         |   1 +
 spec/build/cpukit/optexceptionmanager.yml |  17 +++
 7 files changed, 255 insertions(+), 1 deletion(-)
 create mode 100644 cpukit/include/rtems/exception.h
 create mode 100644 spec/build/cpukit/optexceptionmanager.yml

diff --git a/cpukit/include/rtems/exception.h b/cpukit/include/rtems/exception.h
new file mode 100644
index 0000000000..dea1712409
--- /dev/null
+++ b/cpukit/include/rtems/exception.h
@@ -0,0 +1,159 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @brief This header file defines the Exception Manager API.
+ */
+
+/*
+ * Copyright (C) 2021 On-Line Applications Research Corporation (OAR)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file is part of the RTEMS quality process and was automatically
+ * generated.  If you find something that needs to be fixed or
+ * worded better please post a report or patch to an RTEMS mailing list
+ * or raise a bug report:
+ *
+ * https://www.rtems.org/bugs.html
+ *
+ * For information on updating and regenerating please refer to the How-To
+ * section in the Software Requirements Engineering chapter of the
+ * RTEMS Software Engineering manual.  The manual is provided as a part of
+ * a release.  For development sources please refer to the online
+ * documentation at:
+ *
+ * https://docs.rtems.org
+ */
+
+/* Generated from spec:/rtems/fatal/if/header */
+
+#ifndef _RTEMS_EXCEPTION_H
+#define _RTEMS_EXCEPTION_H
+
+#include <rtems/fatal.h>
+#include <rtems/score/userextimpl.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Generated from spec:/rtems/fatal/if/group */
+
+/**
+ * @defgroup RTEMSAPIClassicException Exception Manager
+ *
+ * @ingroup RTEMSAPIClassic
+ *
+ * @brief The Exception Manager processes all machine exceptions and passes
+ *   any unhandled exceptions to the Fatal Error Manager.
+ */
+
+/**
+ * @ingroup RTEMSAPIClassicException
+ *
+ * @brief Invokes the fatal error handler.
+ *
+ * @param exception_frame is the CPU_Exception_frame describing the exception.
+ *
+ * @return Returns whether the exception was handled with finality.
+ *
+ * This directive processes non-irq exceptions.
+ *
+ * @par Constraints
+ * @parblock
+ * The following constraints apply to this directive:
+ *
+ * * The directive must only be called from the CPU exception context.
+ *
+ * * The directive invokes the Exception Manager extensions in extension
+ *   forward order.
+ *
+ * * The directive invokes the Fatal Error Manager if no exception handlers
+ *
+ * * The directive must only be called with interrupts disabled.
+ *   handle the exception.
+ * @endparblock
+ */
+static inline bool rtems_exception_manage(
+  rtems_exception_frame *exception_frame
+)
+{
+  return _User_extensions_Exception( exception_frame );
+}
+
+/**
+ *  The following lists the generic exception classes supported by the Exception
+ *  Management API.
+ */
+typedef enum {
+  EXCEPTION_UNKNOWN,
+  EXCEPTION_FPU,
+  EXCEPTION_TAGGED_OVERFLOW,
+  EXCEPTION_DIV_ZERO,
+  EXCEPTION_DATA_ABORT_READ,
+  EXCEPTION_DATA_ABORT_WRITE,
+  EXCEPTION_DATA_ABORT_UNSPECIFIED,
+  EXCEPTION_INSTRUCTION_ABORT,
+  EXCEPTION_MMU_UNSPECIFIED,
+  EXCEPTION_ACCESS_ALIGNMENT,
+  EXCEPTION_SUPERVISOR,
+  EXCEPTION_TRAPPED_INSTRUCTION,
+  EXCEPTION_PC_ALIGNMENT,
+  EXCEPTION_SP_ALIGNMENT,
+  EXCEPTION_BREAKPOINT,
+  EXCEPTION_BREAK_INSTRUCTION,
+  EXCEPTION_STEP,
+  EXCEPTION_WATCHPOINT,
+  EXCEPTION_MAX
+} Exception_Class;
+
+/**
+ * @brief Retrieves the generic exception class of the machine exception.
+ *
+ * @param exception_frame The CPU_Exception_frame describing the machine
+ * exception.
+ * @return The class of exception represented by the CPU_Exception_frame.
+ */
+Exception_Class Exception_Manager_Get_class( CPU_Exception_frame *ef );
+
+/**
+ * @brief Copies data to the new exception frame from the old exception frame.
+ *
+ * @param old_ef The existing CPU_Exception_frame describing the machine
+ * exception.
+ * @param new_ef The new CPU_Exception_frame describing the machine
+ * exception.
+ */
+void Exception_Manager_Copy_CPU_Exception_frame(
+  CPU_Exception_frame *new_ef,
+  CPU_Exception_frame *old_ef
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTEMS_EXCEPTION_H */
diff --git a/cpukit/include/rtems/score/userext.h b/cpukit/include/rtems/score/userext.h
index 28b90a06ad..c8261643aa 100644
--- a/cpukit/include/rtems/score/userext.h
+++ b/cpukit/include/rtems/score/userext.h
@@ -188,6 +188,23 @@ typedef void( *User_extensions_thread_exitted_extension )(
   struct _Thread_Control *executing
 );
 
+/**
+ * @brief Exception extension.
+ *
+ * This extension should not call any RTEMS directives.
+ *
+ * @param[in] exception_frame The exception frame describing the machine
+ * exception state.
+ * @param[in] handled This parameter indicates whether the exception has
+ * already been handled with finality. This must be set if the exception is
+ * consumed and the visitor should not further alter the exception frame if it
+ * is already set.
+ */
+typedef void( *User_extensions_exception_extension )(
+  CPU_Exception_frame *exception_frame,
+  bool                *handled
+);
+
 /**
  * @brief Fatal error extension.
  *
@@ -241,6 +258,7 @@ typedef struct {
   User_extensions_thread_exitted_extension thread_exitted;
   User_extensions_fatal_extension          fatal;
   User_extensions_thread_terminate_extension thread_terminate;
+  User_extensions_exception_extension      exception;
 }   User_extensions_Table;
 
 /** @} */
diff --git a/cpukit/include/rtems/score/userextimpl.h b/cpukit/include/rtems/score/userextimpl.h
index fd075a94ec..00e6a5e77e 100644
--- a/cpukit/include/rtems/score/userextimpl.h
+++ b/cpukit/include/rtems/score/userextimpl.h
@@ -230,6 +230,24 @@ void _User_extensions_Thread_exitted_visitor(
   const User_extensions_Table *callouts
 );
 
+typedef struct {
+  CPU_Exception_frame *exception_frame;
+  bool                *handled;
+} User_extensions_Exception_context;
+
+/**
+ * @brief Calls the exception function of the thread callout for the visitor.
+ *
+ * @param executing The currently executing thread.
+ * @param arg Is used as the user extension exception context.
+ * @param callouts The user extension table for the operation.
+ */
+void _User_extensions_Exception_visitor(
+  Thread_Control              *executing,
+  void                        *arg,
+  const User_extensions_Table *callouts
+);
+
 typedef struct {
   Internal_errors_Source source;
   Internal_errors_t      error;
@@ -430,6 +448,29 @@ static inline void _User_extensions_Thread_exitted( Thread_Control *executing )
   );
 }
 
+/**
+ * @brief Forwards all visitors that there was a machine exception.
+ *
+ * @param exception_frame The CPU_Exception_frame describing the machine
+ * exception.
+ * @return True if the exception was handled with finality.
+ */
+static inline bool _User_extensions_Exception(
+  CPU_Exception_frame *exception_frame
+)
+{
+  bool handled = false;
+  User_extensions_Exception_context ctx = { exception_frame, &handled };
+
+  _User_extensions_Iterate(
+    &ctx,
+    _User_extensions_Exception_visitor,
+    CHAIN_ITERATOR_FORWARD
+  );
+
+  return handled;
+}
+
 /**
  * @brief Forwards all visitors that there was a fatal failure.
  *
diff --git a/cpukit/score/src/userextiterate.c b/cpukit/score/src/userextiterate.c
index a25a4ad768..a25a94058e 100644
--- a/cpukit/score/src/userextiterate.c
+++ b/cpukit/score/src/userextiterate.c
@@ -4,7 +4,8 @@
  * @ingroup RTEMSScoreUserExt
  *
  * @brief This source file contains the definition of ::_User_extensions_List
- *   and the implementation of _User_extensions_Fatal_visitor(),
+ *   and the implementation of _User_extensions_Exception_visitor(),
+ *   _User_extensions_Fatal_visitor(),
  *   _User_extensions_Iterate(), _User_extensions_Thread_begin_visitor(),
  *   _User_extensions_Thread_create_visitor(),
  *   _User_extensions_Thread_delete_visitor(),
@@ -125,6 +126,21 @@ void _User_extensions_Thread_exitted_visitor(
   }
 }
 
+void _User_extensions_Exception_visitor(
+  Thread_Control              *executing,
+  void                        *arg,
+  const User_extensions_Table *callouts
+)
+{
+  User_extensions_exception_extension callout = callouts->exception;
+
+  if ( callout != NULL ) {
+    const User_extensions_Exception_context *ctx = arg;
+
+    (*callout)( ctx->exception_frame, ctx->handled );
+  }
+}
+
 void _User_extensions_Fatal_visitor(
   Thread_Control              *executing,
   void                        *arg,
diff --git a/spec/build/cpukit/cpuopts.yml b/spec/build/cpukit/cpuopts.yml
index 0a07f6d5e9..5568ed1316 100644
--- a/spec/build/cpukit/cpuopts.yml
+++ b/spec/build/cpukit/cpuopts.yml
@@ -39,6 +39,8 @@ links:
   uid: optdebug
 - role: build-dependency
   uid: optdrvmgr
+- role: build-dependency
+  uid: optexceptionmanager
 - role: build-dependency
   uid: optmpci
 - role: build-dependency
diff --git a/spec/build/cpukit/librtemscpu.yml b/spec/build/cpukit/librtemscpu.yml
index 0abff9d439..e69b67f368 100644
--- a/spec/build/cpukit/librtemscpu.yml
+++ b/spec/build/cpukit/librtemscpu.yml
@@ -99,6 +99,7 @@ install:
   - cpukit/include/rtems/dumpbuf.h
   - cpukit/include/rtems/endian.h
   - cpukit/include/rtems/error.h
+  - cpukit/include/rtems/exception.h
   - cpukit/include/rtems/extension.h
   - cpukit/include/rtems/extensiondata.h
   - cpukit/include/rtems/extensionimpl.h
diff --git a/spec/build/cpukit/optexceptionmanager.yml b/spec/build/cpukit/optexceptionmanager.yml
new file mode 100644
index 0000000000..2188e16cf1
--- /dev/null
+++ b/spec/build/cpukit/optexceptionmanager.yml
@@ -0,0 +1,17 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+actions:
+- get-boolean: null
+- env-enable: null
+- define-condition: null
+build-type: option
+copyrights:
+- Copyright (C) 2021 On-Line Applications Research (OAR)
+default: true
+default-by-family: []
+default-by-variant: []
+description: |
+  Enable the Exception Manager
+enabled-by:
+links: []
+name: RTEMS_EXCEPTION_MANAGER
+type: build
-- 
2.20.1



More information about the devel mailing list