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