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