1 #ifndef _X86_DESC_H_ 2 #define _X86_DESC_H_ 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