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)