xref: /kvm-unit-tests/lib/x86/desc.h (revision 10594e42ecdda42e5eff703439b7079a0c93e8e5)
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 struct {
24 	u16 prev;
25 	u16 res1;
26 	u32 esp0;
27 	u16 ss0;
28 	u16 res2;
29 	u32 esp1;
30 	u16 ss1;
31 	u16 res3;
32 	u32 esp2;
33 	u16 ss2;
34 	u16 res4;
35 	u32 cr3;
36 	u32 eip;
37 	u32 eflags;
38 	u32 eax, ecx, edx, ebx, esp, ebp, esi, edi;
39 	u16 es;
40 	u16 res5;
41 	u16 cs;
42 	u16 res6;
43 	u16 ss;
44 	u16 res7;
45 	u16 ds;
46 	u16 res8;
47 	u16 fs;
48 	u16 res9;
49 	u16 gs;
50 	u16 res10;
51 	u16 ldt;
52 	u16 res11;
53 	u16 t:1;
54 	u16 res12:15;
55 	u16 iomap_base;
56 } tss32_t;
57 
58 typedef struct  __attribute__((packed)) {
59 	u32 res1;
60 	u64 rsp0;
61 	u64 rsp1;
62 	u64 rsp2;
63 	u64 res2;
64 	u64 ist1;
65 	u64 ist2;
66 	u64 ist3;
67 	u64 ist4;
68 	u64 ist5;
69 	u64 ist6;
70 	u64 ist7;
71 	u64 res3;
72 	u16 res4;
73 	u16 iomap_base;
74 } tss64_t;
75 
76 #define ASM_TRY(catch)                                  \
77     "movl $0, %%gs:4 \n\t"                              \
78     ".pushsection .data.ex \n\t"                        \
79     ".quad 1111f, " catch "\n\t"                        \
80     ".popsection \n\t"                                  \
81     "1111:"
82 
83 #define DB_VECTOR   1
84 #define BP_VECTOR   3
85 #define UD_VECTOR   6
86 #define GP_VECTOR   13
87 
88 /*
89  * selector     32-bit                        64-bit
90  * 0x00         NULL descriptor               NULL descriptor
91  * 0x08         ring-0 code segment (32-bit)  ring-0 code segment (64-bit)
92  * 0x10         ring-0 data segment (32-bit)  ring-0 data segment (32/64-bit)
93  * 0x18         ring-0 code segment (P=0)     ring-0 code segment (64-bit, P=0)
94  * 0x20         intr_alt_stack TSS            ring-0 code segment (32-bit)
95  * 0x28         ring-0 code segment (16-bit)  same
96  * 0x30         ring-0 data segment (16-bit)  same
97  * 0x38 (0x3b)  ring-3 code segment (32-bit)  same
98  * 0x40 (0x43)  ring-3 data segment (32-bit)  ring-3 data segment (32/64-bit)
99  * 0x48 (0x4b)  **unused**                    ring-3 code segment (64-bit)
100  * 0x50--0x78   free to use for test cases    same
101  * 0x80         primary TSS (CPU 0)           same
102  *
103  * Note that the same segment can be used for 32-bit and 64-bit data segments
104  * (the L bit is only defined for code segments)
105  *
106  * Selectors 0x08-0x10 and 0x3b-0x4b are set up for use with the SYSCALL
107  * and SYSRET instructions.
108  */
109 
110 #define KERNEL_CS   0x08
111 #define KERNEL_DS   0x10
112 #define NP_SEL      0x18
113 #ifdef __x86_64__
114 #define KERNEL_CS32 0x20
115 #else
116 #define TSS_INTR    0x20
117 #endif
118 #define KERNEL_CS16 0x28
119 #define KERNEL_DS16 0x30
120 #define USER_CS32   0x3b
121 #define USER_DS     0x43
122 #ifdef __x86_64__
123 #define USER_CS64   0x4b
124 #endif
125 
126 /* Synonyms */
127 #define KERNEL_DS32 KERNEL_DS
128 #define USER_DS32   USER_DS
129 
130 #ifdef __x86_64__
131 #define KERNEL_CS64 KERNEL_CS
132 #define USER_CS     USER_CS64
133 #define KERNEL_DS64 KERNEL_DS
134 #define USER_DS64   USER_DS
135 #else
136 #define KERNEL_CS32 KERNEL_CS
137 #define USER_CS     USER_CS32
138 #endif
139 
140 #define FIRST_SPARE_SEL 0x50
141 #define TSS_MAIN 0x80
142 
143 typedef struct {
144     unsigned short offset0;
145     unsigned short selector;
146     unsigned short ist : 3;
147     unsigned short : 5;
148     unsigned short type : 4;
149     unsigned short : 1;
150     unsigned short dpl : 2;
151     unsigned short p : 1;
152     unsigned short offset1;
153 #ifdef __x86_64__
154     unsigned offset2;
155     unsigned reserved;
156 #endif
157 } idt_entry_t;
158 
159 typedef struct {
160 	u16 limit_low;
161 	u16 base_low;
162 	u8 base_middle;
163 	u8 access;
164 	u8 granularity;
165 	u8 base_high;
166 } gdt_entry_t;
167 
168 extern idt_entry_t boot_idt[256];
169 
170 #ifndef __x86_64__
171 extern gdt_entry_t gdt32[];
172 extern tss32_t tss;
173 extern tss32_t tss_intr;
174 void set_gdt_task_gate(u16 tss_sel, u16 sel);
175 void set_idt_task_gate(int vec, u16 sel);
176 void set_intr_task_gate(int vec, void *fn);
177 void setup_tss32(void);
178 #else
179 extern tss64_t tss;
180 #endif
181 
182 unsigned exception_vector(void);
183 unsigned exception_error_code(void);
184 bool exception_rflags_rf(void);
185 void set_idt_entry(int vec, void *addr, int dpl);
186 void set_idt_sel(int vec, u16 sel);
187 void set_idt_dpl(int vec, u16 dpl);
188 void set_gdt_entry(int sel, u32 base,  u32 limit, u8 access, u8 gran);
189 void set_intr_alt_stack(int e, void *fn);
190 void print_current_tss_info(void);
191 void handle_exception(u8 v, void (*func)(struct ex_regs *regs));
192 
193 bool test_for_exception(unsigned int ex, void (*trigger_func)(void *data),
194 			void *data);
195 void __set_exception_jmpbuf(jmp_buf *addr);
196 #define set_exception_jmpbuf(jmpbuf) \
197 	(setjmp(jmpbuf) ? : (__set_exception_jmpbuf(&(jmpbuf)), 0))
198 
199 #endif
200