Merge tag 'x86_mm_for_6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
[platform/kernel/linux-rpi.git] / arch / x86 / mm / tlb.c
index 2d25391..453ea95 100644 (file)
@@ -1142,21 +1142,28 @@ void flush_tlb_one_kernel(unsigned long addr)
  */
 STATIC_NOPV void native_flush_tlb_one_user(unsigned long addr)
 {
-       u32 loaded_mm_asid = this_cpu_read(cpu_tlbstate.loaded_mm_asid);
+       u32 loaded_mm_asid;
+       bool cpu_pcide;
 
+       /* Flush 'addr' from the kernel PCID: */
        asm volatile("invlpg (%0)" ::"r" (addr) : "memory");
 
+       /* If PTI is off there is no user PCID and nothing to flush. */
        if (!static_cpu_has(X86_FEATURE_PTI))
                return;
 
+       loaded_mm_asid = this_cpu_read(cpu_tlbstate.loaded_mm_asid);
+       cpu_pcide      = this_cpu_read(cpu_tlbstate.cr4) & X86_CR4_PCIDE;
+
        /*
-        * Some platforms #GP if we call invpcid(type=1/2) before CR4.PCIDE=1.
-        * Just use invalidate_user_asid() in case we are called early.
+        * invpcid_flush_one(pcid>0) will #GP if CR4.PCIDE==0.  Check
+        * 'cpu_pcide' to ensure that *this* CPU will not trigger those
+        * #GP's even if called before CR4.PCIDE has been initialized.
         */
-       if (!this_cpu_has(X86_FEATURE_INVPCID_SINGLE))
-               invalidate_user_asid(loaded_mm_asid);
-       else
+       if (boot_cpu_has(X86_FEATURE_INVPCID) && cpu_pcide)
                invpcid_flush_one(user_pcid(loaded_mm_asid), addr);
+       else
+               invalidate_user_asid(loaded_mm_asid);
 }
 
 void flush_tlb_one_user(unsigned long addr)