Add a test utility that enables: 1. Running test function in User Mode or Kernel Mode. 2. Catching an exception. 3. Running a callback function to test return val. Signed-off-by: Arbel Moshe <arbel.moshe@xxxxxxxxxx> Reviewed-by: Liran Alon <liran.alon@xxxxxxxxxx> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> --- lib/x86/fault_test.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/x86/fault_test.h | 42 ++++++++++++++++++++++++++++++++++++++++++ x86/Makefile.common | 1 + 3 files changed, 95 insertions(+) create mode 100644 lib/x86/fault_test.c create mode 100644 lib/x86/fault_test.h diff --git a/lib/x86/fault_test.c b/lib/x86/fault_test.c new file mode 100644 index 0000000..71ac982 --- /dev/null +++ b/lib/x86/fault_test.c @@ -0,0 +1,52 @@ +#include "fault_test.h" + +jmp_buf jmpbuf; + +static void restore_exec_to_jmpbuf(void) +{ + longjmp(jmpbuf, 1); +} + +static void fault_test_fault(struct ex_regs *regs) +{ + regs->rip = (unsigned long)&restore_exec_to_jmpbuf; +} + +static bool fault_test(struct fault_test_arg *arg) +{ + uint64_t val; + bool raised_vector = false; + test_fault_func func = (test_fault_func) arg->func; + /* Init as success in case there isn't callback */ + bool callback_success = true; + + if (arg->usermode) { + val = run_in_user((usermode_func) func, arg->fault_vector, + arg->arg[0], arg->arg[1], arg->arg[2], + arg->arg[3], &raised_vector); + } else { + handle_exception(arg->fault_vector, fault_test_fault); + if (setjmp(jmpbuf) == 0) + val = func(arg->arg[0], arg->arg[1], arg->arg[2], + arg->arg[3]); + else + raised_vector = true; + } + + if (!raised_vector) { + arg->retval = val; + if (arg->callback != NULL) + callback_success = arg->callback(arg); + } + + return arg->should_fault ? + raised_vector : (!raised_vector && callback_success); +} + +void test_run(struct fault_test *test) +{ + bool passed = fault_test(&(test->arg)); + + report("%s", passed, test->name); +} + diff --git a/lib/x86/fault_test.h b/lib/x86/fault_test.h new file mode 100644 index 0000000..dfa715b --- /dev/null +++ b/lib/x86/fault_test.h @@ -0,0 +1,42 @@ +#ifndef __FAULT_TEST__ +#define __FAULT_TEST__ + +#include "x86/msr.h" +#include "x86/processor.h" +#include "x86/apic-defs.h" +#include "x86/apic.h" +#include "x86/desc.h" +#include "x86/isr.h" +#include "alloc.h" +#include "setjmp.h" +#include "usermode.h" + +#include "libcflat.h" +#include <stdint.h> + +#define FAULT_TEST(nm, a) { .name = nm, .arg = a} + +struct fault_test_arg; + +typedef uint64_t (*test_fault_func)(uint64_t arg1, uint64_t arg2, + uint64_t arg3, uint64_t arg4); +typedef bool (*test_fault_callback)(struct fault_test_arg *arg); + +struct fault_test_arg { + bool usermode; + unsigned int fault_vector; + bool should_fault; + uint64_t arg[4]; + uint64_t retval; + test_fault_func func; + test_fault_callback callback; +}; + +struct fault_test { + const char *name; + struct fault_test_arg arg; +}; + +void test_run(struct fault_test *test); + +#endif diff --git a/x86/Makefile.common b/x86/Makefile.common index 8a9d245..cbd5847 100644 --- a/x86/Makefile.common +++ b/x86/Makefile.common @@ -20,6 +20,7 @@ cflatobjs += lib/x86/isr.o cflatobjs += lib/x86/acpi.o cflatobjs += lib/x86/stack.o cflatobjs += lib/x86/usermode.o +cflatobjs += lib/x86/fault_test.o OBJDIRS += lib/x86 -- 2.14.1