Built device interrupts

This commit is contained in:
2026-07-03 12:57:40 +01:00
parent c8e89e8115
commit 5ea521d054
12 changed files with 367 additions and 23 deletions
+23
View File
@@ -36,6 +36,8 @@ fn check(name: []const u8, ok: bool) void {
pub fn run(case: []const u8, boot_info: *const BootInfo) void {
if (eql(case, "smoke")) {
smoke(boot_info);
} else if (eql(case, "timer")) {
timer();
} else if (eql(case, "fault-ud")) {
faultInvalidOpcode();
} else if (eql(case, "fault-pf")) {
@@ -91,6 +93,26 @@ fn smoke(boot_info: *const BootInfo) void {
log("DANOS-TEST-DONE\n", .{});
}
/// Verify device interrupts fire and return: the timer tick counter must advance
/// on its own. Interrupts are already enabled by kmain before tests run.
fn timer() void {
log("DANOS-TEST-BEGIN: timer\n", .{});
const start = arch.ticks();
// Busy-wait for the counter to advance. arch.ticks() is a volatile load, so
// the compiler re-reads it each iteration and sees the interrupt's update.
// The cap is only a safety net; the harness timeout is the real backstop.
var spins: u64 = 0;
while (arch.ticks() == start and spins < 5_000_000_000) spins +%= 1;
check("timer interrupts advance the tick count", arch.ticks() > start);
log("DANOS-TEST-RESULT: {s} ({d} passed, {d} failed)\n", .{
if (failed == 0) "PASS" else "FAIL",
passed,
failed,
});
log("DANOS-TEST-DONE\n", .{});
}
fn faultInvalidOpcode() void {
log("DANOS-TEST-BEGIN: fault-ud\n", .{});
asm volatile ("ud2");
@@ -108,6 +130,7 @@ fn faultPageFault() void {
fn faultDoubleFault() void {
log("DANOS-TEST-BEGIN: fault-df\n", .{});
arch.disableInterrupts(); // so only the ud2 delivery (not a timer tick) triggers the #DF
// Point RSP at unmapped memory, then fault: the CPU can't push the fault
// frame, which escalates to #DF — survivable only because #DF runs on IST1.
var bad_sp: u64 = 0x5000000000;