1/* @title: Virtual memory management */
2#pragma once
3#include <console/printf.h>
4#include <err.h>
5#include <mem/demand_page.h>
6#include <mem/tlb.h>
7#include <stdbool.h>
8#include <stdint.h>
9#include <types/types.h>
10struct limine_executable_address_response;
11struct limine_memmap_response;
12
13struct page_table;
14
15enum vmm_map_page_size : uint8_t {
16 VMM_MAP_PAGE_SIZE_4KB,
17 VMM_MAP_PAGE_SIZE_2MB,
18 VMM_MAP_PAGE_SIZE_1GB,
19};
20
21/* Big bitmap set that is embedded in vmm_request */
22enum vmm_flags : uint64_t {
23 VMM_FLAG_NONE = 0,
24 VMM_FLAG_USER = 1 << 1,
25 VMM_FLAG_MODIFY_LEAF = 1 << 2, /* This flag exists since
26 * certain calls simply serve
27 * to modify the leaf (e.g. faulting
28 * on a demand page and
29 * mapping in the physical frame)
30 *
31 * By default, we panic if the
32 * leaf is modified, and this
33 * flag says "don't panic,
34 * I know what I'm doing" */
35
36 VMM_FLAG_CLEAR_LEAF = 1 << 3, /* Clear all the data (besides the lock bit,
37 * transiently), zeroing out the leaf */
38
39 VMM_FLAG_HANDLE_PTE_EXISTING = 1 << 4, /* Will return ERR_EXIST
40 * when used in conjunction
41 * with MODIFY_LEAF and PRESENT
42 * is seen on the leaf PTE */
43};
44
45/* e.g. vmm_map_page(virt, phys, .page_flags = PAGE_PRESENT | PAGE_WRITE,
46 * .page_size = VMM_MAP_PAGE_SIZE_2MB);
47 * vmm_api_internal.h has the defaults */
48struct vmm_request {
49 page_flags_t page_flags;
50 enum vmm_flags vmm_flags;
51 enum vmm_map_page_size page_size;
52 enum tlb_mode tlb_mode;
53};
54
55/* map/unmap page full get these, everyone else uses it to call into it,
56 * wrappers automatically build these, everything's hunky dory! */
57struct vmm_map_request {
58 struct page_table *pml4;
59 vaddr_t virt;
60 paddr_t phys;
61 size_t len;
62
63 struct vmm_request rq;
64
65 /* Internal flags */
66 bool is_unmap_internal;
67};
68
69void vmm_init(struct limine_memmap_response *memmap,
70 struct limine_executable_address_response *xa);
71
72bool vmm_phys_is_kernel_text(paddr_t phys);
73
74enum err vmm_map_aliased_full(vaddr_t virt, size_t len, paddr_t phys,
75 struct vmm_request rq);
76enum err vmm_unshare_path_full(vaddr_t virt, struct vmm_request rq);
77
78enum err vmm_map_page_full(vaddr_t virt, paddr_t phys, struct vmm_request rq);
79enum err vmm_map_page_user_full(struct page_table *pml4, vaddr_t virt,
80 paddr_t phys, struct vmm_request rq);
81void vmm_unmap_page_full(vaddr_t virt, struct vmm_request rq);
82enum err vmm_mark_demand_page_full(vaddr_t virt, enum demand_page_flags flags,
83 struct vmm_request rq);
84enum err vmm_mark_demand_page_user_full(struct page_table *pml4, vaddr_t virt,
85 enum demand_page_flags flags,
86 struct vmm_request rq);
87enum err vmm_map_demand_page_full(vaddr_t virt, paddr_t phys,
88 enum demand_page_flags flags,
89 struct vmm_request rq);
90
91paddr_t vmm_get_phys_full(vaddr_t virt, struct vmm_request rq);
92pte_t vmm_get_leaf_pte_full(vaddr_t virt, struct vmm_request rq);
93void vmm_unmap_full(void *addr, uint64_t len, struct vmm_request rq);
94void *vmm_map_full(paddr_t paddr, vaddr_t vaddr, uint64_t len,
95 struct vmm_request rq);
96void *vmm_map_bump_full(uint64_t addr, uint64_t len, struct vmm_request rq);
97uintptr_t vmm_make_user_pml4(void);
98void vmm_unmap_all_user_pages_full(struct page_table *pml4,
99 struct vmm_request rq);
100void vmm_reclaim_page_tables(void);
101struct page_table *vmm_phys_to_pml4(paddr_t paddr);
102
103#include <mem/vmm_api_internal.h>
104