]> xenbits.xensource.com Git - people/royger/xen-test-framework.git/commitdiff
Exception table infrastructure
authorAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 16 Dec 2015 19:04:03 +0000 (19:04 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Tue, 22 Dec 2015 20:47:28 +0000 (20:47 +0000)
To redirect control flow if a fault occurs.  Entries are registered with the
_ASM_EXTABLE() and placed in the .ex_table section, which is collected
together by the linker.

The .ex_table section is sorted on boot (to facilitate fast searching), and
searched in do_exception() when a fault or abort is encountered.  If a
matching entry is found, control flow is redirected and the exception returned
from.

Some of the changes are to make the two asm_macros.h files safe to include in
C code.  In addition, an extra selftest is added, making use of the exception
table infrastructure.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
arch/x86/link.lds.S
arch/x86/setup.c
arch/x86/traps.c
build/files.mk
common/extable.c [new file with mode: 0644]
include/arch/x86/asm_macros.h
include/xtf/asm_macros.h
include/xtf/extable.h [new file with mode: 0644]
include/xtf/traps.h
tests/selftest/main.c

index 4ad6864092e1c525517eef0230bf24a2b26427b5..75324f51a294702872b4eb8b8d805757ec95ff01 100644 (file)
@@ -40,6 +40,11 @@ SECTIONS
         .rodata : {
                 *(.rodata)
                 *(.rodata.*)
+
+       . = ALIGN(8);
+       __start_ex_table = .;
+                *(.ex_table)
+        __stop_ex_table = .;
         }
 
         .note : {
index 773bcd9ba6b6825222031df1bca8739965d7f7a3..3cd40c6823f092f1a63b7b04f9f2ff3d048cac31 100644 (file)
@@ -1,6 +1,7 @@
 #include <xtf/lib.h>
 #include <xtf/console.h>
 #include <xtf/hypercall.h>
+#include <xtf/extable.h>
 
 #include <arch/x86/desc.h>
 #include <arch/x86/mm.h>
@@ -121,6 +122,8 @@ void arch_setup(void)
 
     init_hypercalls();
 
+    sort_extable();
+
     setup_pv_console();
 }
 
index 61a2cd2308f9833d264d17d8b21171a07feb31fa..c28becbf034e4e10f88b0f647b6e1d79b68a8acd 100644 (file)
@@ -56,8 +56,16 @@ static bool is_trap_or_interrupt(const struct cpu_regs *regs)
  */
 void do_exception(struct cpu_regs *regs)
 {
+    unsigned long fixup_addr;
     bool safe = is_trap_or_interrupt(regs);
 
+    /* Look in the exception table to see if a redirection has been set up. */
+    if ( !safe && (fixup_addr = search_extable(regs->ip)) )
+    {
+        regs->ip = fixup_addr;
+        safe = true;
+    }
+
     if ( !safe )
         panic("Unhandled exception: vec %u at %04x:%p\n",
               regs->entry_vector, regs->cs, _p(regs->ip));
index 6d93772ed383170106f6be2098bc3c874cde58fd..28fea2b50c153144408f71b3739cc7d74f6f1eeb 100644 (file)
@@ -5,6 +5,7 @@
 # obj-$(env)   are objects unique to a specific environment
 
 obj-perarch += $(ROOT)/common/console.o
+obj-perarch += $(ROOT)/common/extable.o
 obj-perarch += $(ROOT)/common/heapsort.o
 obj-perarch += $(ROOT)/common/lib.o
 obj-perarch += $(ROOT)/common/libc/string.o
diff --git a/common/extable.c b/common/extable.c
new file mode 100644 (file)
index 0000000..d5b47c9
--- /dev/null
@@ -0,0 +1,65 @@
+#include <xtf/lib.h>
+#include <xtf/extable.h>
+
+struct extable_entry
+{
+    unsigned long fault;
+    unsigned long cont;
+};
+
+extern struct extable_entry __start_ex_table[], __stop_ex_table[];
+
+unsigned long search_extable(unsigned long addr)
+{
+    const struct extable_entry *start = __start_ex_table,
+        *stop = __stop_ex_table, *mid;
+
+    while ( start <= stop )
+    {
+        mid = start + (stop - start) / 2;
+
+        if ( addr == mid->fault )
+            return mid->cont;
+        else if ( addr > mid->fault )
+            start = mid + 1;
+        else
+            stop = mid - 1;
+    }
+
+    return 0;
+}
+
+static int compare_extable_entry(const void *_l, const void *_r)
+{
+    const struct extable_entry *l = _l, *r = _r;
+
+    return l->fault - r->fault;
+}
+
+static void swap_extable_entry(void *_l, void *_r)
+{
+    struct extable_entry tmp, *l = _l, *r = _r;
+
+    tmp = *l;
+    *l = *r;
+    *r = tmp;
+}
+
+void sort_extable(void)
+{
+    heapsort(__start_ex_table,
+             __stop_ex_table - __start_ex_table,
+             sizeof(__start_ex_table[0]),
+             compare_extable_entry,
+             swap_extable_entry);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
index f0da23d53fe6c6a34f5e574bca4e0e46e16abcfa..f436a9ab788cc73550952f5d20e867c613984f9c 100644 (file)
@@ -6,15 +6,23 @@
 #ifndef XTF_X86_ASM_MACROS_H
 #define XTF_X86_ASM_MACROS_H
 
+#ifdef __ASSEMBLY__
 /* Declare data at the architectures width. */
-#if defined(__x86_64__)
-# define _WORD .quad
-#elif defined(__i386__)
-# define _WORD .long
+# if defined(__x86_64__)
+#  define _WORD .quad
+# elif defined(__i386__)
+#  define _WORD .long
+# endif
 #else
-# error Bad architecture for _WORD
+# if defined(__x86_64__)
+#  define _WORD ".quad "
+# elif defined(__i386__)
+#  define _WORD ".long "
+# endif
 #endif
 
+#ifdef __ASSEMBLY__
+
 .macro SAVE_ALL
     cld
 #if defined(__x86_64__)
@@ -76,6 +84,8 @@
 #endif
 .endm
 
+#endif /* __ASSEMBLY__ */
+
 #endif /* XTF_X86_ASM_MACROS_H */
 
 /*
index 96a5fecd0c9f606ac6031e337943d57a7dcb2848..ace31687c810340a1c0cd8b47d117a21f4b4754d 100644 (file)
@@ -10,6 +10,8 @@
 
 #include <arch/x86/asm_macros.h>
 
+#ifdef __ASSEMBLY__
+
 /**
  * Declare a global symbol.
  * @param name Symbol name.
@@ -60,6 +62,8 @@ name:
 4:.align 4                                        ; \
     .popsection
 
+#endif /* __ASSEMBLY__ */
+
 #endif /* XTF_ASM_MACROS_H */
 
 /*
diff --git a/include/xtf/extable.h b/include/xtf/extable.h
new file mode 100644 (file)
index 0000000..3fe6658
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef XTF_EXTABLE_H
+#define XTF_EXTABLE_H
+
+#include <xtf/types.h>
+#include <xtf/asm_macros.h>
+
+#ifdef __ASSEMBLY__
+
+/* Exception Table entry for asm code. */
+#define _ASM_EXTABLE(fault, fixup)              \
+    .pushsection .ex_table, "a";                \
+    _WORD fault, fixup;                         \
+    .popsection
+
+#else
+
+/* Exception Table entry for C inline assembly. */
+#define _ASM_EXTABLE(fault, fixup)              \
+    ".pushsection .ex_table, \"a\";\n"          \
+    _WORD #fault ", " #fixup ";\n"              \
+    ".popsection;\n"
+
+/*
+ * Sort the exception table.  Required to be called once on boot to make
+ * searching efficient.
+ */
+void sort_extable(void);
+
+/*
+ * Search the exception table to see whether an entry has been registered for
+ * the provided fault address.  If so, returns the fixup address.  If not,
+ * returns zero.
+ */
+unsigned long search_extable(unsigned long fault_addr);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* XTF_EXTABLE_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
index 38108b86c03b4c9f4ce3f0b0aab3701bc74f93b1..7f3ba30830643afc19692c027006a807255e7c19 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef XTF_TRAPS_H
 #define XTF_TRAPS_H
 
+#include <xtf/extable.h>
+
 #include <arch/x86/traps.h>
 
 #endif /* XTF_TRAPS_H */
index d8f5a964b4f4566c2da4b74b76ea6503c597031f..fed4c22add3841a8f20948f51298e0b6d99f8f09 100644 (file)
@@ -14,11 +14,24 @@ static void test_int3_breakpoint(void)
     asm volatile ("int3");
 }
 
+static void test_extable(void)
+{
+    printk("Test: Exception Table\n");
+
+    /*
+     * Check that control flow is successfully redirected with a ud2a
+     * instruction and appropriate extable entry.
+     */
+    asm volatile ("1: ud2a; 2:"
+                  _ASM_EXTABLE(1b, 2b));
+}
+
 void test_main(void)
 {
     printk("XTF Selftests\n");
 
     test_int3_breakpoint();
+    test_extable();
 
     xtf_success();
 }