xref: /xv6-public/mmu.h (revision b5f17007)
155e95b16Srtm /*
255e95b16Srtm  * This file contains definitions for the x86 memory management unit (MMU),
355e95b16Srtm  * including paging- and segmentation-related data structures and constants,
455e95b16Srtm  * the %cr0, %cr4, and %eflags registers, and traps.
555e95b16Srtm  */
655e95b16Srtm 
755e95b16Srtm /*
8564f787eSrsc  *	Register flags and fundamental constants.
955e95b16Srtm  */
1055e95b16Srtm 
1155e95b16Srtm #define PGSIZE		4096		// bytes mapped by a page
1255e95b16Srtm 
1355e95b16Srtm // Eflags register
1455e95b16Srtm #define FL_CF		0x00000001	// Carry Flag
1555e95b16Srtm #define FL_PF		0x00000004	// Parity Flag
1655e95b16Srtm #define FL_AF		0x00000010	// Auxiliary carry Flag
1755e95b16Srtm #define FL_ZF		0x00000040	// Zero Flag
1855e95b16Srtm #define FL_SF		0x00000080	// Sign Flag
1955e95b16Srtm #define FL_TF		0x00000100	// Trap Flag
2055e95b16Srtm #define FL_IF		0x00000200	// Interrupt Flag
2155e95b16Srtm #define FL_DF		0x00000400	// Direction Flag
2255e95b16Srtm #define FL_OF		0x00000800	// Overflow Flag
2355e95b16Srtm #define FL_IOPL_MASK	0x00003000	// I/O Privilege Level bitmask
2455e95b16Srtm #define FL_IOPL_0	0x00000000	//   IOPL == 0
2555e95b16Srtm #define FL_IOPL_1	0x00001000	//   IOPL == 1
2655e95b16Srtm #define FL_IOPL_2	0x00002000	//   IOPL == 2
2755e95b16Srtm #define FL_IOPL_3	0x00003000	//   IOPL == 3
2855e95b16Srtm #define FL_NT		0x00004000	// Nested Task
2955e95b16Srtm #define FL_RF		0x00010000	// Resume Flag
3055e95b16Srtm #define FL_VM		0x00020000	// Virtual 8086 mode
3155e95b16Srtm #define FL_AC		0x00040000	// Alignment Check
3255e95b16Srtm #define FL_VIF		0x00080000	// Virtual Interrupt Flag
3355e95b16Srtm #define FL_VIP		0x00100000	// Virtual Interrupt Pending
3455e95b16Srtm #define FL_ID		0x00200000	// ID flag
3555e95b16Srtm 
3655e95b16Srtm // Page fault error codes
3755e95b16Srtm #define FEC_PR		0x1	// Page fault caused by protection violation
3855e95b16Srtm #define FEC_WR		0x2	// Page fault caused by a write
3955e95b16Srtm #define FEC_U		0x4	// Page fault occured while in user mode
4055e95b16Srtm 
4155e95b16Srtm /*
4255e95b16Srtm  *
43564f787eSrsc  *	Segmentation data structures and constants.
4455e95b16Srtm  *
4555e95b16Srtm  */
4655e95b16Srtm 
4755e95b16Srtm #ifdef __ASSEMBLER__
4855e95b16Srtm 
4955e95b16Srtm /*
5055e95b16Srtm  * Macros to build GDT entries in assembly.
5155e95b16Srtm  */
5255e95b16Srtm #define SEG_NULL						\
5355e95b16Srtm 	.word 0, 0;						\
5455e95b16Srtm 	.byte 0, 0, 0, 0
5555e95b16Srtm #define SEG(type,base,lim)					\
5655e95b16Srtm 	.word (((lim) >> 12) & 0xffff), ((base) & 0xffff);	\
5755e95b16Srtm 	.byte (((base) >> 16) & 0xff), (0x90 | (type)),		\
5855e95b16Srtm 		(0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff)
5955e95b16Srtm 
6055e95b16Srtm #else	// not __ASSEMBLER__
6155e95b16Srtm 
6255e95b16Srtm // Segment Descriptors
63*b5f17007Srsc struct segdesc {
64b5ee5165Srsc 	uint lim_15_0 : 16;  // Low bits of segment limit
65b5ee5165Srsc 	uint base_15_0 : 16; // Low bits of segment base address
66b5ee5165Srsc 	uint base_23_16 : 8; // Middle bits of segment base address
67b5ee5165Srsc 	uint type : 4;       // Segment type (see STS_ constants)
68b5ee5165Srsc 	uint s : 1;          // 0 = system, 1 = application
69b5ee5165Srsc 	uint dpl : 2;        // Descriptor Privilege Level
70b5ee5165Srsc 	uint p : 1;          // Present
71b5ee5165Srsc 	uint lim_19_16 : 4;  // High bits of segment limit
72b5ee5165Srsc 	uint avl : 1;        // Unused (available for software use)
73b5ee5165Srsc 	uint rsv1 : 1;       // Reserved
74b5ee5165Srsc 	uint db : 1;         // 0 = 16-bit segment, 1 = 32-bit segment
75b5ee5165Srsc 	uint g : 1;          // Granularity: limit scaled by 4K when set
76b5ee5165Srsc 	uint base_31_24 : 8; // High bits of segment base address
7755e95b16Srtm };
7855e95b16Srtm // Null segment
79*b5f17007Srsc #define SEG_NULL	(struct segdesc){ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
8055e95b16Srtm // Segment that is loadable but faults when used
81*b5f17007Srsc #define SEG_FAULT	(struct segdesc){ 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 }
8255e95b16Srtm // Normal segment
83*b5f17007Srsc #define SEG(type, base, lim, dpl) (struct segdesc)			\
8455e95b16Srtm { ((lim) >> 12) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff,	\
85b5ee5165Srsc     type, 1, dpl, 1, (uint) (lim) >> 28, 0, 0, 1, 1,		\
86b5ee5165Srsc     (uint) (base) >> 24 }
87*b5f17007Srsc #define SEG16(type, base, lim, dpl) (struct segdesc)			\
8855e95b16Srtm { (lim) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff,		\
89b5ee5165Srsc     type, 1, dpl, 1, (uint) (lim) >> 16, 0, 0, 1, 0,		\
90b5ee5165Srsc     (uint) (base) >> 24 }
9155e95b16Srtm 
9255e95b16Srtm #endif /* !__ASSEMBLER__ */
9355e95b16Srtm 
9455e95b16Srtm // Application segment type bits
9555e95b16Srtm #define STA_X		0x8	    // Executable segment
9655e95b16Srtm #define STA_E		0x4	    // Expand down (non-executable segments)
9755e95b16Srtm #define STA_C		0x4	    // Conforming code segment (executable only)
9855e95b16Srtm #define STA_W		0x2	    // Writeable (non-executable segments)
9955e95b16Srtm #define STA_R		0x2	    // Readable (executable segments)
10055e95b16Srtm #define STA_A		0x1	    // Accessed
10155e95b16Srtm 
10255e95b16Srtm // System segment type bits
10355e95b16Srtm #define STS_T16A	0x1	    // Available 16-bit TSS
10455e95b16Srtm #define STS_LDT		0x2	    // Local Descriptor Table
10555e95b16Srtm #define STS_T16B	0x3	    // Busy 16-bit TSS
10655e95b16Srtm #define STS_CG16	0x4	    // 16-bit Call Gate
10755e95b16Srtm #define STS_TG		0x5	    // Task Gate / Coum Transmitions
10855e95b16Srtm #define STS_IG16	0x6	    // 16-bit Interrupt Gate
10955e95b16Srtm #define STS_TG16	0x7	    // 16-bit Trap Gate
11055e95b16Srtm #define STS_T32A	0x9	    // Available 32-bit TSS
11155e95b16Srtm #define STS_T32B	0xB	    // Busy 32-bit TSS
11255e95b16Srtm #define STS_CG32	0xC	    // 32-bit Call Gate
11355e95b16Srtm #define STS_IG32	0xE	    // 32-bit Interrupt Gate
11455e95b16Srtm #define STS_TG32	0xF	    // 32-bit Trap Gate
11555e95b16Srtm 
11655e95b16Srtm 
11755e95b16Srtm /*
11855e95b16Srtm  *
119564f787eSrsc  *	Traps.
12055e95b16Srtm  *
12155e95b16Srtm  */
12255e95b16Srtm 
12355e95b16Srtm #ifndef __ASSEMBLER__
12455e95b16Srtm 
12555e95b16Srtm // Task state segment format (as described by the Pentium architecture book)
126*b5f17007Srsc struct taskstate {
127ef2bd07aSrsc 	uint32_t link;	// Old ts selector
128ef2bd07aSrsc 	uintptr_t esp0;	// Stack pointers and segment selectors
129ef2bd07aSrsc 	uint16_t ss0;	//   after an increase in privilege level
130ef2bd07aSrsc 	uint16_t padding1;
131ef2bd07aSrsc 	uintptr_t esp1;
132ef2bd07aSrsc 	uint16_t ss1;
133ef2bd07aSrsc 	uint16_t padding2;
134ef2bd07aSrsc 	uintptr_t esp2;
135ef2bd07aSrsc 	uint16_t ss2;
136ef2bd07aSrsc 	uint16_t padding3;
137ef2bd07aSrsc 	physaddr_t cr3;	// Page directory base
138ef2bd07aSrsc 	uintptr_t eip;	// Saved state from last task switch
139ef2bd07aSrsc 	uint32_t eflags;
140ef2bd07aSrsc 	uint32_t eax;	// More saved state (registers)
141ef2bd07aSrsc 	uint32_t ecx;
142ef2bd07aSrsc 	uint32_t edx;
143ef2bd07aSrsc 	uint32_t ebx;
144ef2bd07aSrsc 	uintptr_t esp;
145ef2bd07aSrsc 	uintptr_t ebp;
146ef2bd07aSrsc 	uint32_t esi;
147ef2bd07aSrsc 	uint32_t edi;
148ef2bd07aSrsc 	uint16_t es;		// Even more saved state (segment selectors)
149ef2bd07aSrsc 	uint16_t padding4;
150ef2bd07aSrsc 	uint16_t cs;
151ef2bd07aSrsc 	uint16_t padding5;
152ef2bd07aSrsc 	uint16_t ss;
153ef2bd07aSrsc 	uint16_t padding6;
154ef2bd07aSrsc 	uint16_t ds;
155ef2bd07aSrsc 	uint16_t padding7;
156ef2bd07aSrsc 	uint16_t fs;
157ef2bd07aSrsc 	uint16_t padding8;
158ef2bd07aSrsc 	uint16_t gs;
159ef2bd07aSrsc 	uint16_t padding9;
160ef2bd07aSrsc 	uint16_t ldt;
161ef2bd07aSrsc 	uint16_t padding10;
162ef2bd07aSrsc 	uint16_t t;		// Trap on task switch
163ef2bd07aSrsc 	uint16_t iomb;	// I/O map base address
16455e95b16Srtm };
16555e95b16Srtm 
16655e95b16Srtm // Gate descriptors for interrupts and traps
167*b5f17007Srsc struct gatedesc {
168b5ee5165Srsc 	uint off_15_0 : 16;   // low 16 bits of offset in segment
169b5ee5165Srsc 	uint ss : 16;         // segment selector
170b5ee5165Srsc 	uint args : 5;        // # args, 0 for interrupt/trap gates
171b5ee5165Srsc 	uint rsv1 : 3;        // reserved(should be zero I guess)
172b5ee5165Srsc 	uint type : 4;        // type(STS_{TG,IG32,TG32})
173b5ee5165Srsc 	uint s : 1;           // must be 0 (system)
174b5ee5165Srsc 	uint dpl : 2;         // descriptor(meaning new) privilege level
175b5ee5165Srsc 	uint p : 1;           // Present
176b5ee5165Srsc 	uint off_31_16 : 16;  // high bits of offset in segment
17755e95b16Srtm };
17855e95b16Srtm 
17955e95b16Srtm // Set up a normal interrupt/trap gate descriptor.
18055e95b16Srtm // - istrap: 1 for a trap (= exception) gate, 0 for an interrupt gate.
18155e95b16Srtm // - sel: Code segment selector for interrupt/trap handler
18255e95b16Srtm // - off: Offset in code segment for interrupt/trap handler
18355e95b16Srtm // - dpl: Descriptor Privilege Level -
18455e95b16Srtm //	  the privilege level required for software to invoke
18555e95b16Srtm //	  this interrupt/trap gate explicitly using an int instruction.
186ef2bd07aSrsc #define SETGATE(gate, istrap, sel, off, d)			\
18755e95b16Srtm {								\
188ef2bd07aSrsc 	(gate).off_15_0 = (uint32_t) (off) & 0xffff;		\
189ef2bd07aSrsc 	(gate).ss = (sel);					\
190ef2bd07aSrsc 	(gate).args = 0;					\
191ef2bd07aSrsc 	(gate).rsv1 = 0;					\
192ef2bd07aSrsc 	(gate).type = (istrap) ? STS_TG32 : STS_IG32;	\
193ef2bd07aSrsc 	(gate).s = 0;					\
194ef2bd07aSrsc 	(gate).dpl = (d);					\
195ef2bd07aSrsc 	(gate).p = 1;					\
196ef2bd07aSrsc 	(gate).off_31_16 = (uint32_t) (off) >> 16;		\
19755e95b16Srtm }
19855e95b16Srtm 
19955e95b16Srtm // Set up a call gate descriptor.
200ef2bd07aSrsc #define SETCALLGATE(gate, ss, off, d)           	        \
20155e95b16Srtm {								\
202ef2bd07aSrsc 	(gate).off_15_0 = (uint32_t) (off) & 0xffff;		\
203ef2bd07aSrsc 	(gate).ss = (ss);					\
204ef2bd07aSrsc 	(gate).args = 0;					\
205ef2bd07aSrsc 	(gate).rsv1 = 0;					\
206ef2bd07aSrsc 	(gate).type = STS_CG32;				\
207ef2bd07aSrsc 	(gate).s = 0;					\
208ef2bd07aSrsc 	(gate).dpl = (d);					\
209ef2bd07aSrsc 	(gate).p = 1;					\
210ef2bd07aSrsc 	(gate).off_31_16 = (uint32_t) (off) >> 16;		\
21155e95b16Srtm }
21255e95b16Srtm 
21355e95b16Srtm #endif /* !__ASSEMBLER__ */
21455e95b16Srtm 
215