From: Andi Kleen <andi@firstfloor.org>
To: linux-kernel@vger.kernel.org
Cc: x86@kernel.org, Andi Kleen <ak@linux.intel.com>
Subject: [PATCH 8/8] x86: Use rd/wr fs/gs base in arch_prctl
Date: Tue, 14 Oct 2014 22:11:51 -0700 [thread overview]
Message-ID: <1413349911-3620-8-git-send-email-andi@firstfloor.org> (raw)
In-Reply-To: <1413349911-3620-1-git-send-email-andi@firstfloor.org>
From: Andi Kleen <ak@linux.intel.com>
Convert arch_prctl to use the new instructions to
change fs/gs if available, instead of using MSRs.
This is merely a small performance optimization,
no new functionality.
With the new instructions the syscall is really obsolete,
as everything can be set directly in ring 3. But the syscall
is widely used by existing software, so we still support it.
The syscall still enforces that the addresses are not
in kernel space, even though that is not needed more.
This is mainly so that the programs written for new CPUs
do not suddenly fail on old CPUs.
With the new instructions available it prefers to use
them in the context switch, instead of using the old
"use GDT segment rewrite" trick.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
arch/x86/kernel/process_64.c | 45 ++++++++++++++++++++++++++++++++++++--------
1 file changed, 37 insertions(+), 8 deletions(-)
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 9bad75a..7669b3b 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -486,15 +486,23 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
int ret = 0;
int doit = task == current;
int cpu;
+ int fast_seg = boot_cpu_has(X86_FEATURE_FSGSBASE);
switch (code) {
case ARCH_SET_GS:
+ /*
+ * With fast_seg we don't need that check anymore,
+ * but keep it so that programs do not suddenly
+ * start failing when run on older CPUs.
+ * If you really want to set a address in kernel space
+ * use WRGSBASE directly.
+ */
if (addr >= TASK_SIZE_OF(task))
return -EPERM;
cpu = get_cpu();
/* handle small bases via the GDT because that's faster to
switch. */
- if (addr <= 0xffffffff) {
+ if (addr <= 0xffffffff && !fast_seg) {
set_32bit_tls(task, GS_TLS, addr);
if (doit) {
load_TLS(&task->thread, cpu);
@@ -506,8 +514,17 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
task->thread.gsindex = 0;
task->thread.gs = addr;
if (doit) {
- load_gs_index(0);
- ret = wrmsrl_safe(MSR_KERNEL_GS_BASE, addr);
+ if (fast_seg) {
+ local_irq_disable();
+ swapgs();
+ loadsegment(gs, 0);
+ wrgsbase(addr);
+ swapgs();
+ local_irq_enable();
+ } else {
+ load_gs_index(0);
+ ret = wrmsrl_safe(MSR_KERNEL_GS_BASE, addr);
+ }
}
}
put_cpu();
@@ -520,7 +537,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
cpu = get_cpu();
/* handle small bases via the GDT because that's faster to
switch. */
- if (addr <= 0xffffffff) {
+ if (addr <= 0xffffffff && !fast_seg) {
set_32bit_tls(task, FS_TLS, addr);
if (doit) {
load_TLS(&task->thread, cpu);
@@ -535,7 +552,10 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
/* set the selector to 0 to not confuse
__switch_to */
loadsegment(fs, 0);
- ret = wrmsrl_safe(MSR_FS_BASE, addr);
+ if (fast_seg)
+ wrfsbase(addr);
+ else
+ ret = wrmsrl_safe(MSR_FS_BASE, addr);
}
}
put_cpu();
@@ -544,6 +564,8 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
unsigned long base;
if (task->thread.fsindex == FS_TLS_SEL)
base = read_32bit_tls(task, FS_TLS);
+ else if (doit && fast_seg)
+ base = rdfsbase();
else if (doit)
rdmsrl(MSR_FS_BASE, base);
else
@@ -558,9 +580,16 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
base = read_32bit_tls(task, GS_TLS);
else if (doit) {
savesegment(gs, gsindex);
- if (gsindex)
- rdmsrl(MSR_KERNEL_GS_BASE, base);
- else
+ if (gsindex) {
+ if (fast_seg) {
+ local_irq_disable();
+ swapgs();
+ base = rdgsbase();
+ swapgs();
+ local_irq_enable();
+ } else
+ rdmsrl(MSR_KERNEL_GS_BASE, base);
+ } else
base = task->thread.gs;
} else
base = task->thread.gs;
--
1.9.3
next prev parent reply other threads:[~2014-10-15 5:12 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-10-15 5:11 [PATCH 1/8] percpu: Add a DEFINE_PER_CPU_2PAGE_ALIGNED Andi Kleen
2014-10-15 5:11 ` [PATCH 2/8] x86: Naturally align the debug IST stack Andi Kleen
2014-10-15 5:11 ` [PATCH 3/8] x86: Add intrinsics/macros for new rd/wr fs/gs base instructions Andi Kleen
2014-10-15 5:11 ` [PATCH 4/8] x86: Add support for rd/wr fs/gs base Andi Kleen
2014-10-15 5:11 ` [PATCH 5/8] x86: Make old K8 swapgs workaround conditional Andi Kleen
2014-10-15 5:11 ` [PATCH 6/8] x86: Enumerate kernel FSGS capability in AT_HWCAP2 Andi Kleen
2014-10-15 5:11 ` [PATCH 7/8] x86: Add documentation for rd/wr fs/gs base Andi Kleen
2014-10-20 20:28 ` Konrad Rzeszutek Wilk
2014-10-15 5:11 ` Andi Kleen [this message]
2014-10-27 15:00 ` [PATCH 1/8] percpu: Add a DEFINE_PER_CPU_2PAGE_ALIGNED Tejun Heo
2014-11-10 23:55 Andi Kleen
2014-11-10 23:55 ` [PATCH 8/8] x86: Use rd/wr fs/gs base in arch_prctl Andi Kleen
2014-11-11 20:08 ` Andy Lutomirski
2015-04-10 15:50 Updated RD/WRFS/GSBASE patchkit Andi Kleen
2015-04-10 15:50 ` [PATCH 8/8] x86: Use rd/wr fs/gs base in arch_prctl Andi Kleen
2015-04-10 19:19 ` Andy Lutomirski
2015-04-10 19:58 ` Andi Kleen
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=1413349911-3620-8-git-send-email-andi@firstfloor.org \
--to=andi@firstfloor.org \
--cc=ak@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=x86@kernel.org \
/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