1 #ifndef _X86_DESC_H_ 2 #define _X86_DESC_H_ 3 4 /* 5 * selector 32-bit 64-bit 6 * 0x00 NULL descriptor NULL descriptor 7 * 0x08 ring-0 code segment (32-bit) ring-0 code segment (64-bit) 8 * 0x10 ring-0 data segment (32-bit) ring-0 data segment (32/64-bit) 9 * 0x18 ring-0 code segment (P=0) ring-0 code segment (64-bit, P=0) 10 * 0x20 intr_alt_stack TSS ring-0 code segment (32-bit) 11 * 0x28 ring-0 code segment (16-bit) same 12 * 0x30 ring-0 data segment (16-bit) same 13 * 0x38 (0x3b) ring-3 code segment (32-bit) same 14 * 0x40 (0x43) ring-3 data segment (32-bit) ring-3 data segment (32/64-bit) 15 * 0x48 (0x4b) **unused** ring-3 code segment (64-bit) 16 * 0x50-0x78 free to use for test cases same 17 * 0x80-0x870 primary TSS (CPU 0..254) same 18 * 0x878-0x1068 percpu area (CPU 0..254) not used 19 * 20 * Note that the same segment can be used for 32-bit and 64-bit data segments 21 * (the L bit is only defined for code segments) 22 * 23 * Selectors 0x08-0x10 and 0x3b-0x4b are set up for use with the SYSCALL 24 * and SYSRET instructions. 25 */ 26 27 #define KERNEL_CS 0x08 28 #define KERNEL_DS 0x10 29 #define NP_SEL 0x18 30 #ifdef __x86_64__ 31 #define KERNEL_CS32 0x20 32 #else 33 #define TSS_INTR 0x20 34 #endif 35 #define KERNEL_CS16 0x28 36 #define KERNEL_DS16 0x30 37 #define USER_CS32 0x3b 38 #define USER_DS 0x43 39 #ifdef __x86_64__ 40 #define USER_CS64 0x4b 41 #endif 42 43 /* Synonyms */ 44 #define KERNEL_DS32 KERNEL_DS 45 #define USER_DS32 USER_DS 46 47 #ifdef __x86_64__ 48 #define KERNEL_CS64 KERNEL_CS 49 #define USER_CS USER_CS64 50 #define KERNEL_DS64 KERNEL_DS 51 #define USER_DS64 USER_DS 52 #else 53 #define KERNEL_CS32 KERNEL_CS 54 #define USER_CS USER_CS32 55 #endif 56 57 #define FIRST_SPARE_SEL 0x50 58 #define TSS_MAIN 0x80 59 60 #ifdef __ASSEMBLER__ 61 #define __ASM_FORM(x, ...) x,## __VA_ARGS__ 62 #else 63 #define __ASM_FORM(x, ...) " " xstr(x,##__VA_ARGS__) " " 64 #endif 65 66 #ifndef __x86_64__ 67 #define __ASM_SEL(a,b) __ASM_FORM(a) 68 #else 69 #define __ASM_SEL(a,b) __ASM_FORM(b) 70 #endif 71 72 #ifndef __ASSEMBLER__ 73 74 #include <setjmp.h> 75 76 void setup_idt(void); 77 void load_idt(void); 78 void setup_alt_stack(void); 79 80 struct ex_regs { 81 unsigned long rax, rcx, rdx, rbx; 82 unsigned long dummy, rbp, rsi, rdi; 83 #ifdef __x86_64__ 84 unsigned long r8, r9, r10, r11; 85 unsigned long r12, r13, r14, r15; 86 #endif 87 unsigned long vector; 88 unsigned long error_code; 89 unsigned long rip; 90 unsigned long cs; 91 unsigned long rflags; 92 #ifdef __x86_64__ 93 unsigned long rsp; 94 unsigned long ss; 95 #endif 96 }; 97 98 typedef void (*handler)(struct ex_regs *regs); 99 100 typedef struct { 101 u16 prev; 102 u16 res1; 103 u32 esp0; 104 u16 ss0; 105 u16 res2; 106 u32 esp1; 107 u16 ss1; 108 u16 res3; 109 u32 esp2; 110 u16 ss2; 111 u16 res4; 112 u32 cr3; 113 u32 eip; 114 u32 eflags; 115 u32 eax, ecx, edx, ebx, esp, ebp, esi, edi; 116 u16 es; 117 u16 res5; 118 u16 cs; 119 u16 res6; 120 u16 ss; 121 u16 res7; 122 u16 ds; 123 u16 res8; 124 u16 fs; 125 u16 res9; 126 u16 gs; 127 u16 res10; 128 u16 ldt; 129 u16 res11; 130 u16 t:1; 131 u16 res12:15; 132 u16 iomap_base; 133 } tss32_t; 134 135 typedef struct __attribute__((packed)) { 136 u32 res1; 137 u64 rsp0; 138 u64 rsp1; 139 u64 rsp2; 140 u64 res2; 141 u64 ist1; 142 u64 ist2; 143 u64 ist3; 144 u64 ist4; 145 u64 ist5; 146 u64 ist6; 147 u64 ist7; 148 u64 res3; 149 u16 res4; 150 u16 iomap_base; 151 } tss64_t; 152 153 #define __ASM_TRY(prefix, catch) \ 154 "movl $0, %%gs:4\n\t" \ 155 ".pushsection .data.ex\n\t" \ 156 __ASM_SEL(.long, .quad) " 1111f, " catch "\n\t" \ 157 ".popsection \n\t" \ 158 prefix "\n\t" \ 159 "1111:" 160 161 #define ASM_TRY(catch) __ASM_TRY("", catch) 162 163 /* Forced emulation prefix, used to invoke the emulator unconditionally. */ 164 #define KVM_FEP "ud2; .byte 'k', 'v', 'm';" 165 #define ASM_TRY_FEP(catch) __ASM_TRY(KVM_FEP, catch) 166 167 static inline bool is_fep_available(void) 168 { 169 /* 170 * Use the non-FEP ASM_TRY() as KVM will inject a #UD on the prefix 171 * itself if forced emulation is not available. 172 */ 173 asm goto(ASM_TRY("%l[fep_unavailable]") 174 KVM_FEP "nop\n\t" 175 ::: "memory" : fep_unavailable); 176 return true; 177 fep_unavailable: 178 return false; 179 } 180 181 typedef struct { 182 unsigned short offset0; 183 unsigned short selector; 184 unsigned short ist : 3; 185 unsigned short : 5; 186 unsigned short type : 4; 187 unsigned short : 1; 188 unsigned short dpl : 2; 189 unsigned short p : 1; 190 unsigned short offset1; 191 #ifdef __x86_64__ 192 unsigned offset2; 193 unsigned reserved; 194 #endif 195 } idt_entry_t; 196 197 typedef struct { 198 uint16_t limit1; 199 uint16_t base1; 200 uint8_t base2; 201 union { 202 uint16_t type_limit_flags; /* Type and limit flags */ 203 struct { 204 uint16_t type:4; 205 uint16_t s:1; 206 uint16_t dpl:2; 207 uint16_t p:1; 208 uint16_t limit2:4; 209 uint16_t avl:1; 210 uint16_t l:1; 211 uint16_t db:1; 212 uint16_t g:1; 213 } __attribute__((__packed__)); 214 } __attribute__((__packed__)); 215 uint8_t base3; 216 } __attribute__((__packed__)) gdt_entry_t; 217 218 #ifdef __x86_64__ 219 struct system_desc64 { 220 gdt_entry_t common; 221 uint32_t base4; 222 uint32_t zero; 223 } __attribute__((__packed__)); 224 #endif 225 226 #define DESC_BUSY 2 227 228 extern idt_entry_t boot_idt[256]; 229 230 #ifndef __x86_64__ 231 extern tss32_t tss[]; 232 extern tss32_t tss_intr; 233 void set_gdt_task_gate(u16 tss_sel, u16 sel); 234 void set_idt_task_gate(int vec, u16 sel); 235 void set_intr_task_gate(int vec, void *fn); 236 void setup_tss32(void); 237 #else 238 extern tss64_t tss[]; 239 #endif 240 extern gdt_entry_t gdt[]; 241 242 unsigned exception_vector(void); 243 unsigned exception_error_code(void); 244 bool exception_rflags_rf(void); 245 void set_desc_entry(idt_entry_t *e, size_t e_sz, void *addr, 246 u16 sel, u16 type, u16 dpl); 247 void set_idt_entry(int vec, void *addr, int dpl); 248 void set_idt_sel(int vec, u16 sel); 249 void set_idt_dpl(int vec, u16 dpl); 250 void set_gdt_entry(int sel, unsigned long base, u32 limit, u8 access, u8 gran); 251 void set_gdt_entry_base(int sel, unsigned long base); 252 void clear_tss_busy(int sel); 253 void load_gdt_tss(size_t tss_offset); 254 void set_intr_alt_stack(int e, void *fn); 255 void print_current_tss_info(void); 256 handler handle_exception(u8 v, handler fn); 257 void unhandled_exception(struct ex_regs *regs, bool cpu); 258 const char* exception_mnemonic(int vector); 259 260 bool test_for_exception(unsigned int ex, void (*trigger_func)(void *data), 261 void *data); 262 void __set_exception_jmpbuf(jmp_buf *addr); 263 #define set_exception_jmpbuf(jmpbuf) \ 264 (setjmp(jmpbuf) ? : (__set_exception_jmpbuf(&(jmpbuf)), 0)) 265 266 static inline void *get_idt_addr(idt_entry_t *entry) 267 { 268 uintptr_t addr = entry->offset0 | ((u32)entry->offset1 << 16); 269 #ifdef __x86_64__ 270 addr |= (u64)entry->offset2 << 32; 271 #endif 272 return (void *)addr; 273 } 274 275 extern gdt_entry_t *get_gdt_entry(u16 sel); 276 extern gdt_entry_t *get_tss_descr(void); 277 gdt_entry_t *get_ldt_descr(void); 278 279 extern unsigned long get_gdt_entry_base(gdt_entry_t *entry); 280 extern unsigned long get_gdt_entry_limit(gdt_entry_t *entry); 281 282 #define __asm_safe(fep, insn, inputs...) \ 283 ({ \ 284 asm volatile(__ASM_TRY(fep, "1f") \ 285 insn "\n\t" \ 286 "1:\n\t" \ 287 : \ 288 : inputs \ 289 : "memory"); \ 290 exception_vector(); \ 291 }) 292 293 #define asm_safe(insn, inputs...) \ 294 __asm_safe("", insn, inputs) 295 296 #define asm_fep_safe(insn, inputs...) \ 297 __asm_safe_out1(KVM_FEP, insn,, inputs) 298 299 #define __asm_safe_out1(fep, insn, output, inputs...) \ 300 ({ \ 301 asm volatile(__ASM_TRY(fep, "1f") \ 302 insn "\n\t" \ 303 "1:\n\t" \ 304 : output \ 305 : inputs \ 306 : "memory"); \ 307 exception_vector(); \ 308 }) 309 310 #define asm_safe_out1(insn, output, inputs...) \ 311 __asm_safe_out1("", insn, output, inputs) 312 313 #define asm_fep_safe_out1(insn, output, inputs...) \ 314 __asm_safe_out1(KVM_FEP, insn, output, inputs) 315 316 #define __asm_safe_out2(fep, insn, output1, output2, inputs...) \ 317 ({ \ 318 asm volatile(__ASM_TRY(fep, "1f") \ 319 insn "\n\t" \ 320 "1:\n\t" \ 321 : output1, output2 \ 322 : inputs \ 323 : "memory"); \ 324 exception_vector(); \ 325 }) 326 327 #define asm_safe_out2(fep, insn, output1, output2, inputs...) \ 328 __asm_safe_out2("", insn, output1, output2, inputs) 329 330 #define asm_fep_safe_out2(insn, output1, output2, inputs...) \ 331 __asm_safe_out2(KVM_FEP, insn, output1, output2, inputs) 332 333 #define __asm_safe_report(want, insn, inputs...) \ 334 do { \ 335 int vector = asm_safe(insn, inputs); \ 336 \ 337 report(vector == want, "Expected %s on '%s', got %s", \ 338 want ? exception_mnemonic(want) : "SUCCESS", \ 339 insn, \ 340 vector ? exception_mnemonic(vector) : "SUCCESS"); \ 341 } while (0) 342 343 #define asm_safe_report(insn, inputs...) \ 344 __asm_safe_report(0, insn, inputs) 345 346 #define asm_safe_report_ex __asm_safe_report 347 348 349 #endif /* __ASSEMBLER__ */ 350 351 #endif /* _X86_DESC_H_ */ 352