summaryrefslogtreecommitdiff
path: root/arch/x86/machine/pmap.h
blob: 89237c149eb4929047444558d8910b45e7e21066 (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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/*
 * Copyright (c) 2010, 2011, 2012 Richard Braun.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef _X86_PMAP_H
#define _X86_PMAP_H

#include <kern/param.h>
#include <kern/types.h>
#include <lib/stdint.h>

/*
 * Page directory/table properties.
 */
#ifdef PAE
#define PMAP_PDE_SHIFT  21
#define PMAP_PT_SHIFT   9
#define PMAP_NR_PDT     4
#define PMAP_PTE_PMASK  0x0000000ffffff000ULL
#else /* PAE */
#define PMAP_PDE_SHIFT  22
#define PMAP_PT_SHIFT   10
#define PMAP_NR_PDT     1
#define PMAP_PTE_PMASK  (~PAGE_MASK)
#endif /* PAE */

#define PMAP_PTE_SHIFT 12

/*
 * The amount of virtual memory described by a page directory/table entry.
 */
#define PMAP_PDE_MAPSIZE    (1 << PMAP_PDE_SHIFT)
#define PMAP_PTE_MAPSIZE    (1 << PMAP_PTE_SHIFT)

/*
 * Number of entries in a page directory/table.
 */
#define PMAP_PTE_PER_PT (1 << PMAP_PT_SHIFT)

/*
 * PDE/PTE flags.
 */
#define PMAP_PTE_PRESENT        0x001
#define PMAP_PTE_WRITE          0x002
#define PMAP_PTE_USER           0x004
#define PMAP_PTE_WRITE_THROUGH  0x008
#define PMAP_PTE_CACHE_DISABLE  0x010
#define PMAP_PTE_ACCESSED       0x020
#define PMAP_PTE_DIRTY          0x040
#define PMAP_PTE_GLOBAL         0x100
#define PMAP_PTE_AVAIL1         0x200
#define PMAP_PTE_AVAIL2         0x400
#define PMAP_PTE_AVAIL3         0x800

/*
 * Flags related to page protection.
 */
#define PMAP_PTE_PROT_MASK PMAP_PTE_WRITE

/*
 * Index of the first PDE for the kernel address space.
 */
#define PMAP_PDE_KERN (VM_MIN_KERNEL_ADDRESS >> PMAP_PDE_SHIFT)

/*
 * PDE index for the page directory.
 */
#define PMAP_PDE_PTE (VM_MAX_KERNEL_ADDRESS >> PMAP_PDE_SHIFT)

/*
 * Page table entry (also usable as a page directory entry or page directory
 * pointer table entry).
 */
#ifdef PAE
typedef uint64_t pmap_pte_t;
#else /* PAE */
typedef uint32_t pmap_pte_t;
#endif /* PAE */

/*
 * Base virtual address of the linear mapping of PTEs.
 */
#define PMAP_PTE_BASE   ((pmap_pte_t *)(PMAP_PDE_PTE << PMAP_PDE_SHIFT))

/*
 * Base virtual address of the page directory, in the linear mapping of PTEs.
 */
#define PMAP_PDP_BASE   (PMAP_PTE_BASE + (PMAP_PDE_PTE * PMAP_PTE_PER_PT))

/*
 * Virtual address of the PDE that points to the PDP.
 */
#define PMAP_PDP_PDE    (PMAP_PDP_BASE + PMAP_PDE_PTE)

/*
 * Number of pages to reserve for the pmap module after the kernel.
 *
 * This pool of pure virtual memory can be used to reserve virtual addresses
 * before the VM system is initialized.
 */
#define PMAP_RESERVED_PAGES 2

/*
 * Physical address map.
 */
struct pmap {
    pmap_pte_t *pdir;   /* Page directory virtual address */
    vm_phys_t pdir_pa;  /* Page directory physical address */
#ifdef PAE
    pmap_pte_t *pdpt;   /* Page directory pointer table physical address */
#endif /* PAE */
};

/*
 * The kernel pmap.
 */
extern struct pmap *kernel_pmap;

/*
 * Kernel page directory.
 */
extern pmap_pte_t pmap_kpdir[PMAP_NR_PDT * PMAP_PTE_PER_PT];

#ifdef PAE
/*
 * Kernel page directory pointer table.
 */
extern pmap_pte_t pmap_kpdpt[PMAP_NR_PDT];
#endif /* PAE */

/*
 * Address below which using the low level kernel pmap functions is safe.
 * Its value is adjusted by calling pmap_growkernel().
 */
extern unsigned long pmap_klimit;

/*
 * Early initialization of the pmap module.
 *
 * When this function is called, basic paging is enabled and the kernel
 * already runs at virtual addresses.
 */
void pmap_bootstrap(void);

/*
 * Allocate pure virtual memory.
 *
 * This memory is obtained from a very small pool of reserved pages located
 * immediately after the kernel. Its purpose is to allow early mappings to
 * be created before the VM system is available.
 */
unsigned long pmap_bootalloc(unsigned int nr_pages);

/*
 * Return the available kernel virtual space in virt_start and virt_end.
 *
 * This function is called early, during initialization of the VM system, and
 * can't be used after since the VM has taken control of the kernel address
 * space.
 */
void pmap_virtual_space(unsigned long *virt_start, unsigned long *virt_end);

/*
 * Preallocate resources so that addresses up to va can be mapped safely in
 * the kernel pmap.
 */
void pmap_growkernel(unsigned long va);

/*
 * Kernel specific mapping functions.
 *
 * Resources for the new mappings must be preallocated.
 */
void pmap_kenter(unsigned long va, vm_phys_t pa);
void pmap_kremove(unsigned long start, unsigned long end);
void pmap_kprotect(unsigned long start, unsigned long end, int prot);
vm_phys_t pmap_kextract(unsigned long va);

/*
 * Zero a page at the given physical address.
 */
void pmap_zero_page(vm_phys_t pa);

#endif /* _X86_PMAP_H */