static inline void __native_flush_tlb(void)
{
+ if (static_cpu_has(X86_FEATURE_INVPCID)) {
+ u64 descriptor[2];
+
+ descriptor[0] = PCID_KERNEL;
+ asm volatile(__ASM_INVPCID : : "d"(&descriptor), "a"(INVPCID_ALL_NONGLOBAL) : "memory");
+ return;
+ }
+
+#if defined(CONFIG_X86_64) && defined(CONFIG_PAX_MEMORY_UDEREF)
+ if (static_cpu_has(X86_FEATURE_PCID)) {
+ unsigned int cpu = raw_get_cpu();
+
+ native_write_cr3(__pa(get_cpu_pgd(cpu, user)) | PCID_USER);
+ native_write_cr3(__pa(get_cpu_pgd(cpu, kernel)) | PCID_KERNEL);
+ raw_put_cpu_no_resched();
+ return;
+ }
+#endif
+
+ /*
+ * If current->mm == NULL then we borrow a mm which may change during a
+ * task switch and therefore we must not be preempted while we write CR3
+ * back:
+ */
+ preempt_disable();
native_write_cr3(native_read_cr3());
+ preempt_enable();
}
static inline void __native_flush_tlb_global_irq_disabled(void)