All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Chang S. Bae" <chang.seok.bae@intel.com>
To: Andy Lutomirski <luto@kernel.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@kernel.org>, "H . Peter Anvin" <hpa@zytor.com>,
	Andi Kleen <ak@linux.intel.com>
Cc: Markus T Metzger <markus.t.metzger@intel.com>,
	Ravi Shankar <ravi.v.shankar@intel.com>,
	"Chang S . Bae" <chang.seok.bae@intel.com>,
	LKML <linux-kernel@vger.kernel.org>
Subject: [PATCH v5 06/13] x86/fsgsbase/64: Preserve FS/GS state in __switch_to() if FSGSBASE is on
Date: Fri,  1 Feb 2019 12:53:12 -0800	[thread overview]
Message-ID: <20190201205319.15995-8-chang.seok.bae@intel.com> (raw)
In-Reply-To: <20190201205319.15995-1-chang.seok.bae@intel.com>

From: Andy Lutomirski <luto@kernel.org>

With the new FSGSBASE instructions, we can efficiently read and write
the FSBASE and GSBASE in __switch_to().  Use that capability to preserve
the full state.

This will enable user code to do whatever it wants with the new
instructions without any kernel-induced gotchas.  (There can still be
architectural gotchas: movl %gs,%eax; movl %eax,%gs may change GSBASE
if WRGSBASE was used, but users are expected to read the CPU manual
before doing things like that.)

This is a considerable speedup.  It seems to save about 100 cycles
per context switch compared to the baseline 4.6-rc1 behavior on my
Skylake laptop.

[ chang: 5~10% performance improvements were seen by a context switch
  benchmark that ran threads with different FS/GSBASE values (to the
  baseline 4.16). Minor edit on the changelog. ]

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com>
Reviewed-by: Andi Kleen <ak@linux.intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/kernel/process_64.c | 34 ++++++++++++++++++++++++++++------
 1 file changed, 28 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index ebc55ed31fe7..d8ade9530fdb 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -245,8 +245,18 @@ static __always_inline void save_fsgs(struct task_struct *task)
 {
 	savesegment(fs, task->thread.fsindex);
 	savesegment(gs, task->thread.gsindex);
-	save_base_legacy(task, task->thread.fsindex, FS);
-	save_base_legacy(task, task->thread.gsindex, GS);
+	if (static_cpu_has(X86_FEATURE_FSGSBASE)) {
+		/*
+		 * If FSGSBASE is enabled, we can't make any useful guesses
+		 * about the base, and user code expects us to save the current
+		 * value.  Fortunately, reading the base directly is efficient.
+		 */
+		task->thread.fsbase = rdfsbase();
+		task->thread.gsbase = __rdgsbase_inactive();
+	} else {
+		save_base_legacy(task, task->thread.fsindex, FS);
+		save_base_legacy(task, task->thread.gsindex, GS);
+	}
 }
 
 #if IS_ENABLED(CONFIG_KVM)
@@ -325,10 +335,22 @@ static __always_inline void load_seg_legacy(unsigned short prev_index,
 static __always_inline void x86_fsgsbase_load(struct thread_struct *prev,
 					      struct thread_struct *next)
 {
-	load_seg_legacy(prev->fsindex, prev->fsbase,
-			next->fsindex, next->fsbase, FS);
-	load_seg_legacy(prev->gsindex, prev->gsbase,
-			next->gsindex, next->gsbase, GS);
+	if (static_cpu_has(X86_FEATURE_FSGSBASE)) {
+		/* Update the FS and GS selectors if they could have changed. */
+		if (unlikely(prev->fsindex || next->fsindex))
+			loadseg(FS, next->fsindex);
+		if (unlikely(prev->gsindex || next->gsindex))
+			loadseg(GS, next->gsindex);
+
+		/* Update the bases. */
+		wrfsbase(next->fsbase);
+		__wrgsbase_inactive(next->gsbase);
+	} else {
+		load_seg_legacy(prev->fsindex, prev->fsbase,
+				next->fsindex, next->fsbase, FS);
+		load_seg_legacy(prev->gsindex, prev->gsbase,
+				next->gsindex, next->gsbase, GS);
+	}
 }
 
 static unsigned long x86_fsgsbase_read_task(struct task_struct *task,
-- 
2.19.1


  parent reply	other threads:[~2019-02-01 20:55 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-01 20:53 [PATCH v5 00/13] x86: Enable FSGSBASE instructions Chang S. Bae
2019-02-01 20:53 ` [PATCH v5 01/13] taint: Introduce a new taint flag (insecure) Chang S. Bae
2019-02-02  2:42   ` Andy Lutomirski
2019-02-05 21:21     ` Andrew Morton
2019-02-05 22:46       ` Randy Dunlap
2019-02-05 23:07         ` hpa
2019-02-01 20:53 ` [PATCH v5 02/13] x86/fsgsbase/64: Add 'unsafe_fsgsbase' to enable CR4.FSGSBASE Chang S. Bae
2019-02-01 20:53 ` [PATCH v5 03/13] kbuild: Raise the minimum required binutils version to 2.21 Chang S. Bae
2019-02-02  2:45   ` Andy Lutomirski
2019-02-05  0:08     ` Andrew Morton
2019-02-01 20:53 ` [PATCH v5 04/13] x86/fsgsbase/64: Add intrinsics for FSGSBASE instructions Chang S. Bae
2019-02-02  2:52   ` Andy Lutomirski
2019-02-01 20:53 ` [PATCH v5 04/13] x86/fsgsbase/64: Add intrinsics/macros " Chang S. Bae
2019-02-01 20:53 ` [PATCH v5 05/13] x86/fsgsbase/64: Enable FSGSBASE instructions in the helper functions Chang S. Bae
2019-02-02  2:57   ` Andy Lutomirski
2019-02-01 20:53 ` Chang S. Bae [this message]
2019-02-01 20:53 ` [PATCH v5 07/13] x86/fsgsbase/64: When copying a thread, use the FSGSBASE instructions if available Chang S. Bae
2019-02-02 17:28   ` Andy Lutomirski
2019-02-01 20:53 ` [PATCH v5 08/13] x86/fsgsbase/64: Introduce the FIND_PERCPU_BASE macro Chang S. Bae
2019-02-02 17:17   ` Andy Lutomirski
2019-02-13 18:46     ` Bae, Chang Seok
2019-02-01 20:53 ` [PATCH v5 09/13] x86/fsgsbase/64: Use the per-CPU base as GSBASE at the paranoid_entry Chang S. Bae
2019-02-01 20:53 ` [PATCH v5 10/13] selftests/x86/fsgsbase: Test WRGSBASE Chang S. Bae
2019-02-01 20:53 ` [PATCH v5 11/13] x86/fsgsbase/64: Enable FSGSBASE by default and add a chicken bit Chang S. Bae
2019-02-01 20:53 ` [PATCH v5 12/13] x86/elf: Enumerate kernel FSGSBASE capability in AT_HWCAP2 Chang S. Bae
2019-02-01 20:53 ` [PATCH v5 13/13] x86/fsgsbase/64: Add documentation for FSGSBASE Chang S. Bae
2019-02-01 23:02 ` [PATCH v5 00/13] x86: Enable FSGSBASE instructions Andi Kleen
2019-02-02  2:43 ` Andy Lutomirski
2019-02-05  6:26   ` hpa

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=20190201205319.15995-8-chang.seok.bae@intel.com \
    --to=chang.seok.bae@intel.com \
    --cc=ak@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=markus.t.metzger@intel.com \
    --cc=mingo@kernel.org \
    --cc=ravi.v.shankar@intel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.