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

# MVH Kernel Boot Requirements: Bootloader Setup Guide

> Bootloader prerequisites for MVH Kernel: 64-bit Long Mode, identity-mapped first GiB of RAM, total memory size in KiB, and the kernel entry point symbol.

Before you transfer control to MVH Kernel, your bootloader must satisfy three hard prerequisites. The kernel performs no fallback detection and no self-recovery for any of them — if any requirement is unmet when execution reaches `_kernel64_start`, the CPU will fault. This page describes each requirement, explains what you must pass at the entry point, and shows how any x86\_64 bootloader capable of loading an ELF64 image can satisfy all three.

<Warning>
  Do **not** jump to `_kernel64_start` without satisfying all three requirements listed below. The kernel does not check whether it is in Long Mode, does not attempt to build its own identity map, and does not fall back gracefully if the memory-size argument is zero or missing. Violating any requirement will result in an immediate CPU fault.
</Warning>

***

## Kernel Binary Details

| Property               | Value             |
| ---------------------- | ----------------- |
| **Architecture**       | x86\_64           |
| **Binary format**      | ELF64             |
| **Entry point symbol** | `_kernel64_start` |
| **Version**            | 1.1.2             |

Load the MVH Kernel ELF64 image with your bootloader's standard ELF loader, then resolve the `_kernel64_start` symbol from the ELF header to find the entry address. Do not hard-code a load address — always read it from the ELF program headers.

***

## Requirements

<Steps>
  <Step title="x86_64 Long Mode">
    The CPU must already be running in **64-bit Long Mode (IA-32e mode)** before you call the kernel entry point. This means:

    * A valid Global Descriptor Table (GDT) is loaded with a 64-bit code segment.
    * The CPU is executing with CS pointing to that 64-bit code segment descriptor.
    * `CR0.PE` (Protected Mode Enable) and `CR0.PG` (Paging) are both set.
    * `EFER.LME` and `EFER.LMA` are both set.

    Most modern bootloaders (GRUB2 with multiboot2, Limine, custom UEFI stubs) enter Long Mode automatically before handing off to a 64-bit kernel. If you are writing a custom bootloader, complete the full Long Mode transition sequence — real mode → protected mode → Long Mode — before jumping to the kernel.
  </Step>

  <Step title="Identity-Mapped First GiB">
    The **first 1 024 MiB (1 GiB) of physical memory must be identity-mapped** in the active page tables before you enter the kernel. An identity map means that for every physical address `P` in `[0, 1 GiB)`, the virtual address `P` must resolve to physical address `P`.

    MVH Kernel's PMM and VMM initialisation code accesses its own data structures through virtual addresses that equal their physical addresses. If the identity map is absent or incomplete, the very first kernel memory access will page-fault before the kernel has had a chance to install its own page tables.

    You may map the first GiB as a single 1 GiB huge page, as 512 × 2 MiB large pages, or as 262 144 × 4 KiB pages — the kernel does not require any particular granularity. After VMM initialisation the kernel rebuilds the page tables under its own control; your bootloader mappings only need to survive until `vmm_init` completes.
  </Step>

  <Step title="Boot Memory Size in KiB">
    You must supply the **total usable physical RAM in KiB** to the kernel. The PMM's `pmm_init` function receives this value as its first argument (`uint64_t memory_kib`) and uses it to size the page-frame bitmap. If you pass zero, the PMM will mark no pages as available and every subsequent `pmm_alloc_pages` call will fail, causing the kernel to panic during heap or VMM initialisation.

    How you deliver this value depends on your bootloader protocol — see the example below.
  </Step>
</Steps>

***

## Passing the Memory Size

The mechanism for passing `memory_kib` to the kernel depends on your bootloader protocol. The examples below show two common approaches.

<CodeGroup>
  ```c GRUB2 / Multiboot2 (C stub) theme={null}
  // In your multiboot2 entry stub, parse the memory map tag
  // and accumulate usable RAM before calling the kernel.
  #include <multiboot2.h>

  extern void _kernel64_start(uint64_t memory_kib);

  void multiboot2_entry(uint32_t magic, struct multiboot_info *info)
  {
      uint64_t usable_kib = 0;

      struct multiboot_tag *tag = (struct multiboot_tag *)(info + 1);
      while (tag->type != MULTIBOOT_TAG_TYPE_END) {
          if (tag->type == MULTIBOOT_TAG_TYPE_MMAP) {
              struct multiboot_tag_mmap *mmap = (struct multiboot_tag_mmap *)tag;
              multiboot_memory_map_t *entry = mmap->entries;
              while ((uint8_t *)entry < (uint8_t *)mmap + mmap->size) {
                  if (entry->type == MULTIBOOT_MEMORY_AVAILABLE)
                      usable_kib += entry->len / 1024;
                  entry = (multiboot_memory_map_t *)
                      ((uint8_t *)entry + mmap->entry_size);
              }
          }
          tag = (struct multiboot_tag *)
              ((uint8_t *)tag + ((tag->size + 7) & ~7));
      }

      _kernel64_start(usable_kib);
  }
  ```

  ```c Limine / Custom Protocol (C stub) theme={null}
  // With Limine's memory-map response, sum up usable entries
  // and pass the total to the kernel entry point.
  #include <limine.h>

  extern void _kernel64_start(uint64_t memory_kib);

  void limine_entry(void)
  {
      extern struct limine_memmap_response *memmap_response;

      uint64_t usable_kib = 0;
      for (uint64_t i = 0; i < memmap_response->entry_count; i++) {
          struct limine_memmap_entry *e = memmap_response->entries[i];
          if (e->type == LIMINE_MEMMAP_USABLE)
              usable_kib += e->length / 1024;
      }

      _kernel64_start(usable_kib);
  }
  ```

  ```asm Assembly (direct call) theme={null}
  ; Assuming `usable_kib` has already been computed and stored in rax:
  ; Place the value in rdi (first System V AMD64 ABI argument),
  ; then jump to the kernel entry point.

      mov  rdi, rax          ; rdi = memory_kib (first argument)
      call _kernel64_start   ; transfer control to MVH Kernel
  ```
</CodeGroup>

<Note>
  Always derive `memory_kib` from your bootloader's memory map rather than from a hard-coded constant. The PMM uses this value to size internal structures; an under-count wastes physical RAM, and an over-count can cause the PMM to mark non-existent or reserved pages as available.
</Note>

***

## What the Kernel Initialises After Entry

Once your bootloader transfers control to `_kernel64_start` with all three requirements met, MVH Kernel performs the following initialisation sequence automatically — you do not need to call any of these steps yourself:

1. **HAL** — initialises platform hardware (VGA, serial, PS/2, PCI, RTC, PIT).
2. **PMM** — builds the physical page-frame bitmap from `memory_kib`.
3. **VMM** — installs the kernel page tables with security protections.
4. **Kernel Heap** — initialises the 1 MiB coalescing heap.
5. **Kernel Log** — starts the structured ring log.
6. **VFS + RAMFS** — mounts the volatile RAM filesystem as root.
7. **Device Manager** — registers all built-in drivers.
8. **Interrupt Layer** — loads the IDT, remaps the 8259 PIC, and starts the 100 Hz PIT.
9. **Interactive Shell** — enters the command loop and waits for keyboard input.

***

## Compatible Bootloaders

Any x86\_64 bootloader that can load an ELF64 binary and enter Long Mode before the handoff is compatible. Tested and recommended options include:

| Bootloader                   | Protocol             | Notes                                                                        |
| ---------------------------- | -------------------- | ---------------------------------------------------------------------------- |
| **GRUB2**                    | Multiboot2           | Use a 64-bit multiboot2 entry stub; GRUB enters Long Mode automatically      |
| **Limine**                   | Limine boot protocol | Native 64-bit entry; provides a clean memory map API                         |
| **Custom UEFI stub**         | Any                  | UEFI already runs in Long Mode; parse `EFI_MEMORY_DESCRIPTOR` for usable RAM |
| **Custom bare-metal loader** | Any                  | Implement Long Mode transition and identity map manually before the jump     |
