Introduce tests.extra/hardware_revoker_IRQs
diff --git a/tests.extra/hardware_revoker_IRQs/README.md b/tests.extra/hardware_revoker_IRQs/README.md
new file mode 100644
index 0000000..bc8925c
--- /dev/null
+++ b/tests.extra/hardware_revoker_IRQs/README.md
@@ -0,0 +1 @@
+This is a minimal "the clock is ticking" test for a hardware revoker.
diff --git a/tests.extra/hardware_revoker_IRQs/top.cc b/tests.extra/hardware_revoker_IRQs/top.cc
new file mode 100644
index 0000000..f3e50d3
--- /dev/null
+++ b/tests.extra/hardware_revoker_IRQs/top.cc
@@ -0,0 +1,53 @@
+#include <debug.hh>
+#include <fail-simulator-on-error.h>
+
+using Debug = ConditionalDebug<true, "top">;
+
+#if __has_include(<platform-hardware_revoker.hh>)
+# include <platform-hardware_revoker.hh>
+#else
+# error No platform-hardware_revoker.hh found, are you building for the right platform?
+#endif
+
+using Revoker = HardwareRevoker<uint32_t, REVOKABLE_MEMORY_START>;
+static_assert(Revoker::IsAsynchronous, "This test is for async revokers");
+
+void __cheri_compartment("top") entry()
+{
+ Revoker r{};
+ r.init();
+
+ uint32_t epoch = r.system_epoch_get();
+ Debug::log("At startup, revocation epoch is {}; waiting...", epoch);
+
+ // Just in case a revocation is somehow active...
+ epoch &= ~1;
+ r.system_bg_revoker_kick();
+
+ for (int i = 0; i < 10; i++)
+ {
+ bool res;
+ uint32_t newepoch;
+ Timeout t{50};
+
+ res = r.wait_for_completion(&t, (epoch & ~1) + 2);
+ newepoch = r.system_epoch_get();
+
+ Debug::log("After wait: for {}, result {}, epoch now is {}, "
+ "wait elapsed {} remaining {}",
+ epoch,
+ res,
+ newepoch,
+ t.elapsed,
+ t.remaining);
+
+ Debug::Assert(t.remaining > 0,
+ "Timed out waiting for revoker to advance");
+
+ if (res)
+ {
+ epoch = newepoch;
+ r.system_bg_revoker_kick();
+ }
+ }
+}
diff --git a/tests.extra/hardware_revoker_IRQs/xmake.lua b/tests.extra/hardware_revoker_IRQs/xmake.lua
new file mode 100644
index 0000000..a8c713f
--- /dev/null
+++ b/tests.extra/hardware_revoker_IRQs/xmake.lua
@@ -0,0 +1,26 @@
+set_project("Hardware Revoker IRQ Basic Functionality Test")
+sdkdir = "../../sdk"
+includes(sdkdir)
+set_toolchains("cheriot-clang")
+
+option("board")
+ set_default("ibex-safe-simulator")
+
+compartment("top")
+ add_files("top.cc")
+
+firmware("top_compartment")
+ add_deps("freestanding", "debug")
+ add_deps("top")
+ on_load(function(target)
+ target:values_set("board", "$(board)")
+ target:values_set("threads", {
+ {
+ compartment = "top",
+ priority = 1,
+ entry_point = "entry",
+ stack_size = 0x300,
+ trusted_stack_frames = 1
+ }
+ }, {expand = false})
+ end)