From: Benoît Canet <benoit.canet.cont...@gmail.com>
Committer: Nadav Har'El <n...@scylladb.com>
Branch: master

syscall: save/restore FPU state on syscall

As issue #798 explains, if an application uses floating point and then,
in the same function, also calls the SYSCALL instruction, the compiler
will not realize it needs to save the caller-saved floating-point state
(because it thinks it calls an x86 instruction, not a function).
So we need to do this saving in the SYSCALL implementation, before we
go on calling OSv functions which might clobber the FPU state.

The patch Uses fpu_lock to do the work of saving and restoring FPU state.

The case where this fix is actually needed is rare (in fact, we never
saw it in practice): Most applications do not in fact mix FPU use and
SYSCALL calling in a single function. But nevertheless, we add it to be
safe in case some application ever does it.

Unfortunately, the extra FPU saving means we slow down every SYSCALL
instruction. Note that it only slows down SYSCALL instructions, which
most applications do not use (golang is the notable exception), and
does NOT slow down the normal OSv ABI (the call to "system calls" as
ordinary functions). Also, we do not slow down the vDSO ABI which
golang uses instead of SYSCALL for system calls which are supposed to
be really quick.

Signed-off-by: Benoît Canet <ben...@scylladb.com>
Message-Id: <1477570022-14541-11-git-send-email-ben...@scylladb.com>
Signed-off-by: Nadav Har'El <n...@scylladb.com>

---
diff --git a/arch/x64/entry.S b/arch/x64/entry.S
--- a/arch/x64/entry.S
+++ b/arch/x64/entry.S
@@ -217,7 +217,6 @@ syscall_entry:
# From http://stackoverflow.com/questions/2535989/what-are-the-calling-conventions-for-unix-linux-system-calls-on-x86-64: # "User-level applications use as integer registers for passing the sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9. The kernel interface uses %rdi, %rsi, %rdx, %r10, %r8 and %r9"

-    # FIXME: fpu
     pushq_cfi %rbx
     pushq_cfi %rdx
     pushq_cfi %rsi
@@ -250,6 +249,7 @@ syscall_entry:
     # Because we pushed an even number of 8 bytes after aligning the stack,
     # it is still 16-byte aligned and we don't need to adjust it here.

+    # FPU save/restore is done inside the wrapper
     callq syscall_wrapper

     popq_cfi %r9
diff --git a/linux.cc b/linux.cc
--- a/linux.cc
+++ b/linux.cc
@@ -311,6 +311,10 @@ static int sys_exit(int ret)

 long syscall(long number, ...)
 {
+    // Save FPU state and restore it at the end of this function
+    sched::fpu_lock fpu;
+    SCOPE_LOCK(fpu);
+
     switch (number) {
     SYSCALL2(open, const char *, int);
     SYSCALL3(read, int, char *, size_t);

--
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to