summaryrefslogtreecommitdiff
path: root/src/kernel/arch/amd64/32/paging.c
blob: 975dd98cc3739d1c515d90f1340f903e898a6bc0 (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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include <stddef.h>
#include <stdint.h>

struct pml4e {
	uint64_t present   : 1;
	uint64_t writeable : 1;
	uint64_t user      : 1;
	uint64_t writethru : 1;

	uint64_t uncached  : 1;
	uint64_t accessed  : 1;
	uint64_t _unused1  : 1;
	uint64_t reserved  : 1; // always 0

	uint64_t _unused2  : 3;
	uint64_t _unused3  : 1; // HLAT thing

	uint64_t address   : 40;

	uint64_t _unused4  : 11;
	uint64_t noexec    : 1;
} __attribute__((packed));

struct pdpte { // page directory pointer table entry, 1gb page | 512 * pde
	uint64_t present   : 1;
	uint64_t writeable : 1;
	uint64_t user      : 1;
	uint64_t writethru : 1;

	uint64_t uncached  : 1;
	uint64_t accessed  : 1;
	uint64_t _unused1  : 1;
	uint64_t large     : 1; // 1gb page

	uint64_t _unused2  : 3;
	uint64_t _unused3  : 1; // HLAT

	uint64_t address   : 40;

	uint64_t _unused4  : 11;
	uint64_t noexec    : 1;
} __attribute__((packed));

struct pde { // page directory entry, 2mb page | 512 * pte
	uint64_t present   : 1;
	uint64_t writeable : 1;
	uint64_t user      : 1;
	uint64_t writethru : 1;

	uint64_t uncached  : 1;
	uint64_t accessed  : 1;
	uint64_t dirty     : 1; // only if large
	uint64_t large     : 1; // 2mb

	uint64_t global    : 1; // only if large ; TODO enable CR4.PGE
	uint64_t _unused2  : 2;
	uint64_t _unused3  : 1; // HLAT

	uint64_t address   : 40; // highest bit - PAT

	uint64_t _unused4  : 7;
	uint64_t pke       : 4;
	uint64_t noexec    : 1;
} __attribute__((packed));

struct pte { // page table entry, 4kb page
	uint64_t present   : 1;
	uint64_t writeable : 1;
	uint64_t user      : 1;
	uint64_t writethru : 1;

	uint64_t uncached  : 1;
	uint64_t accessed  : 1;
	uint64_t dirty     : 1;
	uint64_t pat       : 1;

	uint64_t global    : 1; // TODO enable CR4.PGE
	uint64_t _unused2  : 2;
	uint64_t _unused3  : 1; // HLAT

	uint64_t address   : 40;

	uint64_t _unused4  : 7;
	uint64_t pke       : 4;
	uint64_t noexec    : 1;
} __attribute__((packed));

__attribute__((aligned(4096)))
struct pml4e pml4_identity[512];

__attribute__((aligned(4096)))
struct pdpte pdpte_low[512]; // 0-512gb

__attribute__((aligned(4096)))
struct pde pde_low[512]; // 0-1gb


static void *memset32(void *s, int c, size_t n) {
	uint8_t *s2 = s;
	for (size_t i = 0; i < n; i++)
		s2[i] = c;
	return s;
}


void pml4_identity_init(void) {
	memset32(pml4_identity, 0, sizeof pml4_identity);
	memset32(pdpte_low, 0, sizeof pdpte_low);
	memset32(pde_low, 0, sizeof pde_low);

	pml4_identity[0] = (struct pml4e) {
		.present = 1,
		.writeable = 1,
		.address = ((uintptr_t)pdpte_low) >> 12,
	};

	pdpte_low[0] = (struct pdpte) {
		.present = 1,
		.writeable = 1,
		.address = ((uintptr_t)pde_low) >> 12,
	};

	for (int i = 0; i < 512; i++) {
		pde_low[i] = (struct pde) {
			.present = 1,
			.writeable = 1,
			.large = 1,
			.address = (i * 2 * 1024 * 1024) >> 12,
		};
	}
}