summaryrefslogtreecommitdiff
path: root/mmu.h
blob: 200594ea3055b9327ff3888abd5d39e40c68b7b5 (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
/*
 * This file contains definitions for the x86 memory management unit (MMU).
 */

// Eflags register
#define FL_CF		0x00000001	// Carry Flag
#define FL_PF		0x00000004	// Parity Flag
#define FL_AF		0x00000010	// Auxiliary carry Flag
#define FL_ZF		0x00000040	// Zero Flag
#define FL_SF		0x00000080	// Sign Flag
#define FL_TF		0x00000100	// Trap Flag
#define FL_IF		0x00000200	// Interrupt Flag
#define FL_DF		0x00000400	// Direction Flag
#define FL_OF		0x00000800	// Overflow Flag
#define FL_IOPL_MASK	0x00003000	// I/O Privilege Level bitmask
#define FL_IOPL_0	0x00000000	//   IOPL == 0
#define FL_IOPL_1	0x00001000	//   IOPL == 1
#define FL_IOPL_2	0x00002000	//   IOPL == 2
#define FL_IOPL_3	0x00003000	//   IOPL == 3
#define FL_NT		0x00004000	// Nested Task
#define FL_RF		0x00010000	// Resume Flag
#define FL_VM		0x00020000	// Virtual 8086 mode
#define FL_AC		0x00040000	// Alignment Check
#define FL_VIF		0x00080000	// Virtual Interrupt Flag
#define FL_VIP		0x00100000	// Virtual Interrupt Pending
#define FL_ID		0x00200000	// ID flag

// Segment Descriptor
struct segdesc {
	uint lim_15_0 : 16;  // Low bits of segment limit
	uint base_15_0 : 16; // Low bits of segment base address
	uint base_23_16 : 8; // Middle bits of segment base address
	uint type : 4;       // Segment type (see STS_ constants)
	uint s : 1;          // 0 = system, 1 = application
	uint dpl : 2;        // Descriptor Privilege Level
	uint p : 1;          // Present
	uint lim_19_16 : 4;  // High bits of segment limit
	uint avl : 1;        // Unused (available for software use)
	uint rsv1 : 1;       // Reserved
	uint db : 1;         // 0 = 16-bit segment, 1 = 32-bit segment
	uint g : 1;          // Granularity: limit scaled by 4K when set
	uint base_31_24 : 8; // High bits of segment base address
};

// Null segment
#define SEG_NULL	(struct segdesc){ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }

// Normal segment
#define SEG(type, base, lim, dpl) (struct segdesc)			\
{ ((lim) >> 12) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff,	\
    type, 1, dpl, 1, (uint) (lim) >> 28, 0, 0, 1, 1,		\
    (uint) (base) >> 24 }

#define SEG16(type, base, lim, dpl) (struct segdesc)			\
{ (lim) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff,		\
    type, 1, dpl, 1, (uint) (lim) >> 16, 0, 0, 1, 0,		\
    (uint) (base) >> 24 }

// Application segment type bits
#define STA_X		0x8	    // Executable segment
#define STA_E		0x4	    // Expand down (non-executable segments)
#define STA_C		0x4	    // Conforming code segment (executable only)
#define STA_W		0x2	    // Writeable (non-executable segments)
#define STA_R		0x2	    // Readable (executable segments)
#define STA_A		0x1	    // Accessed

// System segment type bits
#define STS_T16A	0x1	    // Available 16-bit TSS
#define STS_LDT		0x2	    // Local Descriptor Table
#define STS_T16B	0x3	    // Busy 16-bit TSS
#define STS_CG16	0x4	    // 16-bit Call Gate
#define STS_TG		0x5	    // Task Gate / Coum Transmitions
#define STS_IG16	0x6	    // 16-bit Interrupt Gate
#define STS_TG16	0x7	    // 16-bit Trap Gate
#define STS_T32A	0x9	    // Available 32-bit TSS
#define STS_T32B	0xB	    // Busy 32-bit TSS
#define STS_CG32	0xC	    // 32-bit Call Gate
#define STS_IG32	0xE	    // 32-bit Interrupt Gate
#define STS_TG32	0xF	    // 32-bit Trap Gate

// Task state segment format
struct taskstate {
	uint link;	// Old ts selector
	uint esp0;	// Stack pointers and segment selectors
	ushort ss0;	//   after an increase in privilege level
	ushort padding1;
	uint * esp1;
	ushort ss1;
	ushort padding2;
	uint * esp2;
	ushort ss2;
	ushort padding3;
	void * cr3;	// Page directory base
	uint * eip;	// Saved state from last task switch
	uint eflags;
	uint eax;	// More saved state (registers)
	uint ecx;
	uint edx;
	uint ebx;
	uint * esp;
	uint * ebp;
	uint esi;
	uint edi;
	ushort es;		// Even more saved state (segment selectors)
	ushort padding4;
	ushort cs;
	ushort padding5;
	ushort ss;
	ushort padding6;
	ushort ds;
	ushort padding7;
	ushort fs;
	ushort padding8;
	ushort gs;
	ushort padding9;
	ushort ldt;
	ushort padding10;
	ushort t;		// Trap on task switch
	ushort iomb;	// I/O map base address
};

// Gate descriptors for interrupts and traps
struct gatedesc {
	uint off_15_0 : 16;   // low 16 bits of offset in segment
	uint ss : 16;         // segment selector
	uint args : 5;        // # args, 0 for interrupt/trap gates
	uint rsv1 : 3;        // reserved(should be zero I guess)
	uint type : 4;        // type(STS_{TG,IG32,TG32})
	uint s : 1;           // must be 0 (system)
	uint dpl : 2;         // descriptor(meaning new) privilege level
	uint p : 1;           // Present
	uint off_31_16 : 16;  // high bits of offset in segment
};

// Set up a normal interrupt/trap gate descriptor.
// - istrap: 1 for a trap (= exception) gate, 0 for an interrupt gate.
//   interrupt gate clears FL_IF, trap gate leaves FL_IF alone
// - sel: Code segment selector for interrupt/trap handler
// - off: Offset in code segment for interrupt/trap handler
// - dpl: Descriptor Privilege Level -
//	  the privilege level required for software to invoke
//	  this interrupt/trap gate explicitly using an int instruction.
#define SETGATE(gate, istrap, sel, off, d)			\
{								\
	(gate).off_15_0 = (uint) (off) & 0xffff;		\
	(gate).ss = (sel);					\
	(gate).args = 0;					\
	(gate).rsv1 = 0;					\
	(gate).type = (istrap) ? STS_TG32 : STS_IG32;	\
	(gate).s = 0;					\
	(gate).dpl = (d);					\
	(gate).p = 1;					\
	(gate).off_31_16 = (uint) (off) >> 16;		\
}