forked from jackmiller1/ece391-kernel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathx86_desc.h
216 lines (180 loc) · 5.25 KB
/
x86_desc.h
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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/* x86_desc.h - Defines for various x86 descriptors, descriptor tables,
* and selectors
* vim:ts=4 noexpandtab
*/
#ifndef _X86_DESC_H
#define _X86_DESC_H
#include "types.h"
/* Segment selector values */
#define KERNEL_CS 0x0010
#define KERNEL_DS 0x0018
#define USER_CS 0x0023
#define USER_DS 0x002B
#define KERNEL_TSS 0x0030
#define KERNEL_LDT 0x0038
/* Size of the task state segment (TSS) */
#define TSS_SIZE 104
/* Number of vectors in the interrupt descriptor table (IDT) */
#define NUM_VEC 256
#ifndef ASM
/* This structure is used to load descriptor base registers
* like the GDTR and IDTR */
typedef struct x86_desc {
uint16_t padding;
uint16_t size;
uint32_t addr;
} x86_desc_t;
/* This is a segment descriptor. It goes in the GDT. */
typedef struct seg_desc {
union {
uint32_t val;
struct {
uint16_t seg_lim_15_00;
uint16_t base_15_00;
uint8_t base_23_16;
uint32_t type : 4;
uint32_t sys : 1;
uint32_t dpl : 2;
uint32_t present : 1;
uint32_t seg_lim_19_16 : 4;
uint32_t avail : 1;
uint32_t reserved : 1;
uint32_t opsize : 1;
uint32_t granularity : 1;
uint8_t base_31_24;
} __attribute__((packed));
};
} seg_desc_t;
/* TSS structure */
typedef struct __attribute__((packed)) tss_t {
uint16_t prev_task_link;
uint16_t prev_task_link_pad;
uint32_t esp0;
uint16_t ss0;
uint16_t ss0_pad;
uint32_t esp1;
uint16_t ss1;
uint16_t ss1_pad;
uint32_t esp2;
uint16_t ss2;
uint16_t ss2_pad;
uint32_t cr3;
uint32_t eip;
uint32_t eflags;
uint32_t eax;
uint32_t ecx;
uint32_t edx;
uint32_t ebx;
uint32_t esp;
uint32_t ebp;
uint32_t esi;
uint32_t edi;
uint16_t es;
uint16_t es_pad;
uint16_t cs;
uint16_t cs_pad;
uint16_t ss;
uint16_t ss_pad;
uint16_t ds;
uint16_t ds_pad;
uint16_t fs;
uint16_t fs_pad;
uint16_t gs;
uint16_t gs_pad;
uint16_t ldt_segment_selector;
uint16_t ldt_pad;
uint16_t debug_trap : 1;
uint16_t io_pad : 15;
uint16_t io_base_addr;
} tss_t;
/* Some external descriptors declared in .S files */
extern x86_desc_t gdt_desc;
extern uint16_t ldt_desc;
extern uint32_t ldt_size;
extern seg_desc_t ldt_desc_ptr;
extern seg_desc_t gdt_ptr;
extern uint32_t ldt;
extern uint32_t tss_size;
extern seg_desc_t tss_desc_ptr;
extern tss_t tss;
/* Sets runtime-settable parameters in the GDT entry for the LDT */
#define SET_LDT_PARAMS(str, addr, lim) \
do { \
str.base_31_24 = ((uint32_t)(addr) & 0xFF000000) >> 24; \
str.base_23_16 = ((uint32_t)(addr) & 0x00FF0000) >> 16; \
str.base_15_00 = (uint32_t)(addr) & 0x0000FFFF; \
str.seg_lim_19_16 = ((lim) & 0x000F0000) >> 16; \
str.seg_lim_15_00 = (lim) & 0x0000FFFF; \
} while(0)
/* Sets runtime parameters for the TSS */
#define SET_TSS_PARAMS(str, addr, lim) \
do { \
str.base_31_24 = ((uint32_t)(addr) & 0xFF000000) >> 24; \
str.base_23_16 = ((uint32_t)(addr) & 0x00FF0000) >> 16; \
str.base_15_00 = (uint32_t)(addr) & 0x0000FFFF; \
str.seg_lim_19_16 = ((lim) & 0x000F0000) >> 16; \
str.seg_lim_15_00 = (lim) & 0x0000FFFF; \
} while(0)
/* An interrupt descriptor entry (goes into the IDT) */
typedef union idt_desc_t {
uint32_t val;
struct {
uint16_t offset_15_00;
uint16_t seg_selector;
uint8_t reserved4;
uint32_t reserved3 : 1;
uint32_t reserved2 : 1;
uint32_t reserved1 : 1;
uint32_t size : 1;
uint32_t reserved0 : 1;
uint32_t dpl : 2;
uint32_t present : 1;
uint16_t offset_31_16;
} __attribute__((packed));
} idt_desc_t;
/* The IDT itself (declared in x86_desc.S */
extern idt_desc_t idt[NUM_VEC];
/* The descriptor used to load the IDTR */
extern x86_desc_t idt_desc_ptr;
/* Sets runtime parameters for an IDT entry */
#define SET_IDT_ENTRY(str, handler) \
do { \
str.offset_31_16 = ((uint32_t)(handler) & 0xFFFF0000) >> 16; \
str.offset_15_00 = ((uint32_t)(handler) & 0xFFFF); \
} while(0)
/* Load task register. This macro takes a 16-bit index into the GDT,
* which points to the TSS entry. x86 then reads the GDT's TSS
* descriptor and loads the base address specified in that descriptor
* into the task register */
#define ltr(desc) \
do { \
asm volatile("ltr %w0" \
: \
: "r" (desc) \
: "memory", "cc" ); \
} while(0)
/* Load the interrupt descriptor table (IDT). This macro takes a 32-bit
* address which points to a 6-byte structure. The 6-byte structure
* (defined as "struct x86_desc" above) contains a 2-byte size field
* specifying the size of the IDT, and a 4-byte address field specifying
* the base address of the IDT. */
#define lidt(desc) \
do { \
asm volatile("lidt (%0)" \
: \
: "g" (desc) \
: "memory"); \
} while(0)
/* Load the local descriptor table (LDT) register. This macro takes a
* 16-bit index into the GDT, which points to the LDT entry. x86 then
* reads the GDT's LDT descriptor and loads the base address specified
* in that descriptor into the LDT register */
#define lldt(desc) \
do { \
asm volatile("lldt %%ax" \
: \
: "a" (desc) \
: "memory" ); \
} while(0)
#endif /* ASM */
#endif /* _x86_DESC_H */