Master the fundamental concepts of build a mini kernel through this focused micro-challenge.
The IDT maps interrupt vectors to handler addresses with privilege and gate type. CPU pushes error code and vector on fault; your stub saves registers and calls C handlers.
Per vector:
For example, vector 0x0E page fault pushes faulting address on stack for your handler to inspect CR2.
The IDT you're building here is what every x86 kernel uses to route hardware IRQs, CPU exceptions, and syscalls to handler code, and vector 128 (0x80) is the literal interrupt number Linux used for system calls for two decades before syscall/sysret replaced it. Forgetting to end a handler with iret instead of ret is a classic bug that corrupts the interrupted task's entire register and flag state.
Before you call the implementation done, walk failure modes on purpose. Test empty structures, single-element edge cases, maximum concurrency, and errno paths that must not crash the program. OS code usually fails in production when happy-path tests pass but invariants break under contention or memory pressure.
Keep structures small and name fields after kernel counterparts when possible. That lets you read man pages and kernel source side by side while you work. Print observable events during development; remove noisy logs once tests pass reliably.
You will load IDT with assembly stubs that dispatch to C. This exercise requires differentiating IRQ handlers from CPU exception handlers in your logging.
Simulate interrupt handling infrastructure in C.
Requirements:
Test:
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
All starter code and reference implementations are available for your local setup.
View on Github