MOS Source Code
Loading...
Searching...
No Matches
pml4.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2
4
5#include "mos/mm/mm.hpp"
9#include "mos/platform/platform_defs.hpp"
10
11#include <algorithm>
12#include <mos/mos_global.h>
13#include <mos_stdlib.hpp>
14#include <mos_string.hpp>
15
16#if MOS_PLATFORM_PAGING_LEVELS < 4
17void pml4_traverse(pml4_t pml4, ptr_t *vaddr, size_t *n_pages, pagetable_walk_options_t callback, void *data)
18{
19 pml3_traverse(pml4.pml3, vaddr, n_pages, callback, data);
20}
21
22pml4e_t *pml4_entry(pml4_t pml4, ptr_t vaddr)
23{
24 MOS_UNUSED(vaddr);
25 return pml4.pml3.table;
26}
27
28bool pml4e_is_present(const pml4e_t *pml4e)
29{
30 return pml3e_is_present(pml4e);
31}
32
33pml3_t pml4e_get_pml3(const pml4e_t *pml4e)
34{
35 return (pml3_t) { .table = (pml3e_t *) pml4e };
36}
37
38#else
39void pml4_traverse(pml4_t pml4, ptr_t *vaddr, size_t *n_pages, pagetable_walk_options_t options, void *data)
40{
41 for (size_t i = pml4_index(*vaddr); i < PML4_ENTRIES && *n_pages; i++)
42 {
43 pml4e_t *pml4e = pml4_entry(pml4, *vaddr);
44 pml3_t pml3 = { 0 };
45
46 if (pml4e_is_present(pml4e))
47 {
48 pml3 = pml4e_get_or_create_pml3(pml4e);
49 }
50 else
51 {
52 if (options.readonly)
53 {
54 // skip to the next pml3e
55 *vaddr += std::min(*n_pages, (size_t) PML4E_NPAGES) * MOS_PAGE_SIZE;
56 *n_pages -= std::min(*n_pages, (size_t) PML4E_NPAGES);
57 continue;
58 }
59
60 pml3 = pml_create_table(pml3);
61 platform_pml4e_set_pml3(pml4e, pml3, va_pfn(pml3.table));
62 }
63
64 if (options.pml4e_pre_traverse)
65 options.pml4e_pre_traverse(pml4, pml4e, *vaddr, data);
66 pml3_traverse(pml3, vaddr, n_pages, options, data);
67 }
68}
69
70bool pml4_destroy_range(pml4_t pml4, ptr_t *vaddr, size_t *n_pages)
71{
72#if MOS_PLATFORM_PAGING_LEVELS <= 4
73 const bool should_zap_this_pml4 = pml4_index(*vaddr) == 0 && *n_pages == (MOS_USER_END_VADDR + 1) / MOS_PAGE_SIZE;
74#else
75 const bool should_zap_this_pml4 = pml4_index(*vaddr) == 0 && *n_pages >= PML4_ENTRIES * PML4E_NPAGES;
76#endif
77
78 for (size_t i = pml4_index(*vaddr); i < PML4_ENTRIES && *n_pages; i++)
79 {
80 pml4e_t *pml4e = pml4_entry(pml4, *vaddr);
81
82 if (pml4e_is_present(pml4e))
83 {
84 pml3_t pml3 = platform_pml4e_get_pml3(pml4e);
85 if (pml3_destroy_range(pml3, vaddr, n_pages))
86 pmlxe_destroy(pml4e); // pml3 was destroyed
87 }
88 else
89 {
90 // skip to the next pml3e
91 *vaddr += std::min(*n_pages, (size_t) PML4E_NPAGES) * MOS_PAGE_SIZE;
92 *n_pages -= std::min(*n_pages, (size_t) PML4E_NPAGES);
93 continue;
94 }
95 }
96
97 if (should_zap_this_pml4)
99
100 return should_zap_this_pml4;
101}
102
103pml4e_t *pml4_entry(pml4_t pml4, ptr_t vaddr)
104{
105 return &pml4.table[pml4_index(vaddr)];
106}
107
108bool pml4e_is_present(const pml4e_t *pml4e)
109{
110 return platform_pml4e_get_present(pml4e);
111}
112
114{
115 if (pml4e_is_present(pml4e))
116 return platform_pml4e_get_pml3(pml4e);
117
118 pml3_t pml3 = pml_create_table(pml3);
119 platform_pml4e_set_pml3(pml4e, pml3, va_pfn(pml3.table));
120 return pml3;
121}
122#endif
void platform_pml4e_set_pml3(pml4e_t *pml4e, pml3_t pml3, pfn_t pml3_pfn)
Definition mm.cpp:212
pml3_t platform_pml4e_get_pml3(const pml4e_t *pml4e)
Definition mm.cpp:207
bool platform_pml4e_get_present(const pml4e_t *pml4e)
Definition mm.cpp:220
#define MOS_PAGE_SIZE
Definition autoconf.h:6
bool callback(pb_istream_t *stream, uint8_t *buf, size_t count)
#define va_pfn(va)
Definition mm.hpp:78
#define MOS_UNUSED(x)
Definition mos_global.h:65
bool pml3e_is_present(const pml3e_t *pml3e)
Definition pml3.cpp:27
void pml3_traverse(pml3_t pml3, ptr_t *vaddr, size_t *n_pages, pagetable_walk_options_t callback, void *data)
Definition pml3.cpp:16
__nodiscard bool pml3_destroy_range(pml3_t pml3, ptr_t *vaddr, size_t *n_pages)
void pml4_traverse(pml4_t pml4, ptr_t *vaddr, size_t *n_pages, pagetable_walk_options_t callback, void *data)
Definition pml4.cpp:17
pml4e_t * pml4_entry(pml4_t pml4, ptr_t vaddr)
Definition pml4.cpp:22
bool pml4e_is_present(const pml4e_t *pml4e)
Definition pml4.cpp:28
pml3_t pml4e_get_pml3(const pml4e_t *pml4e)
Definition pml4.cpp:33
__nodiscard bool pml4_destroy_range(pml4_t pml4, ptr_t *vaddr, size_t *n_pages)
pml3_t pml4e_get_or_create_pml3(pml4e_t *pml4e)
pml3e_t pml4e_t
Definition pml_types.hpp:72
#define pml_destroy_table(x)
#define pml_create_table(x)
pml2e_t pml3e_t
Definition pml_types.hpp:60
#define pmlxe_destroy(pmlxe)
#define MOS_USER_END_VADDR
#define PML4_ENTRIES
void(* pml4e_pre_traverse)(pml4_t pml4, pml4e_t *e, ptr_t vaddr, void *data)
Definition pml_types.hpp:98
unsigned long ptr_t
Definition types.h:21