xref: /kvm-unit-tests/lib/x86/fault_test.c (revision cd5f2fb4ad641c51fe0f1a85264dc3f6ede6e131)
1 #include "fault_test.h"
2 
3 static jmp_buf jmpbuf;
4 
restore_exec_to_jmpbuf(void)5 static void restore_exec_to_jmpbuf(void)
6 {
7 	longjmp(jmpbuf, 1);
8 }
9 
fault_test_fault(struct ex_regs * regs)10 static void fault_test_fault(struct ex_regs *regs)
11 {
12 	regs->rip = (unsigned long)&restore_exec_to_jmpbuf;
13 }
14 
fault_test(struct fault_test_arg * arg)15 static bool fault_test(struct fault_test_arg *arg)
16 {
17 	volatile uint64_t val;
18 	bool raised_vector = false;
19 	test_fault_func func = (test_fault_func) arg->func;
20 	/* Init as success in case there isn't callback */
21 	bool callback_success = true;
22 	handler old;
23 
24 	if (arg->usermode) {
25 		val = run_in_user((usermode_func) func, arg->fault_vector,
26 				arg->arg[0], arg->arg[1], arg->arg[2],
27 				arg->arg[3], &raised_vector);
28 	} else {
29 		old = handle_exception(arg->fault_vector, fault_test_fault);
30 		if (setjmp(jmpbuf) == 0)
31 			val = func(arg->arg[0], arg->arg[1], arg->arg[2],
32 					arg->arg[3]);
33 		else
34 			raised_vector = true;
35 		handle_exception(arg->fault_vector, old);
36 	}
37 
38 	if (!raised_vector) {
39 		arg->retval = val;
40 		if (arg->callback != NULL)
41 			callback_success = arg->callback(arg);
42 	}
43 
44 	return arg->should_fault ?
45 		raised_vector : (!raised_vector && callback_success);
46 }
47 
test_run(struct fault_test * test)48 void test_run(struct fault_test *test)
49 {
50 	bool passed = fault_test(&(test->arg));
51 
52 	report(passed, "%s", test->name);
53 }
54 
55