mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: riel@redhat.com
To: linux-kernel@vger.kernel.org
Cc: mingo@redhat.com, hpa@zytor.com, matt.fleming@intel.com,
	bp@suse.de, oleg@redhat.com, pbonzini@redhat.com,
	tglx@linutronix.de, luto@amacapital.net
Subject: [RFC PATCH 11/11] (BROKEN) x86,fpu: broken signal handler stack setup
Date: Sun, 11 Jan 2015 16:46:33 -0500	[thread overview]
Message-ID: <1421012793-30106-12-git-send-email-riel@redhat.com> (raw)
In-Reply-To: <1421012793-30106-1-git-send-email-riel@redhat.com>

From: Rik van Riel <riel@redhat.com>

The previous patches result in situations where the FPU state
for a task is not present in the FPU registers, when using eager
fpu mode. The signal frame setup and restore code needs to be
adjusted to deal with that situation.

Without this patch, the signal handler stack setup is broken.

With it, it is still broken.

However, I have been staring at it for too long to figure out
why. This patch needs other eyeballs.

In other words: HELP!

The LTP signal handling tests all seem to pass, but SPECjbb2005
crashes in minutes in the signal handler code:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f4df1f3e753, pid=1711, tid=139972332160768
#
# JRE version: OpenJDK Runtime Environment (8.0) (build 1.8.0-internal-0)
# Java VM: OpenJDK 64-Bit Server VM (25.0-b57-internal mixed mode linux-amd64 compressed oops)
# Problematic frame:
# V  [libjvm.so+0x854753]  JVM_handle_linux_signal+0x5e193

Not-signed-off-by: Rik van Riel <riel@redhat.com>
Signed-off-by: Rik van Riel <riel@redhat.com>
---
 arch/x86/include/asm/fpu-internal.h | 31 +++++++++++++++++-----------
 arch/x86/kernel/xsave.c             | 41 ++++++++++++++++++-------------------
 2 files changed, 39 insertions(+), 33 deletions(-)

diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h
index 095dacc..ac45074 100644
--- a/arch/x86/include/asm/fpu-internal.h
+++ b/arch/x86/include/asm/fpu-internal.h
@@ -358,6 +358,8 @@ static inline void __drop_fpu(struct task_struct *tsk)
 			     _ASM_EXTABLE(1b, 2b));
 		__thread_fpu_end(tsk);
 	}
+	/* disable lazy fpu restore */
+	tsk->thread.fpu.last_cpu = ~0;
 }
 
 static inline void drop_fpu(struct task_struct *tsk)
@@ -377,12 +379,12 @@ static inline void drop_init_fpu(struct task_struct *tsk)
 	if (!use_eager_fpu())
 		drop_fpu(tsk);
 	else {
-		if (use_xsave())
-			xrstor_state(init_xstate_buf, -1);
-		else
-			fxrstor_checking(&init_xstate_buf->i387);
+		preempt_disable();
+		__thread_fpu_end(tsk);
+		fpu_finit(&tsk->thread.fpu);
+		set_thread_flag(TIF_LOAD_FPU);
+		preempt_enable();
 	}
-	clear_thread_flag(TIF_LOAD_FPU);
 }
 
 /*
@@ -467,7 +469,7 @@ static inline void switch_fpu_finish(void)
 	if (fpu_lazy_restore(tsk, raw_smp_processor_id()))
 		return;
 
-	if (unlikely(restore_fpu_checking(tsk)))
+	if (restore_fpu_checking(tsk))
 		drop_init_fpu(tsk);
 }
 
@@ -525,16 +527,21 @@ static inline void __save_fpu(struct task_struct *tsk)
  */
 static inline void save_init_fpu(struct task_struct *tsk)
 {
-	WARN_ON_ONCE(!__thread_has_fpu(tsk));
+	preempt_disable();
 
-	if (use_eager_fpu()) {
+	if (unlikely(!__thread_has_fpu(tsk)))
+		goto out;
+
+	if (use_eager_fpu())
 		__save_fpu(tsk);
-		return;
-	}
+	else
+		__save_init_fpu(tsk);
 
-	preempt_disable();
-	__save_init_fpu(tsk);
 	__thread_fpu_end(tsk);
+
+ out:
+	/* disable lazy fpu restore */
+	tsk->thread.fpu.last_cpu = ~0;
 	preempt_enable();
 }
 
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
index 4c540c4..5434491 100644
--- a/arch/x86/kernel/xsave.c
+++ b/arch/x86/kernel/xsave.c
@@ -251,18 +251,13 @@ int save_xstate_sig(void __user *buf, void __user *buf_fx, int size)
 			sizeof(struct user_i387_ia32_struct), NULL,
 			(struct _fpstate_ia32 __user *) buf) ? -1 : 1;
 
-	if (user_has_fpu()) {
-		/* Save the live register state to the user directly. */
-		if (save_user_xstate(buf_fx))
-			return -1;
-		/* Update the thread's fxstate to save the fsave header. */
-		if (ia32_fxstate)
-			fpu_fxsave(&tsk->thread.fpu);
-	} else {
-		sanitize_i387_state(tsk);
-		if (__copy_to_user(buf_fx, xsave, xstate_size))
-			return -1;
-	}
+	/* Atomically save the FPU state from registers. */
+	save_init_fpu(tsk);
+
+	/* Then copy it to userspace. */
+	sanitize_i387_state(tsk);
+	if (__copy_to_user(buf_fx, xsave, xstate_size))
+		return -1;
 
 	/* Save the fsave header for the 32-bit frames. */
 	if ((ia32_fxstate || !use_fxsr()) && save_fsave_header(tsk, buf))
@@ -400,23 +395,27 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size)
 			set_used_math();
 		}
 
-		if (use_eager_fpu()) {
-			preempt_disable();
-			math_state_restore();
-			preempt_enable();
-		}
+		if (use_eager_fpu())
+			set_thread_flag(TIF_LOAD_FPU);
 
 		return err;
 	} else {
+		struct xsave_struct *xsave = &tsk->thread.fpu.state->xsave;
 		/*
-		 * For 64-bit frames and 32-bit fsave frames, restore the user
-		 * state to the registers directly (with exceptions handled).
+		 * Copy the xstate from user space into the kernel buffer.
+		 * Clear task used math during the operation, to ensure the
+		 * context switching code does not overwrite the xstate buffer
+		 * with whatever is in the FPU registers.
 		 */
-		user_fpu_begin();
-		if (restore_user_xstate(buf_fx, xstate_bv, fx_only)) {
+		drop_fpu(tsk);
+		if (__copy_from_user(xsave, buf_fx, state_size)) {
 			drop_init_fpu(tsk);
 			return -1;
 		}
+		set_used_math();
+
+		if (use_eager_fpu())
+			set_thread_flag(TIF_LOAD_FPU);
 	}
 
 	return 0;
-- 
1.9.3


  parent reply	other threads:[~2015-01-11 22:05 UTC|newest]

Thread overview: 76+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-11 21:46 [RFC PATCH 0/11 BROKEN] move FPU context loading to userspace switch riel
2015-01-11 21:46 ` [RFC PATCH 01/11] x86,fpu: document the data structures a little riel
2015-01-12 21:18   ` Borislav Petkov
2015-01-12 21:38     ` Rik van Riel
2015-01-12 21:52   ` Dave Hansen
2015-01-13 15:59     ` Rik van Riel
2015-01-11 21:46 ` [RFC PATCH 02/11] x86,fpu: replace fpu_switch_t with a thread flag riel
2015-01-13 15:24   ` Oleg Nesterov
2015-01-13 16:35     ` Rik van Riel
2015-01-13 16:55       ` Oleg Nesterov
2015-01-11 21:46 ` [RFC PATCH 03/11] x86,fpu: move __thread_fpu_begin to when the task has the fpu riel
2015-01-13 15:24   ` Oleg Nesterov
2015-01-13 16:37     ` Rik van Riel
2015-01-11 21:46 ` [RFC PATCH 04/11] x86,fpu: defer FPU restore until return to userspace riel
2015-01-13 15:53   ` Oleg Nesterov
2015-01-13 17:07   ` Andy Lutomirski
2015-01-13 17:11   ` Oleg Nesterov
2015-01-13 17:18     ` Andy Lutomirski
2015-01-13 17:44       ` Rik van Riel
2015-01-13 17:57         ` Andy Lutomirski
2015-01-13 18:13           ` Rik van Riel
2015-01-13 18:26             ` Andy Lutomirski
2015-01-13 17:54     ` Rik van Riel
2015-01-13 18:22       ` Oleg Nesterov
2015-01-13 18:30         ` Oleg Nesterov
2015-01-13 20:06           ` Rik van Riel
2015-01-14 17:56             ` Oleg Nesterov
2015-01-13 17:58   ` Oleg Nesterov
2015-01-13 19:32     ` Rik van Riel
2015-01-11 21:46 ` [RFC PATCH 05/11] x86,fpu: ensure FPU state is reloaded from memory if task is traced riel
2015-01-13 16:19   ` Oleg Nesterov
2015-01-13 16:33     ` Rik van Riel
2015-01-13 16:50       ` Oleg Nesterov
2015-01-13 16:57         ` Rik van Riel
2015-01-11 21:46 ` [RFC PATCH 06/11] x86,fpu: lazily skip fpu restore with eager fpu mode, too riel
2015-01-13 17:11   ` Andy Lutomirski
2015-01-13 20:43     ` Rik van Riel
2015-01-14 18:36   ` Oleg Nesterov
2015-01-15  2:49     ` Rik van Riel
2015-01-15 19:34       ` Oleg Nesterov
2015-01-11 21:46 ` [RFC PATCH 07/11] x86,fpu: store current fpu pointer, instead of fpu_owner_task riel
2015-01-11 21:46 ` [RFC PATCH 08/11] x86,fpu: restore user FPU state lazily after __kernel_fpu_end riel
2015-01-14 18:43   ` Oleg Nesterov
2015-01-14 19:08     ` Oleg Nesterov
2015-01-11 21:46 ` [RFC PATCH 09/11] x86,fpu,kvm: keep vcpu FPU active as long as it is resident riel
2015-01-11 21:46 ` [RFC PATCH 10/11] x86,fpu: fix fpu_copy to deal with not-loaded fpu riel
2015-01-11 21:46 ` riel [this message]
2015-01-15 19:19 ` [PATCH 0/3] x86, fpu: kernel_fpu_begin/end initial cleanups/fix Oleg Nesterov
2015-01-15 19:19   ` [PATCH 1/3] x86, fpu: introduce per-cpu "bool in_kernel_fpu" Oleg Nesterov
2015-01-16  2:22     ` Rik van Riel
2015-01-20 12:54     ` [tip:x86/fpu] x86, fpu: Introduce per-cpu in_kernel_fpu state tip-bot for Oleg Nesterov
2015-01-15 19:20   ` [PATCH 2/3] x86, fpu: don't abuse ->has_fpu in __kernel_fpu_{begin,end}() Oleg Nesterov
2015-01-16  2:27     ` Rik van Riel
2015-01-16 15:54       ` Oleg Nesterov
2015-01-16 16:07         ` Rik van Riel
2015-01-20 12:55     ` [tip:x86/fpu] x86, fpu: Don't abuse has_fpu in __kernel_fpu_begin /end() tip-bot for Oleg Nesterov
2015-01-15 19:20   ` [PATCH 3/3] x86, fpu: fix math_state_restore() race with kernel_fpu_begin() Oleg Nesterov
2015-01-16  2:30     ` Rik van Riel
2015-01-16 16:03       ` Oleg Nesterov
2015-01-20 12:55     ` [tip:x86/fpu] x86, fpu: Fix " tip-bot for Oleg Nesterov
2015-01-19 18:51   ` [PATCH 0/3] x86, fpu: more eagerfpu cleanups Oleg Nesterov
2015-01-19 18:51     ` [PATCH 1/3] x86, fpu: __kernel_fpu_begin() should clear fpu_owner_task even if use_eager_fpu() Oleg Nesterov
2015-01-20 14:15       ` Rik van Riel
2015-02-20 18:13       ` Borislav Petkov
2015-03-03 11:27       ` [tip:x86/fpu] x86/fpu: " tip-bot for Oleg Nesterov
2015-01-19 18:51     ` [PATCH 2/3] x86, fpu: always allow FPU in interrupt " Oleg Nesterov
2015-01-20 14:46       ` Rik van Riel
2015-01-20 22:46       ` Andy Lutomirski
2015-02-20 21:48       ` Borislav Petkov
2015-03-03 11:28       ` [tip:x86/fpu] x86/fpu: Always " tip-bot for Oleg Nesterov
2015-01-19 18:52     ` [PATCH 3/3] x86, fpu: don't abuse FPU in kernel threads " Oleg Nesterov
2015-01-20 14:53       ` Rik van Riel
2015-02-23 15:31       ` Borislav Petkov
2015-03-03 11:28       ` [tip:x86/fpu] x86/fpu: Don' t " tip-bot for Oleg Nesterov
2015-02-20 12:10     ` [PATCH 0/3] x86, fpu: more eagerfpu cleanups Borislav Petkov
2015-02-20 13:30       ` Oleg Nesterov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1421012793-30106-12-git-send-email-riel@redhat.com \
    --to=riel@redhat.com \
    --cc=bp@suse.de \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@amacapital.net \
    --cc=matt.fleming@intel.com \
    --cc=mingo@redhat.com \
    --cc=oleg@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome