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