]> xenbits.xensource.com Git - people/royger/xen-test-framework.git/commitdiff
Introduce exec_user() to run a function at user privilege
authorAndrew Cooper <andrew.cooper3@citrix.com>
Thu, 24 Dec 2015 23:36:47 +0000 (23:36 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Tue, 5 Jan 2016 20:32:53 +0000 (20:32 +0000)
Add a selftest to confirm functionality.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
arch/x86/entry_32.S
arch/x86/entry_64.S
include/xtf/lib.h
tests/selftest/main.c

index bda1150302fea7dc6a82a08c44e517c320861527..2b08b49115094c047e41d5609b4b0f5080bdd5b8 100644 (file)
@@ -1,4 +1,5 @@
 #include <arch/x86/processor.h>
+#include <arch/x86/segment.h>
 #include <xtf/asm_macros.h>
 
 /*
@@ -89,3 +90,25 @@ ENTRY(entry_ret_to_kernel)      /* int $0x20 (return to kernel) */
         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
index e1b5baadcf2d989b92fc00b94cd28d1ad1f49ca9..730ee5b5dd3cdfa24f713663e11a03e9c97f8dab 100644 (file)
@@ -1,4 +1,5 @@
 #include <arch/x86/processor.h>
+#include <arch/x86/segment.h>
 #include <xtf/asm_macros.h>
 
 /*
@@ -102,3 +103,25 @@ ENTRY(entry_ret_to_kernel)      /* int $0x20 (return to kernel) */
         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
index b4a75798d1bd92935a5bd304e6a77029ea7cb5db..d18ac2b6b9a85115ab595b22cb46442c884a9419 100644 (file)
@@ -18,6 +18,9 @@ void heapsort(void *base, size_t nmemb, size_t size,
               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 */
 
 /*
index 2595fba694b7a1c0136189b8f44aec1efb246435..45eb3bc147109072c4874928f186a347434470e0 100644 (file)
@@ -2,6 +2,7 @@
 #include <xtf/report.h>
 #include <xtf/console.h>
 
+#include <xtf/lib.h>
 #include <xtf/traps.h>
 #include <xtf/exlog.h>
 
@@ -130,6 +131,44 @@ static void test_exlog(void)
     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");
@@ -137,6 +176,7 @@ void test_main(void)
     test_int3_breakpoint();
     test_extable();
     test_exlog();
+    test_exec_user();
 
     xtf_success();
 }