Regression test for IRQs on thread exit path
diff --git a/tests.extra/regress-thread_exit_IRQ/README.md b/tests.extra/regress-thread_exit_IRQ/README.md
new file mode 100644
index 0000000..e0e9f2f
--- /dev/null
+++ b/tests.extra/regress-thread_exit_IRQ/README.md
@@ -0,0 +1,6 @@
+This checks for a specific bug fixed in 2024/11, where it was possible to
+invoke the scheduler's exception entrypoint, which must run with IRQs deferred,
+with IRQs enabled if a thread exited from its initial activation via a slightly
+unusual path.
+
+See https://github.com/CHERIoT-Platform/cheriot-rtos/pull/346
diff --git a/tests.extra/regress-thread_exit_IRQ/helper.cc b/tests.extra/regress-thread_exit_IRQ/helper.cc
new file mode 100644
index 0000000..023b4fe
--- /dev/null
+++ b/tests.extra/regress-thread_exit_IRQ/helper.cc
@@ -0,0 +1,5 @@
+#include "helper.h"
+[[cheri::interrupt_state(enabled)]] void* help(void)
+{
+	return __builtin_return_address(0);
+}
diff --git a/tests.extra/regress-thread_exit_IRQ/helper.h b/tests.extra/regress-thread_exit_IRQ/helper.h
new file mode 100644
index 0000000..578659e
--- /dev/null
+++ b/tests.extra/regress-thread_exit_IRQ/helper.h
@@ -0,0 +1,2 @@
+#include <compartment.h>
+void* __cheri_compartment("helper") help(void);
diff --git a/tests.extra/regress-thread_exit_IRQ/top.cc b/tests.extra/regress-thread_exit_IRQ/top.cc
new file mode 100644
index 0000000..57087ce
--- /dev/null
+++ b/tests.extra/regress-thread_exit_IRQ/top.cc
@@ -0,0 +1,5 @@
+#include "helper.h"
+void __cheri_compartment("top") entry()
+{
+	asm volatile ("cmove cra, %0; cret" : : "C"(help()));
+}
diff --git a/tests.extra/regress-thread_exit_IRQ/xmake.lua b/tests.extra/regress-thread_exit_IRQ/xmake.lua
new file mode 100644
index 0000000..38462b2
--- /dev/null
+++ b/tests.extra/regress-thread_exit_IRQ/xmake.lua
@@ -0,0 +1,29 @@
+set_project("CHERIoT Scheduler IRQ Exception PoC")
+sdkdir = "../../sdk"
+includes(sdkdir)
+set_toolchains("cheriot-clang")
+
+option("board")
+    set_default("sail")
+
+compartment("helper")
+    add_files("helper.cc")
+
+compartment("top")
+    add_files("top.cc")
+
+firmware("top_compartment")
+    add_deps("freestanding", "debug")
+    add_deps("top", "helper")
+    on_load(function(target)
+        target:values_set("board", "$(board)")
+        target:values_set("threads", {
+            {
+                compartment = "top",
+                priority = 1,
+                entry_point = "entry",
+                stack_size = 0x200,
+                trusted_stack_frames = 1
+            }
+        }, {expand = false})
+    end)