]> xenbits.xensource.com Git - xtf.git/commitdiff
Rudimentary syscall handling for PV guests
authorAndrew Cooper <andrew.cooper3@citrix.com>
Thu, 22 Mar 2018 11:50:50 +0000 (11:50 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 18 Apr 2018 12:52:52 +0000 (13:52 +0100)
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
arch/x86/entry_32.S
arch/x86/entry_64.S
arch/x86/include/arch/test.h [new file with mode: 0644]
arch/x86/include/arch/xtf.h
arch/x86/pv/traps.c
arch/x86/traps.c
include/xen/arch-x86/xen-x86_32.h
include/xen/arch-x86/xen-x86_64.h

index b49b0e772b843561e2013353d366269c24937625..9968b57bea3adaf9554a243faa656c69c8656227 100644 (file)
@@ -154,6 +154,35 @@ ENTRY(exec_user_stub)
 ENDFUNC(exec_user_stub)
 .popsection
 
+#if defined(CONFIG_PV)
+ENTRY(entry_SYSCALL)
+        push $0
+        push $0x100
+
+        push %es
+        push %ds
+
+        SAVE_ALL
+
+        mov $__KERN_DS, %eax    /* Restore data segments. */
+        mov %eax, %ds
+        mov %eax, %es
+
+        push %esp               /* struct cpu_regs * */
+        call do_syscall
+        add $4, %esp
+
+        RESTORE_ALL
+
+        pop %ds
+        pop %es
+
+        add $8, %esp            /* Pop error_code/entry_vector. */
+
+        jmp HYPERCALL_iret
+ENDFUNC(entry_SYSCALL)
+#endif
+
 /*
  * Local variables:
  * tab-width: 8
index 756ccb194365238fc77e6535ef7345a5a2d3732f..5136dd64474d26dfac7da8343d8745c233606da1 100644 (file)
@@ -148,6 +148,26 @@ ENTRY(exec_user_stub)
 ENDFUNC(exec_user_stub)
 .popsection
 
+#if defined(CONFIG_PV)
+ENTRY(entry_SYSCALL)
+        env_ADJUST_FRAME
+
+        push $0
+        movl $0x100, 4(%rsp)
+
+        SAVE_ALL
+
+        mov %rsp, %rdi          /* struct cpu_regs * */
+        call do_syscall
+
+        RESTORE_ALL
+
+        movq $VGCF_in_syscall, (%rsp) /* Clobber error_code/entry_vector */
+        jmp HYPERCALL_iret
+
+ENDFUNC(entry_SYSCALL)
+#endif /* CONFIG_PV */
+
 /*
  * Local variables:
  * tab-width: 8
diff --git a/arch/x86/include/arch/test.h b/arch/x86/include/arch/test.h
new file mode 100644 (file)
index 0000000..a34cdbb
--- /dev/null
@@ -0,0 +1,26 @@
+/**
+ * @file arch/x86/include/arch/test.h
+ *
+ * %x86 API for tests.
+ */
+#ifndef XTF_X86_TEST_H
+#define XTF_X86_TEST_H
+
+#include <arch/regs.h>
+
+/**
+ * May be implemented by a guest to handle SYSCALL invocations.
+ */
+void do_syscall(struct cpu_regs *regs);
+
+#endif /* XTF_X86_TEST_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
index 3609d5d90876076f3c4584a2e0da31499daa2609..6cedf08e81cec850ecd017b83e47f71da3e5ee41 100644 (file)
@@ -12,6 +12,7 @@
 #include <arch/msr.h>
 #include <arch/pagetable.h>
 #include <arch/symbolic-const.h>
+#include <arch/test.h>
 #include <arch/x86-dbg-reg.h>
 
 extern char _end[];
index 1899d0b9a0bad741c37694a30acca211b26172a9..92dca02714e0005ffb310bb32e8998599696897a 100644 (file)
@@ -35,6 +35,8 @@ void entry_XM(void);
 void entry_VE(void);
 void entry_ret_to_kernel(void);
 
+void entry_SYSCALL(void);
+
 struct xen_trap_info pv_default_trap_info[] =
 {
     { X86_EXC_DE,  0|4, __KERN_CS, _u(entry_DE)  },
@@ -108,7 +110,7 @@ static int __maybe_unused remap_linear_range(const void *start, const void *end,
     return ret;
 }
 
-void arch_init_traps(void)
+static void init_callbacks(void)
 {
     /* PV equivalent of `lidt`. */
     int rc = hypercall_set_trap_table(pv_default_trap_info);
@@ -116,6 +118,37 @@ void arch_init_traps(void)
     if ( rc )
         panic("Failed to set trap table: %d\n", rc);
 
+    xen_callback_register_t cb;
+
+#ifdef __x86_64__
+    cb = (xen_callback_register_t) {
+        .type = CALLBACKTYPE_syscall,
+        .flags = CALLBACKF_mask_events,
+        .address = INIT_XEN_CALLBACK(__KERN_CS, _u(entry_SYSCALL)),
+    };
+
+    rc = hypercall_register_callback(&cb);
+    if ( rc )
+        panic("Failed to register syscall callback: %d\n", rc);
+#endif
+
+    cb = (xen_callback_register_t) {
+        .type = CALLBACKTYPE_syscall32,
+        .flags = CALLBACKF_mask_events,
+        .address = INIT_XEN_CALLBACK(__KERN_CS, _u(entry_SYSCALL)),
+    };
+
+    rc = hypercall_register_callback(&cb);
+    if ( rc )
+        panic("Failed to register syscall32 callback: %d\n", rc);
+}
+
+void arch_init_traps(void)
+{
+    int rc;
+
+    init_callbacks();
+
     /* Register gdt[] with Xen.  Need to map it read-only first. */
     if ( remap_linear(gdt, PF_SYM(AD, P)) )
         panic("Unable to remap gdt[] as read-only\n");
index 8fee587930d8a5d64ff0e459e44188d8e891f422..b0a1f9b71581724ac9256605b3b8bfbdec00d40c 100644 (file)
@@ -68,6 +68,11 @@ void do_exception(struct cpu_regs *regs)
     }
 }
 
+void __weak do_syscall(struct cpu_regs *regs)
+{
+    panic("Unhandled syscall\n");
+}
+
 /*
  * Local variables:
  * mode: C
index 63ff666d4d19106489391bfeed9dc3e9ff6a5156..c8f5f171a0dc1dfae41ff18d8718c89001b882bf 100644 (file)
@@ -85,6 +85,9 @@ struct xen_callback {
 };
 typedef struct xen_callback xen_callback_t;
 
+#define INIT_XEN_CALLBACK(_cs, _ip) \
+    ((xen_callback_t){ .cs = _cs, .eip = _ip })
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* XEN_PUBLIC_ARCH_X86_XEN_X86_32_H */
index 8bc577f1f521502cf3d4b90c65f8c9d5e5b4f226..30bc74d7245f6cdd85294645b929dc246ecf2141 100644 (file)
@@ -17,6 +17,9 @@
 
 #define MACH2PHYS_VIRT_START 0xFFFF800000000000UL
 
+/* Guest exited in SYSCALL context? Return to guest with SYSRET? */
+#define VGCF_in_syscall 0x100
+
 #ifndef __ASSEMBLY__
 
 /* Anonymous unions include all permissible names (e.g., al/ah/ax/eax/rax). */
@@ -90,6 +93,8 @@ struct arch_vcpu_info {
 
 typedef unsigned long xen_callback_t;
 
+#define INIT_XEN_CALLBACK(_cs, _ip) (_ip)
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* XEN_PUBLIC_ARCH_X86_XEN_X86_64_H */