diff mbox

[2/5] x86: Add Test Utility to run in User Mode and catch exceptions

Message ID 20171224100801.145806-3-arbel.moshe@oracle.com (mailing list archive)
State New, archived
Headers show

Commit Message

Arbel Moshe Dec. 24, 2017, 10:07 a.m. UTC
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@oracle.com>
Reviewed-by: Liran Alon <liran.alon@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
 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 mbox

Patch

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