tests/kernel/common: Add nested irq_offload() test

Add a very simple test of the CONFIG_IRQ_OFFSET_NESTED feature that
exercises nested interrupts in a portable way.  It calls irq_offset()
from within a k_timer callback and validates that the return lands
back in the original interrupt successfully.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
diff --git a/tests/kernel/common/src/irq_offload.c b/tests/kernel/common/src/irq_offload.c
index 66b6e04..de406d0 100644
--- a/tests/kernel/common/src/irq_offload.c
+++ b/tests/kernel/common/src/irq_offload.c
@@ -192,3 +192,46 @@
 	zassert_true(diff > 0,
 			"arch_nop() takes %d cpu cycles", diff);
 }
+
+static struct k_timer nestoff_timer;
+static bool timer_executed, nested_executed;
+
+void nestoff_offload(const void *parameter)
+{
+	nested_executed = true;
+}
+
+
+static void nestoff_timer_fn(struct k_timer *timer)
+{
+	zassert_false(nested_executed, "nested irq_offload ran too soon");
+	irq_offload(nestoff_offload, NULL);
+	zassert_true(nested_executed, "nested irq_offload did not run");
+
+	/* Set this last, to be sure we return to this context and not
+	 * the enclosing interrupt
+	 */
+	timer_executed = true;
+}
+
+
+/* Invoke irq_offload() from an interrupt and verify that the
+ * resulting nested interrupt doesn't explode
+ */
+void test_nested_irq_offload(void)
+{
+	if (!IS_ENABLED(CONFIG_IRQ_OFFLOAD_NESTED)) {
+		ztest_test_skip();
+	}
+
+	k_timer_init(&nestoff_timer, nestoff_timer_fn, NULL);
+
+	zassert_false(timer_executed, "timer ran too soon");
+	zassert_false(nested_executed, "nested irq_offload ran too soon");
+
+	k_timer_start(&nestoff_timer, K_TICKS(1), K_FOREVER);
+	k_timer_status_sync(&nestoff_timer);
+
+	zassert_true(timer_executed, "timer did not run");
+	zassert_true(nested_executed, "nested irq_offload did not run");
+}
diff --git a/tests/kernel/common/src/main.c b/tests/kernel/common/src/main.c
index a8cdaec..6bf1197 100644
--- a/tests/kernel/common/src/main.c
+++ b/tests/kernel/common/src/main.c
@@ -45,6 +45,7 @@
 extern void test_thread_context(void);
 extern void test_bootdelay(void);
 extern void test_irq_offload(void);
+extern void test_nested_irq_offload(void);
 extern void test_bitarray_declare(void);
 extern void test_bitarray_set_clear(void);
 extern void test_bitarray_alloc_free(void);
@@ -125,6 +126,7 @@
 	ztest_test_suite(common,
 			 ztest_unit_test(test_bootdelay),
 			 ztest_unit_test(test_irq_offload),
+			 ztest_unit_test(test_nested_irq_offload),
 			 ztest_unit_test(test_byteorder_memcpy_swap),
 			 ztest_unit_test(test_byteorder_mem_swap),
 			 ztest_unit_test(test_sys_get_be64),