> ## 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.

# Kernel Panic API — MVH Kernel Halt and Diagnostics

> Reference for the MVH Kernel panic API: kernel_panic, kernel_panic_exception, and exception_frame_t. Both panic functions are noreturn and halt the system.

When MVH Kernel encounters an unrecoverable error, it enters a controlled panic state that displays a stable panic code, the decoded exception name, hardware error-code flag analysis (page-fault and selector-error formats), the full set of general-purpose registers, the x86\_64 control registers (CR0, CR2, CR3, CR4), and a bounded frame-pointer stack trace. All output is written to both the VGA text console and the serial port so that you can capture it headlessly. Once a panic is triggered the system halts and does not return.

<Warning>
  Both `kernel_panic` and `kernel_panic_exception` are declared `noreturn`. Calling either function halts the system immediately and irrevocably — execution never returns to the call site.
</Warning>

## Stable Panic Codes

The kernel assigns a fixed numeric code to each common exception type. You can list all defined panic codes from the kernel shell:

```
paniccodes
```

Panic codes are stable across kernel releases so you can use them in automated crash analysis pipelines. The code is printed in the panic banner alongside the human-readable exception name.

## Types

### `exception_frame_t`

A complete snapshot of the processor state at the moment an exception fires. The kernel's low-level exception stubs push these fields onto the stack in the order listed, then pass a pointer to this structure to `kernel_panic_exception`.

```c theme={null}
typedef struct {
    /* Extended general-purpose registers (pushed by stub) */
    uint64_t r15;
    uint64_t r14;
    uint64_t r13;
    uint64_t r12;
    uint64_t r11;
    uint64_t r10;
    uint64_t r9;
    uint64_t r8;

    /* Standard general-purpose and base registers (pushed by stub) */
    uint64_t rbp;
    uint64_t rdi;
    uint64_t rsi;
    uint64_t rdx;
    uint64_t rcx;
    uint64_t rbx;
    uint64_t rax;

    /* Exception metadata (pushed by stub / CPU) */
    uint64_t vector;       /* Exception vector number (0–255)                   */
    uint64_t error_code;   /* Hardware error code; 0 for exceptions without one */

    /* CPU-pushed interrupt frame */
    uint64_t rip;          /* Instruction pointer at the point of exception     */
    uint64_t cs;           /* Code segment selector                             */
    uint64_t rflags;       /* RFLAGS register value                             */
} exception_frame_t;
```

<ResponseField name="r15 – r8" type="uint64_t">
  The eight extended 64-bit general-purpose registers (`r15` through `r8`) saved by the exception stub before transferring control to the panic handler.
</ResponseField>

<ResponseField name="rbp" type="uint64_t">
  The base pointer register. The panic handler walks this chain to produce the frame-pointer stack trace displayed in the panic output.
</ResponseField>

<ResponseField name="rdi" type="uint64_t">
  First integer argument register (System V AMD64 ABI).
</ResponseField>

<ResponseField name="rsi" type="uint64_t">
  Second integer argument register.
</ResponseField>

<ResponseField name="rdx" type="uint64_t">
  Third integer argument register / data register.
</ResponseField>

<ResponseField name="rcx" type="uint64_t">
  Fourth integer argument register / counter register.
</ResponseField>

<ResponseField name="rbx" type="uint64_t">
  Base register (callee-saved).
</ResponseField>

<ResponseField name="rax" type="uint64_t">
  Accumulator register; holds the return value of the most recently completed function call.
</ResponseField>

<ResponseField name="vector" type="uint64_t">
  The x86\_64 exception vector number (0–255). Well-known values include `0` (divide error), `6` (invalid opcode), `8` (double fault), `13` (general protection fault), and `14` (page fault).
</ResponseField>

<ResponseField name="error_code" type="uint64_t">
  The hardware-supplied error code. The panic handler decodes this field for vector 13 (GPF, selector-error format) and vector 14 (page fault, CR2 + P/W/U/I flags). Set to `0` for exceptions that do not push an error code.
</ResponseField>

<ResponseField name="rip" type="uint64_t">
  The instruction pointer value at the time of the exception — the address of the faulting or next instruction, depending on the exception class.
</ResponseField>

<ResponseField name="cs" type="uint64_t">
  The code segment selector active when the exception occurred.
</ResponseField>

<ResponseField name="rflags" type="uint64_t">
  The full 64-bit RFLAGS value captured by the CPU on exception entry.
</ResponseField>

***

## Functions

### `kernel_panic`

```c theme={null}
void kernel_panic(const char *message) __attribute__((noreturn));
```

Trigger a kernel panic with a plain text message. Use this function when your own code detects an unrecoverable condition — for example, a failed assertion, a corrupted data structure, or an unexpected null pointer at a point where recovery is impossible.

The panic handler prints the message, the current register state, the control registers, and a stack trace, then halts all further execution.

<ParamField path="message" type="const char *" required>
  A null-terminated human-readable description of the failure. This string is displayed verbatim in the panic banner on both VGA and serial output. Keep it concise — one short sentence is ideal.
</ParamField>

<Warning>
  `kernel_panic` never returns. Any code after the call site is unreachable.
</Warning>

***

### `kernel_panic_exception`

```c theme={null}
void kernel_panic_exception(const exception_frame_t *frame) __attribute__((noreturn));
```

Trigger a kernel panic from an exception frame. This function is called automatically by the kernel's `exception_dispatch` routine for every unhandled CPU exception — you do not need to call it yourself under normal circumstances.

The panic handler reads the vector number and error code from the frame to select the correct stable panic code, decode the error flags, and print the full register dump.

<ParamField path="frame" type="const exception_frame_t *" required>
  Pointer to a fully populated `exception_frame_t` built by the low-level exception stub. The structure must remain valid for the duration of the call (in practice it lives on the kernel stack and is never freed, since the function never returns).
</ParamField>

<Note>
  `kernel_panic_exception` is called automatically by `exception_dispatch` for all CPU exceptions. You only need to call it directly if you are writing a custom exception stub that bypasses the standard dispatch path.
</Note>

***

## Example

The following example shows how to use `kernel_panic` as a hard assertion guard inside a kernel subsystem initialisation routine.

```c theme={null}
#include <mvh/panic.h>

/* A simple kernel assertion macro built on kernel_panic. */
#define KASSERT(cond, msg)          \
    do {                            \
        if (!(cond)) {              \
            kernel_panic(msg);      \
        }                           \
    } while (0)

void memory_subsystem_init(void *heap_base, size_t heap_size) {
    /* Ensure the heap pointer is valid before proceeding. */
    KASSERT(heap_base != NULL,
            "memory_subsystem_init: heap_base is NULL");

    /* Ensure the heap is at least 64 KiB. */
    KASSERT(heap_size >= 65536u,
            "memory_subsystem_init: heap too small (minimum 64 KiB)");

    /*
     * If either assertion fails, kernel_panic() prints the message,
     * dumps all registers and the stack trace, then halts the system.
     * Execution never reaches this comment in that case.
     */

    /* Normal initialisation continues here. */
}
```
