> ## 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 Log API — Ring Buffer Logging in MVH Kernel

> Reference for the MVH Kernel log API: klog_init, klog_write, klog_write_category, klog_set_console, klog_copy, and klog_size for ring buffer logging.

The kernel log is a 16 KiB circular ring buffer that stores structured, timestamped log entries. Each entry carries a severity level string and an optional category tag alongside the message text. When the buffer is full, the oldest entries are overwritten so that the most recent activity is always available. You can mirror log output to the VGA console at any time, and you can snapshot the current buffer contents into your own memory for further processing.

<Note>
  The ring buffer has a fixed capacity of 16 KiB. When it is full, the oldest entries are silently overwritten. If you need a persistent log, copy the buffer to stable storage with `klog_copy` before it wraps.
</Note>

## Suggested Level Strings

The kernel log API accepts arbitrary level strings, but the following values are used by convention throughout MVH Kernel itself:

| Level     | Meaning                                         |
| --------- | ----------------------------------------------- |
| `"INFO"`  | Normal operational messages                     |
| `"WARN"`  | Non-fatal conditions that may require attention |
| `"ERROR"` | Recoverable error conditions                    |
| `"DEBUG"` | Verbose diagnostic output                       |

***

## Functions

### `klog_init`

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

Initialise the kernel log ring buffer. You must call this function exactly once during kernel startup, before calling any other log API function. Calling it a second time resets the ring and discards all existing log data.

***

### `klog_write`

```c theme={null}
void klog_write(const char *level, const char *message);
```

Write a log entry with a level and message. Use this function when you do not need a category tag.

<ParamField path="level" type="const char *" required>
  A null-terminated severity string such as `"INFO"`, `"WARN"`, `"ERROR"`, or `"DEBUG"`. The string is copied into the entry, so you do not need to keep the pointer alive after the call.
</ParamField>

<ParamField path="message" type="const char *" required>
  A null-terminated log message. The message is copied into the ring buffer along with the level and a kernel-generated timestamp.
</ParamField>

***

### `klog_write_category`

```c theme={null}
void klog_write_category(const char *level, const char *category, const char *message);
```

Write a log entry with a level, an optional category tag, and a message. This is the preferred form when you want to associate entries with a named subsystem (for example `"ACPI"`, `"PCI"`, `"VMM"`).

<ParamField path="level" type="const char *" required>
  A null-terminated severity string. See `klog_write` for suggested values.
</ParamField>

<ParamField path="category" type="const char *" required>
  A null-terminated subsystem or component name. The `dmesg` shell command can filter by category, so choosing consistent category names makes log inspection easier.
</ParamField>

<ParamField path="message" type="const char *" required>
  A null-terminated log message.
</ParamField>

***

### `klog_set_console`

```c theme={null}
void klog_set_console(uint8_t enabled);
```

Control whether new log entries are mirrored to the VGA text console in real time. Console mirroring is disabled by default; enable it early in the boot sequence if you want live log output on screen.

<ParamField path="enabled" type="uint8_t" required>
  Pass `1` to enable VGA console mirroring, or `0` to disable it. This setting affects only entries written after the call — it does not replay previously buffered entries.
</ParamField>

***

### `klog_copy`

```c theme={null}
uint32_t klog_copy(char *output, uint32_t capacity);
```

Copy the current contents of the ring buffer into a caller-supplied byte buffer. The copy is a linear snapshot of all data currently in the ring, oldest entry first.

<ParamField path="output" type="char *" required>
  Pointer to a buffer that will receive the log data. The buffer must be at least `capacity` bytes long. The copied data is not null-terminated automatically — add a null terminator yourself if you intend to treat the result as a C string.
</ParamField>

<ParamField path="capacity" type="uint32_t" required>
  The maximum number of bytes to copy. To guarantee a complete snapshot, pass a value of at least 16 384 (16 KiB).
</ParamField>

<ResponseField name="return" type="uint32_t">
  The number of bytes written to `output`. This is `min(klog_size(), capacity)`.
</ResponseField>

***

### `klog_size`

```c theme={null}
uint32_t klog_size(void);
```

Return the number of bytes of log data currently stored in the ring buffer.

<ResponseField name="return" type="uint32_t">
  The current occupancy of the ring buffer in bytes, in the range `[0, 16384]`.
</ResponseField>

***

## Shell Command

The built-in `dmesg` shell command dumps the full contents of the kernel log ring buffer to the console:

```
dmesg
```

***

## Example

The following example initialises the log, writes several categorised entries at different severity levels, then takes a snapshot of the entire ring for further inspection.

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

void demo_logging(void) {
    /* Initialise the ring buffer once at boot. */
    klog_init();

    /* Mirror all subsequent log entries to the VGA console. */
    klog_set_console(1);

    /* Write entries at various levels with a subsystem category. */
    klog_write_category("INFO",  "BOOT",   "Kernel log subsystem ready.");
    klog_write_category("INFO",  "PCI",    "Scanning PCI bus.");
    klog_write_category("WARN",  "ACPI",   "ACPI table checksum mismatch — continuing.");
    klog_write_category("ERROR", "SERIAL", "COM1 UART not responding.");
    klog_write(         "DEBUG",           "Raw tick counter: see timer subsystem.");

    /* Snapshot the ring into a local buffer. */
    char snapshot[16384];
    uint32_t bytes = klog_copy(snapshot, sizeof(snapshot));
    snapshot[bytes] = '\0'; /* Null-terminate for safe string use. */

    printf("--- kernel log snapshot (%u bytes) ---\n%s\n", bytes, snapshot);
}
```
