> ## Documentation Index
> Fetch the complete documentation index at: https://kernel.mvhcloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Interrupt API — IDT, PIC, and IRQ Statistics in MVH Kernel

> MVH Kernel interrupt API: interrupt_init, interrupt_enable, interrupt_disable, exception_dispatch, interrupt_count, interrupt_total, and spurious count.

The interrupt layer manages the x86\_64 Interrupt Descriptor Table (IDT), the remapped 8259 Programmable Interrupt Controller (PIC), and a set of per-vector software counters that let you observe interrupt activity at runtime. When you call `interrupt_init`, the kernel installs 256 IDT gate descriptors, remaps both PIC chips to avoid conflicts with CPU exception vectors, programs the Programmable Interval Timer (PIT) to fire at 100 Hz, and unmasks the interrupt lines that the kernel uses. Interrupt and exception handling are then fully operational for the remainder of the boot session.

## Architecture Overview

| Component          | Detail                                                                   |
| ------------------ | ------------------------------------------------------------------------ |
| IDT                | 256 interrupt gate descriptors (vectors `0x00`–`0xFF`)                   |
| Exception vectors  | `0`–`31` — CPU exception stubs that all dispatch to `exception_dispatch` |
| 8259 PIC remapping | Master PIC remapped to vectors `0x20`–`0x27`; slave to `0x28`–`0x2F`     |
| PIT frequency      | 100 Hz (10 ms per tick)                                                  |
| Unused IRQ lines   | Masked at the PIC to suppress spurious activity                          |

Exception vectors `0`–`31` are reserved by the x86\_64 architecture for CPU-generated faults, traps, and aborts (e.g., `#DE` Divide Error at vector `0`, `#PF` Page Fault at vector `14`). The kernel installs stub handlers for all 32 exception vectors; each stub calls `exception_dispatch`, which prints diagnostic information and halts the processor. Hardware interrupts from PIC-attached devices use vectors `0x20` and above.

***

## Functions

### `interrupt_init`

Initialize the IDT, reprogram the 8259 PIC, configure the PIT at 100 Hz, and install all exception and hardware interrupt handlers. Call this once during early kernel initialization, before enabling interrupts with `interrupt_enable`.

```c theme={null}
void interrupt_init(void);
```

After this call returns, the interrupt subsystem is fully configured but interrupts remain disabled until you explicitly call `interrupt_enable`.

***

### `interrupt_enable`

Enable hardware interrupts on the current CPU by executing the `STI` (Set Interrupt Flag) instruction.

```c theme={null}
void interrupt_enable(void);
```

Call `interrupt_enable` only after `interrupt_init` has completed. Once enabled, the processor begins accepting and dispatching hardware interrupts through the IDT.

***

### `interrupt_disable`

Disable hardware interrupts on the current CPU by executing the `CLI` (Clear Interrupt Flag) instruction.

```c theme={null}
void interrupt_disable(void);
```

Use `interrupt_disable` to create short critical sections that must not be preempted by interrupt handlers. Keep the disabled window as brief as possible to avoid missing time-critical hardware events.

<Note>
  `interrupt_disable` masks hardware IRQs but does not prevent NMIs (Non-Maskable Interrupts). NMIs bypass the interrupt flag and always reach the CPU.
</Note>

***

### `exception_dispatch`

The kernel's unified exception handler. Called automatically by the IDT exception stubs for all CPU exception vectors (`0`–`31`). This function prints fault information and halts the processor; it never returns.

```c theme={null}
void exception_dispatch(void *frame) __attribute__((noreturn));
```

<ParamField path="frame" type="void *">
  Pointer to the CPU exception frame pushed onto the kernel stack by the IDT stub. The exact layout depends on the exception vector; some exceptions push an error code. `exception_dispatch` interprets the frame internally.
</ParamField>

<Note>
  Do not call `exception_dispatch` directly from your code. It is invoked automatically by the IDT exception stubs whenever the CPU raises an unhandled fault, trap, or abort. Triggering it manually will halt the system unconditionally.
</Note>

***

### `interrupt_count`

Return the number of times a specific IDT vector has fired since `interrupt_init` was called.

```c theme={null}
uint64_t interrupt_count(uint8_t vector);
```

<ParamField path="vector" type="uint8_t" required>
  IDT vector number to query (`0`–`255`). PIC hardware IRQs start at vector `0x20` (IRQ0 = PIT, IRQ1 = PS/2 keyboard, etc.).
</ParamField>

<ResponseField name="return" type="uint64_t">
  Cumulative interrupt count for the given vector since system initialization. Returns `0` for vectors that have never fired.
</ResponseField>

***

### `interrupt_total`

Return the total number of interrupts that have fired across all 256 IDT vectors.

```c theme={null}
uint64_t interrupt_total(void);
```

<ResponseField name="return" type="uint64_t">
  Sum of per-vector counters across all 256 vectors. This value monotonically increases for the lifetime of the system.
</ResponseField>

***

### `interrupt_spurious_count`

Return the number of spurious interrupts that the PIC has generated since `interrupt_init` was called.

```c theme={null}
uint64_t interrupt_spurious_count(void);
```

<ResponseField name="return" type="uint64_t">
  Cumulative count of spurious interrupts detected and silently discarded by the kernel. A small, slowly growing number is normal. A rapidly increasing count may indicate a hardware problem or an IRQ line that is incorrectly left unmasked.
</ResponseField>

***

## Querying Interrupt Statistics

You can read per-vector counters at any time from kernel code. The `irqstat` built-in shell command displays these counters in a formatted table.

```sh theme={null}
irqstat
```

To read statistics programmatically:

```c theme={null}
#include "mvh/interrupt.h"
#include <stdint.h>

void show_irq_stats(void) {
    /* Total interrupts since boot */
    uint64_t total = interrupt_total();
    (void)total;

    /* PIT ticks — IRQ0 is remapped to vector 0x20 */
    uint64_t pit_ticks = interrupt_count(0x20);
    (void)pit_ticks;

    /* PS/2 keyboard interrupts — IRQ1 is remapped to vector 0x21 */
    uint64_t kbd_count = interrupt_count(0x21);
    (void)kbd_count;

    /* Spurious PIC interrupts */
    uint64_t spurious = interrupt_spurious_count();
    (void)spurious;
}
```

***

## Example: Initialization Sequence

The following shows the recommended interrupt initialization order during kernel startup.

```c theme={null}
#include "mvh/interrupt.h"

void kernel_main(void) {
    /* Set up IDT, remap PIC, configure PIT at 100 Hz */
    interrupt_init();

    /* Perform any critical setup that must not be interrupted */
    /* ... */

    /* Enable hardware interrupts — the system is now live */
    interrupt_enable();

    /* From this point onward, PIT ticks, keyboard events, and
       other hardware interrupts are dispatched through the IDT. */
}
```

<Note>
  If the CPU raises an exception (e.g., a page fault or divide-by-zero) after `interrupt_init` returns, the corresponding IDT stub calls `exception_dispatch` automatically. The kernel prints fault details and halts — there is no attempt to recover from unhandled exceptions.
</Note>
