aboutsummaryrefslogtreecommitdiff
path: root/kernel/include/mm/pagetable.h
blob: cc1fa3eace9cd50794e2b93c3d853711d6779ac1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#pragma once

#include "mm/page.h"
#include "vm/vmmap.h"

#define PT_PRESENT 0x001
#define PT_WRITE 0x002
#define PT_USER 0x004
#define PT_WRITE_THROUGH 0x008
#define PT_CACHE_DISABLED 0x010
#define PT_ACCESSED 0x020
#define PT_DIRTY 0x040
#define PT_SIZE 0x080
#define PT_GLOBAL 0x100

#define PT_ENTRY_COUNT (PAGE_SIZE / sizeof(uintptr_t))

typedef struct page
{
    uint8_t data[PAGE_SIZE];
} page_t;

// Generalized structure for all directory like entries
typedef struct pt
{
    uintptr_t phys[PT_ENTRY_COUNT];
} pt_t, pd_t, pdp_t, pml4_t;

#define INDEX_MASK 0b111111111
#define PML4E(x) ((((uintptr_t)(x)) >> 39) & INDEX_MASK)
#define PDPE(x) ((((uintptr_t)(x)) >> 30) & INDEX_MASK)
#define PDE(x) ((((uintptr_t)(x)) >> 21) & INDEX_MASK)
#define PTE(x) ((((uintptr_t)(x)) >> 12) & INDEX_MASK)

#define PT_ENTRY_COUNT (PAGE_SIZE / sizeof(uintptr_t))
#define PT_VADDR_SIZE (PAGE_SIZE * PT_ENTRY_COUNT)
#define PD_VADDR_SIZE (PAGE_SIZE * PT_ENTRY_COUNT * PT_ENTRY_COUNT)
#define PDP_VADDR_SIZE \
    (PAGE_SIZE * PT_ENTRY_COUNT * PT_ENTRY_COUNT * PT_ENTRY_COUNT)
#define PML4_VADDR_SIZE                                             \
    (PAGE_SIZE * PT_ENTRY_COUNT * PT_ENTRY_COUNT * PT_ENTRY_COUNT * \
     PT_ENTRY_COUNT)

#define IS_PRESENT(n) ((n)&PT_PRESENT)
#define IS_2MB_PAGE(n) ((n)&PT_SIZE)
#define IS_1GB_PAGE IS_2MB_PAGE

#define GDB_PT_PHYSADDR(pt, v) (pt->phys[PTE(v)] & PAGE_MASK)
#define GDB_PD_PHYSADDR(pd, v) (pd->phys[PDE(v)] & PAGE_MASK)
#define GDB_PDP_PHYSADDR(pdp, v) (pdp->phys[PDPE(v)] & PAGE_MASK)
#define GDB_PML4_PHYSADDR(pml4, v) (pml4->phys[PML4E(v)] & PAGE_MASK)

#define GDB_PHYSADDR(pml4, v)                                             \
    (GDB_PT_PHYSADDR(                                                     \
         GDB_PD_PHYSADDR(                                                 \
             GDB_PDP_PHYSADDR(GDB_PML4_PHYSADDR(pml4, (v)) + PHYS_OFFSET, \
                              (v)) +                                      \
                 PHYS_OFFSET,                                             \
             (v)) +                                                       \
             PHYS_OFFSET,                                                 \
         (v)) +                                                           \
     PHYS_OFFSET)
#define GDB_CUR_PHYSADDR(v) GDB_PHYSADDR(curproc->p_pml4, (v))

uintptr_t pt_virt_to_phys_helper(pml4_t *pml4, uintptr_t vaddr);

uintptr_t pt_virt_to_phys(uintptr_t vaddr);

void pt_init(void);

/* Currently unused. */
void pt_template_init(void);

pml4_t *pt_get();

void pt_set(pml4_t *pml4);

pml4_t *clone_pml4(pml4_t *pml4, long include_user_mappings);

pml4_t *pt_create();

void pt_destroy(pml4_t *pml4);

long pt_map(pml4_t *pml4, uintptr_t paddr, uintptr_t vaddr, uint32_t pdflags,
            uint32_t ptflags);

long pt_map_range(pml4_t *pml4, uintptr_t paddr, uintptr_t vaddr,
                  uintptr_t vmax, uint32_t pdflags, uint32_t ptflags);

void pt_unmap(pml4_t *pml4, uintptr_t vaddr);

void pt_unmap_range(pml4_t *pml4, uintptr_t vaddr, uintptr_t vmax);

void check_invalid_mappings(pml4_t *pml4, vmmap_t *vmmap, char *prompt);