17d36db35SAvi Kivity #include "idt.h" 27d36db35SAvi Kivity #include "libcflat.h" 3*23ba7b39SGleb Natapov #include "processor.h" 47d36db35SAvi Kivity 57d36db35SAvi Kivity typedef struct { 67d36db35SAvi Kivity unsigned short offset0; 77d36db35SAvi Kivity unsigned short selector; 87d36db35SAvi Kivity unsigned short ist : 3; 97d36db35SAvi Kivity unsigned short : 5; 107d36db35SAvi Kivity unsigned short type : 4; 117d36db35SAvi Kivity unsigned short : 1; 127d36db35SAvi Kivity unsigned short dpl : 2; 137d36db35SAvi Kivity unsigned short p : 1; 147d36db35SAvi Kivity unsigned short offset1; 15*23ba7b39SGleb Natapov #ifdef __x86_64__ 167d36db35SAvi Kivity unsigned offset2; 177d36db35SAvi Kivity unsigned reserved; 18*23ba7b39SGleb Natapov #endif 197d36db35SAvi Kivity } idt_entry_t; 207d36db35SAvi Kivity 217d36db35SAvi Kivity static idt_entry_t idt[256]; 227d36db35SAvi Kivity 23*23ba7b39SGleb Natapov void load_lidt(idt_entry_t *idt, int nentries) 247d36db35SAvi Kivity { 25*23ba7b39SGleb Natapov struct descriptor_table_ptr dt; 267d36db35SAvi Kivity 277d36db35SAvi Kivity dt.limit = nentries * sizeof(*idt) - 1; 28*23ba7b39SGleb Natapov dt.base = (unsigned long)idt; 29*23ba7b39SGleb Natapov lidt(&dt); 307d36db35SAvi Kivity asm volatile ("lidt %0" : : "m"(dt)); 317d36db35SAvi Kivity } 327d36db35SAvi Kivity 33*23ba7b39SGleb Natapov void set_idt_entry(int vec, void *addr, int dpl) 347d36db35SAvi Kivity { 35*23ba7b39SGleb Natapov idt_entry_t *e = &idt[vec]; 367d36db35SAvi Kivity memset(e, 0, sizeof *e); 377d36db35SAvi Kivity e->offset0 = (unsigned long)addr; 387d36db35SAvi Kivity e->selector = read_cs(); 397d36db35SAvi Kivity e->ist = 0; 407d36db35SAvi Kivity e->type = 14; 417d36db35SAvi Kivity e->dpl = dpl; 427d36db35SAvi Kivity e->p = 1; 437d36db35SAvi Kivity e->offset1 = (unsigned long)addr >> 16; 44*23ba7b39SGleb Natapov #ifdef __x86_64__ 457d36db35SAvi Kivity e->offset2 = (unsigned long)addr >> 32; 46*23ba7b39SGleb Natapov #endif 477d36db35SAvi Kivity } 487d36db35SAvi Kivity 497d36db35SAvi Kivity struct ex_regs { 507d36db35SAvi Kivity unsigned long rax, rcx, rdx, rbx; 517d36db35SAvi Kivity unsigned long dummy, rbp, rsi, rdi; 52*23ba7b39SGleb Natapov #ifdef __x86_64__ 537d36db35SAvi Kivity unsigned long r8, r9, r10, r11; 547d36db35SAvi Kivity unsigned long r12, r13, r14, r15; 55*23ba7b39SGleb Natapov #endif 567d36db35SAvi Kivity unsigned long vector; 577d36db35SAvi Kivity unsigned long error_code; 587d36db35SAvi Kivity unsigned long rip; 597d36db35SAvi Kivity unsigned long cs; 607d36db35SAvi Kivity unsigned long rflags; 617d36db35SAvi Kivity }; 627d36db35SAvi Kivity 637d36db35SAvi Kivity struct ex_record { 647d36db35SAvi Kivity unsigned long rip; 657d36db35SAvi Kivity unsigned long handler; 667d36db35SAvi Kivity }; 677d36db35SAvi Kivity 687d36db35SAvi Kivity extern struct ex_record exception_table_start, exception_table_end; 697d36db35SAvi Kivity 707d36db35SAvi Kivity void do_handle_exception(struct ex_regs *regs) 717d36db35SAvi Kivity { 727d36db35SAvi Kivity struct ex_record *ex; 737d36db35SAvi Kivity unsigned ex_val; 747d36db35SAvi Kivity 757d36db35SAvi Kivity ex_val = regs->vector | (regs->error_code << 16); 767d36db35SAvi Kivity 777d36db35SAvi Kivity asm("mov %0, %%gs:4" : : "r"(ex_val)); 787d36db35SAvi Kivity 797d36db35SAvi Kivity for (ex = &exception_table_start; ex != &exception_table_end; ++ex) { 807d36db35SAvi Kivity if (ex->rip == regs->rip) { 817d36db35SAvi Kivity regs->rip = ex->handler; 827d36db35SAvi Kivity return; 837d36db35SAvi Kivity } 847d36db35SAvi Kivity } 857d36db35SAvi Kivity printf("unhandled excecption\n"); 867d36db35SAvi Kivity exit(7); 877d36db35SAvi Kivity } 887d36db35SAvi Kivity 89*23ba7b39SGleb Natapov #ifdef __x86_64__ 90*23ba7b39SGleb Natapov # define R "r" 91*23ba7b39SGleb Natapov # define W "q" 92*23ba7b39SGleb Natapov # define S "8" 93*23ba7b39SGleb Natapov #else 94*23ba7b39SGleb Natapov # define R "e" 95*23ba7b39SGleb Natapov # define W "l" 96*23ba7b39SGleb Natapov # define S "4" 97*23ba7b39SGleb Natapov #endif 98*23ba7b39SGleb Natapov 997d36db35SAvi Kivity asm (".pushsection .text \n\t" 1007d36db35SAvi Kivity "ud_fault: \n\t" 101*23ba7b39SGleb Natapov "push"W" $0 \n\t" 102*23ba7b39SGleb Natapov "push"W" $6 \n\t" 1037d36db35SAvi Kivity "jmp handle_exception \n\t" 1047d36db35SAvi Kivity 1057d36db35SAvi Kivity "gp_fault: \n\t" 106*23ba7b39SGleb Natapov "push"W" $13 \n\t" 1077d36db35SAvi Kivity "jmp handle_exception \n\t" 1087d36db35SAvi Kivity 109597e0ef2SAvi Kivity "de_fault: \n\t" 110*23ba7b39SGleb Natapov "push"W" $0 \n\t" 111*23ba7b39SGleb Natapov "push"W" $0 \n\t" 112597e0ef2SAvi Kivity "jmp handle_exception \n\t" 113597e0ef2SAvi Kivity 1147d36db35SAvi Kivity "handle_exception: \n\t" 115*23ba7b39SGleb Natapov #ifdef __x86_64__ 1167d36db35SAvi Kivity "push %r15; push %r14; push %r13; push %r12 \n\t" 1177d36db35SAvi Kivity "push %r11; push %r10; push %r9; push %r8 \n\t" 118*23ba7b39SGleb Natapov #endif 119*23ba7b39SGleb Natapov "push %"R"di; push %"R"si; push %"R"bp; sub $"S", %"R"sp \n\t" 120*23ba7b39SGleb Natapov "push %"R"bx; push %"R"dx; push %"R"cx; push %"R"ax \n\t" 121*23ba7b39SGleb Natapov "mov %"R"sp, %"R"di \n\t" 1227d36db35SAvi Kivity "call do_handle_exception \n\t" 123*23ba7b39SGleb Natapov "pop %"R"ax; pop %"R"cx; pop %"R"dx; pop %"R"bx \n\t" 124*23ba7b39SGleb Natapov "add $"S", %"R"sp; pop %"R"bp; pop %"R"si; pop %"R"di \n\t" 125*23ba7b39SGleb Natapov #ifdef __x86_64__ 1267d36db35SAvi Kivity "pop %r8; pop %r9; pop %r10; pop %r11 \n\t" 1277d36db35SAvi Kivity "pop %r12; pop %r13; pop %r14; pop %r15 \n\t" 128*23ba7b39SGleb Natapov #endif 129*23ba7b39SGleb Natapov "add $"S", %"R"sp \n\t" 130*23ba7b39SGleb Natapov "add $"S", %"R"sp \n\t" 131*23ba7b39SGleb Natapov "iret"W" \n\t" 1327d36db35SAvi Kivity ".popsection"); 1337d36db35SAvi Kivity 1347d36db35SAvi Kivity 1357d36db35SAvi Kivity void setup_idt(void) 1367d36db35SAvi Kivity { 137597e0ef2SAvi Kivity extern char ud_fault, gp_fault, de_fault; 1387d36db35SAvi Kivity 139*23ba7b39SGleb Natapov load_lidt(idt, 256); 140*23ba7b39SGleb Natapov set_idt_entry(0, &de_fault, 0); 141*23ba7b39SGleb Natapov set_idt_entry(6, &ud_fault, 0); 142*23ba7b39SGleb Natapov set_idt_entry(13, &gp_fault, 0); 1437d36db35SAvi Kivity } 1447d36db35SAvi Kivity 1457d36db35SAvi Kivity unsigned exception_vector(void) 1467d36db35SAvi Kivity { 1477d36db35SAvi Kivity unsigned short vector; 1487d36db35SAvi Kivity 1497d36db35SAvi Kivity asm("mov %%gs:4, %0" : "=rm"(vector)); 1507d36db35SAvi Kivity return vector; 1517d36db35SAvi Kivity } 1527d36db35SAvi Kivity 1537d36db35SAvi Kivity unsigned exception_error_code(void) 1547d36db35SAvi Kivity { 1557d36db35SAvi Kivity unsigned short error_code; 1567d36db35SAvi Kivity 1577d36db35SAvi Kivity asm("mov %%gs:6, %0" : "=rm"(error_code)); 1587d36db35SAvi Kivity return error_code; 1597d36db35SAvi Kivity } 160