| #include "fault_test.h" |
| |
| static 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) |
| { |
| volatile 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; |
| handler old; |
| |
| 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 { |
| old = 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; |
| handle_exception(arg->fault_vector, old); |
| } |
| |
| 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(passed, "%s", test->name); |
| } |
| |