xref: /kvm-unit-tests/lib/x86/desc.h (revision e97e1c827fadc972c4efc8fc0650984b6fcc74e8)
1 #ifndef __IDT_TEST__
2 #define __IDT_TEST__
3 
4 #include <setjmp.h>
5 
6 void setup_idt(void);
7 void setup_alt_stack(void);
8 
9 struct ex_regs {
10     unsigned long rax, rcx, rdx, rbx;
11     unsigned long dummy, rbp, rsi, rdi;
12 #ifdef __x86_64__
13     unsigned long r8, r9, r10, r11;
14     unsigned long r12, r13, r14, r15;
15 #endif
16     unsigned long vector;
17     unsigned long error_code;
18     unsigned long rip;
19     unsigned long cs;
20     unsigned long rflags;
21 };
22 
23 typedef void (*handler)(struct ex_regs *regs);
24 
25 typedef struct {
26 	u16 prev;
27 	u16 res1;
28 	u32 esp0;
29 	u16 ss0;
30 	u16 res2;
31 	u32 esp1;
32 	u16 ss1;
33 	u16 res3;
34 	u32 esp2;
35 	u16 ss2;
36 	u16 res4;
37 	u32 cr3;
38 	u32 eip;
39 	u32 eflags;
40 	u32 eax, ecx, edx, ebx, esp, ebp, esi, edi;
41 	u16 es;
42 	u16 res5;
43 	u16 cs;
44 	u16 res6;
45 	u16 ss;
46 	u16 res7;
47 	u16 ds;
48 	u16 res8;
49 	u16 fs;
50 	u16 res9;
51 	u16 gs;
52 	u16 res10;
53 	u16 ldt;
54 	u16 res11;
55 	u16 t:1;
56 	u16 res12:15;
57 	u16 iomap_base;
58 } tss32_t;
59 
60 typedef struct  __attribute__((packed)) {
61 	u32 res1;
62 	u64 rsp0;
63 	u64 rsp1;
64 	u64 rsp2;
65 	u64 res2;
66 	u64 ist1;
67 	u64 ist2;
68 	u64 ist3;
69 	u64 ist4;
70 	u64 ist5;
71 	u64 ist6;
72 	u64 ist7;
73 	u64 res3;
74 	u16 res4;
75 	u16 iomap_base;
76 } tss64_t;
77 
78 #ifdef __x86_64
79 #define ASM_TRY(catch)                                  \
80     "movl $0, %%gs:4 \n\t"                              \
81     ".pushsection .data.ex \n\t"                        \
82     ".quad 1111f, " catch "\n\t"                        \
83     ".popsection \n\t"                                  \
84     "1111:"
85 #else
86 #define ASM_TRY(catch)                                  \
87     "movl $0, %%gs:4 \n\t"                              \
88     ".pushsection .data.ex \n\t"                        \
89     ".long 1111f, " catch "\n\t"                        \
90     ".popsection \n\t"                                  \
91     "1111:"
92 #endif
93 
94 /*
95  * selector     32-bit                        64-bit
96  * 0x00         NULL descriptor               NULL descriptor
97  * 0x08         ring-0 code segment (32-bit)  ring-0 code segment (64-bit)
98  * 0x10         ring-0 data segment (32-bit)  ring-0 data segment (32/64-bit)
99  * 0x18         ring-0 code segment (P=0)     ring-0 code segment (64-bit, P=0)
100  * 0x20         intr_alt_stack TSS            ring-0 code segment (32-bit)
101  * 0x28         ring-0 code segment (16-bit)  same
102  * 0x30         ring-0 data segment (16-bit)  same
103  * 0x38 (0x3b)  ring-3 code segment (32-bit)  same
104  * 0x40 (0x43)  ring-3 data segment (32-bit)  ring-3 data segment (32/64-bit)
105  * 0x48 (0x4b)  **unused**                    ring-3 code segment (64-bit)
106  * 0x50-0x78    free to use for test cases    same
107  * 0x80-0x870   primary TSS (CPU 0..254)      same
108  * 0x878-0x1068 percpu area (CPU 0..254)      not used
109  *
110  * Note that the same segment can be used for 32-bit and 64-bit data segments
111  * (the L bit is only defined for code segments)
112  *
113  * Selectors 0x08-0x10 and 0x3b-0x4b are set up for use with the SYSCALL
114  * and SYSRET instructions.
115  */
116 
117 #define KERNEL_CS   0x08
118 #define KERNEL_DS   0x10
119 #define NP_SEL      0x18
120 #ifdef __x86_64__
121 #define KERNEL_CS32 0x20
122 #else
123 #define TSS_INTR    0x20
124 #endif
125 #define KERNEL_CS16 0x28
126 #define KERNEL_DS16 0x30
127 #define USER_CS32   0x3b
128 #define USER_DS     0x43
129 #ifdef __x86_64__
130 #define USER_CS64   0x4b
131 #endif
132 
133 /* Synonyms */
134 #define KERNEL_DS32 KERNEL_DS
135 #define USER_DS32   USER_DS
136 
137 #ifdef __x86_64__
138 #define KERNEL_CS64 KERNEL_CS
139 #define USER_CS     USER_CS64
140 #define KERNEL_DS64 KERNEL_DS
141 #define USER_DS64   USER_DS
142 #else
143 #define KERNEL_CS32 KERNEL_CS
144 #define USER_CS     USER_CS32
145 #endif
146 
147 #define FIRST_SPARE_SEL 0x50
148 #define TSS_MAIN 0x80
149 
150 typedef struct {
151     unsigned short offset0;
152     unsigned short selector;
153     unsigned short ist : 3;
154     unsigned short : 5;
155     unsigned short type : 4;
156     unsigned short : 1;
157     unsigned short dpl : 2;
158     unsigned short p : 1;
159     unsigned short offset1;
160 #ifdef __x86_64__
161     unsigned offset2;
162     unsigned reserved;
163 #endif
164 } idt_entry_t;
165 
166 typedef struct {
167 	u16 limit_low;
168 	u16 base_low;
169 	u8 base_middle;
170 	u8 access;
171 	u8 granularity;
172 	u8 base_high;
173 } gdt_entry_t;
174 
175 struct segment_desc64 {
176 	uint16_t limit1;
177 	uint16_t base1;
178 	uint8_t  base2;
179 	union {
180 		uint16_t  type_limit_flags;      /* Type and limit flags */
181 		struct {
182 			uint16_t type:4;
183 			uint16_t s:1;
184 			uint16_t dpl:2;
185 			uint16_t p:1;
186 			uint16_t limit:4;
187 			uint16_t avl:1;
188 			uint16_t l:1;
189 			uint16_t db:1;
190 			uint16_t g:1;
191 		} __attribute__((__packed__));
192 	} __attribute__((__packed__));
193 	uint8_t  base3;
194 	uint32_t base4;
195 	uint32_t zero;
196 } __attribute__((__packed__));
197 
198 #define DESC_BUSY ((uint64_t) 1 << 41)
199 
200 extern idt_entry_t boot_idt[256];
201 
202 #ifndef __x86_64__
203 extern gdt_entry_t gdt32[];
204 extern tss32_t tss;
205 extern tss32_t tss_intr;
206 void set_gdt_task_gate(u16 tss_sel, u16 sel);
207 void set_idt_task_gate(int vec, u16 sel);
208 void set_intr_task_gate(int vec, void *fn);
209 void setup_tss32(void);
210 #else
211 extern tss64_t tss;
212 #endif
213 
214 unsigned exception_vector(void);
215 int write_cr4_checking(unsigned long val);
216 unsigned exception_error_code(void);
217 bool exception_rflags_rf(void);
218 void set_idt_entry(int vec, void *addr, int dpl);
219 void set_idt_sel(int vec, u16 sel);
220 void set_idt_dpl(int vec, u16 dpl);
221 void set_gdt_entry(int sel, u32 base,  u32 limit, u8 access, u8 gran);
222 void set_intr_alt_stack(int e, void *fn);
223 void print_current_tss_info(void);
224 handler handle_exception(u8 v, handler fn);
225 void unhandled_exception(struct ex_regs *regs, bool cpu);
226 
227 bool test_for_exception(unsigned int ex, void (*trigger_func)(void *data),
228 			void *data);
229 void __set_exception_jmpbuf(jmp_buf *addr);
230 #define set_exception_jmpbuf(jmpbuf) \
231 	(setjmp(jmpbuf) ? : (__set_exception_jmpbuf(&(jmpbuf)), 0))
232 
233 static inline void *get_idt_addr(idt_entry_t *entry)
234 {
235 	uintptr_t addr = entry->offset0 | ((u32)entry->offset1 << 16);
236 #ifdef __x86_64__
237 	addr |= (u64)entry->offset2 << 32;
238 #endif
239 	return (void *)addr;
240 }
241 
242 #endif
243