17d36db35SAvi Kivity #include "idt.h" 27d36db35SAvi Kivity #include "libcflat.h" 37d36db35SAvi Kivity 47d36db35SAvi Kivity typedef struct { 57d36db35SAvi Kivity unsigned short offset0; 67d36db35SAvi Kivity unsigned short selector; 77d36db35SAvi Kivity unsigned short ist : 3; 87d36db35SAvi Kivity unsigned short : 5; 97d36db35SAvi Kivity unsigned short type : 4; 107d36db35SAvi Kivity unsigned short : 1; 117d36db35SAvi Kivity unsigned short dpl : 2; 127d36db35SAvi Kivity unsigned short p : 1; 137d36db35SAvi Kivity unsigned short offset1; 147d36db35SAvi Kivity unsigned offset2; 157d36db35SAvi Kivity unsigned reserved; 167d36db35SAvi Kivity } idt_entry_t; 177d36db35SAvi Kivity 187d36db35SAvi Kivity static idt_entry_t idt[256]; 197d36db35SAvi Kivity 207d36db35SAvi Kivity typedef struct { 217d36db35SAvi Kivity unsigned short limit; 227d36db35SAvi Kivity unsigned long linear_addr; 237d36db35SAvi Kivity } __attribute__((packed)) descriptor_table_t; 247d36db35SAvi Kivity 257d36db35SAvi Kivity void lidt(idt_entry_t *idt, int nentries) 267d36db35SAvi Kivity { 277d36db35SAvi Kivity descriptor_table_t dt; 287d36db35SAvi Kivity 297d36db35SAvi Kivity dt.limit = nentries * sizeof(*idt) - 1; 307d36db35SAvi Kivity dt.linear_addr = (unsigned long)idt; 317d36db35SAvi Kivity asm volatile ("lidt %0" : : "m"(dt)); 327d36db35SAvi Kivity } 337d36db35SAvi Kivity 347d36db35SAvi Kivity unsigned short read_cs() 357d36db35SAvi Kivity { 367d36db35SAvi Kivity unsigned short r; 377d36db35SAvi Kivity 387d36db35SAvi Kivity asm volatile ("mov %%cs, %0" : "=r"(r)); 397d36db35SAvi Kivity return r; 407d36db35SAvi Kivity } 417d36db35SAvi Kivity 427d36db35SAvi Kivity void set_idt_entry(idt_entry_t *e, void *addr, int dpl) 437d36db35SAvi Kivity { 447d36db35SAvi Kivity memset(e, 0, sizeof *e); 457d36db35SAvi Kivity e->offset0 = (unsigned long)addr; 467d36db35SAvi Kivity e->selector = read_cs(); 477d36db35SAvi Kivity e->ist = 0; 487d36db35SAvi Kivity e->type = 14; 497d36db35SAvi Kivity e->dpl = dpl; 507d36db35SAvi Kivity e->p = 1; 517d36db35SAvi Kivity e->offset1 = (unsigned long)addr >> 16; 527d36db35SAvi Kivity e->offset2 = (unsigned long)addr >> 32; 537d36db35SAvi Kivity } 547d36db35SAvi Kivity 557d36db35SAvi Kivity struct ex_regs { 567d36db35SAvi Kivity unsigned long rax, rcx, rdx, rbx; 577d36db35SAvi Kivity unsigned long dummy, rbp, rsi, rdi; 587d36db35SAvi Kivity unsigned long r8, r9, r10, r11; 597d36db35SAvi Kivity unsigned long r12, r13, r14, r15; 607d36db35SAvi Kivity unsigned long vector; 617d36db35SAvi Kivity unsigned long error_code; 627d36db35SAvi Kivity unsigned long rip; 637d36db35SAvi Kivity unsigned long cs; 647d36db35SAvi Kivity unsigned long rflags; 657d36db35SAvi Kivity }; 667d36db35SAvi Kivity 677d36db35SAvi Kivity struct ex_record { 687d36db35SAvi Kivity unsigned long rip; 697d36db35SAvi Kivity unsigned long handler; 707d36db35SAvi Kivity }; 717d36db35SAvi Kivity 727d36db35SAvi Kivity extern struct ex_record exception_table_start, exception_table_end; 737d36db35SAvi Kivity 747d36db35SAvi Kivity void do_handle_exception(struct ex_regs *regs) 757d36db35SAvi Kivity { 767d36db35SAvi Kivity struct ex_record *ex; 777d36db35SAvi Kivity unsigned ex_val; 787d36db35SAvi Kivity 797d36db35SAvi Kivity ex_val = regs->vector | (regs->error_code << 16); 807d36db35SAvi Kivity 817d36db35SAvi Kivity asm("mov %0, %%gs:4" : : "r"(ex_val)); 827d36db35SAvi Kivity 837d36db35SAvi Kivity for (ex = &exception_table_start; ex != &exception_table_end; ++ex) { 847d36db35SAvi Kivity if (ex->rip == regs->rip) { 857d36db35SAvi Kivity regs->rip = ex->handler; 867d36db35SAvi Kivity return; 877d36db35SAvi Kivity } 887d36db35SAvi Kivity } 897d36db35SAvi Kivity printf("unhandled excecption\n"); 907d36db35SAvi Kivity exit(7); 917d36db35SAvi Kivity } 927d36db35SAvi Kivity 937d36db35SAvi Kivity asm (".pushsection .text \n\t" 947d36db35SAvi Kivity "ud_fault: \n\t" 957d36db35SAvi Kivity "pushq $0 \n\t" 967d36db35SAvi Kivity "pushq $6 \n\t" 977d36db35SAvi Kivity "jmp handle_exception \n\t" 987d36db35SAvi Kivity 997d36db35SAvi Kivity "gp_fault: \n\t" 1007d36db35SAvi Kivity "pushq $13 \n\t" 1017d36db35SAvi Kivity "jmp handle_exception \n\t" 1027d36db35SAvi Kivity 103*597e0ef2SAvi Kivity "de_fault: \n\t" 104*597e0ef2SAvi Kivity "pushq $0 \n\t" 105*597e0ef2SAvi Kivity "pushq $0 \n\t" 106*597e0ef2SAvi Kivity "jmp handle_exception \n\t" 107*597e0ef2SAvi Kivity 1087d36db35SAvi Kivity "handle_exception: \n\t" 1097d36db35SAvi Kivity "push %r15; push %r14; push %r13; push %r12 \n\t" 1107d36db35SAvi Kivity "push %r11; push %r10; push %r9; push %r8 \n\t" 1117d36db35SAvi Kivity "push %rdi; push %rsi; push %rbp; sub $8, %rsp \n\t" 1127d36db35SAvi Kivity "push %rbx; push %rdx; push %rcx; push %rax \n\t" 1137d36db35SAvi Kivity "mov %rsp, %rdi \n\t" 1147d36db35SAvi Kivity "call do_handle_exception \n\t" 1157d36db35SAvi Kivity "pop %rax; pop %rcx; pop %rdx; pop %rbx \n\t" 1167d36db35SAvi Kivity "add $8, %rsp; pop %rbp; pop %rsi; pop %rdi \n\t" 1177d36db35SAvi Kivity "pop %r8; pop %r9; pop %r10; pop %r11 \n\t" 1187d36db35SAvi Kivity "pop %r12; pop %r13; pop %r14; pop %r15 \n\t" 1197d36db35SAvi Kivity "add $16, %rsp \n\t" 1207d36db35SAvi Kivity "iretq \n\t" 1217d36db35SAvi Kivity ".popsection"); 1227d36db35SAvi Kivity 1237d36db35SAvi Kivity 1247d36db35SAvi Kivity void setup_idt(void) 1257d36db35SAvi Kivity { 126*597e0ef2SAvi Kivity extern char ud_fault, gp_fault, de_fault; 1277d36db35SAvi Kivity 1287d36db35SAvi Kivity lidt(idt, 256); 129*597e0ef2SAvi Kivity set_idt_entry(&idt[0], &de_fault, 0); 1307d36db35SAvi Kivity set_idt_entry(&idt[6], &ud_fault, 0); 1317d36db35SAvi Kivity set_idt_entry(&idt[13], &gp_fault, 0); 1327d36db35SAvi Kivity } 1337d36db35SAvi Kivity 1347d36db35SAvi Kivity unsigned exception_vector(void) 1357d36db35SAvi Kivity { 1367d36db35SAvi Kivity unsigned short vector; 1377d36db35SAvi Kivity 1387d36db35SAvi Kivity asm("mov %%gs:4, %0" : "=rm"(vector)); 1397d36db35SAvi Kivity return vector; 1407d36db35SAvi Kivity } 1417d36db35SAvi Kivity 1427d36db35SAvi Kivity unsigned exception_error_code(void) 1437d36db35SAvi Kivity { 1447d36db35SAvi Kivity unsigned short error_code; 1457d36db35SAvi Kivity 1467d36db35SAvi Kivity asm("mov %%gs:6, %0" : "=rm"(error_code)); 1477d36db35SAvi Kivity return error_code; 1487d36db35SAvi Kivity } 149