[rtems commit] validation: Test Interrupt Manager

Sebastian Huber sebh at rtems.org
Thu Mar 24 10:01:58 UTC 2022


Module:    rtems
Branch:    master
Commit:    aebf6b661954b4b0ca65342af504b41631bdef78
Changeset: http://git.rtems.org/rtems/commit/?id=aebf6b661954b4b0ca65342af504b41631bdef78

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Thu Sep  2 15:29:10 2021 +0200

validation: Test Interrupt Manager

The test source code is generated from specification items
by the "./spec2modules.py" script contained in the
git://git.rtems.org/rtems-central.git Git repository.

Please read the "How-To" section in the "Software Requirements Engineering"
chapter of the RTEMS Software Engineering manual to get more information about
the process.

Update #3716.

---

 spec/build/testsuites/validation/grp.yml           |   2 +
 spec/build/testsuites/validation/validation-0.yml  |  13 -
 .../testsuites/validation/validation-intr.yml      |  32 ++
 .../validation/validation-no-clock-0.yml           |   1 +
 .../testsuites/validation/validation-non-smp.yml   |   1 +
 .../validation/validation-smp-only-0.yml           |   3 +
 testsuites/validation/tc-bsp-interrupt-spurious.c  | 538 +++++++++++++++++++++
 testsuites/validation/tc-intr-clear.c              |  39 +-
 testsuites/validation/tc-intr-entry-install.c      | 226 ++++++---
 testsuites/validation/tc-intr-entry-remove.c       | 133 +++--
 testsuites/validation/tc-intr-get-affinity.c       |  53 +-
 testsuites/validation/tc-intr-get-attributes.c     |   2 +-
 testsuites/validation/tc-intr-handler-iterate.c    |   2 +-
 testsuites/validation/tc-intr-is-pending.c         |  87 ++--
 testsuites/validation/tc-intr-non-smp.c            | 171 +++++++
 testsuites/validation/tc-intr-raise-on.c           |  70 ++-
 testsuites/validation/tc-intr-raise.c              |  63 ++-
 testsuites/validation/tc-intr-set-affinity.c       | 276 ++++++++---
 testsuites/validation/tc-intr-smp-only.c           | 226 +++++++++
 testsuites/validation/tc-intr-vector-disable.c     |  56 ++-
 testsuites/validation/tc-intr-vector-enable.c      |  56 ++-
 testsuites/validation/tc-intr-vector-is-enabled.c  |  46 +-
 testsuites/validation/tc-intr.c                    | 286 +++++++++++
 testsuites/validation/ts-validation-intr.c         |  81 ++++
 24 files changed, 2120 insertions(+), 343 deletions(-)

diff --git a/spec/build/testsuites/validation/grp.yml b/spec/build/testsuites/validation/grp.yml
index da617e2..1608202 100644
--- a/spec/build/testsuites/validation/grp.yml
+++ b/spec/build/testsuites/validation/grp.yml
@@ -41,6 +41,8 @@ links:
 - role: build-dependency
   uid: validation-cache
 - role: build-dependency
+  uid: validation-intr
+- role: build-dependency
   uid: validation-no-clock-0
 - role: build-dependency
   uid: validation-non-smp
diff --git a/spec/build/testsuites/validation/validation-0.yml b/spec/build/testsuites/validation/validation-0.yml
index c7a93e9..03a6f43 100644
--- a/spec/build/testsuites/validation/validation-0.yml
+++ b/spec/build/testsuites/validation/validation-0.yml
@@ -13,19 +13,6 @@ links: []
 source:
 - testsuites/validation/tc-acfg-appl-needs-clock-driver.c
 - testsuites/validation/tc-event-send-receive.c
-- testsuites/validation/tc-intr-clear.c
-- testsuites/validation/tc-intr-entry-install.c
-- testsuites/validation/tc-intr-entry-remove.c
-- testsuites/validation/tc-intr-get-affinity.c
-- testsuites/validation/tc-intr-get-attributes.c
-- testsuites/validation/tc-intr-handler-iterate.c
-- testsuites/validation/tc-intr-is-pending.c
-- testsuites/validation/tc-intr-raise.c
-- testsuites/validation/tc-intr-raise-on.c
-- testsuites/validation/tc-intr-set-affinity.c
-- testsuites/validation/tc-intr-vector-disable.c
-- testsuites/validation/tc-intr-vector-enable.c
-- testsuites/validation/tc-intr-vector-is-enabled.c
 - testsuites/validation/tc-message-construct-errors.c
 - testsuites/validation/tc-object.c
 - testsuites/validation/tc-signal-catch.c
diff --git a/spec/build/testsuites/validation/validation-intr.yml b/spec/build/testsuites/validation/validation-intr.yml
new file mode 100644
index 0000000..3bef9b7
--- /dev/null
+++ b/spec/build/testsuites/validation/validation-intr.yml
@@ -0,0 +1,32 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+build-type: test-program
+cflags: []
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+cppflags: []
+cxxflags: []
+enabled-by: true
+features: c cprogram
+includes: []
+ldflags: []
+links: []
+source:
+- testsuites/validation/tc-intr-clear.c
+- testsuites/validation/tc-intr-entry-install.c
+- testsuites/validation/tc-intr-entry-remove.c
+- testsuites/validation/tc-intr-get-affinity.c
+- testsuites/validation/tc-intr-get-attributes.c
+- testsuites/validation/tc-intr-handler-iterate.c
+- testsuites/validation/tc-intr-is-pending.c
+- testsuites/validation/tc-intr-raise.c
+- testsuites/validation/tc-intr-raise-on.c
+- testsuites/validation/tc-intr-set-affinity.c
+- testsuites/validation/tc-intr-vector-disable.c
+- testsuites/validation/tc-intr-vector-enable.c
+- testsuites/validation/tc-intr-vector-is-enabled.c
+- testsuites/validation/ts-validation-intr.c
+stlib: []
+target: testsuites/validation/ts-validation-intr.exe
+type: build
+use-after: []
+use-before: []
diff --git a/spec/build/testsuites/validation/validation-no-clock-0.yml b/spec/build/testsuites/validation/validation-no-clock-0.yml
index 786a07e..763d0b3 100644
--- a/spec/build/testsuites/validation/validation-no-clock-0.yml
+++ b/spec/build/testsuites/validation/validation-no-clock-0.yml
@@ -27,6 +27,7 @@ source:
 - testsuites/validation/tc-clock-set.c
 - testsuites/validation/tc-cpuuse.c
 - testsuites/validation/tc-events.c
+- testsuites/validation/tc-intr.c
 - testsuites/validation/tc-score-fatal.c
 - testsuites/validation/tr-event-constant.c
 - testsuites/validation/tr-mtx-seize-try.c
diff --git a/spec/build/testsuites/validation/validation-non-smp.yml b/spec/build/testsuites/validation/validation-non-smp.yml
index 656a8a1..3aeaa29 100644
--- a/spec/build/testsuites/validation/validation-non-smp.yml
+++ b/spec/build/testsuites/validation/validation-non-smp.yml
@@ -12,6 +12,7 @@ includes: []
 ldflags: []
 links: []
 source:
+- testsuites/validation/tc-intr-non-smp.c
 - testsuites/validation/ts-validation-non-smp.c
 stlib: []
 target: testsuites/validation/ts-validation-non-smp.exe
diff --git a/spec/build/testsuites/validation/validation-smp-only-0.yml b/spec/build/testsuites/validation/validation-smp-only-0.yml
index 3de2054..1909f7e 100644
--- a/spec/build/testsuites/validation/validation-smp-only-0.yml
+++ b/spec/build/testsuites/validation/validation-smp-only-0.yml
@@ -9,10 +9,13 @@ enabled-by: RTEMS_SMP
 features: c cprogram
 includes: []
 ldflags:
+- -Wl,--wrap=bsp_interrupt_handler_default
 - -Wl,--wrap=_Scheduler_EDF_SMP_Yield
 links: []
 source:
 - testsuites/validation/tc-acfg-scheduler-edf-smp.c
+- testsuites/validation/tc-bsp-interrupt-spurious.c
+- testsuites/validation/tc-intr-smp-only.c
 - testsuites/validation/tc-score-tq-smp.c
 - testsuites/validation/ts-validation-smp-only-0.c
 stlib: []
diff --git a/testsuites/validation/tc-bsp-interrupt-spurious.c b/testsuites/validation/tc-bsp-interrupt-spurious.c
new file mode 100644
index 0000000..de13933
--- /dev/null
+++ b/testsuites/validation/tc-bsp-interrupt-spurious.c
@@ -0,0 +1,538 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSTestCaseBspReqInterruptSpurious
+ */
+
+/*
+ * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * 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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <setjmp.h>
+#include <bsp/irq-generic.h>
+
+#include "tx-support.h"
+
+#include <rtems/test.h>
+
+/**
+ * @defgroup RTEMSTestCaseBspReqInterruptSpurious \
+ *   spec:/bsp/req/interrupt-spurious
+ *
+ * @ingroup RTEMSTestSuiteTestsuitesValidationSmpOnly0
+ *
+ * @{
+ */
+
+typedef enum {
+  BspReqInterruptSpurious_Pre_First_Null,
+  BspReqInterruptSpurious_Pre_First_Entry,
+  BspReqInterruptSpurious_Pre_First_NA
+} BspReqInterruptSpurious_Pre_First;
+
+typedef enum {
+  BspReqInterruptSpurious_Post_Result_FatalError,
+  BspReqInterruptSpurious_Post_Result_Dispatch,
+  BspReqInterruptSpurious_Post_Result_NA
+} BspReqInterruptSpurious_Post_Result;
+
+typedef enum {
+  BspReqInterruptSpurious_Post_FatalSource_SpuriousInterrupt,
+  BspReqInterruptSpurious_Post_FatalSource_NA
+} BspReqInterruptSpurious_Post_FatalSource;
+
+typedef enum {
+  BspReqInterruptSpurious_Post_FatalCode_Vector,
+  BspReqInterruptSpurious_Post_FatalCode_NA
+} BspReqInterruptSpurious_Post_FatalCode;
+
+typedef struct {
+  uint8_t Skip : 1;
+  uint8_t Pre_First_NA : 1;
+  uint8_t Post_Result : 2;
+  uint8_t Post_FatalSource : 1;
+  uint8_t Post_FatalCode : 1;
+} BspReqInterruptSpurious_Entry;
+
+/**
+ * @brief Test context for spec:/bsp/req/interrupt-spurious test case.
+ */
+typedef struct {
+  /**
+   * @brief This member provides a jump buffer to return from the fatal error.
+   */
+  jmp_buf before_call;
+
+  /**
+   * @brief This member provides an interrupt entry to be dispatched.
+   */
+  rtems_interrupt_entry entry;
+
+  /**
+   * @brief If this member is true, then the interrupt shall be cleared.
+   */
+  bool do_clear;
+
+  /**
+   * @brief This member is true, then an interrupt occurred.
+   */
+  volatile bool interrupt_occurred;
+
+  /**
+   * @brief This member provides an entry dispatch counter.
+   */
+  uint32_t entry_counter;
+
+  /**
+   * @brief This member provides a fatal error counter.
+   */
+  uint32_t fatal_counter;
+
+  /**
+   * @brief This member contains the fatal source.
+   */
+  rtems_fatal_source fatal_source;
+
+  /**
+   * @brief This member contains a fatal code.
+   */
+  rtems_fatal_code fatal_code;
+
+  /**
+   * @brief This member contains the vector number of a testable interrupt.
+   */
+  rtems_vector_number test_vector;
+
+  /**
+   * @brief This member references the pointer to the first entry of the
+   *   interrupt vector.
+   */
+  rtems_interrupt_entry **first;
+
+  struct {
+    /**
+     * @brief This member defines the pre-condition states for the next action.
+     */
+    size_t pcs[ 1 ];
+
+    /**
+     * @brief If this member is true, then the test action loop is executed.
+     */
+    bool in_action_loop;
+
+    /**
+     * @brief This member contains the next transition map index.
+     */
+    size_t index;
+
+    /**
+     * @brief This member contains the current transition map entry.
+     */
+    BspReqInterruptSpurious_Entry entry;
+
+    /**
+     * @brief If this member is true, then the current transition variant
+     *   should be skipped.
+     */
+    bool skip;
+  } Map;
+} BspReqInterruptSpurious_Context;
+
+static BspReqInterruptSpurious_Context
+  BspReqInterruptSpurious_Instance;
+
+static const char * const BspReqInterruptSpurious_PreDesc_First[] = {
+  "Null",
+  "Entry",
+  "NA"
+};
+
+static const char * const * const BspReqInterruptSpurious_PreDesc[] = {
+  BspReqInterruptSpurious_PreDesc_First,
+  NULL
+};
+
+typedef BspReqInterruptSpurious_Context Context;
+
+static bool test_case_active;
+
+static void Disable( const Context *ctx )
+{
+  (void) rtems_interrupt_vector_disable( ctx->test_vector );
+}
+
+static void ProcessInterrupt( Context *ctx )
+{
+  ctx->interrupt_occurred = true;
+
+  if ( ctx->do_clear ) {
+    rtems_status_code sc;
+
+    sc = rtems_interrupt_clear( ctx->test_vector );
+    T_rsc_success( sc );
+  }
+
+  Disable( ctx );
+}
+
+static void EntryRoutine( void *arg )
+{
+  Context *ctx;
+
+  ctx = arg;
+  ++ctx->entry_counter;
+  ProcessInterrupt( ctx );
+}
+
+static void Fatal(
+  rtems_fatal_source source,
+  rtems_fatal_code   code,
+  void              *arg
+)
+{
+  Context *ctx;
+
+  ctx = arg;
+  ctx->fatal_source = source;
+  ctx->fatal_code = code;
+  ++ctx->fatal_counter;
+  longjmp( ctx->before_call, 1 );
+}
+
+void __real_bsp_interrupt_handler_default( rtems_vector_number vector );
+
+void __wrap_bsp_interrupt_handler_default( rtems_vector_number vector );
+
+void __wrap_bsp_interrupt_handler_default( rtems_vector_number vector )
+{
+  if ( test_case_active ) {
+    Context *ctx;
+
+    ctx = T_fixture_context();
+    ProcessInterrupt( ctx );
+
+    if ( setjmp( ctx->before_call ) == 0 ) {
+      __real_bsp_interrupt_handler_default( vector );
+    }
+  } else {
+    __real_bsp_interrupt_handler_default( vector );
+  }
+}
+
+static void BspReqInterruptSpurious_Pre_First_Prepare(
+  BspReqInterruptSpurious_Context  *ctx,
+  BspReqInterruptSpurious_Pre_First state
+)
+{
+  switch ( state ) {
+    case BspReqInterruptSpurious_Pre_First_Null: {
+      /*
+       * While the pointer to the first interrupt entry of the interrupt vector
+       * specified by the ``vector`` parameter is equal to NULL.
+       */
+      *ctx->first = NULL;
+      break;
+    }
+
+    case BspReqInterruptSpurious_Pre_First_Entry: {
+      /*
+       * While the pointer to the first interrupt entry of the interrupt vector
+       * specified by the ``vector`` parameter references an object of type
+       * rtems_interrupt_entry.
+       */
+      *ctx->first = &ctx->entry;
+      break;
+    }
+
+    case BspReqInterruptSpurious_Pre_First_NA:
+      break;
+  }
+}
+
+static void BspReqInterruptSpurious_Post_Result_Check(
+  BspReqInterruptSpurious_Context    *ctx,
+  BspReqInterruptSpurious_Post_Result state
+)
+{
+  switch ( state ) {
+    case BspReqInterruptSpurious_Post_Result_FatalError: {
+      /*
+       * A fatal error shall occur.
+       */
+      T_eq_u32( ctx->entry_counter, 0 );
+      T_eq_u32( ctx->fatal_counter, 1 );
+      break;
+    }
+
+    case BspReqInterruptSpurious_Post_Result_Dispatch: {
+      /*
+       * The interrupt entries installed at the interrupt vector specified by
+       * the ``vector`` parameter shall be dispatched.
+       */
+      T_eq_u32( ctx->entry_counter, 1 );
+      T_eq_u32( ctx->fatal_counter, 0 );
+      break;
+    }
+
+    case BspReqInterruptSpurious_Post_Result_NA:
+      break;
+  }
+}
+
+static void BspReqInterruptSpurious_Post_FatalSource_Check(
+  BspReqInterruptSpurious_Context         *ctx,
+  BspReqInterruptSpurious_Post_FatalSource state
+)
+{
+  switch ( state ) {
+    case BspReqInterruptSpurious_Post_FatalSource_SpuriousInterrupt: {
+      /*
+       * The fatal source shall be equal to
+       * RTEMS_FATAL_SOURCE_SPURIOUS_INTERRUPT.
+       */
+      T_eq_int( ctx->fatal_source, RTEMS_FATAL_SOURCE_SPURIOUS_INTERRUPT );
+      break;
+    }
+
+    case BspReqInterruptSpurious_Post_FatalSource_NA:
+      break;
+  }
+}
+
+static void BspReqInterruptSpurious_Post_FatalCode_Check(
+  BspReqInterruptSpurious_Context       *ctx,
+  BspReqInterruptSpurious_Post_FatalCode state
+)
+{
+  switch ( state ) {
+    case BspReqInterruptSpurious_Post_FatalCode_Vector: {
+      /*
+       * The fatal code shall be equal to the ``vector`` parameter.
+       */
+      T_eq_ulong( ctx->fatal_code, ctx->test_vector );
+      break;
+    }
+
+    case BspReqInterruptSpurious_Post_FatalCode_NA:
+      break;
+  }
+}
+
+static void BspReqInterruptSpurious_Setup(
+  BspReqInterruptSpurious_Context *ctx
+)
+{
+  rtems_interrupt_attributes attr = {
+    .can_raise = true
+  };
+  rtems_status_code sc;
+
+  ctx->test_vector = GetTestableInterruptVector( &attr );
+  T_assert_lt_u32( ctx->test_vector, BSP_INTERRUPT_VECTOR_COUNT );
+  ctx->first = &bsp_interrupt_handler_table[
+    bsp_interrupt_handler_index( ctx->test_vector )
+  ];
+
+  sc = rtems_interrupt_get_attributes( ctx->test_vector, &attr );
+  T_rsc_success( sc );
+  ctx->do_clear = attr.can_clear && !attr.cleared_by_acknowledge;
+
+  rtems_interrupt_entry_initialize( &ctx->entry, EntryRoutine, ctx, "Info" );
+  test_case_active = true;
+  SetFatalHandler( Fatal, ctx );
+}
+
+static void BspReqInterruptSpurious_Setup_Wrap( void *arg )
+{
+  BspReqInterruptSpurious_Context *ctx;
+
+  ctx = arg;
+  ctx->Map.in_action_loop = false;
+  BspReqInterruptSpurious_Setup( ctx );
+}
+
+static void BspReqInterruptSpurious_Teardown(
+  BspReqInterruptSpurious_Context *ctx
+)
+{
+  SetFatalHandler( NULL, NULL );
+  test_case_active = false;
+}
+
+static void BspReqInterruptSpurious_Teardown_Wrap( void *arg )
+{
+  BspReqInterruptSpurious_Context *ctx;
+
+  ctx = arg;
+  ctx->Map.in_action_loop = false;
+  BspReqInterruptSpurious_Teardown( ctx );
+}
+
+static void BspReqInterruptSpurious_Action(
+  BspReqInterruptSpurious_Context *ctx
+)
+{
+  ctx->interrupt_occurred = false;
+  ctx->entry_counter = 0;
+  ctx->fatal_counter = 0;
+  ctx->fatal_source = RTEMS_FATAL_SOURCE_LAST;
+  ctx->fatal_code = UINT32_MAX;
+
+  if ( *ctx->first == NULL ) {
+    rtems_status_code sc;
+
+    (void) rtems_interrupt_vector_enable( ctx->test_vector );
+
+    sc = rtems_interrupt_raise( ctx->test_vector );
+    T_rsc_success( sc );
+
+    while ( !ctx->interrupt_occurred ) {
+      /* Wait */
+    }
+
+    Disable( ctx );
+  } else {
+    bsp_interrupt_spurious( ctx->test_vector );
+  }
+}
+
+static const BspReqInterruptSpurious_Entry
+BspReqInterruptSpurious_Entries[] = {
+  { 0, 0, BspReqInterruptSpurious_Post_Result_FatalError,
+    BspReqInterruptSpurious_Post_FatalSource_SpuriousInterrupt,
+    BspReqInterruptSpurious_Post_FatalCode_Vector },
+  { 0, 0, BspReqInterruptSpurious_Post_Result_Dispatch,
+    BspReqInterruptSpurious_Post_FatalSource_NA,
+    BspReqInterruptSpurious_Post_FatalCode_NA }
+};
+
+static const uint8_t
+BspReqInterruptSpurious_Map[] = {
+  0, 1
+};
+
+static size_t BspReqInterruptSpurious_Scope( void *arg, char *buf, size_t n )
+{
+  BspReqInterruptSpurious_Context *ctx;
+
+  ctx = arg;
+
+  if ( ctx->Map.in_action_loop ) {
+    return T_get_scope(
+      BspReqInterruptSpurious_PreDesc,
+      buf,
+      n,
+      ctx->Map.pcs
+    );
+  }
+
+  return 0;
+}
+
+static T_fixture BspReqInterruptSpurious_Fixture = {
+  .setup = BspReqInterruptSpurious_Setup_Wrap,
+  .stop = NULL,
+  .teardown = BspReqInterruptSpurious_Teardown_Wrap,
+  .scope = BspReqInterruptSpurious_Scope,
+  .initial_context = &BspReqInterruptSpurious_Instance
+};
+
+static inline BspReqInterruptSpurious_Entry BspReqInterruptSpurious_PopEntry(
+  BspReqInterruptSpurious_Context *ctx
+)
+{
+  size_t index;
+
+  index = ctx->Map.index;
+  ctx->Map.index = index + 1;
+  return BspReqInterruptSpurious_Entries[
+    BspReqInterruptSpurious_Map[ index ]
+  ];
+}
+
+static void BspReqInterruptSpurious_TestVariant(
+  BspReqInterruptSpurious_Context *ctx
+)
+{
+  BspReqInterruptSpurious_Pre_First_Prepare( ctx, ctx->Map.pcs[ 0 ] );
+  BspReqInterruptSpurious_Action( ctx );
+  BspReqInterruptSpurious_Post_Result_Check( ctx, ctx->Map.entry.Post_Result );
+  BspReqInterruptSpurious_Post_FatalSource_Check(
+    ctx,
+    ctx->Map.entry.Post_FatalSource
+  );
+  BspReqInterruptSpurious_Post_FatalCode_Check(
+    ctx,
+    ctx->Map.entry.Post_FatalCode
+  );
+}
+
+/**
+ * @fn void T_case_body_BspReqInterruptSpurious( void )
+ */
+T_TEST_CASE_FIXTURE(
+  BspReqInterruptSpurious,
+  &BspReqInterruptSpurious_Fixture
+)
+{
+  BspReqInterruptSpurious_Context *ctx;
+
+  ctx = T_fixture_context();
+  ctx->Map.in_action_loop = true;
+  ctx->Map.index = 0;
+
+  for (
+    ctx->Map.pcs[ 0 ] = BspReqInterruptSpurious_Pre_First_Null;
+    ctx->Map.pcs[ 0 ] < BspReqInterruptSpurious_Pre_First_NA;
+    ++ctx->Map.pcs[ 0 ]
+  ) {
+    ctx->Map.entry = BspReqInterruptSpurious_PopEntry( ctx );
+    BspReqInterruptSpurious_TestVariant( ctx );
+  }
+}
+
+/** @} */
diff --git a/testsuites/validation/tc-intr-clear.c b/testsuites/validation/tc-intr-clear.c
index 8c4e1e1..1c6c451 100644
--- a/testsuites/validation/tc-intr-clear.c
+++ b/testsuites/validation/tc-intr-clear.c
@@ -63,7 +63,7 @@
 /**
  * @defgroup RTEMSTestCaseRtemsIntrReqClear spec:/rtems/intr/req/clear
  *
- * @ingroup RTEMSTestSuiteTestsuitesValidation0
+ * @ingroup RTEMSTestSuiteTestsuitesValidationIntr
  *
  * @{
  */
@@ -134,6 +134,12 @@ typedef struct {
 
   struct {
     /**
+     * @brief This member defines the pre-condition indices for the next
+     *   action.
+     */
+    size_t pci[ 2 ];
+
+    /**
      * @brief This member defines the pre-condition states for the next action.
      */
     size_t pcs[ 2 ];
@@ -560,13 +566,23 @@ static inline RtemsIntrReqClear_Entry RtemsIntrReqClear_PopEntry(
   ];
 }
 
+static void RtemsIntrReqClear_SetPreConditionStates(
+  RtemsIntrReqClear_Context *ctx
+)
+{
+  ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
+
+  if ( ctx->Map.entry.Pre_CanClear_NA ) {
+    ctx->Map.pcs[ 1 ] = RtemsIntrReqClear_Pre_CanClear_NA;
+  } else {
+    ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
+  }
+}
+
 static void RtemsIntrReqClear_TestVariant( RtemsIntrReqClear_Context *ctx )
 {
   RtemsIntrReqClear_Pre_Vector_Prepare( ctx, ctx->Map.pcs[ 0 ] );
-  RtemsIntrReqClear_Pre_CanClear_Prepare(
-    ctx,
-    ctx->Map.entry.Pre_CanClear_NA ? RtemsIntrReqClear_Pre_CanClear_NA : ctx->Map.pcs[ 1 ]
-  );
+  RtemsIntrReqClear_Pre_CanClear_Prepare( ctx, ctx->Map.pcs[ 1 ] );
   RtemsIntrReqClear_Action( ctx );
   RtemsIntrReqClear_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
   RtemsIntrReqClear_Post_Cleared_Check( ctx, ctx->Map.entry.Post_Cleared );
@@ -584,16 +600,17 @@ T_TEST_CASE_FIXTURE( RtemsIntrReqClear, &RtemsIntrReqClear_Fixture )
   ctx->Map.index = 0;
 
   for (
-    ctx->Map.pcs[ 0 ] = RtemsIntrReqClear_Pre_Vector_Valid;
-    ctx->Map.pcs[ 0 ] < RtemsIntrReqClear_Pre_Vector_NA;
-    ++ctx->Map.pcs[ 0 ]
+    ctx->Map.pci[ 0 ] = RtemsIntrReqClear_Pre_Vector_Valid;
+    ctx->Map.pci[ 0 ] < RtemsIntrReqClear_Pre_Vector_NA;
+    ++ctx->Map.pci[ 0 ]
   ) {
     for (
-      ctx->Map.pcs[ 1 ] = RtemsIntrReqClear_Pre_CanClear_Yes;
-      ctx->Map.pcs[ 1 ] < RtemsIntrReqClear_Pre_CanClear_NA;
-      ++ctx->Map.pcs[ 1 ]
+      ctx->Map.pci[ 1 ] = RtemsIntrReqClear_Pre_CanClear_Yes;
+      ctx->Map.pci[ 1 ] < RtemsIntrReqClear_Pre_CanClear_NA;
+      ++ctx->Map.pci[ 1 ]
     ) {
       ctx->Map.entry = RtemsIntrReqClear_PopEntry( ctx );
+      RtemsIntrReqClear_SetPreConditionStates( ctx );
       RtemsIntrReqClear_TestVariant( ctx );
     }
   }
diff --git a/testsuites/validation/tc-intr-entry-install.c b/testsuites/validation/tc-intr-entry-install.c
index f5280c1..7144867 100644
--- a/testsuites/validation/tc-intr-entry-install.c
+++ b/testsuites/validation/tc-intr-entry-install.c
@@ -63,7 +63,7 @@
  * @defgroup RTEMSTestCaseRtemsIntrReqEntryInstall \
  *   spec:/rtems/intr/req/entry-install
  *
- * @ingroup RTEMSTestSuiteTestsuitesValidation0
+ * @ingroup RTEMSTestSuiteTestsuitesValidationIntr
  *
  * @{
  */
@@ -174,9 +174,14 @@ typedef struct {
   bool initialized_during_setup;
 
   /**
-   * @brief If this member is true, then an interrupt occurred.
+   * @brief This member provides a counter for handler invocations.
    */
-  bool interrupt_occurred;
+  uint32_t handler_counter;
+
+  /**
+   * @brief This member provides a counter snapshot for each entry.
+   */
+  uint32_t counter_by_entry[ 3 ];;
 
   /**
    * @brief This member provides the vector number of a testable interrupt
@@ -272,6 +277,12 @@ typedef struct {
 
   struct {
     /**
+     * @brief This member defines the pre-condition indices for the next
+     *   action.
+     */
+    size_t pci[ 8 ];
+
+    /**
      * @brief This member defines the pre-condition states for the next action.
      */
     size_t pcs[ 8 ];
@@ -409,29 +420,66 @@ static void Install(
   ctx->other_installed = true;
 }
 
-static void OtherRoutine( void *arg )
+static void Routine( Context *ctx, uint32_t counter )
 {
-  Context          *ctx;
   rtems_status_code sc;
 
-  (void) arg;
-  ctx = T_fixture_context();
-  sc = rtems_interrupt_vector_disable( ctx->test_vector );
-  T_rsc_success( sc );
+  ctx->handler_counter = counter;
+
+  if (
+    ctx->attributes.can_clear &&
+    !ctx->attributes.cleared_by_acknowledge
+  ) {
+    sc = rtems_interrupt_clear( ctx->test_vector );
+    T_rsc_success( sc );
+  }
 
-  ctx->interrupt_occurred = true;
+  if ( counter > 3 ) {
+    sc = rtems_interrupt_vector_disable( ctx->test_vector );
+    T_rsc_success( sc );
+  }
 }
 
 static void EntryRoutine( void *arg )
 {
-  T_eq_ptr( arg, &entry_arg );
-  OtherRoutine( NULL );
+  Context *ctx;
+  uint32_t counter;
+
+  ctx = T_fixture_context();
+  counter = ctx->handler_counter + 1;
+
+  if ( arg == &other_arg ) {
+    ctx->counter_by_entry[ 1 ] = counter;
+  } else {
+    ctx->counter_by_entry[ 0 ] = counter;
+    T_eq_ptr( arg, &entry_arg );
+  }
+
+  Routine( ctx, counter );
+}
+
+static void OtherRoutine( void *arg )
+{
+  Context *ctx;
+  uint32_t counter;
+
+  (void) arg;
+  ctx = T_fixture_context();
+  counter = ctx->handler_counter + 1;
+  ctx->counter_by_entry[ 1 ] = counter;
+  Routine( ctx, counter );
 }
 
 static void ThirdRoutine( void *arg )
 {
+  Context *ctx;
+  uint32_t counter;
+
+  ctx = T_fixture_context();
+  counter = ctx->handler_counter + 1;
+  ctx->counter_by_entry[ 2 ] = counter;
   T_eq_ptr( arg, &third_arg );
-  OtherRoutine( NULL );
+  Routine( ctx, counter );
 }
 
 static void InstallThird( Context *ctx )
@@ -489,6 +537,11 @@ static void Action( void *arg )
     &ctx->enabled_after
   );
   T_rsc_success( sc );
+
+  if ( ctx->status == RTEMS_SUCCESSFUL ) {
+    sc = rtems_interrupt_raise( ctx->test_vector );
+    T_rsc_success( sc );
+  }
 }
 
 static void VisitInstalled(
@@ -940,7 +993,7 @@ static void RtemsIntrReqEntryInstall_Post_Enable_Check(
        * The enabled status of the interrupt vector specified by ``vector``
        * shall not be modified by the rtems_interrupt_entry_install() call.
        */
-      if ( !ctx->interrupt_occurred ) {
+      if ( ctx->handler_counter == 0 ) {
         T_eq( ctx->enabled_before, ctx->enabled_after );
       }
       break;
@@ -950,9 +1003,7 @@ static void RtemsIntrReqEntryInstall_Post_Enable_Check(
       /*
        * The interrupt vector specified by ``vector`` shall be enabled.
        */
-      if ( ctx->attributes.can_enable ) {
-        T_true( ctx->enabled_after || ctx->interrupt_occurred );
-      }
+      T_true( ctx->enabled_after || ctx->handler_counter > 3 );
       break;
     }
 
@@ -960,10 +1011,13 @@ static void RtemsIntrReqEntryInstall_Post_Enable_Check(
       /*
        * The interrupt vector specified by ``vector`` may be enabled.
        */
-      /* The comment of pre-condition ``CanEnable`` for the ``Yes`` state. */
-      if ( ctx->attributes.can_enable ) {
-        T_true( ctx->enabled_after || ctx->interrupt_occurred );
-      }
+      /*
+       * Interrupt vectors which cannot be enabled are not selected as a
+       * testable interrupt vector by GetTestableInterruptVector(), so this
+       * path is not validated by this test.  See also comment for
+       * ``CanEnable`` pre-condition state ``Yes``.
+       */
+      T_true( ctx->enabled_after || ctx->handler_counter > 3 );
       break;
     }
 
@@ -973,8 +1027,11 @@ static void RtemsIntrReqEntryInstall_Post_Enable_Check(
        */
       /*
        * Interrupt vectors which cannot be enabled are not selected as a
-       * testable interrupt vector by GetTestableInterruptVector().
+       * testable interrupt vector by GetTestableInterruptVector(), so this
+       * path is not validated by this test.  See also comment for
+       * ``CanEnable`` pre-condition state ``Yes``.
        */
+      T_true( ctx->enabled_after || ctx->handler_counter > 3 );
       break;
     }
 
@@ -998,6 +1055,24 @@ static void RtemsIntrReqEntryInstall_Post_Installed_Check(
   );
   T_rsc_success( sc );
 
+  if ( ctx->status == RTEMS_SUCCESSFUL ) {
+    uint32_t counter;
+
+    counter = 1;
+
+    if ( ctx->other_installed ) {
+      T_eq_u32( ctx->counter_by_entry[ 1 ], counter );
+      ++counter;
+    }
+
+    if ( ctx->third_installed ) {
+      T_eq_u32( ctx->counter_by_entry[ 2 ], counter );
+      ++counter;
+    }
+
+    T_eq_u32( ctx->counter_by_entry[ 0 ], counter );
+  }
+
   switch ( state ) {
     case RtemsIntrReqEntryInstall_Post_Installed_No: {
       /*
@@ -1038,10 +1113,13 @@ static void RtemsIntrReqEntryInstall_Setup(
   RtemsIntrReqEntryInstall_Context *ctx
 )
 {
+  rtems_interrupt_attributes required = {
+    .can_raise = true
+  };
   rtems_status_code sc;
 
   ctx->initialized_during_setup = bsp_interrupt_is_initialized();
-  ctx->test_vector = GetTestableInterruptVector( NULL );
+  ctx->test_vector = GetTestableInterruptVector( &required );
   sc = rtems_interrupt_get_attributes( ctx->test_vector, &ctx->attributes );
   T_rsc_success( sc );
 }
@@ -1059,7 +1137,13 @@ static void RtemsIntrReqEntryInstall_Prepare(
   RtemsIntrReqEntryInstall_Context *ctx
 )
 {
-  ctx->interrupt_occurred = false;
+  size_t i;
+
+  for ( i = 0; i < RTEMS_ARRAY_SIZE( ctx->counter_by_entry ); ++i ) {
+    ctx->counter_by_entry[ i ] = 0;
+  }
+
+  ctx->handler_counter = 0;
   ctx->other_installed = false;
   ctx->third_installed = false;
 }
@@ -1254,6 +1338,36 @@ static inline RtemsIntrReqEntryInstall_Entry RtemsIntrReqEntryInstall_PopEntry(
   ];
 }
 
+static void RtemsIntrReqEntryInstall_SetPreConditionStates(
+  RtemsIntrReqEntryInstall_Context *ctx
+)
+{
+  ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
+  ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
+  ctx->Map.pcs[ 2 ] = ctx->Map.pci[ 2 ];
+
+  if ( ctx->Map.entry.Pre_Routine_NA ) {
+    ctx->Map.pcs[ 3 ] = RtemsIntrReqEntryInstall_Pre_Routine_NA;
+  } else {
+    ctx->Map.pcs[ 3 ] = ctx->Map.pci[ 3 ];
+  }
+
+  ctx->Map.pcs[ 4 ] = ctx->Map.pci[ 4 ];
+  ctx->Map.pcs[ 5 ] = ctx->Map.pci[ 5 ];
+
+  if ( ctx->Map.entry.Pre_CanEnable_NA ) {
+    ctx->Map.pcs[ 6 ] = RtemsIntrReqEntryInstall_Pre_CanEnable_NA;
+  } else {
+    ctx->Map.pcs[ 6 ] = ctx->Map.pci[ 6 ];
+  }
+
+  if ( ctx->Map.entry.Pre_Installed_NA ) {
+    ctx->Map.pcs[ 7 ] = RtemsIntrReqEntryInstall_Pre_Installed_NA;
+  } else {
+    ctx->Map.pcs[ 7 ] = ctx->Map.pci[ 7 ];
+  }
+}
+
 static void RtemsIntrReqEntryInstall_TestVariant(
   RtemsIntrReqEntryInstall_Context *ctx
 )
@@ -1261,20 +1375,11 @@ static void RtemsIntrReqEntryInstall_TestVariant(
   RtemsIntrReqEntryInstall_Pre_Vector_Prepare( ctx, ctx->Map.pcs[ 0 ] );
   RtemsIntrReqEntryInstall_Pre_Options_Prepare( ctx, ctx->Map.pcs[ 1 ] );
   RtemsIntrReqEntryInstall_Pre_Entry_Prepare( ctx, ctx->Map.pcs[ 2 ] );
-  RtemsIntrReqEntryInstall_Pre_Routine_Prepare(
-    ctx,
-    ctx->Map.entry.Pre_Routine_NA ? RtemsIntrReqEntryInstall_Pre_Routine_NA : ctx->Map.pcs[ 3 ]
-  );
+  RtemsIntrReqEntryInstall_Pre_Routine_Prepare( ctx, ctx->Map.pcs[ 3 ] );
   RtemsIntrReqEntryInstall_Pre_Init_Prepare( ctx, ctx->Map.pcs[ 4 ] );
   RtemsIntrReqEntryInstall_Pre_ISR_Prepare( ctx, ctx->Map.pcs[ 5 ] );
-  RtemsIntrReqEntryInstall_Pre_CanEnable_Prepare(
-    ctx,
-    ctx->Map.entry.Pre_CanEnable_NA ? RtemsIntrReqEntryInstall_Pre_CanEnable_NA : ctx->Map.pcs[ 6 ]
-  );
-  RtemsIntrReqEntryInstall_Pre_Installed_Prepare(
-    ctx,
-    ctx->Map.entry.Pre_Installed_NA ? RtemsIntrReqEntryInstall_Pre_Installed_NA : ctx->Map.pcs[ 7 ]
-  );
+  RtemsIntrReqEntryInstall_Pre_CanEnable_Prepare( ctx, ctx->Map.pcs[ 6 ] );
+  RtemsIntrReqEntryInstall_Pre_Installed_Prepare( ctx, ctx->Map.pcs[ 7 ] );
   RtemsIntrReqEntryInstall_Action( ctx );
   RtemsIntrReqEntryInstall_Post_Status_Check(
     ctx,
@@ -1305,46 +1410,47 @@ T_TEST_CASE_FIXTURE(
   ctx->Map.index = 0;
 
   for (
-    ctx->Map.pcs[ 0 ] = RtemsIntrReqEntryInstall_Pre_Vector_Valid;
-    ctx->Map.pcs[ 0 ] < RtemsIntrReqEntryInstall_Pre_Vector_NA;
-    ++ctx->Map.pcs[ 0 ]
+    ctx->Map.pci[ 0 ] = RtemsIntrReqEntryInstall_Pre_Vector_Valid;
+    ctx->Map.pci[ 0 ] < RtemsIntrReqEntryInstall_Pre_Vector_NA;
+    ++ctx->Map.pci[ 0 ]
   ) {
     for (
-      ctx->Map.pcs[ 1 ] = RtemsIntrReqEntryInstall_Pre_Options_Unique;
-      ctx->Map.pcs[ 1 ] < RtemsIntrReqEntryInstall_Pre_Options_NA;
-      ++ctx->Map.pcs[ 1 ]
+      ctx->Map.pci[ 1 ] = RtemsIntrReqEntryInstall_Pre_Options_Unique;
+      ctx->Map.pci[ 1 ] < RtemsIntrReqEntryInstall_Pre_Options_NA;
+      ++ctx->Map.pci[ 1 ]
     ) {
       for (
-        ctx->Map.pcs[ 2 ] = RtemsIntrReqEntryInstall_Pre_Entry_Obj;
-        ctx->Map.pcs[ 2 ] < RtemsIntrReqEntryInstall_Pre_Entry_NA;
-        ++ctx->Map.pcs[ 2 ]
+        ctx->Map.pci[ 2 ] = RtemsIntrReqEntryInstall_Pre_Entry_Obj;
+        ctx->Map.pci[ 2 ] < RtemsIntrReqEntryInstall_Pre_Entry_NA;
+        ++ctx->Map.pci[ 2 ]
       ) {
         for (
-          ctx->Map.pcs[ 3 ] = RtemsIntrReqEntryInstall_Pre_Routine_Valid;
-          ctx->Map.pcs[ 3 ] < RtemsIntrReqEntryInstall_Pre_Routine_NA;
-          ++ctx->Map.pcs[ 3 ]
+          ctx->Map.pci[ 3 ] = RtemsIntrReqEntryInstall_Pre_Routine_Valid;
+          ctx->Map.pci[ 3 ] < RtemsIntrReqEntryInstall_Pre_Routine_NA;
+          ++ctx->Map.pci[ 3 ]
         ) {
           for (
-            ctx->Map.pcs[ 4 ] = RtemsIntrReqEntryInstall_Pre_Init_Yes;
-            ctx->Map.pcs[ 4 ] < RtemsIntrReqEntryInstall_Pre_Init_NA;
-            ++ctx->Map.pcs[ 4 ]
+            ctx->Map.pci[ 4 ] = RtemsIntrReqEntryInstall_Pre_Init_Yes;
+            ctx->Map.pci[ 4 ] < RtemsIntrReqEntryInstall_Pre_Init_NA;
+            ++ctx->Map.pci[ 4 ]
           ) {
             for (
-              ctx->Map.pcs[ 5 ] = RtemsIntrReqEntryInstall_Pre_ISR_Yes;
-              ctx->Map.pcs[ 5 ] < RtemsIntrReqEntryInstall_Pre_ISR_NA;
-              ++ctx->Map.pcs[ 5 ]
+              ctx->Map.pci[ 5 ] = RtemsIntrReqEntryInstall_Pre_ISR_Yes;
+              ctx->Map.pci[ 5 ] < RtemsIntrReqEntryInstall_Pre_ISR_NA;
+              ++ctx->Map.pci[ 5 ]
             ) {
               for (
-                ctx->Map.pcs[ 6 ] = RtemsIntrReqEntryInstall_Pre_CanEnable_Yes;
-                ctx->Map.pcs[ 6 ] < RtemsIntrReqEntryInstall_Pre_CanEnable_NA;
-                ++ctx->Map.pcs[ 6 ]
+                ctx->Map.pci[ 6 ] = RtemsIntrReqEntryInstall_Pre_CanEnable_Yes;
+                ctx->Map.pci[ 6 ] < RtemsIntrReqEntryInstall_Pre_CanEnable_NA;
+                ++ctx->Map.pci[ 6 ]
               ) {
                 for (
-                  ctx->Map.pcs[ 7 ] = RtemsIntrReqEntryInstall_Pre_Installed_None;
-                  ctx->Map.pcs[ 7 ] < RtemsIntrReqEntryInstall_Pre_Installed_NA;
-                  ++ctx->Map.pcs[ 7 ]
+                  ctx->Map.pci[ 7 ] = RtemsIntrReqEntryInstall_Pre_Installed_None;
+                  ctx->Map.pci[ 7 ] < RtemsIntrReqEntryInstall_Pre_Installed_NA;
+                  ++ctx->Map.pci[ 7 ]
                 ) {
                   ctx->Map.entry = RtemsIntrReqEntryInstall_PopEntry( ctx );
+                  RtemsIntrReqEntryInstall_SetPreConditionStates( ctx );
                   RtemsIntrReqEntryInstall_Prepare( ctx );
                   RtemsIntrReqEntryInstall_TestVariant( ctx );
                   RtemsIntrReqEntryInstall_Cleanup( ctx );
diff --git a/testsuites/validation/tc-intr-entry-remove.c b/testsuites/validation/tc-intr-entry-remove.c
index ad07464..c73bcbb 100644
--- a/testsuites/validation/tc-intr-entry-remove.c
+++ b/testsuites/validation/tc-intr-entry-remove.c
@@ -63,7 +63,7 @@
  * @defgroup RTEMSTestCaseRtemsIntrReqEntryRemove \
  *   spec:/rtems/intr/req/entry-remove
  *
- * @ingroup RTEMSTestSuiteTestsuitesValidation0
+ * @ingroup RTEMSTestSuiteTestsuitesValidationIntr
  *
  * @{
  */
@@ -290,6 +290,12 @@ typedef struct {
 
   struct {
     /**
+     * @brief This member defines the pre-condition indices for the next
+     *   action.
+     */
+    size_t pci[ 9 ];
+
+    /**
      * @brief This member defines the pre-condition states for the next action.
      */
     size_t pcs[ 9 ];
@@ -1023,7 +1029,7 @@ static void RtemsIntrReqEntryRemove_Post_Installed_Check(
 
       if ( expected_entries > 0 ) {
         ctx->entry_counter = 0;
-        bsp_interrupt_handler_dispatch( ctx->test_vector );
+        bsp_interrupt_handler_dispatch_unchecked( ctx->test_vector );
         T_eq_u32( ctx->entry_counter, 0 );
       } else {
         rtems_interrupt_entry *first;
@@ -1063,7 +1069,7 @@ static void RtemsIntrReqEntryRemove_Post_Installed_Check(
 
       if ( ctx->installed ) {
         ctx->entry_counter = 0;
-        bsp_interrupt_handler_dispatch( ctx->test_vector );
+        bsp_interrupt_handler_dispatch_unchecked( ctx->test_vector );
         T_eq_u32( ctx->entry_counter, 1 );
       }
       break;
@@ -1304,34 +1310,60 @@ static inline RtemsIntrReqEntryRemove_Entry RtemsIntrReqEntryRemove_PopEntry(
   ];
 }
 
+static void RtemsIntrReqEntryRemove_SetPreConditionStates(
+  RtemsIntrReqEntryRemove_Context *ctx
+)
+{
+  ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
+  ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
+
+  if ( ctx->Map.entry.Pre_Routine_NA ) {
+    ctx->Map.pcs[ 2 ] = RtemsIntrReqEntryRemove_Pre_Routine_NA;
+  } else {
+    ctx->Map.pcs[ 2 ] = ctx->Map.pci[ 2 ];
+  }
+
+  if ( ctx->Map.entry.Pre_EntryObj_NA ) {
+    ctx->Map.pcs[ 3 ] = RtemsIntrReqEntryRemove_Pre_EntryObj_NA;
+  } else {
+    ctx->Map.pcs[ 3 ] = ctx->Map.pci[ 3 ];
+  }
+
+  ctx->Map.pcs[ 4 ] = ctx->Map.pci[ 4 ];
+  ctx->Map.pcs[ 5 ] = ctx->Map.pci[ 5 ];
+
+  if ( ctx->Map.entry.Pre_CanDisable_NA ) {
+    ctx->Map.pcs[ 6 ] = RtemsIntrReqEntryRemove_Pre_CanDisable_NA;
+  } else {
+    ctx->Map.pcs[ 6 ] = ctx->Map.pci[ 6 ];
+  }
+
+  if ( ctx->Map.entry.Pre_First_NA ) {
+    ctx->Map.pcs[ 7 ] = RtemsIntrReqEntryRemove_Pre_First_NA;
+  } else {
+    ctx->Map.pcs[ 7 ] = ctx->Map.pci[ 7 ];
+  }
+
+  if ( ctx->Map.entry.Pre_Last_NA ) {
+    ctx->Map.pcs[ 8 ] = RtemsIntrReqEntryRemove_Pre_Last_NA;
+  } else {
+    ctx->Map.pcs[ 8 ] = ctx->Map.pci[ 8 ];
+  }
+}
+
 static void RtemsIntrReqEntryRemove_TestVariant(
   RtemsIntrReqEntryRemove_Context *ctx
 )
 {
   RtemsIntrReqEntryRemove_Pre_Vector_Prepare( ctx, ctx->Map.pcs[ 0 ] );
   RtemsIntrReqEntryRemove_Pre_Entry_Prepare( ctx, ctx->Map.pcs[ 1 ] );
-  RtemsIntrReqEntryRemove_Pre_Routine_Prepare(
-    ctx,
-    ctx->Map.entry.Pre_Routine_NA ? RtemsIntrReqEntryRemove_Pre_Routine_NA : ctx->Map.pcs[ 2 ]
-  );
-  RtemsIntrReqEntryRemove_Pre_EntryObj_Prepare(
-    ctx,
-    ctx->Map.entry.Pre_EntryObj_NA ? RtemsIntrReqEntryRemove_Pre_EntryObj_NA : ctx->Map.pcs[ 3 ]
-  );
+  RtemsIntrReqEntryRemove_Pre_Routine_Prepare( ctx, ctx->Map.pcs[ 2 ] );
+  RtemsIntrReqEntryRemove_Pre_EntryObj_Prepare( ctx, ctx->Map.pcs[ 3 ] );
   RtemsIntrReqEntryRemove_Pre_Init_Prepare( ctx, ctx->Map.pcs[ 4 ] );
   RtemsIntrReqEntryRemove_Pre_ISR_Prepare( ctx, ctx->Map.pcs[ 5 ] );
-  RtemsIntrReqEntryRemove_Pre_CanDisable_Prepare(
-    ctx,
-    ctx->Map.entry.Pre_CanDisable_NA ? RtemsIntrReqEntryRemove_Pre_CanDisable_NA : ctx->Map.pcs[ 6 ]
-  );
-  RtemsIntrReqEntryRemove_Pre_First_Prepare(
-    ctx,
-    ctx->Map.entry.Pre_First_NA ? RtemsIntrReqEntryRemove_Pre_First_NA : ctx->Map.pcs[ 7 ]
-  );
-  RtemsIntrReqEntryRemove_Pre_Last_Prepare(
-    ctx,
-    ctx->Map.entry.Pre_Last_NA ? RtemsIntrReqEntryRemove_Pre_Last_NA : ctx->Map.pcs[ 8 ]
-  );
+  RtemsIntrReqEntryRemove_Pre_CanDisable_Prepare( ctx, ctx->Map.pcs[ 6 ] );
+  RtemsIntrReqEntryRemove_Pre_First_Prepare( ctx, ctx->Map.pcs[ 7 ] );
+  RtemsIntrReqEntryRemove_Pre_Last_Prepare( ctx, ctx->Map.pcs[ 8 ] );
   RtemsIntrReqEntryRemove_Action( ctx );
   RtemsIntrReqEntryRemove_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
   RtemsIntrReqEntryRemove_Post_Disabled_Check(
@@ -1359,51 +1391,52 @@ T_TEST_CASE_FIXTURE(
   ctx->Map.index = 0;
 
   for (
-    ctx->Map.pcs[ 0 ] = RtemsIntrReqEntryRemove_Pre_Vector_Valid;
-    ctx->Map.pcs[ 0 ] < RtemsIntrReqEntryRemove_Pre_Vector_NA;
-    ++ctx->Map.pcs[ 0 ]
+    ctx->Map.pci[ 0 ] = RtemsIntrReqEntryRemove_Pre_Vector_Valid;
+    ctx->Map.pci[ 0 ] < RtemsIntrReqEntryRemove_Pre_Vector_NA;
+    ++ctx->Map.pci[ 0 ]
   ) {
     for (
-      ctx->Map.pcs[ 1 ] = RtemsIntrReqEntryRemove_Pre_Entry_Obj;
-      ctx->Map.pcs[ 1 ] < RtemsIntrReqEntryRemove_Pre_Entry_NA;
-      ++ctx->Map.pcs[ 1 ]
+      ctx->Map.pci[ 1 ] = RtemsIntrReqEntryRemove_Pre_Entry_Obj;
+      ctx->Map.pci[ 1 ] < RtemsIntrReqEntryRemove_Pre_Entry_NA;
+      ++ctx->Map.pci[ 1 ]
     ) {
       for (
-        ctx->Map.pcs[ 2 ] = RtemsIntrReqEntryRemove_Pre_Routine_Valid;
-        ctx->Map.pcs[ 2 ] < RtemsIntrReqEntryRemove_Pre_Routine_NA;
-        ++ctx->Map.pcs[ 2 ]
+        ctx->Map.pci[ 2 ] = RtemsIntrReqEntryRemove_Pre_Routine_Valid;
+        ctx->Map.pci[ 2 ] < RtemsIntrReqEntryRemove_Pre_Routine_NA;
+        ++ctx->Map.pci[ 2 ]
       ) {
         for (
-          ctx->Map.pcs[ 3 ] = RtemsIntrReqEntryRemove_Pre_EntryObj_Installed;
-          ctx->Map.pcs[ 3 ] < RtemsIntrReqEntryRemove_Pre_EntryObj_NA;
-          ++ctx->Map.pcs[ 3 ]
+          ctx->Map.pci[ 3 ] = RtemsIntrReqEntryRemove_Pre_EntryObj_Installed;
+          ctx->Map.pci[ 3 ] < RtemsIntrReqEntryRemove_Pre_EntryObj_NA;
+          ++ctx->Map.pci[ 3 ]
         ) {
           for (
-            ctx->Map.pcs[ 4 ] = RtemsIntrReqEntryRemove_Pre_Init_Yes;
-            ctx->Map.pcs[ 4 ] < RtemsIntrReqEntryRemove_Pre_Init_NA;
-            ++ctx->Map.pcs[ 4 ]
+            ctx->Map.pci[ 4 ] = RtemsIntrReqEntryRemove_Pre_Init_Yes;
+            ctx->Map.pci[ 4 ] < RtemsIntrReqEntryRemove_Pre_Init_NA;
+            ++ctx->Map.pci[ 4 ]
           ) {
             for (
-              ctx->Map.pcs[ 5 ] = RtemsIntrReqEntryRemove_Pre_ISR_Yes;
-              ctx->Map.pcs[ 5 ] < RtemsIntrReqEntryRemove_Pre_ISR_NA;
-              ++ctx->Map.pcs[ 5 ]
+              ctx->Map.pci[ 5 ] = RtemsIntrReqEntryRemove_Pre_ISR_Yes;
+              ctx->Map.pci[ 5 ] < RtemsIntrReqEntryRemove_Pre_ISR_NA;
+              ++ctx->Map.pci[ 5 ]
             ) {
               for (
-                ctx->Map.pcs[ 6 ] = RtemsIntrReqEntryRemove_Pre_CanDisable_Yes;
-                ctx->Map.pcs[ 6 ] < RtemsIntrReqEntryRemove_Pre_CanDisable_NA;
-                ++ctx->Map.pcs[ 6 ]
+                ctx->Map.pci[ 6 ] = RtemsIntrReqEntryRemove_Pre_CanDisable_Yes;
+                ctx->Map.pci[ 6 ] < RtemsIntrReqEntryRemove_Pre_CanDisable_NA;
+                ++ctx->Map.pci[ 6 ]
               ) {
                 for (
-                  ctx->Map.pcs[ 7 ] = RtemsIntrReqEntryRemove_Pre_First_Yes;
-                  ctx->Map.pcs[ 7 ] < RtemsIntrReqEntryRemove_Pre_First_NA;
-                  ++ctx->Map.pcs[ 7 ]
+                  ctx->Map.pci[ 7 ] = RtemsIntrReqEntryRemove_Pre_First_Yes;
+                  ctx->Map.pci[ 7 ] < RtemsIntrReqEntryRemove_Pre_First_NA;
+                  ++ctx->Map.pci[ 7 ]
                 ) {
                   for (
-                    ctx->Map.pcs[ 8 ] = RtemsIntrReqEntryRemove_Pre_Last_Yes;
-                    ctx->Map.pcs[ 8 ] < RtemsIntrReqEntryRemove_Pre_Last_NA;
-                    ++ctx->Map.pcs[ 8 ]
+                    ctx->Map.pci[ 8 ] = RtemsIntrReqEntryRemove_Pre_Last_Yes;
+                    ctx->Map.pci[ 8 ] < RtemsIntrReqEntryRemove_Pre_Last_NA;
+                    ++ctx->Map.pci[ 8 ]
                   ) {
                     ctx->Map.entry = RtemsIntrReqEntryRemove_PopEntry( ctx );
+                    RtemsIntrReqEntryRemove_SetPreConditionStates( ctx );
                     RtemsIntrReqEntryRemove_Prepare( ctx );
                     RtemsIntrReqEntryRemove_TestVariant( ctx );
                     RtemsIntrReqEntryRemove_Cleanup( ctx );
diff --git a/testsuites/validation/tc-intr-get-affinity.c b/testsuites/validation/tc-intr-get-affinity.c
index 375a131..277cb79 100644
--- a/testsuites/validation/tc-intr-get-affinity.c
+++ b/testsuites/validation/tc-intr-get-affinity.c
@@ -64,7 +64,7 @@
  * @defgroup RTEMSTestCaseRtemsIntrReqGetAffinity \
  *   spec:/rtems/intr/req/get-affinity
  *
- * @ingroup RTEMSTestSuiteTestsuitesValidation0
+ * @ingroup RTEMSTestSuiteTestsuitesValidationIntr
  *
  * @{
  */
@@ -165,6 +165,12 @@ typedef struct {
 
   struct {
     /**
+     * @brief This member defines the pre-condition indices for the next
+     *   action.
+     */
+    size_t pci[ 4 ];
+
+    /**
      * @brief This member defines the pre-condition states for the next action.
      */
     size_t pcs[ 4 ];
@@ -642,6 +648,21 @@ static inline RtemsIntrReqGetAffinity_Entry RtemsIntrReqGetAffinity_PopEntry(
   ];
 }
 
+static void RtemsIntrReqGetAffinity_SetPreConditionStates(
+  RtemsIntrReqGetAffinity_Context *ctx
+)
+{
+  ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
+  ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
+  ctx->Map.pcs[ 2 ] = ctx->Map.pci[ 2 ];
+
+  if ( ctx->Map.entry.Pre_CanGetAffinity_NA ) {
+    ctx->Map.pcs[ 3 ] = RtemsIntrReqGetAffinity_Pre_CanGetAffinity_NA;
+  } else {
+    ctx->Map.pcs[ 3 ] = ctx->Map.pci[ 3 ];
+  }
+}
+
 static void RtemsIntrReqGetAffinity_TestVariant(
   RtemsIntrReqGetAffinity_Context *ctx
 )
@@ -649,10 +670,7 @@ static void RtemsIntrReqGetAffinity_TestVariant(
   RtemsIntrReqGetAffinity_Pre_Vector_Prepare( ctx, ctx->Map.pcs[ 0 ] );
   RtemsIntrReqGetAffinity_Pre_CPUSetSize_Prepare( ctx, ctx->Map.pcs[ 1 ] );
   RtemsIntrReqGetAffinity_Pre_CPUSet_Prepare( ctx, ctx->Map.pcs[ 2 ] );
-  RtemsIntrReqGetAffinity_Pre_CanGetAffinity_Prepare(
-    ctx,
-    ctx->Map.entry.Pre_CanGetAffinity_NA ? RtemsIntrReqGetAffinity_Pre_CanGetAffinity_NA : ctx->Map.pcs[ 3 ]
-  );
+  RtemsIntrReqGetAffinity_Pre_CanGetAffinity_Prepare( ctx, ctx->Map.pcs[ 3 ] );
   RtemsIntrReqGetAffinity_Action( ctx );
   RtemsIntrReqGetAffinity_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
   RtemsIntrReqGetAffinity_Post_CPUSetObj_Check(
@@ -676,26 +694,27 @@ T_TEST_CASE_FIXTURE(
   ctx->Map.index = 0;
 
   for (
-    ctx->Map.pcs[ 0 ] = RtemsIntrReqGetAffinity_Pre_Vector_Valid;
-    ctx->Map.pcs[ 0 ] < RtemsIntrReqGetAffinity_Pre_Vector_NA;
-    ++ctx->Map.pcs[ 0 ]
+    ctx->Map.pci[ 0 ] = RtemsIntrReqGetAffinity_Pre_Vector_Valid;
+    ctx->Map.pci[ 0 ] < RtemsIntrReqGetAffinity_Pre_Vector_NA;
+    ++ctx->Map.pci[ 0 ]
   ) {
     for (
-      ctx->Map.pcs[ 1 ] = RtemsIntrReqGetAffinity_Pre_CPUSetSize_Valid;
-      ctx->Map.pcs[ 1 ] < RtemsIntrReqGetAffinity_Pre_CPUSetSize_NA;
-      ++ctx->Map.pcs[ 1 ]
+      ctx->Map.pci[ 1 ] = RtemsIntrReqGetAffinity_Pre_CPUSetSize_Valid;
+      ctx->Map.pci[ 1 ] < RtemsIntrReqGetAffinity_Pre_CPUSetSize_NA;
+      ++ctx->Map.pci[ 1 ]
     ) {
       for (
-        ctx->Map.pcs[ 2 ] = RtemsIntrReqGetAffinity_Pre_CPUSet_Valid;
-        ctx->Map.pcs[ 2 ] < RtemsIntrReqGetAffinity_Pre_CPUSet_NA;
-        ++ctx->Map.pcs[ 2 ]
+        ctx->Map.pci[ 2 ] = RtemsIntrReqGetAffinity_Pre_CPUSet_Valid;
+        ctx->Map.pci[ 2 ] < RtemsIntrReqGetAffinity_Pre_CPUSet_NA;
+        ++ctx->Map.pci[ 2 ]
       ) {
         for (
-          ctx->Map.pcs[ 3 ] = RtemsIntrReqGetAffinity_Pre_CanGetAffinity_Yes;
-          ctx->Map.pcs[ 3 ] < RtemsIntrReqGetAffinity_Pre_CanGetAffinity_NA;
-          ++ctx->Map.pcs[ 3 ]
+          ctx->Map.pci[ 3 ] = RtemsIntrReqGetAffinity_Pre_CanGetAffinity_Yes;
+          ctx->Map.pci[ 3 ] < RtemsIntrReqGetAffinity_Pre_CanGetAffinity_NA;
+          ++ctx->Map.pci[ 3 ]
         ) {
           ctx->Map.entry = RtemsIntrReqGetAffinity_PopEntry( ctx );
+          RtemsIntrReqGetAffinity_SetPreConditionStates( ctx );
           RtemsIntrReqGetAffinity_TestVariant( ctx );
         }
       }
diff --git a/testsuites/validation/tc-intr-get-attributes.c b/testsuites/validation/tc-intr-get-attributes.c
index f64eef1..713defa 100644
--- a/testsuites/validation/tc-intr-get-attributes.c
+++ b/testsuites/validation/tc-intr-get-attributes.c
@@ -62,7 +62,7 @@
  * @defgroup RTEMSTestCaseRtemsIntrReqGetAttributes \
  *   spec:/rtems/intr/req/get-attributes
  *
- * @ingroup RTEMSTestSuiteTestsuitesValidation0
+ * @ingroup RTEMSTestSuiteTestsuitesValidationIntr
  *
  * @{
  */
diff --git a/testsuites/validation/tc-intr-handler-iterate.c b/testsuites/validation/tc-intr-handler-iterate.c
index e643eb5..77b9b2b 100644
--- a/testsuites/validation/tc-intr-handler-iterate.c
+++ b/testsuites/validation/tc-intr-handler-iterate.c
@@ -63,7 +63,7 @@
  * @defgroup RTEMSTestCaseRtemsIntrReqHandlerIterate \
  *   spec:/rtems/intr/req/handler-iterate
  *
- * @ingroup RTEMSTestSuiteTestsuitesValidation0
+ * @ingroup RTEMSTestSuiteTestsuitesValidationIntr
  *
  * @{
  */
diff --git a/testsuites/validation/tc-intr-is-pending.c b/testsuites/validation/tc-intr-is-pending.c
index 4963827..93be686 100644
--- a/testsuites/validation/tc-intr-is-pending.c
+++ b/testsuites/validation/tc-intr-is-pending.c
@@ -63,7 +63,7 @@
 /**
  * @defgroup RTEMSTestCaseRtemsIntrReqIsPending spec:/rtems/intr/req/is-pending
  *
- * @ingroup RTEMSTestSuiteTestsuitesValidation0
+ * @ingroup RTEMSTestSuiteTestsuitesValidationIntr
  *
  * @{
  */
@@ -152,6 +152,12 @@ typedef struct {
 
   struct {
     /**
+     * @brief This member defines the pre-condition indices for the next
+     *   action.
+     */
+    size_t pci[ 3 ];
+
+    /**
      * @brief This member defines the pre-condition states for the next action.
      */
     size_t pcs[ 3 ];
@@ -284,14 +290,21 @@ static void CheckIsPending(
   if ( has_installed_entries ) {
     /*
      * We cannot test this vector thoroughly, since it is used by a device
-     * driver.
+     * driver.  It may be pending or not.  For example in SMP configurations,
+     * it may be pending while being serviced right now on another processor.
      */
-    T_false( IsPending( ctx ) );
+    (void) IsPending( ctx );
   } else if ( !attr->is_maskable ) {
     /* We can only safely test maskable interrupts */
     T_false( IsPending( ctx ) );
+  } else if ( IsPending( ctx ) ) {
+    /*
+     * If there is already an interrupt pending, then it is probably raised
+     * by a peripheral which we cannot control.
+     */
   } else if (
-    attr->can_disable && ( attr->can_clear || attr->cleared_by_acknowledge )
+    attr->can_raise && attr->can_disable &&
+    ( attr->can_clear || attr->cleared_by_acknowledge )
   ) {
     rtems_interrupt_entry entry;
     rtems_interrupt_level level;
@@ -307,19 +320,21 @@ static void CheckIsPending(
     T_rsc_success( sc );
 
     if ( !IsPending( ctx) && ( attr->can_enable || IsEnabled( ctx ) ) ) {
-      if ( attr->can_disable ) {
-        Disable( ctx );
-        Raise( ctx );
-        T_true( IsPending( ctx ) );
-
-        sc = rtems_interrupt_vector_enable( ctx->vector );
-        T_rsc_success( sc );
-
-        while ( ctx->interrupt_count < 1 ) {
-          /* Wait */
-        }
-      } else {
-        ++ctx->interrupt_count;
+      Disable( ctx );
+      Raise( ctx );
+
+      /*
+       * Some interrupt controllers will signal a pending interrupt if it is
+       * disabled (for example ARM GIC), others will not signal a pending
+       * interrupt if it is disabled (for example Freescale/NXP MPIC).
+       */
+      (void) IsPending( ctx );
+
+      sc = rtems_interrupt_vector_enable( ctx->vector );
+      T_rsc_success( sc );
+
+      while ( ctx->interrupt_count < 1 ) {
+        /* Wait */
       }
 
       rtems_interrupt_local_disable( level );
@@ -593,16 +608,27 @@ static inline RtemsIntrReqIsPending_Entry RtemsIntrReqIsPending_PopEntry(
   ];
 }
 
+static void RtemsIntrReqIsPending_SetPreConditionStates(
+  RtemsIntrReqIsPending_Context *ctx
+)
+{
+  ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
+  ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
+
+  if ( ctx->Map.entry.Pre_IsPending_NA ) {
+    ctx->Map.pcs[ 2 ] = RtemsIntrReqIsPending_Pre_IsPending_NA;
+  } else {
+    ctx->Map.pcs[ 2 ] = ctx->Map.pci[ 2 ];
+  }
+}
+
 static void RtemsIntrReqIsPending_TestVariant(
   RtemsIntrReqIsPending_Context *ctx
 )
 {
   RtemsIntrReqIsPending_Pre_Vector_Prepare( ctx, ctx->Map.pcs[ 0 ] );
   RtemsIntrReqIsPending_Pre_Pending_Prepare( ctx, ctx->Map.pcs[ 1 ] );
-  RtemsIntrReqIsPending_Pre_IsPending_Prepare(
-    ctx,
-    ctx->Map.entry.Pre_IsPending_NA ? RtemsIntrReqIsPending_Pre_IsPending_NA : ctx->Map.pcs[ 2 ]
-  );
+  RtemsIntrReqIsPending_Pre_IsPending_Prepare( ctx, ctx->Map.pcs[ 2 ] );
   RtemsIntrReqIsPending_Action( ctx );
   RtemsIntrReqIsPending_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
   RtemsIntrReqIsPending_Post_IsPending_Check(
@@ -623,21 +649,22 @@ T_TEST_CASE_FIXTURE( RtemsIntrReqIsPending, &RtemsIntrReqIsPending_Fixture )
   ctx->Map.index = 0;
 
   for (
-    ctx->Map.pcs[ 0 ] = RtemsIntrReqIsPending_Pre_Vector_Valid;
-    ctx->Map.pcs[ 0 ] < RtemsIntrReqIsPending_Pre_Vector_NA;
-    ++ctx->Map.pcs[ 0 ]
+    ctx->Map.pci[ 0 ] = RtemsIntrReqIsPending_Pre_Vector_Valid;
+    ctx->Map.pci[ 0 ] < RtemsIntrReqIsPending_Pre_Vector_NA;
+    ++ctx->Map.pci[ 0 ]
   ) {
     for (
-      ctx->Map.pcs[ 1 ] = RtemsIntrReqIsPending_Pre_Pending_Obj;
-      ctx->Map.pcs[ 1 ] < RtemsIntrReqIsPending_Pre_Pending_NA;
-      ++ctx->Map.pcs[ 1 ]
+      ctx->Map.pci[ 1 ] = RtemsIntrReqIsPending_Pre_Pending_Obj;
+      ctx->Map.pci[ 1 ] < RtemsIntrReqIsPending_Pre_Pending_NA;
+      ++ctx->Map.pci[ 1 ]
     ) {
       for (
-        ctx->Map.pcs[ 2 ] = RtemsIntrReqIsPending_Pre_IsPending_Yes;
-        ctx->Map.pcs[ 2 ] < RtemsIntrReqIsPending_Pre_IsPending_NA;
-        ++ctx->Map.pcs[ 2 ]
+        ctx->Map.pci[ 2 ] = RtemsIntrReqIsPending_Pre_IsPending_Yes;
+        ctx->Map.pci[ 2 ] < RtemsIntrReqIsPending_Pre_IsPending_NA;
+        ++ctx->Map.pci[ 2 ]
       ) {
         ctx->Map.entry = RtemsIntrReqIsPending_PopEntry( ctx );
+        RtemsIntrReqIsPending_SetPreConditionStates( ctx );
         RtemsIntrReqIsPending_TestVariant( ctx );
       }
     }
diff --git a/testsuites/validation/tc-intr-non-smp.c b/testsuites/validation/tc-intr-non-smp.c
new file mode 100644
index 0000000..bb75ccc
--- /dev/null
+++ b/testsuites/validation/tc-intr-non-smp.c
@@ -0,0 +1,171 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSTestCaseRtemsIntrValIntrNonSmp
+ */
+
+/*
+ * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * 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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include "tx-support.h"
+
+#include <rtems/test.h>
+
+/**
+ * @defgroup RTEMSTestCaseRtemsIntrValIntrNonSmp \
+ *   spec:/rtems/intr/val/intr-non-smp
+ *
+ * @ingroup RTEMSTestSuiteTestsuitesValidationNonSmp
+ *
+ * @brief Tests some @ref RTEMSAPIClassicIntr interfaces.
+ *
+ * This test case performs the following actions:
+ *
+ * - Validate some interrupt lock macros.
+ *
+ *   - Check that RTEMS_INTERRUPT_LOCK_DECLARE() expands to white space only.
+ *
+ *   - Check that RTEMS_INTERRUPT_LOCK_DEFINE() expands to white space only.
+ *
+ *   - Check that RTEMS_INTERRUPT_LOCK_MEMBER() expands to white space only.
+ *
+ *   - Check that RTEMS_INTERRUPT_LOCK_REFERENCE() expands to white space only.
+ *
+ *   - Check that rtems_interrupt_lock_destroy() expands to white space only.
+ *
+ *   - Check that RTEMS_INTERRUPT_LOCK_INITIALIZER() expands to an empty
+ *     structure initializer.
+ *
+ *   - Check that rtems_interrupt_lock_initialize() expands to white space
+ *     only.
+ *
+ *   - Check that rtems_interrupt_lock_acquire_isr() expands to a code block
+ *     which marks the second parameter as used.
+ *
+ *   - Check that rtems_interrupt_lock_release_isr() expands to a code block
+ *     which marks the second parameter as used.
+ *
+ * @{
+ */
+
+/**
+ * @brief Validate some interrupt lock macros.
+ */
+static void RtemsIntrValIntrNonSmp_Action_0( void )
+{
+  const char *s;
+
+  /*
+   * Check that RTEMS_INTERRUPT_LOCK_DECLARE() expands to white space only.
+   */
+  s = RTEMS_XSTRING( RTEMS_INTERRUPT_LOCK_DECLARE( x, y ) );
+  T_true( IsWhiteSpaceOnly( s ) );
+
+  /*
+   * Check that RTEMS_INTERRUPT_LOCK_DEFINE() expands to white space only.
+   */
+  s = RTEMS_XSTRING( RTEMS_INTERRUPT_LOCK_DEFINE( x, y, z ) );
+  T_true( IsWhiteSpaceOnly( s ) );
+
+  /*
+   * Check that RTEMS_INTERRUPT_LOCK_MEMBER() expands to white space only.
+   */
+  s = RTEMS_XSTRING( RTEMS_INTERRUPT_LOCK_MEMBER( x ) );
+  T_true( IsWhiteSpaceOnly( s ) );
+
+  /*
+   * Check that RTEMS_INTERRUPT_LOCK_REFERENCE() expands to white space only.
+   */
+  s = RTEMS_XSTRING( RTEMS_INTERRUPT_LOCK_REFERENCE( x, y ) );
+  T_true( IsWhiteSpaceOnly( s ) );
+
+  /*
+   * Check that rtems_interrupt_lock_destroy() expands to white space only.
+   */
+  s = RTEMS_XSTRING( rtems_interrupt_lock_destroy( x ) );
+  T_true( IsWhiteSpaceOnly( s ) );
+
+  /*
+   * Check that RTEMS_INTERRUPT_LOCK_INITIALIZER() expands to an empty
+   * structure initializer.
+   */
+  s = RTEMS_XSTRING( RTEMS_INTERRUPT_LOCK_INITIALIZER( x ) );
+  T_true( IsEqualIgnoreWhiteSpace( s, "{}" ) );
+
+  /*
+   * Check that rtems_interrupt_lock_initialize() expands to white space only.
+   */
+  s = RTEMS_XSTRING( rtems_interrupt_lock_initialize( x, y ) );
+  T_true( IsWhiteSpaceOnly( s ) );
+
+  /*
+   * Check that rtems_interrupt_lock_acquire_isr() expands to a code block
+   * which marks the second parameter as used.
+   */
+  s = RTEMS_XSTRING( rtems_interrupt_lock_acquire_isr( x, y ) );
+  T_true( IsEqualIgnoreWhiteSpace( s, "do{(void)y;}while(0)" ) );
+
+  /*
+   * Check that rtems_interrupt_lock_release_isr() expands to a code block
+   * which marks the second parameter as used.
+   */
+  s = RTEMS_XSTRING( rtems_interrupt_lock_release_isr( x, y ) );
+  T_true( IsEqualIgnoreWhiteSpace( s, "do{(void)y;}while(0)" ) );
+}
+
+/**
+ * @fn void T_case_body_RtemsIntrValIntrNonSmp( void )
+ */
+T_TEST_CASE( RtemsIntrValIntrNonSmp )
+{
+  RtemsIntrValIntrNonSmp_Action_0();
+}
+
+/** @} */
diff --git a/testsuites/validation/tc-intr-raise-on.c b/testsuites/validation/tc-intr-raise-on.c
index efe468a..4d30525 100644
--- a/testsuites/validation/tc-intr-raise-on.c
+++ b/testsuites/validation/tc-intr-raise-on.c
@@ -63,7 +63,7 @@
 /**
  * @defgroup RTEMSTestCaseRtemsIntrReqRaiseOn spec:/rtems/intr/req/raise-on
  *
- * @ingroup RTEMSTestSuiteTestsuitesValidation0
+ * @ingroup RTEMSTestSuiteTestsuitesValidationIntr
  *
  * @{
  */
@@ -154,6 +154,12 @@ typedef struct {
 
   struct {
     /**
+     * @brief This member defines the pre-condition indices for the next
+     *   action.
+     */
+    size_t pci[ 3 ];
+
+    /**
      * @brief This member defines the pre-condition states for the next action.
      */
     size_t pcs[ 3 ];
@@ -332,21 +338,21 @@ static void CheckRaiseOn(
     T_rsc_success( sc );
 
     if ( !IsPending( ctx) && ( attr->can_enable || IsEnabled( ctx ) ) ) {
-      T_false( IsPending( ctx ) );
+      Disable( ctx );
+      RaiseOn( ctx );
 
-      if ( attr->can_disable ) {
-        Disable( ctx );
-        RaiseOn( ctx );
-        T_true( IsPending( ctx ) );
+      /*
+       * Some interrupt controllers will signal a pending interrupt if it is
+       * disabled (for example ARM GIC), others will not signal a pending
+       * interrupt if it is disabled (for example Freescale/NXP MPIC).
+       */
+      (void) IsPending( ctx );
 
-        sc = rtems_interrupt_vector_enable( ctx->vector );
-        T_rsc_success( sc );
+      sc = rtems_interrupt_vector_enable( ctx->vector );
+      T_rsc_success( sc );
 
-        while ( ctx->interrupt_count < 1 ) {
-          /* Wait */
-        }
-      } else {
-        ++ctx->interrupt_count;
+      while ( ctx->interrupt_count < 1 ) {
+        /* Wait */
       }
 
       T_false( IsPending( ctx ) );
@@ -672,14 +678,25 @@ static inline RtemsIntrReqRaiseOn_Entry RtemsIntrReqRaiseOn_PopEntry(
   ];
 }
 
+static void RtemsIntrReqRaiseOn_SetPreConditionStates(
+  RtemsIntrReqRaiseOn_Context *ctx
+)
+{
+  ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
+  ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
+
+  if ( ctx->Map.entry.Pre_CanRaiseOn_NA ) {
+    ctx->Map.pcs[ 2 ] = RtemsIntrReqRaiseOn_Pre_CanRaiseOn_NA;
+  } else {
+    ctx->Map.pcs[ 2 ] = ctx->Map.pci[ 2 ];
+  }
+}
+
 static void RtemsIntrReqRaiseOn_TestVariant( RtemsIntrReqRaiseOn_Context *ctx )
 {
   RtemsIntrReqRaiseOn_Pre_Vector_Prepare( ctx, ctx->Map.pcs[ 0 ] );
   RtemsIntrReqRaiseOn_Pre_CPU_Prepare( ctx, ctx->Map.pcs[ 1 ] );
-  RtemsIntrReqRaiseOn_Pre_CanRaiseOn_Prepare(
-    ctx,
-    ctx->Map.entry.Pre_CanRaiseOn_NA ? RtemsIntrReqRaiseOn_Pre_CanRaiseOn_NA : ctx->Map.pcs[ 2 ]
-  );
+  RtemsIntrReqRaiseOn_Pre_CanRaiseOn_Prepare( ctx, ctx->Map.pcs[ 2 ] );
   RtemsIntrReqRaiseOn_Action( ctx );
   RtemsIntrReqRaiseOn_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
   RtemsIntrReqRaiseOn_Post_Pending_Check( ctx, ctx->Map.entry.Post_Pending );
@@ -697,19 +714,19 @@ T_TEST_CASE_FIXTURE( RtemsIntrReqRaiseOn, &RtemsIntrReqRaiseOn_Fixture )
   ctx->Map.index = 0;
 
   for (
-    ctx->Map.pcs[ 0 ] = RtemsIntrReqRaiseOn_Pre_Vector_Valid;
-    ctx->Map.pcs[ 0 ] < RtemsIntrReqRaiseOn_Pre_Vector_NA;
-    ++ctx->Map.pcs[ 0 ]
+    ctx->Map.pci[ 0 ] = RtemsIntrReqRaiseOn_Pre_Vector_Valid;
+    ctx->Map.pci[ 0 ] < RtemsIntrReqRaiseOn_Pre_Vector_NA;
+    ++ctx->Map.pci[ 0 ]
   ) {
     for (
-      ctx->Map.pcs[ 1 ] = RtemsIntrReqRaiseOn_Pre_CPU_Online;
-      ctx->Map.pcs[ 1 ] < RtemsIntrReqRaiseOn_Pre_CPU_NA;
-      ++ctx->Map.pcs[ 1 ]
+      ctx->Map.pci[ 1 ] = RtemsIntrReqRaiseOn_Pre_CPU_Online;
+      ctx->Map.pci[ 1 ] < RtemsIntrReqRaiseOn_Pre_CPU_NA;
+      ++ctx->Map.pci[ 1 ]
     ) {
       for (
-        ctx->Map.pcs[ 2 ] = RtemsIntrReqRaiseOn_Pre_CanRaiseOn_Yes;
-        ctx->Map.pcs[ 2 ] < RtemsIntrReqRaiseOn_Pre_CanRaiseOn_NA;
-        ++ctx->Map.pcs[ 2 ]
+        ctx->Map.pci[ 2 ] = RtemsIntrReqRaiseOn_Pre_CanRaiseOn_Yes;
+        ctx->Map.pci[ 2 ] < RtemsIntrReqRaiseOn_Pre_CanRaiseOn_NA;
+        ++ctx->Map.pci[ 2 ]
       ) {
         ctx->Map.entry = RtemsIntrReqRaiseOn_PopEntry( ctx );
 
@@ -717,6 +734,7 @@ T_TEST_CASE_FIXTURE( RtemsIntrReqRaiseOn, &RtemsIntrReqRaiseOn_Fixture )
           continue;
         }
 
+        RtemsIntrReqRaiseOn_SetPreConditionStates( ctx );
         RtemsIntrReqRaiseOn_TestVariant( ctx );
       }
     }
diff --git a/testsuites/validation/tc-intr-raise.c b/testsuites/validation/tc-intr-raise.c
index 81e8f8e..dde5f2c 100644
--- a/testsuites/validation/tc-intr-raise.c
+++ b/testsuites/validation/tc-intr-raise.c
@@ -63,7 +63,7 @@
 /**
  * @defgroup RTEMSTestCaseRtemsIntrReqRaise spec:/rtems/intr/req/raise
  *
- * @ingroup RTEMSTestSuiteTestsuitesValidation0
+ * @ingroup RTEMSTestSuiteTestsuitesValidationIntr
  *
  * @{
  */
@@ -134,6 +134,12 @@ typedef struct {
 
   struct {
     /**
+     * @brief This member defines the pre-condition indices for the next
+     *   action.
+     */
+    size_t pci[ 2 ];
+
+    /**
      * @brief This member defines the pre-condition states for the next action.
      */
     size_t pcs[ 2 ];
@@ -304,21 +310,21 @@ static void CheckRaise(
     T_rsc_success( sc );
 
     if ( !IsPending( ctx) && ( attr->can_enable || IsEnabled( ctx ) ) ) {
-      T_false( IsPending( ctx ) );
+      Disable( ctx );
+      Raise( ctx );
 
-      if ( attr->can_disable ) {
-        Disable( ctx );
-        Raise( ctx );
-        T_true( IsPending( ctx ) );
+      /*
+       * Some interrupt controllers will signal a pending interrupt if it is
+       * disabled (for example ARM GIC), others will not signal a pending
+       * interrupt if it is disabled (for example Freescale/NXP MPIC).
+       */
+      (void) IsPending( ctx );
 
-        sc = rtems_interrupt_vector_enable( ctx->vector );
-        T_rsc_success( sc );
+      sc = rtems_interrupt_vector_enable( ctx->vector );
+      T_rsc_success( sc );
 
-        while ( ctx->interrupt_count < 1 ) {
-          /* Wait */
-        }
-      } else {
-        ++ctx->interrupt_count;
+      while ( ctx->interrupt_count < 1 ) {
+        /* Wait */
       }
 
       T_false( IsPending( ctx ) );
@@ -550,13 +556,23 @@ static inline RtemsIntrReqRaise_Entry RtemsIntrReqRaise_PopEntry(
   ];
 }
 
+static void RtemsIntrReqRaise_SetPreConditionStates(
+  RtemsIntrReqRaise_Context *ctx
+)
+{
+  ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
+
+  if ( ctx->Map.entry.Pre_CanRaise_NA ) {
+    ctx->Map.pcs[ 1 ] = RtemsIntrReqRaise_Pre_CanRaise_NA;
+  } else {
+    ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
+  }
+}
+
 static void RtemsIntrReqRaise_TestVariant( RtemsIntrReqRaise_Context *ctx )
 {
   RtemsIntrReqRaise_Pre_Vector_Prepare( ctx, ctx->Map.pcs[ 0 ] );
-  RtemsIntrReqRaise_Pre_CanRaise_Prepare(
-    ctx,
-    ctx->Map.entry.Pre_CanRaise_NA ? RtemsIntrReqRaise_Pre_CanRaise_NA : ctx->Map.pcs[ 1 ]
-  );
+  RtemsIntrReqRaise_Pre_CanRaise_Prepare( ctx, ctx->Map.pcs[ 1 ] );
   RtemsIntrReqRaise_Action( ctx );
   RtemsIntrReqRaise_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
   RtemsIntrReqRaise_Post_Pending_Check( ctx, ctx->Map.entry.Post_Pending );
@@ -574,16 +590,17 @@ T_TEST_CASE_FIXTURE( RtemsIntrReqRaise, &RtemsIntrReqRaise_Fixture )
   ctx->Map.index = 0;
 
   for (
-    ctx->Map.pcs[ 0 ] = RtemsIntrReqRaise_Pre_Vector_Valid;
-    ctx->Map.pcs[ 0 ] < RtemsIntrReqRaise_Pre_Vector_NA;
-    ++ctx->Map.pcs[ 0 ]
+    ctx->Map.pci[ 0 ] = RtemsIntrReqRaise_Pre_Vector_Valid;
+    ctx->Map.pci[ 0 ] < RtemsIntrReqRaise_Pre_Vector_NA;
+    ++ctx->Map.pci[ 0 ]
   ) {
     for (
-      ctx->Map.pcs[ 1 ] = RtemsIntrReqRaise_Pre_CanRaise_Yes;
-      ctx->Map.pcs[ 1 ] < RtemsIntrReqRaise_Pre_CanRaise_NA;
-      ++ctx->Map.pcs[ 1 ]
+      ctx->Map.pci[ 1 ] = RtemsIntrReqRaise_Pre_CanRaise_Yes;
+      ctx->Map.pci[ 1 ] < RtemsIntrReqRaise_Pre_CanRaise_NA;
+      ++ctx->Map.pci[ 1 ]
     ) {
       ctx->Map.entry = RtemsIntrReqRaise_PopEntry( ctx );
+      RtemsIntrReqRaise_SetPreConditionStates( ctx );
       RtemsIntrReqRaise_TestVariant( ctx );
     }
   }
diff --git a/testsuites/validation/tc-intr-set-affinity.c b/testsuites/validation/tc-intr-set-affinity.c
index a2a6a45..0295fba 100644
--- a/testsuites/validation/tc-intr-set-affinity.c
+++ b/testsuites/validation/tc-intr-set-affinity.c
@@ -7,7 +7,7 @@
  */
 
 /*
- * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ * Copyright (C) 2021, 2022 embedded brains GmbH (http://www.embedded-brains.de)
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -63,7 +63,7 @@
  * @defgroup RTEMSTestCaseRtemsIntrReqSetAffinity \
  *   spec:/rtems/intr/req/set-affinity
  *
- * @ingroup RTEMSTestSuiteTestsuitesValidation0
+ * @ingroup RTEMSTestSuiteTestsuitesValidationIntr
  *
  * @{
  */
@@ -75,11 +75,23 @@ typedef enum {
 } RtemsIntrReqSetAffinity_Pre_Vector;
 
 typedef enum {
-  RtemsIntrReqSetAffinity_Pre_CPUSetKind_Valid,
-  RtemsIntrReqSetAffinity_Pre_CPUSetKind_Huge,
-  RtemsIntrReqSetAffinity_Pre_CPUSetKind_Askew,
-  RtemsIntrReqSetAffinity_Pre_CPUSetKind_NA
-} RtemsIntrReqSetAffinity_Pre_CPUSetKind;
+  RtemsIntrReqSetAffinity_Pre_CPUSetSize_Askew,
+  RtemsIntrReqSetAffinity_Pre_CPUSetSize_Normal,
+  RtemsIntrReqSetAffinity_Pre_CPUSetSize_Huge,
+  RtemsIntrReqSetAffinity_Pre_CPUSetSize_NA
+} RtemsIntrReqSetAffinity_Pre_CPUSetSize;
+
+typedef enum {
+  RtemsIntrReqSetAffinity_Pre_CPUSetOnline_Valid,
+  RtemsIntrReqSetAffinity_Pre_CPUSetOnline_Empty,
+  RtemsIntrReqSetAffinity_Pre_CPUSetOnline_NA
+} RtemsIntrReqSetAffinity_Pre_CPUSetOnline;
+
+typedef enum {
+  RtemsIntrReqSetAffinity_Pre_CPUSetHuge_NotZero,
+  RtemsIntrReqSetAffinity_Pre_CPUSetHuge_Zero,
+  RtemsIntrReqSetAffinity_Pre_CPUSetHuge_NA
+} RtemsIntrReqSetAffinity_Pre_CPUSetHuge;
 
 typedef enum {
   RtemsIntrReqSetAffinity_Pre_CPUSet_Valid,
@@ -103,7 +115,7 @@ typedef enum {
 } RtemsIntrReqSetAffinity_Post_Status;
 
 typedef enum {
-  RtemsIntrReqSetAffinity_Post_SetAffinity_Yes,
+  RtemsIntrReqSetAffinity_Post_SetAffinity_Set,
   RtemsIntrReqSetAffinity_Post_SetAffinity_Nop,
   RtemsIntrReqSetAffinity_Post_SetAffinity_NA
 } RtemsIntrReqSetAffinity_Post_SetAffinity;
@@ -111,7 +123,9 @@ typedef enum {
 typedef struct {
   uint16_t Skip : 1;
   uint16_t Pre_Vector_NA : 1;
-  uint16_t Pre_CPUSetKind_NA : 1;
+  uint16_t Pre_CPUSetSize_NA : 1;
+  uint16_t Pre_CPUSetOnline_NA : 1;
+  uint16_t Pre_CPUSetHuge_NA : 1;
   uint16_t Pre_CPUSet_NA : 1;
   uint16_t Pre_CanSetAffinity_NA : 1;
   uint16_t Post_Status : 3;
@@ -162,9 +176,15 @@ typedef struct {
 
   struct {
     /**
+     * @brief This member defines the pre-condition indices for the next
+     *   action.
+     */
+    size_t pci[ 6 ];
+
+    /**
      * @brief This member defines the pre-condition states for the next action.
      */
-    size_t pcs[ 4 ];
+    size_t pcs[ 6 ];
 
     /**
      * @brief If this member is true, then the test action loop is executed.
@@ -198,10 +218,22 @@ static const char * const RtemsIntrReqSetAffinity_PreDesc_Vector[] = {
   "NA"
 };
 
-static const char * const RtemsIntrReqSetAffinity_PreDesc_CPUSetKind[] = {
-  "Valid",
-  "Huge",
+static const char * const RtemsIntrReqSetAffinity_PreDesc_CPUSetSize[] = {
   "Askew",
+  "Normal",
+  "Huge",
+  "NA"
+};
+
+static const char * const RtemsIntrReqSetAffinity_PreDesc_CPUSetOnline[] = {
+  "Valid",
+  "Empty",
+  "NA"
+};
+
+static const char * const RtemsIntrReqSetAffinity_PreDesc_CPUSetHuge[] = {
+  "NotZero",
+  "Zero",
   "NA"
 };
 
@@ -219,7 +251,9 @@ static const char * const RtemsIntrReqSetAffinity_PreDesc_CanSetAffinity[] = {
 
 static const char * const * const RtemsIntrReqSetAffinity_PreDesc[] = {
   RtemsIntrReqSetAffinity_PreDesc_Vector,
-  RtemsIntrReqSetAffinity_PreDesc_CPUSetKind,
+  RtemsIntrReqSetAffinity_PreDesc_CPUSetSize,
+  RtemsIntrReqSetAffinity_PreDesc_CPUSetOnline,
+  RtemsIntrReqSetAffinity_PreDesc_CPUSetHuge,
   RtemsIntrReqSetAffinity_PreDesc_CPUSet,
   RtemsIntrReqSetAffinity_PreDesc_CanSetAffinity,
   NULL
@@ -295,43 +329,107 @@ static void RtemsIntrReqSetAffinity_Pre_Vector_Prepare(
   }
 }
 
-static void RtemsIntrReqSetAffinity_Pre_CPUSetKind_Prepare(
+static void RtemsIntrReqSetAffinity_Pre_CPUSetSize_Prepare(
   RtemsIntrReqSetAffinity_Context       *ctx,
-  RtemsIntrReqSetAffinity_Pre_CPUSetKind state
+  RtemsIntrReqSetAffinity_Pre_CPUSetSize state
 )
 {
   switch ( state ) {
-    case RtemsIntrReqSetAffinity_Pre_CPUSetKind_Valid: {
+    case RtemsIntrReqSetAffinity_Pre_CPUSetSize_Askew: {
+      /*
+       * While the ``affinity_size`` parameter is not an integral multiple of
+       * the size of long.
+       */
+      ctx->cpusetsize = SIZE_MAX;
+      break;
+    }
+
+    case RtemsIntrReqSetAffinity_Pre_CPUSetSize_Normal: {
       /*
        * While the ``affinity_size`` parameter is an integral multiple of the
-       * size of long, while the ``affinity_size`` and ``affinity`` parameter
-       * specify a processor set which is within the implementation limits.
+       * size of long, while the ``affinity_size`` parameter is less than or
+       * equal to the maximum processor set size storable in the system.
        */
       ctx->cpusetsize = sizeof( ctx->cpuset_obj[ 0 ] );
       break;
     }
 
-    case RtemsIntrReqSetAffinity_Pre_CPUSetKind_Huge: {
+    case RtemsIntrReqSetAffinity_Pre_CPUSetSize_Huge: {
       /*
        * While the ``affinity_size`` parameter is an integral multiple of the
-       * size of long, while the ``affinity_size`` and ``affinity`` parameter
-       * specify a processor set which exceeds the implementation limits.
+       * size of long, while the ``affinity_size`` parameter is greater than
+       * the maximum processor set size storable in the system.
        */
       ctx->cpusetsize = sizeof( ctx->cpuset_obj );
+      break;
+    }
+
+    case RtemsIntrReqSetAffinity_Pre_CPUSetSize_NA:
+      break;
+  }
+}
+
+static void RtemsIntrReqSetAffinity_Pre_CPUSetOnline_Prepare(
+  RtemsIntrReqSetAffinity_Context         *ctx,
+  RtemsIntrReqSetAffinity_Pre_CPUSetOnline state
+)
+{
+  switch ( state ) {
+    case RtemsIntrReqSetAffinity_Pre_CPUSetOnline_Valid: {
+      /*
+       * While the intersection of the processor set specified by the
+       * ``affinity_size`` and ``affinity`` parameters and the set of online
+       * processors is not empty, while the intersection of the processor set
+       * specified by the ``affinity_size`` and ``affinity`` parameters and the
+       * set of online processors is a supported processor affinity set of the
+       * interrupt vector.
+       */
+      /* Already prepared */
+      break;
+    }
+
+    case RtemsIntrReqSetAffinity_Pre_CPUSetOnline_Empty: {
+      /*
+       * While the intersection of the processor set specified by the
+       * ``affinity_size`` and ``affinity`` parameters and the set of online
+       * processors is empty.
+       */
       CPU_ZERO( &ctx->cpuset_obj[ 0 ] );
       break;
     }
 
-    case RtemsIntrReqSetAffinity_Pre_CPUSetKind_Askew: {
+    case RtemsIntrReqSetAffinity_Pre_CPUSetOnline_NA:
+      break;
+  }
+}
+
+static void RtemsIntrReqSetAffinity_Pre_CPUSetHuge_Prepare(
+  RtemsIntrReqSetAffinity_Context       *ctx,
+  RtemsIntrReqSetAffinity_Pre_CPUSetHuge state
+)
+{
+  switch ( state ) {
+    case RtemsIntrReqSetAffinity_Pre_CPUSetHuge_NotZero: {
       /*
-       * While the ``affinity_size`` parameter is not an integral multiple of
-       * the size of long.
+       * While the processor set specified by the ``affinity_size`` and
+       * ``affinity`` parameters contains at least one processor which is not
+       * storable in a processor set supported by the system.
        */
-      ctx->cpusetsize = SIZE_MAX;
+      /* Already prepared */
+      break;
+    }
+
+    case RtemsIntrReqSetAffinity_Pre_CPUSetHuge_Zero: {
+      /*
+       * While the processor set specified by the ``affinity_size`` and
+       * ``affinity`` parameters contains no processor which is not storable in
+       * a processor set supported by the system.
+       */
+      CPU_ZERO( &ctx->cpuset_obj[ 1 ] );
       break;
     }
 
-    case RtemsIntrReqSetAffinity_Pre_CPUSetKind_NA:
+    case RtemsIntrReqSetAffinity_Pre_CPUSetHuge_NA:
       break;
   }
 }
@@ -455,7 +553,7 @@ static void RtemsIntrReqSetAffinity_Post_SetAffinity_Check(
 )
 {
   switch ( state ) {
-    case RtemsIntrReqSetAffinity_Post_SetAffinity_Yes: {
+    case RtemsIntrReqSetAffinity_Post_SetAffinity_Set: {
       /*
        * The affinity set of the interrupt specified by ``vector`` shall be set
        * to the processor set specified by ``affinity_size`` and ``affinity``
@@ -513,7 +611,7 @@ static void RtemsIntrReqSetAffinity_Action(
 
   if (
     ctx->valid_vector && ctx->cpusetsize == sizeof( ctx->cpuset_obj[ 0 ] ) &&
-    ctx->cpuset == &ctx->cpuset_obj[ 0 ]
+    ctx->cpuset == &ctx->cpuset_obj[ 0 ] && !CPU_EMPTY( &ctx->cpuset_obj[ 0 ] )
   ) {
     for (
       ctx->vector = 0;
@@ -532,6 +630,7 @@ static void RtemsIntrReqSetAffinity_Action(
       T_rsc_success( sc );
 
       CheckSetAffinity( ctx, &attr );
+      ctx->status = RTEMS_SUCCESSFUL;
     }
   } else {
     cpu_set_t set;
@@ -539,6 +638,8 @@ static void RtemsIntrReqSetAffinity_Action(
 
     CPU_ZERO( &set );
     CPU_ZERO( &set2 );
+    CPU_SET( 0, &set );
+    CPU_SET( 0, &set2 );
 
     if ( ctx->valid_vector ) {
       ctx->vector = ctx->some_vector;
@@ -549,7 +650,9 @@ static void RtemsIntrReqSetAffinity_Action(
       ctx->vector = BSP_INTERRUPT_VECTOR_COUNT;
     }
 
-    CPU_ZERO( &ctx->cpuset_obj[ 0 ] );
+    if ( !CPU_EMPTY( &ctx->cpuset_obj[ 0 ] ) ) {
+      CPU_COPY( &set, &ctx->cpuset_obj[ 0 ] );
+    }
 
     ctx->status = rtems_interrupt_set_affinity(
       ctx->vector,
@@ -567,23 +670,34 @@ static void RtemsIntrReqSetAffinity_Action(
 
 static const RtemsIntrReqSetAffinity_Entry
 RtemsIntrReqSetAffinity_Entries[] = {
-  { 0, 0, 0, 0, 0, RtemsIntrReqSetAffinity_Post_Status_InvAddr,
+  { 0, 0, 0, 1, 1, 0, 0, RtemsIntrReqSetAffinity_Post_Status_InvAddr,
+    RtemsIntrReqSetAffinity_Post_SetAffinity_Nop },
+  { 0, 0, 0, 1, 1, 0, 1, RtemsIntrReqSetAffinity_Post_Status_InvAddr,
+    RtemsIntrReqSetAffinity_Post_SetAffinity_Nop },
+  { 0, 0, 0, 1, 1, 0, 1, RtemsIntrReqSetAffinity_Post_Status_InvId,
     RtemsIntrReqSetAffinity_Post_SetAffinity_Nop },
-  { 0, 0, 0, 0, 1, RtemsIntrReqSetAffinity_Post_Status_InvId,
-    RtemsIntrReqSetAffinity_Post_SetAffinity_NA },
-  { 0, 0, 0, 0, 1, RtemsIntrReqSetAffinity_Post_Status_InvAddr,
-    RtemsIntrReqSetAffinity_Post_SetAffinity_NA },
-  { 0, 0, 0, 0, 0, RtemsIntrReqSetAffinity_Post_Status_InvNum,
+  { 0, 0, 0, 0, 1, 0, 0, RtemsIntrReqSetAffinity_Post_Status_InvNum,
     RtemsIntrReqSetAffinity_Post_SetAffinity_Nop },
-  { 0, 0, 0, 0, 0, RtemsIntrReqSetAffinity_Post_Status_Ok,
-    RtemsIntrReqSetAffinity_Post_SetAffinity_Yes },
-  { 0, 0, 0, 0, 0, RtemsIntrReqSetAffinity_Post_Status_Unsat,
+  { 0, 0, 0, 1, 0, 0, 1, RtemsIntrReqSetAffinity_Post_Status_InvId,
+    RtemsIntrReqSetAffinity_Post_SetAffinity_Nop },
+  { 0, 0, 0, 0, 0, 0, 0, RtemsIntrReqSetAffinity_Post_Status_InvNum,
+    RtemsIntrReqSetAffinity_Post_SetAffinity_Nop },
+  { 0, 0, 0, 0, 1, 0, 0, RtemsIntrReqSetAffinity_Post_Status_Ok,
+    RtemsIntrReqSetAffinity_Post_SetAffinity_Set },
+  { 0, 0, 0, 0, 1, 0, 0, RtemsIntrReqSetAffinity_Post_Status_Unsat,
+    RtemsIntrReqSetAffinity_Post_SetAffinity_Nop },
+  { 0, 0, 0, 0, 0, 0, 0, RtemsIntrReqSetAffinity_Post_Status_Ok,
+    RtemsIntrReqSetAffinity_Post_SetAffinity_Set },
+  { 0, 0, 0, 0, 0, 0, 0, RtemsIntrReqSetAffinity_Post_Status_Unsat,
     RtemsIntrReqSetAffinity_Post_SetAffinity_Nop }
 };
 
 static const uint8_t
 RtemsIntrReqSetAffinity_Map[] = {
-  4, 5, 0, 0, 3, 3, 0, 0, 3, 3, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2
+  3, 3, 0, 0, 3, 3, 0, 0, 3, 3, 0, 0, 3, 3, 0, 0, 6, 7, 0, 0, 6, 7, 0, 0, 3, 3,
+  0, 0, 3, 3, 0, 0, 8, 9, 0, 0, 8, 9, 0, 0, 5, 5, 0, 0, 5, 5, 0, 0, 2, 2, 1, 1,
+  2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2,
+  1, 1, 4, 4, 1, 1, 4, 4, 1, 1, 4, 4, 1, 1, 4, 4, 1, 1
 };
 
 static size_t RtemsIntrReqSetAffinity_Scope( void *arg, char *buf, size_t n )
@@ -625,17 +739,44 @@ static inline RtemsIntrReqSetAffinity_Entry RtemsIntrReqSetAffinity_PopEntry(
   ];
 }
 
+static void RtemsIntrReqSetAffinity_SetPreConditionStates(
+  RtemsIntrReqSetAffinity_Context *ctx
+)
+{
+  ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
+  ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
+
+  if ( ctx->Map.entry.Pre_CPUSetOnline_NA ) {
+    ctx->Map.pcs[ 2 ] = RtemsIntrReqSetAffinity_Pre_CPUSetOnline_NA;
+  } else {
+    ctx->Map.pcs[ 2 ] = ctx->Map.pci[ 2 ];
+  }
+
+  if ( ctx->Map.entry.Pre_CPUSetHuge_NA ) {
+    ctx->Map.pcs[ 3 ] = RtemsIntrReqSetAffinity_Pre_CPUSetHuge_NA;
+  } else {
+    ctx->Map.pcs[ 3 ] = ctx->Map.pci[ 3 ];
+  }
+
+  ctx->Map.pcs[ 4 ] = ctx->Map.pci[ 4 ];
+
+  if ( ctx->Map.entry.Pre_CanSetAffinity_NA ) {
+    ctx->Map.pcs[ 5 ] = RtemsIntrReqSetAffinity_Pre_CanSetAffinity_NA;
+  } else {
+    ctx->Map.pcs[ 5 ] = ctx->Map.pci[ 5 ];
+  }
+}
+
 static void RtemsIntrReqSetAffinity_TestVariant(
   RtemsIntrReqSetAffinity_Context *ctx
 )
 {
   RtemsIntrReqSetAffinity_Pre_Vector_Prepare( ctx, ctx->Map.pcs[ 0 ] );
-  RtemsIntrReqSetAffinity_Pre_CPUSetKind_Prepare( ctx, ctx->Map.pcs[ 1 ] );
-  RtemsIntrReqSetAffinity_Pre_CPUSet_Prepare( ctx, ctx->Map.pcs[ 2 ] );
-  RtemsIntrReqSetAffinity_Pre_CanSetAffinity_Prepare(
-    ctx,
-    ctx->Map.entry.Pre_CanSetAffinity_NA ? RtemsIntrReqSetAffinity_Pre_CanSetAffinity_NA : ctx->Map.pcs[ 3 ]
-  );
+  RtemsIntrReqSetAffinity_Pre_CPUSetSize_Prepare( ctx, ctx->Map.pcs[ 1 ] );
+  RtemsIntrReqSetAffinity_Pre_CPUSetOnline_Prepare( ctx, ctx->Map.pcs[ 2 ] );
+  RtemsIntrReqSetAffinity_Pre_CPUSetHuge_Prepare( ctx, ctx->Map.pcs[ 3 ] );
+  RtemsIntrReqSetAffinity_Pre_CPUSet_Prepare( ctx, ctx->Map.pcs[ 4 ] );
+  RtemsIntrReqSetAffinity_Pre_CanSetAffinity_Prepare( ctx, ctx->Map.pcs[ 5 ] );
   RtemsIntrReqSetAffinity_Action( ctx );
   RtemsIntrReqSetAffinity_Post_Status_Check( ctx, ctx->Map.entry.Post_Status );
   RtemsIntrReqSetAffinity_Post_SetAffinity_Check(
@@ -659,28 +800,41 @@ T_TEST_CASE_FIXTURE(
   ctx->Map.index = 0;
 
   for (
-    ctx->Map.pcs[ 0 ] = RtemsIntrReqSetAffinity_Pre_Vector_Valid;
-    ctx->Map.pcs[ 0 ] < RtemsIntrReqSetAffinity_Pre_Vector_NA;
-    ++ctx->Map.pcs[ 0 ]
+    ctx->Map.pci[ 0 ] = RtemsIntrReqSetAffinity_Pre_Vector_Valid;
+    ctx->Map.pci[ 0 ] < RtemsIntrReqSetAffinity_Pre_Vector_NA;
+    ++ctx->Map.pci[ 0 ]
   ) {
     for (
-      ctx->Map.pcs[ 1 ] = RtemsIntrReqSetAffinity_Pre_CPUSetKind_Valid;
-      ctx->Map.pcs[ 1 ] < RtemsIntrReqSetAffinity_Pre_CPUSetKind_NA;
-      ++ctx->Map.pcs[ 1 ]
+      ctx->Map.pci[ 1 ] = RtemsIntrReqSetAffinity_Pre_CPUSetSize_Askew;
+      ctx->Map.pci[ 1 ] < RtemsIntrReqSetAffinity_Pre_CPUSetSize_NA;
+      ++ctx->Map.pci[ 1 ]
     ) {
       for (
-        ctx->Map.pcs[ 2 ] = RtemsIntrReqSetAffinity_Pre_CPUSet_Valid;
-        ctx->Map.pcs[ 2 ] < RtemsIntrReqSetAffinity_Pre_CPUSet_NA;
-        ++ctx->Map.pcs[ 2 ]
+        ctx->Map.pci[ 2 ] = RtemsIntrReqSetAffinity_Pre_CPUSetOnline_Valid;
+        ctx->Map.pci[ 2 ] < RtemsIntrReqSetAffinity_Pre_CPUSetOnline_NA;
+        ++ctx->Map.pci[ 2 ]
       ) {
         for (
-          ctx->Map.pcs[ 3 ] = RtemsIntrReqSetAffinity_Pre_CanSetAffinity_Yes;
-          ctx->Map.pcs[ 3 ] < RtemsIntrReqSetAffinity_Pre_CanSetAffinity_NA;
-          ++ctx->Map.pcs[ 3 ]
+          ctx->Map.pci[ 3 ] = RtemsIntrReqSetAffinity_Pre_CPUSetHuge_NotZero;
+          ctx->Map.pci[ 3 ] < RtemsIntrReqSetAffinity_Pre_CPUSetHuge_NA;
+          ++ctx->Map.pci[ 3 ]
         ) {
-          ctx->Map.entry = RtemsIntrReqSetAffinity_PopEntry( ctx );
-          RtemsIntrReqSetAffinity_Prepare( ctx );
-          RtemsIntrReqSetAffinity_TestVariant( ctx );
+          for (
+            ctx->Map.pci[ 4 ] = RtemsIntrReqSetAffinity_Pre_CPUSet_Valid;
+            ctx->Map.pci[ 4 ] < RtemsIntrReqSetAffinity_Pre_CPUSet_NA;
+            ++ctx->Map.pci[ 4 ]
+          ) {
+            for (
+              ctx->Map.pci[ 5 ] = RtemsIntrReqSetAffinity_Pre_CanSetAffinity_Yes;
+              ctx->Map.pci[ 5 ] < RtemsIntrReqSetAffinity_Pre_CanSetAffinity_NA;
+              ++ctx->Map.pci[ 5 ]
+            ) {
+              ctx->Map.entry = RtemsIntrReqSetAffinity_PopEntry( ctx );
+              RtemsIntrReqSetAffinity_SetPreConditionStates( ctx );
+              RtemsIntrReqSetAffinity_Prepare( ctx );
+              RtemsIntrReqSetAffinity_TestVariant( ctx );
+            }
+          }
         }
       }
     }
diff --git a/testsuites/validation/tc-intr-smp-only.c b/testsuites/validation/tc-intr-smp-only.c
new file mode 100644
index 0000000..4bf5961
--- /dev/null
+++ b/testsuites/validation/tc-intr-smp-only.c
@@ -0,0 +1,226 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSTestCaseRtemsIntrValIntrSmpOnly
+ */
+
+/*
+ * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * 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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include "tx-support.h"
+
+#include <rtems/test.h>
+
+/**
+ * @defgroup RTEMSTestCaseRtemsIntrValIntrSmpOnly \
+ *   spec:/rtems/intr/val/intr-smp-only
+ *
+ * @ingroup RTEMSTestSuiteTestsuitesValidationSmpOnly0
+ *
+ * @brief Tests some @ref RTEMSAPIClassicIntr directives.
+ *
+ * This test case performs the following actions:
+ *
+ * - Validate the interrupt lock directives.
+ *
+ *   - Check that RTEMS_INTERRUPT_LOCK_REFERENCE() expanded to a lock reference
+ *     definition.  Check that the lock is available after static
+ *     initialization.
+ *
+ *   - Check that the lock is available after initialization.
+ *
+ *   - Check that maskable interrupts are disabled before the call to
+ *     rtems_interrupt_lock_interrupt_disable() and disabled afterwards.
+ *
+ *   - Check that the maskable interrupt status is not changed by the
+ *     rtems_interrupt_lock_acquire_isr() call.  Check that the lock is no
+ *     longer available.
+ *
+ *   - Check that the maskable interrupt status is restored by the call to
+ *     rtems_interrupt_lock_release() according to the ``_lock_context``
+ *     parameter.  Check that the lock is available afterwards.
+ *
+ *   - Check that the maskable interrupt status is not changed by the
+ *     rtems_interrupt_lock_destroy() call.
+ *
+ *   - Initialize the lock using rtems_interrupt_lock_initialize().  Check that
+ *     the lock is available after initialization.
+ *
+ *   - Check that maskable interrupts are disabled before the call to
+ *     rtems_interrupt_lock_acquire() and disabled afterwards.  Check that the
+ *     lock is no longer available.
+ *
+ *   - Check that the maskable interrupt status is restored by the call to
+ *     rtems_interrupt_lock_release() according to the ``_lock_context``
+ *     parameter.  Check that the lock is available afterwards.
+ *
+ *   - Check that the maskable interrupt status is not changed by the
+ *     rtems_interrupt_lock_destroy() call.
+ *
+ * @{
+ */
+
+RTEMS_INTERRUPT_LOCK_DECLARE( static, the_lock )
+RTEMS_INTERRUPT_LOCK_DEFINE( static, the_lock, "name " )
+
+/**
+ * @brief Validate the interrupt lock directives.
+ */
+static void RtemsIntrValIntrSmpOnly_Action_0( void )
+{
+  struct {
+    int a;
+    RTEMS_INTERRUPT_LOCK_MEMBER( member )
+    int b;
+  } lock = {
+    .member = RTEMS_INTERRUPT_LOCK_INITIALIZER( "name" )
+  };
+
+  RTEMS_INTERRUPT_LOCK_REFERENCE( ref, &the_lock )
+  rtems_interrupt_lock_context lock_context;
+
+  /*
+   * Check that RTEMS_INTERRUPT_LOCK_REFERENCE() expanded to a lock reference
+   * definition.  Check that the lock is available after static initialization.
+   */
+  T_true( ISRLockIsAvailable( ref ) );
+
+  /*
+   * Check that the lock is available after initialization.
+   */
+  T_true( ISRLockIsAvailable( &lock.member ) );
+
+  /*
+   * Check that maskable interrupts are disabled before the call to
+   * rtems_interrupt_lock_interrupt_disable() and disabled afterwards.
+   */
+  T_true( AreInterruptsEnabled() );
+  T_true( ISRLockIsAvailable( &lock.member ) );
+  rtems_interrupt_lock_interrupt_disable( &lock_context );
+  T_false( AreInterruptsEnabled() );
+  T_true( ISRLockIsAvailable( &lock.member ) );
+
+  /*
+   * Check that the maskable interrupt status is not changed by the
+   * rtems_interrupt_lock_acquire_isr() call.  Check that the lock is no longer
+   * available.
+   */
+  T_false( AreInterruptsEnabled() );
+  T_true( ISRLockIsAvailable( &lock.member ) );
+  rtems_interrupt_lock_acquire_isr( &lock.member, &lock_context );
+  T_false( AreInterruptsEnabled() );
+  T_false( ISRLockIsAvailable( &lock.member ) );
+
+  /*
+   * Check that the maskable interrupt status is restored by the call to
+   * rtems_interrupt_lock_release() according to the ``_lock_context``
+   * parameter.  Check that the lock is available afterwards.
+   */
+  T_false( AreInterruptsEnabled() );
+  T_false( ISRLockIsAvailable( &lock.member ) );
+  rtems_interrupt_lock_release( &lock.member, &lock_context );
+  T_true( AreInterruptsEnabled() );
+  T_true( ISRLockIsAvailable( &lock.member ) );
+
+  /*
+   * Check that the maskable interrupt status is not changed by the
+   * rtems_interrupt_lock_destroy() call.
+   */
+  T_true( AreInterruptsEnabled() );
+  rtems_interrupt_lock_destroy( &lock.member );
+  T_true( AreInterruptsEnabled() );
+
+  /*
+   * Initialize the lock using rtems_interrupt_lock_initialize().  Check that
+   * the lock is available after initialization.
+   */
+  rtems_interrupt_lock_initialize( &lock.member, "name" );
+  T_true( ISRLockIsAvailable( &lock.member ) );
+
+  /*
+   * Check that maskable interrupts are disabled before the call to
+   * rtems_interrupt_lock_acquire() and disabled afterwards.  Check that the
+   * lock is no longer available.
+   */
+  T_true( AreInterruptsEnabled() );
+  T_true( ISRLockIsAvailable( &lock.member ) );
+  rtems_interrupt_lock_acquire( &lock.member, &lock_context );
+  T_false( AreInterruptsEnabled() );
+  T_false( ISRLockIsAvailable( &lock.member ) );
+
+  /*
+   * Check that the maskable interrupt status is restored by the call to
+   * rtems_interrupt_lock_release() according to the ``_lock_context``
+   * parameter.  Check that the lock is available afterwards.
+   */
+  T_false( AreInterruptsEnabled() );
+  T_false( ISRLockIsAvailable( &lock.member ) );
+  rtems_interrupt_lock_release( &lock.member, &lock_context );
+  T_true( AreInterruptsEnabled() );
+  T_true( ISRLockIsAvailable( &lock.member ) );
+
+  /*
+   * Check that the maskable interrupt status is not changed by the
+   * rtems_interrupt_lock_destroy() call.
+   */
+  T_true( AreInterruptsEnabled() );
+  rtems_interrupt_lock_destroy( &lock.member );
+  T_true( AreInterruptsEnabled() );
+}
+
+/**
+ * @fn void T_case_body_RtemsIntrValIntrSmpOnly( void )
+ */
+T_TEST_CASE( RtemsIntrValIntrSmpOnly )
+{
+  RtemsIntrValIntrSmpOnly_Action_0();
+}
+
+/** @} */
diff --git a/testsuites/validation/tc-intr-vector-disable.c b/testsuites/validation/tc-intr-vector-disable.c
index fea05a2..3c7eb11 100644
--- a/testsuites/validation/tc-intr-vector-disable.c
+++ b/testsuites/validation/tc-intr-vector-disable.c
@@ -64,7 +64,7 @@
  * @defgroup RTEMSTestCaseRtemsIntrReqVectorDisable \
  *   spec:/rtems/intr/req/vector-disable
  *
- * @ingroup RTEMSTestSuiteTestsuitesValidation0
+ * @ingroup RTEMSTestSuiteTestsuitesValidationIntr
  *
  * @{
  */
@@ -139,6 +139,12 @@ typedef struct {
 
   struct {
     /**
+     * @brief This member defines the pre-condition indices for the next
+     *   action.
+     */
+    size_t pci[ 3 ];
+
+    /**
      * @brief This member defines the pre-condition states for the next action.
      */
     size_t pcs[ 3 ];
@@ -594,19 +600,32 @@ RtemsIntrReqVectorDisable_PopEntry( RtemsIntrReqVectorDisable_Context *ctx )
   ];
 }
 
+static void RtemsIntrReqVectorDisable_SetPreConditionStates(
+  RtemsIntrReqVectorDisable_Context *ctx
+)
+{
+  ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
+
+  if ( ctx->Map.entry.Pre_IsEnabled_NA ) {
+    ctx->Map.pcs[ 1 ] = RtemsIntrReqVectorDisable_Pre_IsEnabled_NA;
+  } else {
+    ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
+  }
+
+  if ( ctx->Map.entry.Pre_CanDisable_NA ) {
+    ctx->Map.pcs[ 2 ] = RtemsIntrReqVectorDisable_Pre_CanDisable_NA;
+  } else {
+    ctx->Map.pcs[ 2 ] = ctx->Map.pci[ 2 ];
+  }
+}
+
 static void RtemsIntrReqVectorDisable_TestVariant(
   RtemsIntrReqVectorDisable_Context *ctx
 )
 {
   RtemsIntrReqVectorDisable_Pre_Vector_Prepare( ctx, ctx->Map.pcs[ 0 ] );
-  RtemsIntrReqVectorDisable_Pre_IsEnabled_Prepare(
-    ctx,
-    ctx->Map.entry.Pre_IsEnabled_NA ? RtemsIntrReqVectorDisable_Pre_IsEnabled_NA : ctx->Map.pcs[ 1 ]
-  );
-  RtemsIntrReqVectorDisable_Pre_CanDisable_Prepare(
-    ctx,
-    ctx->Map.entry.Pre_CanDisable_NA ? RtemsIntrReqVectorDisable_Pre_CanDisable_NA : ctx->Map.pcs[ 2 ]
-  );
+  RtemsIntrReqVectorDisable_Pre_IsEnabled_Prepare( ctx, ctx->Map.pcs[ 1 ] );
+  RtemsIntrReqVectorDisable_Pre_CanDisable_Prepare( ctx, ctx->Map.pcs[ 2 ] );
   RtemsIntrReqVectorDisable_Action( ctx );
   RtemsIntrReqVectorDisable_Post_Status_Check(
     ctx,
@@ -633,21 +652,22 @@ T_TEST_CASE_FIXTURE(
   ctx->Map.index = 0;
 
   for (
-    ctx->Map.pcs[ 0 ] = RtemsIntrReqVectorDisable_Pre_Vector_Valid;
-    ctx->Map.pcs[ 0 ] < RtemsIntrReqVectorDisable_Pre_Vector_NA;
-    ++ctx->Map.pcs[ 0 ]
+    ctx->Map.pci[ 0 ] = RtemsIntrReqVectorDisable_Pre_Vector_Valid;
+    ctx->Map.pci[ 0 ] < RtemsIntrReqVectorDisable_Pre_Vector_NA;
+    ++ctx->Map.pci[ 0 ]
   ) {
     for (
-      ctx->Map.pcs[ 1 ] = RtemsIntrReqVectorDisable_Pre_IsEnabled_Yes;
-      ctx->Map.pcs[ 1 ] < RtemsIntrReqVectorDisable_Pre_IsEnabled_NA;
-      ++ctx->Map.pcs[ 1 ]
+      ctx->Map.pci[ 1 ] = RtemsIntrReqVectorDisable_Pre_IsEnabled_Yes;
+      ctx->Map.pci[ 1 ] < RtemsIntrReqVectorDisable_Pre_IsEnabled_NA;
+      ++ctx->Map.pci[ 1 ]
     ) {
       for (
-        ctx->Map.pcs[ 2 ] = RtemsIntrReqVectorDisable_Pre_CanDisable_Yes;
-        ctx->Map.pcs[ 2 ] < RtemsIntrReqVectorDisable_Pre_CanDisable_NA;
-        ++ctx->Map.pcs[ 2 ]
+        ctx->Map.pci[ 2 ] = RtemsIntrReqVectorDisable_Pre_CanDisable_Yes;
+        ctx->Map.pci[ 2 ] < RtemsIntrReqVectorDisable_Pre_CanDisable_NA;
+        ++ctx->Map.pci[ 2 ]
       ) {
         ctx->Map.entry = RtemsIntrReqVectorDisable_PopEntry( ctx );
+        RtemsIntrReqVectorDisable_SetPreConditionStates( ctx );
         RtemsIntrReqVectorDisable_TestVariant( ctx );
       }
     }
diff --git a/testsuites/validation/tc-intr-vector-enable.c b/testsuites/validation/tc-intr-vector-enable.c
index c0d985a..024953a 100644
--- a/testsuites/validation/tc-intr-vector-enable.c
+++ b/testsuites/validation/tc-intr-vector-enable.c
@@ -64,7 +64,7 @@
  * @defgroup RTEMSTestCaseRtemsIntrReqVectorEnable \
  *   spec:/rtems/intr/req/vector-enable
  *
- * @ingroup RTEMSTestSuiteTestsuitesValidation0
+ * @ingroup RTEMSTestSuiteTestsuitesValidationIntr
  *
  * @{
  */
@@ -139,6 +139,12 @@ typedef struct {
 
   struct {
     /**
+     * @brief This member defines the pre-condition indices for the next
+     *   action.
+     */
+    size_t pci[ 3 ];
+
+    /**
      * @brief This member defines the pre-condition states for the next action.
      */
     size_t pcs[ 3 ];
@@ -600,19 +606,32 @@ static inline RtemsIntrReqVectorEnable_Entry RtemsIntrReqVectorEnable_PopEntry(
   ];
 }
 
+static void RtemsIntrReqVectorEnable_SetPreConditionStates(
+  RtemsIntrReqVectorEnable_Context *ctx
+)
+{
+  ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
+
+  if ( ctx->Map.entry.Pre_IsEnabled_NA ) {
+    ctx->Map.pcs[ 1 ] = RtemsIntrReqVectorEnable_Pre_IsEnabled_NA;
+  } else {
+    ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
+  }
+
+  if ( ctx->Map.entry.Pre_CanEnable_NA ) {
+    ctx->Map.pcs[ 2 ] = RtemsIntrReqVectorEnable_Pre_CanEnable_NA;
+  } else {
+    ctx->Map.pcs[ 2 ] = ctx->Map.pci[ 2 ];
+  }
+}
+
 static void RtemsIntrReqVectorEnable_TestVariant(
   RtemsIntrReqVectorEnable_Context *ctx
 )
 {
   RtemsIntrReqVectorEnable_Pre_Vector_Prepare( ctx, ctx->Map.pcs[ 0 ] );
-  RtemsIntrReqVectorEnable_Pre_IsEnabled_Prepare(
-    ctx,
-    ctx->Map.entry.Pre_IsEnabled_NA ? RtemsIntrReqVectorEnable_Pre_IsEnabled_NA : ctx->Map.pcs[ 1 ]
-  );
-  RtemsIntrReqVectorEnable_Pre_CanEnable_Prepare(
-    ctx,
-    ctx->Map.entry.Pre_CanEnable_NA ? RtemsIntrReqVectorEnable_Pre_CanEnable_NA : ctx->Map.pcs[ 2 ]
-  );
+  RtemsIntrReqVectorEnable_Pre_IsEnabled_Prepare( ctx, ctx->Map.pcs[ 1 ] );
+  RtemsIntrReqVectorEnable_Pre_CanEnable_Prepare( ctx, ctx->Map.pcs[ 2 ] );
   RtemsIntrReqVectorEnable_Action( ctx );
   RtemsIntrReqVectorEnable_Post_Status_Check(
     ctx,
@@ -639,21 +658,22 @@ T_TEST_CASE_FIXTURE(
   ctx->Map.index = 0;
 
   for (
-    ctx->Map.pcs[ 0 ] = RtemsIntrReqVectorEnable_Pre_Vector_Valid;
-    ctx->Map.pcs[ 0 ] < RtemsIntrReqVectorEnable_Pre_Vector_NA;
-    ++ctx->Map.pcs[ 0 ]
+    ctx->Map.pci[ 0 ] = RtemsIntrReqVectorEnable_Pre_Vector_Valid;
+    ctx->Map.pci[ 0 ] < RtemsIntrReqVectorEnable_Pre_Vector_NA;
+    ++ctx->Map.pci[ 0 ]
   ) {
     for (
-      ctx->Map.pcs[ 1 ] = RtemsIntrReqVectorEnable_Pre_IsEnabled_Yes;
-      ctx->Map.pcs[ 1 ] < RtemsIntrReqVectorEnable_Pre_IsEnabled_NA;
-      ++ctx->Map.pcs[ 1 ]
+      ctx->Map.pci[ 1 ] = RtemsIntrReqVectorEnable_Pre_IsEnabled_Yes;
+      ctx->Map.pci[ 1 ] < RtemsIntrReqVectorEnable_Pre_IsEnabled_NA;
+      ++ctx->Map.pci[ 1 ]
     ) {
       for (
-        ctx->Map.pcs[ 2 ] = RtemsIntrReqVectorEnable_Pre_CanEnable_Yes;
-        ctx->Map.pcs[ 2 ] < RtemsIntrReqVectorEnable_Pre_CanEnable_NA;
-        ++ctx->Map.pcs[ 2 ]
+        ctx->Map.pci[ 2 ] = RtemsIntrReqVectorEnable_Pre_CanEnable_Yes;
+        ctx->Map.pci[ 2 ] < RtemsIntrReqVectorEnable_Pre_CanEnable_NA;
+        ++ctx->Map.pci[ 2 ]
       ) {
         ctx->Map.entry = RtemsIntrReqVectorEnable_PopEntry( ctx );
+        RtemsIntrReqVectorEnable_SetPreConditionStates( ctx );
         RtemsIntrReqVectorEnable_TestVariant( ctx );
       }
     }
diff --git a/testsuites/validation/tc-intr-vector-is-enabled.c b/testsuites/validation/tc-intr-vector-is-enabled.c
index de1d0c2..ea26b80 100644
--- a/testsuites/validation/tc-intr-vector-is-enabled.c
+++ b/testsuites/validation/tc-intr-vector-is-enabled.c
@@ -64,7 +64,7 @@
  * @defgroup RTEMSTestCaseRtemsIntrReqVectorIsEnabled \
  *   spec:/rtems/intr/req/vector-is-enabled
  *
- * @ingroup RTEMSTestSuiteTestsuitesValidation0
+ * @ingroup RTEMSTestSuiteTestsuitesValidationIntr
  *
  * @{
  */
@@ -154,6 +154,12 @@ typedef struct {
 
   struct {
     /**
+     * @brief This member defines the pre-condition indices for the next
+     *   action.
+     */
+    size_t pci[ 3 ];
+
+    /**
      * @brief This member defines the pre-condition states for the next action.
      */
     size_t pcs[ 3 ];
@@ -584,16 +590,27 @@ RtemsIntrReqVectorIsEnabled_PopEntry(
   ];
 }
 
+static void RtemsIntrReqVectorIsEnabled_SetPreConditionStates(
+  RtemsIntrReqVectorIsEnabled_Context *ctx
+)
+{
+  ctx->Map.pcs[ 0 ] = ctx->Map.pci[ 0 ];
+  ctx->Map.pcs[ 1 ] = ctx->Map.pci[ 1 ];
+
+  if ( ctx->Map.entry.Pre_IsEnabled_NA ) {
+    ctx->Map.pcs[ 2 ] = RtemsIntrReqVectorIsEnabled_Pre_IsEnabled_NA;
+  } else {
+    ctx->Map.pcs[ 2 ] = ctx->Map.pci[ 2 ];
+  }
+}
+
 static void RtemsIntrReqVectorIsEnabled_TestVariant(
   RtemsIntrReqVectorIsEnabled_Context *ctx
 )
 {
   RtemsIntrReqVectorIsEnabled_Pre_Vector_Prepare( ctx, ctx->Map.pcs[ 0 ] );
   RtemsIntrReqVectorIsEnabled_Pre_Enabled_Prepare( ctx, ctx->Map.pcs[ 1 ] );
-  RtemsIntrReqVectorIsEnabled_Pre_IsEnabled_Prepare(
-    ctx,
-    ctx->Map.entry.Pre_IsEnabled_NA ? RtemsIntrReqVectorIsEnabled_Pre_IsEnabled_NA : ctx->Map.pcs[ 2 ]
-  );
+  RtemsIntrReqVectorIsEnabled_Pre_IsEnabled_Prepare( ctx, ctx->Map.pcs[ 2 ] );
   RtemsIntrReqVectorIsEnabled_Action( ctx );
   RtemsIntrReqVectorIsEnabled_Post_Status_Check(
     ctx,
@@ -620,21 +637,22 @@ T_TEST_CASE_FIXTURE(
   ctx->Map.index = 0;
 
   for (
-    ctx->Map.pcs[ 0 ] = RtemsIntrReqVectorIsEnabled_Pre_Vector_Valid;
-    ctx->Map.pcs[ 0 ] < RtemsIntrReqVectorIsEnabled_Pre_Vector_NA;
-    ++ctx->Map.pcs[ 0 ]
+    ctx->Map.pci[ 0 ] = RtemsIntrReqVectorIsEnabled_Pre_Vector_Valid;
+    ctx->Map.pci[ 0 ] < RtemsIntrReqVectorIsEnabled_Pre_Vector_NA;
+    ++ctx->Map.pci[ 0 ]
   ) {
     for (
-      ctx->Map.pcs[ 1 ] = RtemsIntrReqVectorIsEnabled_Pre_Enabled_Obj;
-      ctx->Map.pcs[ 1 ] < RtemsIntrReqVectorIsEnabled_Pre_Enabled_NA;
-      ++ctx->Map.pcs[ 1 ]
+      ctx->Map.pci[ 1 ] = RtemsIntrReqVectorIsEnabled_Pre_Enabled_Obj;
+      ctx->Map.pci[ 1 ] < RtemsIntrReqVectorIsEnabled_Pre_Enabled_NA;
+      ++ctx->Map.pci[ 1 ]
     ) {
       for (
-        ctx->Map.pcs[ 2 ] = RtemsIntrReqVectorIsEnabled_Pre_IsEnabled_Yes;
-        ctx->Map.pcs[ 2 ] < RtemsIntrReqVectorIsEnabled_Pre_IsEnabled_NA;
-        ++ctx->Map.pcs[ 2 ]
+        ctx->Map.pci[ 2 ] = RtemsIntrReqVectorIsEnabled_Pre_IsEnabled_Yes;
+        ctx->Map.pci[ 2 ] < RtemsIntrReqVectorIsEnabled_Pre_IsEnabled_NA;
+        ++ctx->Map.pci[ 2 ]
       ) {
         ctx->Map.entry = RtemsIntrReqVectorIsEnabled_PopEntry( ctx );
+        RtemsIntrReqVectorIsEnabled_SetPreConditionStates( ctx );
         RtemsIntrReqVectorIsEnabled_TestVariant( ctx );
       }
     }
diff --git a/testsuites/validation/tc-intr.c b/testsuites/validation/tc-intr.c
new file mode 100644
index 0000000..7b2e6b0
--- /dev/null
+++ b/testsuites/validation/tc-intr.c
@@ -0,0 +1,286 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSTestCaseRtemsIntrValIntr
+ */
+
+/*
+ * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * 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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/irq-extension.h>
+
+#include "tx-support.h"
+
+#include <rtems/test.h>
+
+/**
+ * @defgroup RTEMSTestCaseRtemsIntrValIntr spec:/rtems/intr/val/intr
+ *
+ * @ingroup RTEMSTestSuiteTestsuitesValidationNoClock0
+ *
+ * @brief Tests some @ref RTEMSAPIClassicIntr directives.
+ *
+ * This test case performs the following actions:
+ *
+ * - Validate rtems_interrupt_local_disable() and
+ *   rtems_interrupt_local_enable().
+ *
+ *   - Check that maskable interrupts are enabled before the call to
+ *     rtems_interrupt_local_disable() and disabled afterwards.
+ *
+ *   - Check that maskable interrupts are disabled before the call to
+ *     rtems_interrupt_local_disable() and disabled afterwards.
+ *
+ *   - Check that the maskable interrupt status is restored by the call to
+ *     rtems_interrupt_local_enable() according to the ``_isr_cookie``
+ *     parameter.  In this case maskable interrupts are still disabled
+ *     afterwards.
+ *
+ *   - Check that the maskable interrupt status is restored by the call to
+ *     rtems_interrupt_local_enable() according to the ``_isr_cookie``
+ *     parameter.  In this case maskable interrupts are enabled afterwards.
+ *
+ * - Validate the interrupt lock directives.
+ *
+ *   - Check that maskable interrupts are disabled before the call to
+ *     rtems_interrupt_lock_interrupt_disable() and disabled afterwards.
+ *
+ *   - Check that the maskable interrupt status is not changed by the
+ *     rtems_interrupt_lock_acquire_isr() call.
+ *
+ *   - Check that the maskable interrupt status is restored by the call to
+ *     rtems_interrupt_lock_release() according to the ``_lock_context``
+ *     parameter.
+ *
+ *   - Check that maskable interrupts are disabled before the call to
+ *     rtems_interrupt_lock_acquire() and disabled afterwards.
+ *
+ *   - Check that the maskable interrupt status is restored by the call to
+ *     rtems_interrupt_lock_release() according to the ``_lock_context``
+ *     parameter.
+ *
+ *   - Check that the maskable interrupt status is not changed by the
+ *     rtems_interrupt_lock_destroy() call.
+ *
+ * - Validate the interrupt entry initialization.
+ *
+ *   - Check that the entry is properly initialized by
+ *     RTEMS_INTERRUPT_ENTRY_INITIALIZER().
+ *
+ *   - Call rtems_interrupt_entry_initialize().  Check that the entry is
+ *     properly initialized by rtems_interrupt_entry_initialize().
+ *
+ * @{
+ */
+
+static void EntryRoutine( void *arg )
+{
+  (void) arg;
+}
+
+static void EntryRoutine2( void *arg )
+{
+  (void) arg;
+}
+
+/**
+ * @brief Validate rtems_interrupt_local_disable() and
+ *   rtems_interrupt_local_enable().
+ */
+static void RtemsIntrValIntr_Action_0( void )
+{
+  rtems_interrupt_level level;
+  rtems_interrupt_level level_2;
+
+  /*
+   * Check that maskable interrupts are enabled before the call to
+   * rtems_interrupt_local_disable() and disabled afterwards.
+   */
+  T_true( AreInterruptsEnabled() );
+  rtems_interrupt_local_disable( level );
+  T_false( AreInterruptsEnabled() );
+
+  /*
+   * Check that maskable interrupts are disabled before the call to
+   * rtems_interrupt_local_disable() and disabled afterwards.
+   */
+  T_false( AreInterruptsEnabled() );
+  rtems_interrupt_local_disable( level_2 );
+  T_false( AreInterruptsEnabled() );
+
+  /*
+   * Check that the maskable interrupt status is restored by the call to
+   * rtems_interrupt_local_enable() according to the ``_isr_cookie`` parameter.
+   * In this case maskable interrupts are still disabled afterwards.
+   */
+  T_false( AreInterruptsEnabled() );
+  rtems_interrupt_local_enable( level_2 );
+  T_false( AreInterruptsEnabled() );
+
+  /*
+   * Check that the maskable interrupt status is restored by the call to
+   * rtems_interrupt_local_enable() according to the ``_isr_cookie`` parameter.
+   * In this case maskable interrupts are enabled afterwards.
+   */
+  T_false( AreInterruptsEnabled() );
+  rtems_interrupt_local_enable( level );
+  T_true( AreInterruptsEnabled() );
+}
+
+/**
+ * @brief Validate the interrupt lock directives.
+ */
+static void RtemsIntrValIntr_Action_1( void )
+{
+  RTEMS_INTERRUPT_LOCK_DEFINE( , lock, "name" );
+  rtems_interrupt_lock_context lock_context;
+
+  /*
+   * Check that maskable interrupts are disabled before the call to
+   * rtems_interrupt_lock_interrupt_disable() and disabled afterwards.
+   */
+  T_true( AreInterruptsEnabled() );
+  rtems_interrupt_lock_interrupt_disable( &lock_context );
+  T_false( AreInterruptsEnabled() );
+
+  /*
+   * Check that the maskable interrupt status is not changed by the
+   * rtems_interrupt_lock_acquire_isr() call.
+   */
+  T_false( AreInterruptsEnabled() );
+  rtems_interrupt_lock_acquire_isr( &lock, &lock_context );
+  T_false( AreInterruptsEnabled() );
+
+  /*
+   * Check that the maskable interrupt status is restored by the call to
+   * rtems_interrupt_lock_release() according to the ``_lock_context``
+   * parameter.
+   */
+  T_false( AreInterruptsEnabled() );
+  rtems_interrupt_lock_release( &lock, &lock_context );
+  T_true( AreInterruptsEnabled() );
+
+  /*
+   * Check that maskable interrupts are disabled before the call to
+   * rtems_interrupt_lock_acquire() and disabled afterwards.
+   */
+  T_true( AreInterruptsEnabled() );
+  rtems_interrupt_lock_acquire( &lock, &lock_context );
+  T_false( AreInterruptsEnabled() );
+
+  /*
+   * Check that the maskable interrupt status is restored by the call to
+   * rtems_interrupt_lock_release() according to the ``_lock_context``
+   * parameter.
+   */
+  T_false( AreInterruptsEnabled() );
+  rtems_interrupt_lock_release( &lock, &lock_context );
+  T_true( AreInterruptsEnabled() );
+
+  /*
+   * Check that the maskable interrupt status is not changed by the
+   * rtems_interrupt_lock_destroy() call.
+   */
+  T_true( AreInterruptsEnabled() );
+  rtems_interrupt_lock_destroy( &lock );
+  T_true( AreInterruptsEnabled() );
+}
+
+/**
+ * @brief Validate the interrupt entry initialization.
+ */
+static void RtemsIntrValIntr_Action_2( void )
+{
+  int entry_arg;
+  int entry_arg_2;
+  const char entry_info[] = "1";
+  const char entry_info_2[] = "1";
+  rtems_interrupt_entry entry = RTEMS_INTERRUPT_ENTRY_INITIALIZER(
+    EntryRoutine,
+    &entry_arg,
+    entry_info
+  );
+
+  /*
+   * Check that the entry is properly initialized by
+   * RTEMS_INTERRUPT_ENTRY_INITIALIZER().
+   */
+  T_eq_ptr( entry.handler, EntryRoutine );
+  T_eq_ptr( entry.arg, &entry_arg );
+  T_eq_ptr( entry.next, NULL );
+  T_eq_ptr( entry.info, entry_info );
+
+  /*
+   * Call rtems_interrupt_entry_initialize().  Check that the entry is properly
+   * initialized by rtems_interrupt_entry_initialize().
+   */
+  entry.next = &entry;
+  rtems_interrupt_entry_initialize(
+    &entry,
+    EntryRoutine2,
+    &entry_arg_2,
+    entry_info_2
+  );
+  T_eq_ptr( entry.handler, EntryRoutine2 );
+  T_eq_ptr( entry.arg, &entry_arg_2 );
+  T_eq_ptr( entry.next, NULL );
+  T_eq_ptr( entry.info, entry_info_2 );
+}
+
+/**
+ * @fn void T_case_body_RtemsIntrValIntr( void )
+ */
+T_TEST_CASE( RtemsIntrValIntr )
+{
+  RtemsIntrValIntr_Action_0();
+  RtemsIntrValIntr_Action_1();
+  RtemsIntrValIntr_Action_2();
+}
+
+/** @} */
diff --git a/testsuites/validation/ts-validation-intr.c b/testsuites/validation/ts-validation-intr.c
new file mode 100644
index 0000000..1a79608
--- /dev/null
+++ b/testsuites/validation/ts-validation-intr.c
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSTestSuiteTestsuitesValidationIntr
+ */
+
+/*
+ * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * 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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/test.h>
+
+/**
+ * @defgroup RTEMSTestSuiteTestsuitesValidationIntr \
+ *   spec:/testsuites/validation-intr
+ *
+ * @ingroup RTEMSTestSuites
+ *
+ * @brief This validation test suite provides enough resources to run tests for
+ *   the interrupt controller related directives of the @ref
+ *   RTEMSAPIClassicIntr.
+ *
+ * In SMP configurations, up to three scheduler instances using the SMP EDF
+ * scheduler are provided using up to four processors.
+ *
+ * @{
+ */
+
+const char rtems_test_name[] = "ValidationIntr";
+
+#define CONFIGURE_MAXIMUM_PROCESSORS 5
+
+#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
+
+#include "ts-default.h"
+
+/** @} */



More information about the vc mailing list