.rodata : {
*(.rodata)
*(.rodata.*)
+
+ . = ALIGN(8);
+ __start_ex_table = .;
+ *(.ex_table)
+ __stop_ex_table = .;
}
.note : {
#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>
init_hypercalls();
+ sort_extable();
+
setup_pv_console();
}
*/
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));
# 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
--- /dev/null
+#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:
+ */
#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__)
#endif
.endm
+#endif /* __ASSEMBLY__ */
+
#endif /* XTF_X86_ASM_MACROS_H */
/*
#include <arch/x86/asm_macros.h>
+#ifdef __ASSEMBLY__
+
/**
* Declare a global symbol.
* @param name Symbol name.
4:.align 4 ; \
.popsection
+#endif /* __ASSEMBLY__ */
+
#endif /* XTF_ASM_MACROS_H */
/*
--- /dev/null
+#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:
+ */
#ifndef XTF_TRAPS_H
#define XTF_TRAPS_H
+#include <xtf/extable.h>
+
#include <arch/x86/traps.h>
#endif /* XTF_TRAPS_H */
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();
}