xref: /kvm-unit-tests/lib/x86/desc.c (revision 23ba7b3911dc3b506e2d0b035c9ae247403d4771)
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