From 7c575dc9c353dcf0fc85e331b6a3fb8d8ca4a2d0 Mon Sep 17 00:00:00 2001 From: Andrew Cooper Date: Thu, 16 May 2019 18:12:33 +0000 Subject: [PATCH] Simplify the unhandled_exception handling for tests Tests, being single-purpose by their very nature, don't in practice use the flexibility to change the unhandled exception hook. Furthermore, updating the pointer has to be done carefully (i.e. with compiler barriers) because the compiler doesn't see any connection between the hook and surrounding code which may fault. Switch to the using method already used by the syscall infrastructure and use a single weak do_unhandled_exception() function which may be overridden by guests wanting to implement their own custom behaviour. Signed-off-by: Andrew Cooper --- arch/x86/traps.c | 16 ++++++++-------- include/xtf/traps.h | 7 ++----- tests/nmi-taskswitch-priv/main.c | 3 +-- tests/selftest/main.c | 8 ++------ tests/swint-emulation/main.c | 4 +--- 5 files changed, 14 insertions(+), 24 deletions(-) diff --git a/arch/x86/traps.c b/arch/x86/traps.c index b0a1f9b..2fe0066 100644 --- a/arch/x86/traps.c +++ b/arch/x86/traps.c @@ -16,8 +16,6 @@ unsigned long exec_user_efl_and_mask = ~(IS_DEFINED(CONFIG_PV) ? X86_EFLAGS_IF : 0); unsigned long exec_user_efl_or_mask; -bool (*xtf_unhandled_exception_hook)(struct cpu_regs *regs); - /* * C entry-point for exceptions, after the per-environment stubs have suitably * adjusted the stack. @@ -41,12 +39,9 @@ void do_exception(struct cpu_regs *regs) } } - /* - * If the test has installed an unhandled exception hook, call it in the - * hope that it can resolve the exception. - */ - if ( !safe && xtf_unhandled_exception_hook ) - safe = xtf_unhandled_exception_hook(regs); + /* Try the unhandled_exception() hook. */ + if ( !safe ) + safe = do_unhandled_exception(regs); /* Still unresolved? Give up and panic() with some relevent information. */ if ( !safe ) @@ -68,6 +63,11 @@ void do_exception(struct cpu_regs *regs) } } +bool __weak do_unhandled_exception(struct cpu_regs *regs) +{ + return false; +} + void __weak do_syscall(struct cpu_regs *regs) { panic("Unhandled syscall\n"); diff --git a/include/xtf/traps.h b/include/xtf/traps.h index 6deb496..8fc66af 100644 --- a/include/xtf/traps.h +++ b/include/xtf/traps.h @@ -7,12 +7,9 @@ #include /** - * Function pointer to allow tests to install an unhandled exception hook. - * - * Must only return true if action has been taken resolve the exception. - * i.e. that it is now safe to iret back. If not, a panic() will occur. + * May be implemented by a guest to provide custom exception handling. */ -extern bool (*xtf_unhandled_exception_hook)(struct cpu_regs *regs); +bool do_unhandled_exception(struct cpu_regs *regs); #endif /* XTF_TRAPS_H */ diff --git a/tests/nmi-taskswitch-priv/main.c b/tests/nmi-taskswitch-priv/main.c index f3149e0..d8eb4a2 100644 --- a/tests/nmi-taskswitch-priv/main.c +++ b/tests/nmi-taskswitch-priv/main.c @@ -110,7 +110,7 @@ static env_tss nmi_tss __aligned(16) = .iopb = X86_TSS_INVALID_IO_BITMAP, }; -static bool unhandled_exception(struct cpu_regs *regs) +bool do_unhandled_exception(struct cpu_regs *regs) { if ( regs->entry_vector != X86_EXC_NMI ) return false; @@ -145,7 +145,6 @@ void test_main(void) /* * Set up NMI handling to be a task gate. */ - xtf_unhandled_exception_hook = unhandled_exception; pack_tss_desc(&gdt[GDTE_AVAIL0], &nmi_tss); pack_task_gate(&idt[X86_EXC_NMI], GDTE_AVAIL0 * 8); diff --git a/tests/selftest/main.c b/tests/selftest/main.c index 4309755..31dcda1 100644 --- a/tests/selftest/main.c +++ b/tests/selftest/main.c @@ -203,7 +203,7 @@ static void test_NULL_unmapped(void) xtf_exlog_stop(); } -static bool local_unhandled_exception_hook(struct cpu_regs *regs) +bool do_unhandled_exception(struct cpu_regs *regs) { extern unsigned long hook_fault[], hook_fixup[]; @@ -223,11 +223,7 @@ static void test_unhandled_exception_hook(void) printk("Test: Unhandled Exception Hook\n"); /* Check that the hook catches the exception, and fix it up. */ - xtf_unhandled_exception_hook = local_unhandled_exception_hook; - - asm volatile ("hook_fault: ud2a; hook_fixup:" ::: "memory"); - - xtf_unhandled_exception_hook = NULL; + asm volatile ("hook_fault: ud2a; hook_fixup:"); } static bool test_extable_handler_handler_run; diff --git a/tests/swint-emulation/main.c b/tests/swint-emulation/main.c index e54ceb7..e785e05 100644 --- a/tests/swint-emulation/main.c +++ b/tests/swint-emulation/main.c @@ -212,7 +212,7 @@ void check(void) } /** Print expected information in the case of an unexpected exception. */ -bool unhandled_exception(struct cpu_regs *regs) +bool do_unhandled_exception(struct cpu_regs *regs) { printk("Unhandled Exception at %p\n", _p(regs)); check(); @@ -374,8 +374,6 @@ void test_main(void) if ( !xtf_has_fep ) xtf_skip("FEP support not detected - some tests will be skipped\n"); - /* Setup. Hook unhandled exceptions for debugging purposes. */ - xtf_unhandled_exception_hook = unhandled_exception; set_idt_entries_present(true); set_idt_entries_dpl(3); -- 2.39.5