From: Andrew Cooper Date: Thu, 1 Jun 2017 11:13:22 +0000 (+0100) Subject: Don't automatically recover from traps X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=e8e2cf8f9b2862cef7111a66c52aa2f83a3c541d;p=people%2Fandrewcoop%2Fxen-test-framework.git Don't automatically recover from traps While this property is useful for swint-emulation, it is unhelpful in other situations, as it causes unexpected traps to get swallowed silently. Reuse the existing extable logic (with fault == fixup) to recover, and introduce _ASM_TRAP_OK() to introduce such an extable entry. Adjust the swint-emulation and selftest logic following this behaviour change, which removes the test_int3_breakpoint() case entirely. Signed-off-by: Andrew Cooper --- diff --git a/arch/x86/traps.c b/arch/x86/traps.c index f755d56..5804e08 100644 --- a/arch/x86/traps.c +++ b/arch/x86/traps.c @@ -8,53 +8,6 @@ bool (*xtf_unhandled_exception_hook)(struct cpu_regs *regs); -/* - * Evaluate whether this exception is a trap or an interrupt. i.e. whether it - * save to just return at the current %eip, or whether further action is - * required to resolve the source of the exception. - */ -static bool is_trap_or_interrupt(const struct cpu_regs *regs) -{ - /* All non-reserved vectors are interrupts. */ - if ( regs->entry_vector >= X86_NR_RESERVED_VECTORS ) - return true; - - uint32_t vec_bit = 1u << regs->entry_vector; - - if ( vec_bit & (X86_EXC_TRAPS | X86_EXC_INTERRUPTS) ) - return true; - - /* Architectural faults and aborts all need further action. */ - if ( vec_bit & (X86_EXC_FAULTS | X86_EXC_ABORTS) ) - return false; - - /* - * The Debug Exception is awkward, and either a trap or a fault depending - * on other conditions. - */ - unsigned long dr6 = read_dr6(); - - /* General Detect is a fault. */ - if ( dr6 & X86_DR6_BD ) - return false; - - /* Instruction breakpoints are faults. */ - if ( dr6 & (X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3) ) - { - unsigned long dr7 = read_dr7(), bp; - - for ( bp = 0; bp < 4; ++bp ) - { - if ( (dr6 & (1u << bp)) && /* Breakpoint triggered? */ - ((dr7 & (3u << (bp + 16))) == 0) ) /* Instruction breakpoint? */ - return false; - } - } - - /* All other debug conditions are traps. */ - return true; -} - /* * C entry-point for exceptions, after the per-environment stubs have suitably * adjusted the stack. @@ -62,7 +15,7 @@ static bool is_trap_or_interrupt(const struct cpu_regs *regs) void do_exception(struct cpu_regs *regs) { const struct extable_entry *ex; - bool safe = is_trap_or_interrupt(regs); + bool safe = false; xtf_exlog_log_exception(regs); diff --git a/include/xtf/extable.h b/include/xtf/extable.h index daedd9e..23bfcc1 100644 --- a/include/xtf/extable.h +++ b/include/xtf/extable.h @@ -49,6 +49,12 @@ */ #define _ASM_EXTABLE(fault, fixup) _ASM_EXTABLE_HANDLER(fault, fixup, 0) +/** + * Create an exception table entry, whitelisting a trap as being ok at @param + * loc. (ab)uses the fault fixup logic to fixup to its current position. + */ +#define _ASM_TRAP_OK(loc) _ASM_EXTABLE(loc, loc) + #ifndef __ASSEMBLY__ struct cpu_regs; diff --git a/tests/selftest/main.c b/tests/selftest/main.c index 402c3e3..322b357 100644 --- a/tests/selftest/main.c +++ b/tests/selftest/main.c @@ -18,16 +18,6 @@ const char test_title[] = "XTF Selftests"; -static void test_int3_breakpoint(void) -{ - printk("Test: int3 breakpoint\n"); - - /* - * Check that a breakpoint returns normally from the trap handler. - */ - asm volatile ("int3"); -} - static void test_extable(void) { printk("Test: Exception Table\n"); @@ -82,7 +72,8 @@ static bool check_exlog_entry(unsigned int entry, unsigned int cs, static void test_exlog(void) { - extern unsigned long label_test_exlog_int3[], label_test_exlog_ud2a[]; + extern unsigned long exlog_int3[] asm(".Lexlog_int3"); + extern unsigned long exlog_ud2a[] asm(".Lexlog_ud2a"); printk("Test: Exception Logging\n"); @@ -92,19 +83,20 @@ static void test_exlog(void) if ( !check_nr_entries(0) ) goto out; - asm volatile ("int3; label_test_exlog_int3:"); + asm volatile ("int3; .Lexlog_int3:" + _ASM_TRAP_OK(.Lexlog_int3)); /* Check that one entry has now been logged. */ if ( !check_nr_entries(1) || - !check_exlog_entry(0, __KERN_CS, _u(label_test_exlog_int3), X86_EXC_BP, 0) ) + !check_exlog_entry(0, __KERN_CS, _u(exlog_int3), X86_EXC_BP, 0) ) goto out; - asm volatile ("label_test_exlog_ud2a: ud2a; 1:" - _ASM_EXTABLE(label_test_exlog_ud2a, 1b)); + asm volatile (".Lexlog_ud2a: ud2a; 1:" + _ASM_EXTABLE(.Lexlog_ud2a, 1b)); /* Check that two entries have now been logged. */ if ( !check_nr_entries(2) || - !check_exlog_entry(1, __KERN_CS, _u(label_test_exlog_ud2a), X86_EXC_UD, 0) ) + !check_exlog_entry(1, __KERN_CS, _u(exlog_ud2a), X86_EXC_UD, 0) ) goto out; xtf_exlog_reset(); @@ -113,7 +105,8 @@ static void test_exlog(void) if ( !check_nr_entries(0) ) goto out; - asm volatile ("int3"); + asm volatile ("int3; 1:" + _ASM_TRAP_OK(1b)); /* Check that one entry now exists. */ if ( !check_nr_entries(1) ) @@ -125,7 +118,8 @@ static void test_exlog(void) if ( !check_nr_entries(1) ) goto out; - asm volatile ("int3"); + asm volatile ("int3; 1:" + _ASM_TRAP_OK(1b)); /* Check that the previous breakpoint wasn't logged. */ if ( !check_nr_entries(1) ) @@ -319,7 +313,6 @@ void test_main(void) write_cr4(cr4); } - test_int3_breakpoint(); test_extable(); test_exlog(); test_exec_user(); diff --git a/tests/swint-emulation/lowlevel.S b/tests/swint-emulation/lowlevel.S index 7995764..236ac52 100644 --- a/tests/swint-emulation/lowlevel.S +++ b/tests/swint-emulation/lowlevel.S @@ -70,6 +70,8 @@ GLOBAL(label_\insn\()_\type\()_trap) /* Fixup from fault label to trap label. */ _ASM_EXTABLE(label_\insn\()_\type\()_fault, label_\insn\()_\type\()_trap) + /* Mark traps as ok. */ + _ASM_TRAP_OK(label_\insn\()_\type\()_trap) ENDFUNC(stub_\insn\()_\type) .endm