]> git.buserror.net Git - polintos/scott/priv.git/blob - kernel/include/arch-x64/pagetable.h
Initial checkin from Perforce.
[polintos/scott/priv.git] / kernel / include / arch-x64 / pagetable.h
1 #ifndef _ARCH_PAGETABLE_H
2 #define _ARCH_PAGETABLE_H
3
4 #include <lowlevel/misc.h>
5 #include <lowlevel/atomic.h>
6
7 namespace Arch {
8         union PTE {
9                 typedef ulong Word;
10         
11                 struct {
12                         Word Valid:1;
13                         Word Writeable:1;
14                         Word User:1;
15                         Word WriteThrough:1;
16                         Word CacheDisable:1;
17                         Word Accessed:1;
18                         Word Dirty:1;
19                         Word PageAttrTable:1;
20                         Word Global:1;
21                         Word Avail1:3;
22                         Word Addr:40;
23                         Word Avail2:11;
24                         Word NoExec:1;
25                 };
26                 
27                 Word raw;
28
29                 PTE(Word init) : raw(init)
30                 {
31                 }
32                 
33                 PTE() : raw(0)
34                 {
35                 }
36
37                 operator Word()
38                 {
39                         return raw;
40                 }
41
42                 static Word addr_to_offset(Word addr, int shift)
43                 {
44                         int pages_per_table = page_size / sizeof(Word);
45                         return (addr >> shift) & (pages_per_table - 1);
46                 }
47         
48                 Word pte_to_addr()
49                 {
50                         return raw & 0x000ffffffffff000;
51                 }
52         
53                 static PTE addr_to_pte(Word phys)
54                 {
55                         return phys & 0x000ffffffffff000;
56                 }
57                 
58                 static void flags_to_pte(Mem::PTEFlags flagsin,
59                                          Mem::PTEFlags maskin,
60                                          PTE &flagsout,
61                                          PTE &maskout)
62                 {
63                         maskout = ~0UL;
64                         flagsout = 0;
65                         
66                         if (maskin.Valid) {
67                                 maskout.Valid = 0;
68                                 flagsout.Valid = flagsin.Valid;
69                         }
70                         
71                         if (maskin.Writeable) {
72                                 maskout.Writeable = 0;
73                                 flagsout.Writeable = flagsin.Writeable;
74                         }
75                         
76                         // FIXME: check for and enable NX support
77                         if (0 && maskin.Executable) {
78                                 maskout.NoExec = 0;
79                                 flagsout.NoExec = !flagsin.Executable;
80                         }
81                         
82                         if (maskin.User) {
83                                 maskout.User = 0;
84                                 flagsout.User = flagsin.User;
85                         }
86                 }
87         
88                 Mem::PTEFlags pte_to_flags()
89                 {
90                         Mem::PTEFlags ret = 0;
91                         
92                         ret.Valid = Valid;
93                         ret.User = User;
94                         
95                         if (Valid) {
96                                 ret.Readable = 1;
97                                 ret.Writeable = Writeable;
98                                 ret.Executable = !NoExec;
99                         }
100                         
101                         return ret;
102                 }
103         
104                 void set_pte(PTE *table, uint offset)
105                 {
106                         table[offset] = raw;
107                 }
108                 
109                 PTE xchg_pte(PTE *table, uint offset)
110                 {
111                         return ll_xchg_long(reinterpret_cast<Word *>(&table[offset]), raw);
112                 }
113                 
114                 bool valid_pte()
115                 {
116                         return Valid;
117                 }
118                 
119                 bool dirty_pte()
120                 {
121                         return Dirty;
122                 }
123                 
124                 static void invalidate_tlb_entry(Word addr)
125                 {
126                         ll_invalidate_tlb_entry(addr);
127                 }
128                 
129                 enum {
130                         page_size = Arch::page_size,
131                         page_shift = Arch::page_shift,
132         
133                         pages_per_table = page_size / sizeof(Word),
134                         num_levels = 4,
135                         shift_per_level = 9,
136         
137                         // All "upper" addresses belong to the kernel.
138                         
139                         kmap_start = 256,
140                         kmap_end = 511
141                 };
142         };
143 }
144
145 #endif