| From: Andy Lutomirski <luto@kernel.org> |
| Date: Fri, 29 Jan 2016 11:42:57 -0800 |
| Subject: x86/mm: Add INVPCID helpers |
| |
| commit 060a402a1ddb551455ee410de2eadd3349f2801b upstream. |
| |
| This adds helpers for each of the four currently-specified INVPCID |
| modes. |
| |
| Signed-off-by: Andy Lutomirski <luto@kernel.org> |
| Reviewed-by: Borislav Petkov <bp@suse.de> |
| Cc: Andrew Morton <akpm@linux-foundation.org> |
| Cc: Andrey Ryabinin <aryabinin@virtuozzo.com> |
| Cc: Andy Lutomirski <luto@amacapital.net> |
| Cc: Borislav Petkov <bp@alien8.de> |
| Cc: Brian Gerst <brgerst@gmail.com> |
| Cc: Dave Hansen <dave.hansen@linux.intel.com> |
| Cc: Denys Vlasenko <dvlasenk@redhat.com> |
| Cc: H. Peter Anvin <hpa@zytor.com> |
| Cc: Linus Torvalds <torvalds@linux-foundation.org> |
| Cc: Luis R. Rodriguez <mcgrof@suse.com> |
| Cc: Oleg Nesterov <oleg@redhat.com> |
| Cc: Peter Zijlstra <peterz@infradead.org> |
| Cc: Thomas Gleixner <tglx@linutronix.de> |
| Cc: Toshi Kani <toshi.kani@hp.com> |
| Cc: linux-mm@kvack.org |
| Link: http://lkml.kernel.org/r/8a62b23ad686888cee01da134c91409e22064db9.1454096309.git.luto@kernel.org |
| Signed-off-by: Ingo Molnar <mingo@kernel.org> |
| Cc: Hugh Dickins <hughd@google.com> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| arch/x86/include/asm/tlbflush.h | 48 +++++++++++++++++++++++++++++++++++++++++ |
| 1 file changed, 48 insertions(+) |
| |
| diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h |
| index a7973ddf2d1b..22089098e4fd 100644 |
| --- a/arch/x86/include/asm/tlbflush.h |
| +++ b/arch/x86/include/asm/tlbflush.h |
| @@ -7,6 +7,54 @@ |
| #include <asm/processor.h> |
| #include <asm/system.h> |
| |
| +static inline void __invpcid(unsigned long pcid, unsigned long addr, |
| + unsigned long type) |
| +{ |
| + u64 desc[2] = { pcid, addr }; |
| + |
| + /* |
| + * The memory clobber is because the whole point is to invalidate |
| + * stale TLB entries and, especially if we're flushing global |
| + * mappings, we don't want the compiler to reorder any subsequent |
| + * memory accesses before the TLB flush. |
| + * |
| + * The hex opcode is invpcid (%ecx), %eax in 32-bit mode and |
| + * invpcid (%rcx), %rax in long mode. |
| + */ |
| + asm volatile (".byte 0x66, 0x0f, 0x38, 0x82, 0x01" |
| + : : "m" (desc), "a" (type), "c" (desc) : "memory"); |
| +} |
| + |
| +#define INVPCID_TYPE_INDIV_ADDR 0 |
| +#define INVPCID_TYPE_SINGLE_CTXT 1 |
| +#define INVPCID_TYPE_ALL_INCL_GLOBAL 2 |
| +#define INVPCID_TYPE_ALL_NON_GLOBAL 3 |
| + |
| +/* Flush all mappings for a given pcid and addr, not including globals. */ |
| +static inline void invpcid_flush_one(unsigned long pcid, |
| + unsigned long addr) |
| +{ |
| + __invpcid(pcid, addr, INVPCID_TYPE_INDIV_ADDR); |
| +} |
| + |
| +/* Flush all mappings for a given PCID, not including globals. */ |
| +static inline void invpcid_flush_single_context(unsigned long pcid) |
| +{ |
| + __invpcid(pcid, 0, INVPCID_TYPE_SINGLE_CTXT); |
| +} |
| + |
| +/* Flush all mappings, including globals, for all PCIDs. */ |
| +static inline void invpcid_flush_all(void) |
| +{ |
| + __invpcid(0, 0, INVPCID_TYPE_ALL_INCL_GLOBAL); |
| +} |
| + |
| +/* Flush all mappings for all PCIDs except globals. */ |
| +static inline void invpcid_flush_all_nonglobals(void) |
| +{ |
| + __invpcid(0, 0, INVPCID_TYPE_ALL_NON_GLOBAL); |
| +} |
| + |
| #ifdef CONFIG_PARAVIRT |
| #include <asm/paravirt.h> |
| #else |
| |