From: Gleb Natapov <[email protected]>

Provide easy way for test to hook its own exception handler.

Signed-off-by: Gleb Natapov <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>

diff --git a/lib/x86/desc.c b/lib/x86/desc.c
index aa0b4f4..0da8989 100644
--- a/lib/x86/desc.c
+++ b/lib/x86/desc.c
@@ -90,19 +90,6 @@ void set_idt_entry(int vec, void *addr, int dpl)
 #endif
 }
 
-struct ex_regs {
-    unsigned long rax, rcx, rdx, rbx;
-    unsigned long dummy, rbp, rsi, rdi;
-#ifdef __x86_64__
-    unsigned long r8, r9, r10, r11;
-    unsigned long r12, r13, r14, r15;
-#endif
-    unsigned long vector;
-    unsigned long error_code;
-    unsigned long rip;
-    unsigned long cs;
-    unsigned long rflags;
-};
 
 struct ex_record {
     unsigned long rip;
@@ -111,10 +98,7 @@ struct ex_record {
 
 extern struct ex_record exception_table_start, exception_table_end;
 
-#ifndef __x86_64__
-__attribute__((regparm(1)))
-#endif
-void do_handle_exception(struct ex_regs *regs)
+static void check_exception_table(struct ex_regs *regs)
 {
     struct ex_record *ex;
     unsigned ex_val;
@@ -129,10 +113,34 @@ void do_handle_exception(struct ex_regs *regs)
             return;
         }
     }
-    printf("unhandled excecption\n");
+    printf("unhandled excecption %d\n", regs->vector);
     exit(7);
 }
 
+static void (*exception_handlers[32])(struct ex_regs *regs);
+
+
+void handle_exception(u8 v, void (*func)(struct ex_regs *regs))
+{
+       if (v < 32)
+               exception_handlers[v] = func;
+}
+
+#ifndef __x86_64__
+__attribute__((regparm(1)))
+#endif
+void do_handle_exception(struct ex_regs *regs)
+{
+       if (regs->vector < 32 && exception_handlers[regs->vector]) {
+               exception_handlers[regs->vector](regs);
+               return;
+       }
+       printf("unhandled cpu excecption %d\n", regs->vector);
+       if (regs->vector == 14)
+               printf("PF at %p addr %p\n", regs->rip, read_cr2());
+       exit(7);
+}
+
 #ifdef __x86_64__
 #  define R "r"
 #  define W "q"
@@ -143,22 +151,42 @@ void do_handle_exception(struct ex_regs *regs)
 #  define S "4"
 #endif
 
-asm (".pushsection .text \n\t"
-     "ud_fault: \n\t"
-     "push"W" $0 \n\t"
-     "push"W" $6 \n\t"
-     "jmp handle_exception \n\t"
-
-     "gp_fault: \n\t"
-     "push"W" $13 \n\t"
-     "jmp handle_exception \n\t"
-
-     "de_fault: \n\t"
-     "push"W" $0 \n\t"
-     "push"W" $0 \n\t"
-     "jmp handle_exception \n\t"
+#define EX(NAME, N) extern char NAME##_fault;  \
+       asm (".pushsection .text \n\t"          \
+            #NAME"_fault: \n\t"                \
+            "push"W" $0 \n\t"                  \
+            "push"W" $"#N" \n\t"               \
+            "jmp __handle_exception \n\t"      \
+            ".popsection")
+
+#define EX_E(NAME, N) extern char NAME##_fault;        \
+       asm (".pushsection .text \n\t"          \
+            #NAME"_fault: \n\t"                \
+            "push"W" $"#N" \n\t"               \
+            "jmp __handle_exception \n\t"      \
+            ".popsection")
+
+EX(de, 0);
+EX(db, 1);
+EX(nmi, 2);
+EX(bp, 3);
+EX(of, 4);
+EX(br, 5);
+EX(ud, 6);
+EX(nm, 7);
+EX_E(df, 8);
+EX_E(ts, 10);
+EX_E(np, 11);
+EX_E(ss, 12);
+EX_E(gp, 13);
+EX_E(pf, 14);
+EX(mf, 16);
+EX_E(ac, 17);
+EX(mc, 18);
+EX(xm, 19);
 
-     "handle_exception: \n\t"
+asm (".pushsection .text \n\t"
+     "__handle_exception: \n\t"
 #ifdef __x86_64__
      "push %r15; push %r14; push %r13; push %r12 \n\t"
      "push %r11; push %r10; push %r9; push %r8 \n\t"
@@ -182,15 +210,37 @@ asm (".pushsection .text \n\t"
      "iret"W" \n\t"
      ".popsection");
 
+static void *idt_handlers[32] = {
+       [0] = &de_fault,
+       [1] = &db_fault,
+       [2] = &nmi_fault,
+       [3] = &bp_fault,
+       [4] = &of_fault,
+       [5] = &br_fault,
+       [6] = &ud_fault,
+       [7] = &nm_fault,
+       [8] = &df_fault,
+       [10] = &ts_fault,
+       [11] = &np_fault,
+       [12] = &ss_fault,
+       [13] = &gp_fault,
+       [14] = &pf_fault,
+       [16] = &mf_fault,
+       [17] = &ac_fault,
+       [18] = &mc_fault,
+       [19] = &xm_fault,
+};
 
 void setup_idt(void)
 {
-    extern char ud_fault, gp_fault, de_fault;
-
+    int i;
     load_lidt(idt, 256);
-    set_idt_entry(0, &de_fault, 0);
-    set_idt_entry(6, &ud_fault, 0);
-    set_idt_entry(13, &gp_fault, 0);
+    for (i = 0; i < 32; i++)
+           if (idt_handlers[i])
+                   set_idt_entry(i, idt_handlers[i], 0);
+    handle_exception(0, check_exception_table);
+    handle_exception(6, check_exception_table);
+    handle_exception(13, check_exception_table);
 }
 
 unsigned exception_vector(void)
diff --git a/lib/x86/desc.h b/lib/x86/desc.h
index 2c9db5b..073878d 100644
--- a/lib/x86/desc.h
+++ b/lib/x86/desc.h
@@ -10,6 +10,20 @@ static inline void setup_gdt(void){}
 static inline void setup_tss32(void){}
 #endif
 
+struct ex_regs {
+    unsigned long rax, rcx, rdx, rbx;
+    unsigned long dummy, rbp, rsi, rdi;
+#ifdef __x86_64__
+    unsigned long r8, r9, r10, r11;
+    unsigned long r12, r13, r14, r15;
+#endif
+    unsigned long vector;
+    unsigned long error_code;
+    unsigned long rip;
+    unsigned long cs;
+    unsigned long rflags;
+};
+
 #define ASM_TRY(catch)                                  \
     "movl $0, %%gs:4 \n\t"                              \
     ".pushsection .data.ex \n\t"                        \
@@ -29,5 +43,6 @@ void set_idt_entry(int vec, void *addr, int dpl);
 void set_gdt_entry(int num, u32 base,  u32 limit, u8 access, u8 gran);
 void set_intr_task_gate(int e, void *fn);
 void print_current_tss_info(void);
+void handle_exception(u8 v, void (*func)(struct ex_regs *regs));
 
 #endif
--
To unsubscribe from this list: send the line "unsubscribe kvm-commits" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to