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

# Virtual Memory Manager API — vmm_map_page and Page Flags

> Reference for the MVH Kernel VMM API: vmm_init, vmm_map_page, vmm_unmap_page, vmm_query_page, vmm_mapped_pages. Covers all VMM_* page flag constants.

The Virtual Memory Manager (VMM) provides dynamic 4 KiB page mapping on top of the x86\_64 four-level paging hierarchy (PML4 → PDPT → PD → PT). You use the VMM to establish, modify, and tear down arbitrary virtual-to-physical address mappings at any time after `vmm_init` returns. The VMM allocates intermediate page-table structures (PDPT, PD, PT nodes) from the PMM on demand, so the PMM must be initialized before you call `vmm_init`.

## Page Flag Constants

Each mapping carries a 64-bit flags word whose bits directly correspond to x86\_64 page-table entry attributes. The following constants from `mvh/memory.h` cover every attribute the VMM exposes. Combine them with the bitwise-OR operator when calling `vmm_map_page`.

```c theme={null}
#define VMM_PRESENT       (1ull << 0u)   /* Page is present in memory               */
#define VMM_WRITABLE      (1ull << 1u)   /* Page is writable                        */
#define VMM_USER          (1ull << 2u)   /* Page is accessible from user mode (CPL3)*/
#define VMM_WRITE_THROUGH (1ull << 3u)   /* Write-through caching policy            */
#define VMM_CACHE_DISABLE (1ull << 4u)   /* Disable caching entirely (MMIO use)     */
#define VMM_GLOBAL        (1ull << 8u)   /* TLB entry is not flushed on CR3 switch  */
#define VMM_NO_EXECUTE    (1ull << 63u)  /* Execution from this page is forbidden   */
```

| Constant            | Bit | Typical Use                                       |
| ------------------- | --- | ------------------------------------------------- |
| `VMM_PRESENT`       | 0   | Required for every valid mapping                  |
| `VMM_WRITABLE`      | 1   | Read/write data pages                             |
| `VMM_USER`          | 2   | Future user-space mappings                        |
| `VMM_WRITE_THROUGH` | 3   | Write-through cache policy                        |
| `VMM_CACHE_DISABLE` | 4   | MMIO regions (e.g. framebuffer, LAPIC)            |
| `VMM_GLOBAL`        | 8   | Kernel pages that persist across context switches |
| `VMM_NO_EXECUTE`    | 63  | Data, stack, and heap pages                       |

<Note>
  `VMM_NO_EXECUTE` requires the CPU's NXE bit to be set in `IA32_EFER`. MVH Kernel sets this during early CPU initialization, so `VMM_NO_EXECUTE` is always safe to use on supported hardware.
</Note>

<Note>
  `VMM_USER` is defined and accepted by `vmm_map_page`, but user/kernel privilege separation is **not yet enforced** in the current release — the kernel operates in a single privilege mode. The flag is reserved for forward compatibility with a future user-space implementation.
</Note>

***

## Security Conventions

MVH Kernel enforces the following mapping policies for its own address space:

* **Kernel text (`.text`)** — mapped `VMM_PRESENT | VMM_GLOBAL` (read-only, executable). The `VMM_WRITABLE` flag is intentionally absent to prevent accidental or malicious code modification at runtime.
* **Kernel data/BSS (`.data`, `.bss`)** — mapped `VMM_PRESENT | VMM_WRITABLE | VMM_GLOBAL | VMM_NO_EXECUTE`. Marking these pages non-executable closes the most common code-injection vector.
* **MMIO regions** — mapped with `VMM_CACHE_DISABLE` (and optionally `VMM_WRITE_THROUGH`) to prevent the CPU from caching device-register reads and writes.

When you add new mappings, follow the same principle: grant only the permissions that the mapping actually requires.

***

## Functions

### `vmm_init`

```c theme={null}
int vmm_init(void);
```

Initializes the Virtual Memory Manager, sets up the top-level PML4 page table, and installs the identity map for the first 1024 MiB with the kernel's own text/data permissions. You must call this once, after `pmm_init`, and before any call to `vmm_map_page`.

<ResponseField name="return" type="int">
  `0` on success. A non-zero value indicates a fatal initialization failure (for example, the PMM could not allocate a root PML4 page); the kernel should treat this as unrecoverable.
</ResponseField>

***

### `vmm_map_page`

```c theme={null}
int vmm_map_page(uintptr_t virtual_address, uintptr_t physical_address, uint64_t flags);
```

Maps a single 4 KiB physical page to a virtual address with the specified flags. Both addresses are automatically aligned down to the nearest 4 KiB boundary. If any intermediate page-table node (PDPT, PD, or PT) does not yet exist, the VMM allocates it from the PMM. Mapping an address that is already mapped overwrites the existing entry and invalidates the corresponding TLB entry via `invlpg`.

<ParamField path="virtual_address" type="uintptr_t" required>
  The virtual address to create the mapping at. Aligned down to the nearest page boundary (4096-byte multiple) before use.
</ParamField>

<ParamField path="physical_address" type="uintptr_t" required>
  The physical address of the 4 KiB page to map. Must lie within the identity-mapped first 1024 MiB. Aligned down to the nearest page boundary before use.
</ParamField>

<ParamField path="flags" type="uint64_t" required>
  A bitwise OR of one or more `VMM_*` flag constants. You must always include `VMM_PRESENT`; a mapping without it is immediately invalid. Example: `VMM_PRESENT | VMM_WRITABLE | VMM_NO_EXECUTE` for a writable, non-executable data page.
</ParamField>

<ResponseField name="return" type="int">
  `0` on success. Non-zero if the mapping could not be created — for example, because the PMM failed to allocate a page-table node.
</ResponseField>

<Warning>
  Always include `VMM_PRESENT` in your flags. Omitting it creates a page-table entry that the CPU treats as not-present, which means the virtual address will fault on first access even though `vmm_map_page` returned `0`.
</Warning>

***

### `vmm_unmap_page`

```c theme={null}
int vmm_unmap_page(uintptr_t virtual_address);
```

Removes the mapping for the 4 KiB page containing `virtual_address` and issues an `invlpg` to flush the corresponding TLB entry on the current CPU. The underlying physical page is **not** freed — you are responsible for returning it to the PMM with `pmm_free_pages` if you no longer need it.

<ParamField path="virtual_address" type="uintptr_t" required>
  Any virtual address within the page to unmap. Aligned down to the nearest page boundary before use. Unmapping an address that is not currently mapped is a no-op and returns `0`.
</ParamField>

<ResponseField name="return" type="int">
  `0` on success. Non-zero if an internal error prevents the unmap (for example, a corrupt page-table walk).
</ResponseField>

<Note>
  `vmm_unmap_page` only operates on the current CPU's TLB. In a future multiprocessor build, you will need to issue an inter-processor interrupt (IPI) to flush remote TLBs when unmapping shared mappings.
</Note>

***

### `vmm_query_page`

```c theme={null}
int vmm_query_page(uintptr_t virtual_address, uintptr_t *physical_address, uint64_t *flags);
```

Walks the page-table hierarchy to look up the physical address and attribute flags for the virtual page containing `virtual_address`. Use this function to inspect an existing mapping without modifying it.

<ParamField path="virtual_address" type="uintptr_t" required>
  Any virtual address within the page to query. Aligned down to the nearest page boundary before the walk.
</ParamField>

<ParamField path="physical_address" type="uintptr_t *" required>
  Pointer to a `uintptr_t` that receives the physical base address of the mapped page on success. Must not be `NULL`. Unmodified if the function returns non-zero.
</ParamField>

<ParamField path="flags" type="uint64_t *" required>
  Pointer to a `uint64_t` that receives the page-table entry's flag bits on success. Must not be `NULL`. Unmodified if the function returns non-zero.
</ParamField>

<ResponseField name="return" type="int">
  `0` if the page is mapped and `*physical_address` and `*flags` have been written. Non-zero if the virtual address is not mapped (any level of the walk yields a not-present entry).
</ResponseField>

***

### `vmm_mapped_pages`

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

Returns the total number of virtual pages that are currently mapped (i.e., have a present entry in the page table). This counter is maintained incrementally by `vmm_map_page` and `vmm_unmap_page` and does not require a page-table walk.

<ResponseField name="return" type="uint64_t">
  The number of currently mapped 4 KiB pages.
</ResponseField>

***

### `vmm_self_test`

```c theme={null}
int vmm_self_test(void);
```

Runs the VMM's built-in self-test suite. The test maps, queries, and unmaps pages in various patterns to verify that the page-table walk, `invlpg` issuance, and counter maintenance are all functioning correctly. All temporary mappings are removed before the function returns.

<ResponseField name="return" type="int">
  `0` if all self-test cases pass. Non-zero indicates the index of the first failing sub-test; check the kernel serial log for details.
</ResponseField>

<Tip>
  Call `vmm_self_test` immediately after `vmm_init` in debug builds. It is safe to call against a live VMM because the test fully cleans up after itself.
</Tip>

***

## Usage Example

The following example maps a single physical page at a chosen virtual address with read/write, no-execute permissions, queries it to verify, then unmaps it.

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

void example_vmm_usage(void) {
    /* Allocate one physical page from the PMM */
    void *phys = pmm_alloc_pages(1);
    if (phys == NULL) {
        klog("PMM alloc failed\n");
        return;
    }

    uintptr_t virt = 0xFFFF800000100000ULL; /* Chosen virtual address */
    uintptr_t phys_addr = (uintptr_t)phys;

    /* Map the page: present, writable, non-executable (data page) */
    int rc = vmm_map_page(virt, phys_addr,
                          VMM_PRESENT | VMM_WRITABLE | VMM_NO_EXECUTE);
    if (rc != 0) {
        klog("vmm_map_page failed: %d\n", rc);
        pmm_free_pages(phys, 1);
        return;
    }

    /* Verify the mapping via vmm_query_page */
    uintptr_t queried_phys;
    uint64_t  queried_flags;
    if (vmm_query_page(virt, &queried_phys, &queried_flags) == 0) {
        klog("Mapped virt=0x%llx -> phys=0x%llx flags=0x%llx\n",
             (unsigned long long)virt,
             (unsigned long long)queried_phys,
             (unsigned long long)queried_flags);
    }

    /* Write through the virtual address */
    volatile uint8_t *ptr = (volatile uint8_t *)virt;
    *ptr = 0xAB;

    /* Unmap the page — physical page is NOT freed automatically */
    vmm_unmap_page(virt);

    /* Return the physical page to the PMM */
    pmm_free_pages(phys, 1);

    klog("Total mapped pages: %llu\n",
         (unsigned long long)vmm_mapped_pages());
}
```
