x86: interrupt return path checks kmsgs
[akaros.git] / kern / arch / i686 / mmu.h
1 #ifndef ROS_ARCH_MMU_H
2 #define ROS_ARCH_MMU_H
3
4 #ifndef __ASSEMBLER__
5 #include <ros/common.h>
6 #endif
7
8 #include <ros/arch/mmu.h>
9
10 /*
11  * This file contains definitions for the x86 memory management unit (MMU),
12  * including paging- and segmentation-related data structures and constants,
13  * the %cr0, %cr4, and %eflags registers, and traps.
14  */
15
16 /*
17  *
18  *      Part 1.  Paging data structures and constants.
19  *
20  */
21
22 // A linear address 'la' has a three-part structure as follows:
23 //
24 // +--------10------+-------10-------+---------12----------+
25 // | Page Directory |   Page Table   | Offset within Page  |
26 // |      Index     |      Index     |                     |
27 // +----------------+----------------+---------------------+
28 //  \--- PDX(la) --/ \--- PTX(la) --/ \---- PGOFF(la) ----/
29 //  \----------- PPN(la) -----------/
30 //
31 // The PDX, PTX, PGOFF, and PPN macros decompose linear addresses as shown.
32 // To construct a linear address la from PDX(la), PTX(la), and PGOFF(la),
33 // use PGADDR(PDX(la), PTX(la), PGOFF(la)).
34
35 // page number field of address
36 #define LA2PPN(la)      (((uintptr_t) (la)) >> PTXSHIFT)
37 #define PTE2PPN(pte)    LA2PPN(pte)
38 #define VPN(la)         PPN(la)         // used to index into vpt[]
39
40 // page directory index
41 #define PDX(la)         ((((uintptr_t) (la)) >> PDXSHIFT) & 0x3FF)
42 #define VPD(la)         PDX(la)         // used to index into vpd[]
43
44 // page table index
45 #define PTX(la)         ((((uintptr_t) (la)) >> PTXSHIFT) & 0x3FF)
46
47 // offset in page
48 #define PGOFF(la)       (((uintptr_t) (la)) & 0xFFF)
49
50 // offset in jumbo page
51 #define JPGOFF(la)      (((uintptr_t) (la)) & 0x003FFFFF)
52
53 // construct PTE from PPN and flags
54 #define PTE(ppn, flags) ((ppn) << PTXSHIFT | (flags))
55
56 // construct linear address from indexes and offset
57 #define PGADDR(d, t, o) ((void*SNT) ((d) << PDXSHIFT | (t) << PTXSHIFT | (o)))
58
59 // Page directory and page table constants.
60 #define NPDENTRIES      1024            // page directory entries per page directory
61 #define NPTENTRIES      1024            // page table entries per page table
62
63 #define PTXSHIFT        12              // offset of PTX in a linear address
64 #define PDXSHIFT        22              // offset of PDX in a linear address
65
66 // Page table/directory entry flags.
67 #define PTE_P           0x001   // Present
68 #define PTE_W           0x002   // Writeable
69 #define PTE_U           0x004   // User
70 #define PTE_PWT         0x008   // Write-Through
71 #define PTE_PCD         0x010   // Cache-Disable
72 #define PTE_A           0x020   // Accessed
73 #define PTE_D           0x040   // Dirty
74 #define PTE_PS          0x080   // Page Size (only applies to PDEs)
75 #define PTE_PAT         0x080   // PAT (only applies to second layer PTEs)
76 #define PTE_G           0x100   // Global Page
77
78 #define PTE_PERM        (PTE_W | PTE_U) // The permissions fields
79 // commly used access modes
80 #define PTE_KERN_RW     PTE_W           // Kernel Read/Write
81 #define PTE_KERN_RO     0               // Kernel Read-Only
82 #define PTE_USER_RW     (PTE_W | PTE_U) // Kernel/User Read/Write
83 #define PTE_USER_RO     PTE_U           // Kernel/User Read-Only
84
85 // The PTE_AVAIL bits aren't used by the kernel or interpreted by the
86 // hardware, so user processes are allowed to set them arbitrarily.
87 #define PTE_AVAIL       0xE00   // Available for software use
88
89 // Only flags in PTE_USER may be used in system calls.
90 #define PTE_USER        (PTE_AVAIL | PTE_P | PTE_W | PTE_U)
91
92 // address in page table entry
93 #define PTE_ADDR(pte)   ((physaddr_t) (pte) & ~0xFFF)
94
95 // Control Register flags
96 #define CR0_PE          0x00000001      // Protection Enable
97 #define CR0_MP          0x00000002      // Monitor coProcessor
98 #define CR0_EM          0x00000004      // Emulation
99 #define CR0_TS          0x00000008      // Task Switched
100 #define CR0_ET          0x00000010      // Extension Type
101 #define CR0_NE          0x00000020      // Numeric Error
102 #define CR0_WP          0x00010000      // Write Protect
103 #define CR0_AM          0x00040000      // Alignment Mask
104 #define CR0_NW          0x20000000      // Not Writethrough - more tricky than it sounds
105 #define CR0_CD          0x40000000      // Cache Disable
106 #define CR0_PG          0x80000000      // Paging
107
108 // These two relate to the cacheability (L1, etc) of the page directory
109 #define CR3_PWT         0x00000008      // Page directory caching write through
110 #define CR3_PCD         0x00000010      // Page directory caching disabled
111
112 #define CR4_VME         0x00000001      // V86 Mode Extensions
113 #define CR4_PVI         0x00000002      // Protected-Mode Virtual Interrupts
114 #define CR4_TSD         0x00000004      // Time Stamp Disable
115 #define CR4_DE          0x00000008      // Debugging Extensions
116 #define CR4_PSE         0x00000010      // Page Size Extensions
117 #define CR4_PAE         0x00000020      // Physical Address Extensions
118 #define CR4_MCE         0x00000040      // Machine Check Enable
119 #define CR4_PGE         0x00000080      // Global Pages Enabled
120 #define CR4_PCE         0x00000100      // Performance counter enable
121 #define CR4_OSFXSR      0x00000200      // OS support for FXSAVE/FXRSTOR
122 #define CR4_OSXMME      0x00000400      // OS support for unmasked SIMD FP exceptions
123 #define CR4_VMXE        0x00002000      // VMX enable
124 #define CR4_SMXE        0x00004000      // SMX enable
125 #define CR4_OSXSAVE     0x00040000      // XSAVE and processor extended states-enabled
126
127 // Eflags register
128 #define FL_CF           0x00000001      // Carry Flag
129 #define FL_PF           0x00000004      // Parity Flag
130 #define FL_AF           0x00000010      // Auxiliary carry Flag
131 #define FL_ZF           0x00000040      // Zero Flag
132 #define FL_SF           0x00000080      // Sign Flag
133 #define FL_TF           0x00000100      // Trap Flag
134 #define FL_IF           0x00000200      // Interrupt Flag
135 #define FL_DF           0x00000400      // Direction Flag
136 #define FL_OF           0x00000800      // Overflow Flag
137 #define FL_IOPL_MASK    0x00003000      // I/O Privilege Level bitmask
138 #define FL_IOPL_0       0x00000000      //   IOPL == 0
139 #define FL_IOPL_1       0x00001000      //   IOPL == 1
140 #define FL_IOPL_2       0x00002000      //   IOPL == 2
141 #define FL_IOPL_3       0x00003000      //   IOPL == 3
142 #define FL_NT           0x00004000      // Nested Task
143 #define FL_RF           0x00010000      // Resume Flag
144 #define FL_VM           0x00020000      // Virtual 8086 mode
145 #define FL_AC           0x00040000      // Alignment Check
146 #define FL_VIF          0x00080000      // Virtual Interrupt Flag
147 #define FL_VIP          0x00100000      // Virtual Interrupt Pending
148 #define FL_ID           0x00200000      // ID flag
149
150 // Page fault error codes
151 #define FEC_PR          0x1     // Page fault caused by protection violation
152 #define FEC_WR          0x2     // Page fault caused by a write
153 #define FEC_U           0x4     // Page fault occured while in user mode
154
155
156 /*
157  *
158  *      Part 2.  Segmentation data structures and constants.
159  *
160  */
161
162 /* Segment descriptor and macros temporarily moved to ros/arch/mmu.h.  Bring
163  * them back when fixing x86 TLS vulns (TLSV) */
164
165 /*
166  *
167  *      Part 3.  Traps.
168  *
169  */
170
171 #ifndef __ASSEMBLER__
172
173 // Task state segment format (as described by the Pentium architecture book)
174 typedef struct Taskstate {
175         uint32_t ts_link;       // Old ts selector
176         uintptr_t ts_esp0;      // Stack pointers and segment selectors
177         uint16_t ts_ss0;        //   after an increase in privilege level
178         uint16_t ts_padding1;
179         uintptr_t ts_esp1;
180         uint16_t ts_ss1;
181         uint16_t ts_padding2;
182         uintptr_t ts_esp2;
183         uint16_t ts_ss2;
184         uint16_t ts_padding3;
185         physaddr_t ts_cr3;      // Page directory base
186         uintptr_t ts_eip;       // Saved state from last task switch
187         uint32_t ts_eflags;
188         uint32_t ts_eax;        // More saved state (registers)
189         uint32_t ts_ecx;
190         uint32_t ts_edx;
191         uint32_t ts_ebx;
192         uintptr_t ts_esp;
193         uintptr_t ts_ebp;
194         uint32_t ts_esi;
195         uint32_t ts_edi;
196         uint16_t ts_es;         // Even more saved state (segment selectors)
197         uint16_t ts_padding4;
198         uint16_t ts_cs;
199         uint16_t ts_padding5;
200         uint16_t ts_ss;
201         uint16_t ts_padding6;
202         uint16_t ts_ds;
203         uint16_t ts_padding7;
204         uint16_t ts_fs;
205         uint16_t ts_padding8;
206         uint16_t ts_gs;
207         uint16_t ts_padding9;
208         uint16_t ts_ldt;
209         uint16_t ts_padding10;
210         uint16_t ts_t;          // Trap on task switch
211         uint16_t ts_iomb;       // I/O map base address
212 } taskstate_t;
213
214 // Gate descriptors for interrupts and traps
215 typedef struct Gatedesc {
216         unsigned gd_off_15_0 : 16;   // low 16 bits of offset in segment
217         unsigned gd_ss : 16;         // segment selector
218         unsigned gd_args : 5;        // # args, 0 for interrupt/trap gates
219         unsigned gd_rsv1 : 3;        // reserved(should be zero I guess)
220         unsigned gd_type : 4;        // type(STS_{TG,IG32,TG32})
221         unsigned gd_s : 1;           // must be 0 (system)
222         unsigned gd_dpl : 2;         // DPL - highest ring allowed to use this
223         unsigned gd_p : 1;           // Present
224         unsigned gd_off_31_16 : 16;  // high bits of offset in segment
225 } gatedesc_t;
226
227 // Set up a normal interrupt/trap gate descriptor.
228 // - istrap: 1 for a trap (= exception) gate, 0 for an interrupt gate.
229 //   - interrupt gates automatically disable interrupts (cli)
230 // - sel: Code segment selector for interrupt/trap handler
231 // - off: Offset in code segment for interrupt/trap handler
232 // - dpl: Descriptor Privilege Level -
233 //        the privilege level required for software to invoke
234 //        this interrupt/trap gate explicitly using an int instruction.
235 #define SETGATE(gate, istrap, sel, off, dpl)                    \
236 {                                                               \
237         (gate).gd_off_15_0 = (uint32_t) (off) & 0xffff;         \
238         (gate).gd_ss = (sel);                                   \
239         (gate).gd_args = 0;                                     \
240         (gate).gd_rsv1 = 0;                                     \
241         (gate).gd_type = (istrap) ? STS_TG32 : STS_IG32;        \
242         (gate).gd_s = 0;                                        \
243         (gate).gd_dpl = (dpl);                                  \
244         (gate).gd_p = 1;                                        \
245         (gate).gd_off_31_16 = (uint32_t) (off) >> 16;           \
246 }
247
248 #define ROSETGATE(gate, istrap, sel, off, dpl)                  \
249 {                                                               \
250         (gate).gd_off_15_0 = SINIT((uint32_t) (off) & 0xffff);          \
251         (gate).gd_ss = SINIT(sel);                                      \
252         (gate).gd_args = SINIT(0);                                      \
253         (gate).gd_rsv1 = SINIT(0);                                      \
254         (gate).gd_type = SINIT((istrap) ? STS_TG32 : STS_IG32); \
255         (gate).gd_s = SINIT(0);                                 \
256         (gate).gd_dpl = SINIT(dpl);                                     \
257         (gate).gd_p = SINIT(1);                                 \
258         (gate).gd_off_31_16 = SINIT((uint32_t) (off) >> 16);            \
259 }
260
261 // Set up a call gate descriptor.
262 #define SETCALLGATE(gate, ss, off, dpl)                         \
263 {                                                               \
264         (gate).gd_off_15_0 = (uint32_t) (off) & 0xffff;         \
265         (gate).gd_ss = (ss);                                    \
266         (gate).gd_args = 0;                                     \
267         (gate).gd_rsv1 = 0;                                     \
268         (gate).gd_type = STS_CG32;                              \
269         (gate).gd_s = 0;                                        \
270         (gate).gd_dpl = (dpl);                                  \
271         (gate).gd_p = 1;                                        \
272         (gate).gd_off_31_16 = (uint32_t) (off) >> 16;           \
273 }
274
275 // Pseudo-descriptors used for LGDT, LLDT and LIDT instructions.
276 typedef struct Pseudodesc {
277         uint16_t pd_lim;                // Limit
278         uint32_t pd_base;               // Base address
279 } __attribute__ ((packed)) pseudodesc_t;
280
281 extern segdesc_t (COUNT(SEG_COUNT) RO gdt)[];
282 extern pseudodesc_t gdt_pd;
283
284 // we must guarantee that for any PTE, exactly one of the following is true
285 #define PAGE_PRESENT(pte) ((pte) & PTE_P)
286 #define PAGE_UNMAPPED(pte) ((pte) == 0)
287 #define PAGE_PAGED_OUT(pte) (!PAGE_PRESENT(pte) && !PAGE_UNMAPPED(pte))
288
289 #endif /* !__ASSEMBLER__ */
290
291 #endif /* !ROS_ARCH_MMU_H */