From: Nadav Amit <namit@vmware.com>
To: Ingo Molnar <mingo@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>,
Andy Lutomirski <luto@kernel.org>,
Peter Zijlstra <peterz@infradead.org>,
Dave Hansen <dave.hansen@linux.intel.com>,
Willy Tarreau <w@1wt.eu>, Nadav Amit <nadav.amit@gmail.com>,
<x86@kernel.org>, <linux-kernel@vger.kernel.org>,
Nadav Amit <namit@vmware.com>
Subject: [PATCH RFC v2 3/6] x86: Switching page-table isolation
Date: Thu, 15 Feb 2018 08:35:59 -0800 [thread overview]
Message-ID: <20180215163602.61162-4-namit@vmware.com> (raw)
In-Reply-To: <20180215163602.61162-1-namit@vmware.com>
On context switch, switch the page-table isolation according to the
new task. Accordingly, restore or remove CS64.
The different types of disabling are kept as a bitmap in order to
quickly check whether a certain type of disabling was switched, although
it is assumed only a single type is set at a given time. The code
prepares the facility for future disabling of PTI in other means
(prctl). To do so, the logic means that greater "disabling" value means
stronger disabling, and should override lower ones.
Signed-off-by: Nadav Amit <namit@vmware.com>
---
arch/x86/include/asm/pti.h | 22 ++++++++++++++++++++++
arch/x86/include/asm/tlbflush.h | 12 ++++++++++++
arch/x86/mm/tlb.c | 25 +++++++++++++++++++++++++
3 files changed, 59 insertions(+)
diff --git a/arch/x86/include/asm/pti.h b/arch/x86/include/asm/pti.h
index 96a5fbfedf7a..78a333699874 100644
--- a/arch/x86/include/asm/pti.h
+++ b/arch/x86/include/asm/pti.h
@@ -3,6 +3,11 @@
#define _ASM_X86_PTI_H
#ifndef __ASSEMBLY__
+#include <asm/desc.h>
+
+#define PTI_DISABLE_OFF (0)
+#define PTI_DISABLE_IA32 (1 << 0)
+
#ifdef CONFIG_PAGE_TABLE_ISOLATION
static inline unsigned short mm_pti_disable(struct mm_struct *mm)
{
@@ -12,10 +17,27 @@ static inline unsigned short mm_pti_disable(struct mm_struct *mm)
return mm->context.pti_disable;
}
+static inline void pti_update_user_cs64(unsigned short prev_pti_disable,
+ unsigned short next_pti_disable)
+{
+ struct desc_struct user_cs, *d;
+
+ if ((prev_pti_disable ^ next_pti_disable) & PTI_DISABLE_IA32)
+ return;
+
+ d = get_cpu_gdt_rw(smp_processor_id());
+ user_cs = d[GDT_ENTRY_DEFAULT_USER_CS];
+ user_cs.p = !(next_pti_disable & PTI_DISABLE_IA32);
+ write_gdt_entry(d, GDT_ENTRY_DEFAULT_USER_CS, &user_cs, DESCTYPE_S);
+}
+
extern void pti_init(void);
extern void pti_check_boottime_disable(void);
#else
static inline unsigned short mm_pti_disable(struct mm_struct *mm) { return 0; }
+static inline unsigned short mm_pti_disable(struct mm_struct *mm);
+static inline void pti_update_user_cs64(unsigned short prev_pti_disable,
+ unsigned short next_pti_disable) { }
static inline void pti_check_boottime_disable(void) { }
#endif
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
index cf91a484bb41..ea65cf951c49 100644
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -310,6 +310,18 @@ static inline unsigned short cpu_pti_disable(void)
return this_cpu_read(cpu_tlbstate.pti_disable);
}
+static inline void set_cpu_pti_disable(unsigned short disable)
+{
+ /*
+ * Enabling/disabling CS64 and updating the state must be done
+ * atomically
+ */
+ WARN_ON_ONCE(preemptible());
+
+ pti_update_user_cs64(cpu_pti_disable(), disable);
+ this_cpu_write(cpu_tlbstate.pti_disable, disable);
+}
+
/*
* Save some of cr4 feature set we're using (e.g. Pentium 4MB
* enable and PPro Global page enable), so that any CPU's that boot
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 5bfe61a5e8e3..c67ef3fb4f35 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -178,6 +178,28 @@ static void sync_current_stack_to_mm(struct mm_struct *mm)
}
}
}
+static void switch_pti_disable(struct mm_struct *mm)
+{
+#ifdef CONFIG_PAGE_TABLE_ISOLATION
+ unsigned short prev_pti_disable, next_pti_disable;
+
+ if (!static_cpu_has(X86_FEATURE_PTI))
+ return;
+
+ prev_pti_disable = cpu_pti_disable();
+
+ /*
+ * Avoid concurrent changes to mm_pti_disable()), since we need to
+ * ensure both CS64 and the CPU indication are identical
+ */
+ next_pti_disable = READ_ONCE(mm->context.pti_disable);
+
+ if (prev_pti_disable == next_pti_disable)
+ return;
+
+ set_cpu_pti_disable(next_pti_disable);
+#endif
+}
void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk)
@@ -292,6 +314,9 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
trace_tlb_flush_rcuidle(TLB_FLUSH_ON_TASK_SWITCH, 0);
}
+ /* Disable/reenable page-table isolation as needed */
+ switch_pti_disable(next);
+
this_cpu_write(cpu_tlbstate.loaded_mm, next);
this_cpu_write(cpu_tlbstate.loaded_mm_asid, new_asid);
}
--
2.14.1
next prev parent reply other threads:[~2018-02-15 16:36 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-15 16:35 [PATCH RFC v2 0/6] x86: Disabling PTI in compatibility mode Nadav Amit
2018-02-15 16:35 ` [PATCH RFC v2 1/6] x86: Skip PTI when disable indication is set Nadav Amit
2018-02-15 18:10 ` Dave Hansen
2018-02-15 19:51 ` Andy Lutomirski
2018-02-15 20:51 ` Nadav Amit
2018-02-15 23:35 ` Andy Lutomirski
2018-02-15 16:35 ` [PATCH RFC v2 2/6] x86: Save pti_disable for each mm_context Nadav Amit
2018-02-15 16:35 ` Nadav Amit [this message]
2018-02-15 16:36 ` [PATCH RFC v2 4/6] x86: Disable PTI on compatibility mode Nadav Amit
2018-02-15 20:02 ` Andy Lutomirski
2018-02-15 20:58 ` Nadav Amit
2018-02-15 23:29 ` Andy Lutomirski
2018-02-16 0:08 ` Linus Torvalds
2018-02-16 0:22 ` Nadav Amit
2018-02-16 0:42 ` Linus Torvalds
2018-02-16 3:03 ` Andy Lutomirski
2018-02-16 4:55 ` Nadav Amit
2018-02-16 0:35 ` Andrew Cooper
2018-02-16 15:20 ` Andy Lutomirski
2018-02-16 7:11 ` Cyrill Gorcunov
2018-02-16 22:07 ` Dmitry Safonov
2018-02-16 22:11 ` Nadav Amit
2018-02-16 16:25 ` Dmitry Safonov
2018-02-15 16:36 ` [PATCH RFC v2 5/6] x86: Use global pages when PTI is disabled Nadav Amit
2018-02-15 16:54 ` Dave Hansen
2018-02-15 17:36 ` Nadav Amit
2018-02-15 17:47 ` Nadav Amit
2018-02-15 18:08 ` Dave Hansen
2018-02-15 19:53 ` Andy Lutomirski
2018-02-15 20:32 ` Dave Hansen
2018-02-15 20:45 ` Nadav Amit
2018-02-15 16:36 ` [PATCH RFC v2 6/6] selftest: x86: test using CS64 on compatibility-mode Nadav Amit
2018-02-16 0:21 ` [PATCH RFC v2 0/6] x86: Disabling PTI in compatibility mode Dave Hansen
2018-02-16 0:25 ` Nadav Amit
2018-02-16 0:42 ` Dave Hansen
2018-02-16 0:48 ` Nadav Amit
2018-02-16 0:45 ` Andrew Cooper
2018-02-16 0:51 ` Nadav Amit
2018-02-16 1:04 ` Andrew Cooper
2018-02-16 3:05 ` Andy Lutomirski
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=20180215163602.61162-4-namit@vmware.com \
--to=namit@vmware.com \
--cc=dave.hansen@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@kernel.org \
--cc=mingo@redhat.com \
--cc=nadav.amit@gmail.com \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
--cc=w@1wt.eu \
--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