1/* @title: Virtual memory management */
2#pragma once
3#include <console/printf.h>
4#include <errno.h>
5#include <mem/demand_page.h>
6#include <stdbool.h>
7#include <stdint.h>
8#include <types/types.h>
9struct limine_executable_address_response;
10struct limine_memmap_response;
11
12struct page_table;
13
14enum vmm_map_page_size : uint8_t {
15 VMM_MAP_PAGE_SIZE_4KB,
16 VMM_MAP_PAGE_SIZE_2MB,
17 VMM_MAP_PAGE_SIZE_1GB,
18};
19
20/* Big bitmap set that is embedded in vmm_map_request */
21enum vmm_flags : uint64_t {
22 VMM_FLAG_NONE = 0,
23 VMM_FLAG_NO_TLB_SHOOTDOWN = 1 << 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/* map/unmap page full get these, everyone else uses it to call into it,
46 * wrappers automatically build these, everything's hunky dory! */
47struct vmm_map_request {
48 struct page_table *pml4;
49 vaddr_t virt;
50 paddr_t phys;
51 size_t len;
52 page_flags_t page_flags;
53
54 enum vmm_flags vmm_flags;
55 enum vmm_map_page_size page_size;
56
57 /* Internal flags */
58 bool is_unmap_internal;
59};
60
61void vmm_init(struct limine_memmap_response *memmap,
62 struct limine_executable_address_response *xa);
63
64bool vmm_phys_is_kernel_text(paddr_t phys);
65
66enum errno vmm_map_page_full(struct vmm_map_request *rq);
67void vmm_unmap_page_full(struct vmm_map_request *rq);
68
69enum errno vmm_map_aliased(vaddr_t virt, size_t len, paddr_t phys,
70 page_flags_t leaf_flags, enum vmm_flags vflags);
71enum errno vmm_unshare_path(vaddr_t virt, enum vmm_map_page_size leaf_size,
72 enum vmm_flags vflags);
73
74enum errno vmm_map_page_internal(vaddr_t virt, paddr_t phys, page_flags_t flags,
75 enum vmm_flags vflags,
76 enum vmm_map_page_size size);
77enum errno vmm_map_page_user_internal(struct page_table *pml4, vaddr_t virt,
78 paddr_t phys, page_flags_t flags,
79 enum vmm_flags vflags,
80 enum vmm_map_page_size size);
81void vmm_unmap_page_internal(vaddr_t virt, enum vmm_flags vflags,
82 enum vmm_map_page_size size);
83enum errno vmm_mark_demand_page_internal(vaddr_t virt,
84 enum demand_page_flags flags,
85 enum vmm_map_page_size size);
86enum errno vmm_mark_demand_page_user_internal(struct page_table *pml4,
87 vaddr_t virt,
88 enum demand_page_flags flags,
89 enum vmm_map_page_size size);
90enum errno vmm_map_demand_page_internal(vaddr_t virt, paddr_t phys,
91 enum demand_page_flags flags,
92 enum vmm_map_page_size size);
93
94paddr_t vmm_get_phys_internal(vaddr_t virt, enum vmm_flags flags);
95pte_t vmm_get_leaf_pte_internal(vaddr_t virt, enum vmm_flags flags);
96void vmm_unmap(void *addr, uint64_t len, enum vmm_flags vflags);
97void *vmm_map(paddr_t paddr, vaddr_t vaddr, uint64_t len, uint64_t flags,
98 enum vmm_flags vflags);
99void *vmm_map_bump_internal(uint64_t addr, uint64_t len, uint64_t flags,
100 enum vmm_flags vflags);
101void vmm_unmap_virt(void *addr, uint64_t len, enum vmm_flags vflags);
102uintptr_t vmm_make_user_pml4(void);
103void vmm_unmap_all_user_pages(struct page_table *pml4, enum vmm_flags vflags);
104void vmm_reclaim_page_tables(void);
105struct page_table *vmm_phys_to_pml4(paddr_t paddr);
106
107#include <mem/vmm_api_internal.h>
108