Add a selftest to confirm functionality.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
#include <arch/x86/processor.h>
+#include <arch/x86/segment.h>
#include <xtf/asm_macros.h>
/*
mov 0*4(%esp), %eax /* Stash %eip from iret frame */
mov 3*4(%esp), %esp /* Load %esp from iret frame */
jmp *%eax /* Jump back */
+
+
+ENTRY(exec_user) /* void (*fn)(void) */
+
+ push $__USER_DS /* SS */
+ push %esp
+ addl $4, (%esp) /* ESP */
+ pushf /* EFLAGS */
+
+#if defined(CONFIG_ENV_pv) /* PV guests see the real interrupt flag. Clobber it. */
+ andl $~X86_EFLAGS_IF, (%esp)
+#endif
+
+ push $__USER_CS /* CS */
+ push $1f /* EIP */
+
+ env_IRET /* Drop to user privilege. */
+1:
+ call *4(%esp) /* fn() */
+
+ int $0x20 /* Return to kernel privilege. */
+ ret
#include <arch/x86/processor.h>
+#include <arch/x86/segment.h>
#include <xtf/asm_macros.h>
/*
mov 0*8(%rsp), %rax /* Stash %rip from iret frame */
mov 3*8(%rsp), %rsp /* Load %esp from iret frame */
jmp *%rax /* Jump back */
+
+
+ENTRY(exec_user) /* void (*fn)(void) */
+
+ push $__USER_DS /* SS */
+ push %rsp
+ addq $8, (%rsp) /* RSP */
+ pushf /* RFLAGS */
+
+#if defined(CONFIG_ENV_pv) /* PV guests see the real interrupt flag. Clobber it. */
+ andq $~X86_EFLAGS_IF, (%rsp)
+#endif
+
+ push $__USER_CS /* CS */
+ push $1f /* RIP */
+
+ env_IRETQ /* Drop to user privilege. */
+1:
+ call *%rdi /* fn() */
+
+ int $0x20 /* Return to kernel privilege. */
+ ret
int (*compar)(const void *, const void *),
void (*swap)(void *, void *));
+/* Execute fn() at user privilege on the current stack. */
+void exec_user(void (*fn)(void));
+
#endif /* XTF_LIB_H */
/*
#include <xtf/report.h>
#include <xtf/console.h>
+#include <xtf/lib.h>
#include <xtf/traps.h>
#include <xtf/exlog.h>
xtf_exlog_stop();
}
+static enum {
+ USER_not_seen,
+ USER_seen,
+ USER_bad_cs,
+} seen_from_userspace = USER_not_seen;
+
+static void test_exec_user_cpl3(void)
+{
+ unsigned int cs = read_cs();
+
+ if ( (cs & 3) == 3 )
+ seen_from_userspace = USER_seen;
+ else
+ seen_from_userspace = USER_bad_cs;
+}
+
+static void test_exec_user(void)
+{
+ printk("Test: Userspace execution\n");
+
+ exec_user(test_exec_user_cpl3);
+
+ switch ( seen_from_userspace )
+ {
+ case USER_seen:
+ /* Success */
+ break;
+
+ case USER_not_seen:
+ xtf_failure("Fail: Did not execute function\n");
+ break;
+
+ case USER_bad_cs:
+ xtf_failure("Fail: Not at cpl3\n");
+ break;
+ }
+}
+
void test_main(void)
{
printk("XTF Selftests\n");
test_int3_breakpoint();
test_extable();
test_exlog();
+ test_exec_user();
xtf_success();
}