#define CPU_FTR_DAWR                   LONG_ASM_CONST(0x0400000000000000)
 #define CPU_FTR_DABRX                  LONG_ASM_CONST(0x0800000000000000)
 #define CPU_FTR_PMAO_BUG               LONG_ASM_CONST(0x1000000000000000)
+#define CPU_FTR_P9_TLBIE_BUG           LONG_ASM_CONST(0x2000000000000000)
 #define CPU_FTR_POWER9_DD1             LONG_ASM_CONST(0x4000000000000000)
 #define CPU_FTR_POWER9_DD2_1           LONG_ASM_CONST(0x8000000000000000)
 
            CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
            CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | \
            CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | \
-           CPU_FTR_PKEY)
+           CPU_FTR_PKEY | CPU_FTR_P9_TLBIE_BUG)
 #define CPU_FTRS_POWER9_DD1 ((CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD1) & \
                             (~CPU_FTR_SAO))
 #define CPU_FTRS_POWER9_DD2_0 CPU_FTRS_POWER9
 
                cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD1;
        else if ((version & 0xffffefff) == 0x004e0201)
                cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD2_1;
+
+       if ((version & 0xffff0000) == 0x004e0000)
+               cur_cpu_spec->cpu_features |= CPU_FTR_P9_TLBIE_BUG;
 }
 
 static void __init cpufeatures_setup_finished(void)
 
        asm volatile("ptesync": : :"memory");
        asm volatile(PPC_TLBIE_5(%0, %1, 0, 0, 1)
                     : : "r" (addr), "r" (kvm->arch.lpid) : "memory");
+       if (cpu_has_feature(CPU_FTR_P9_TLBIE_BUG))
+               asm volatile(PPC_TLBIE_5(%0, %1, 0, 0, 1)
+                            : : "r" (addr), "r" (kvm->arch.lpid) : "memory");
        asm volatile("ptesync": : :"memory");
 }
 
 
                        trace_tlbie(kvm->arch.lpid, 0, rbvalues[i],
                                kvm->arch.lpid, 0, 0, 0);
                }
+
+               if (cpu_has_feature(CPU_FTR_P9_TLBIE_BUG)) {
+                       /*
+                        * Need the extra ptesync to make sure we don't
+                        * re-order the tlbie
+                        */
+                       asm volatile("ptesync": : :"memory");
+                       asm volatile(PPC_TLBIE_5(%0,%1,0,0,0) : :
+                                    "r" (rbvalues[0]), "r" (kvm->arch.lpid));
+               }
+
                asm volatile("eieio; tlbsync; ptesync" : : : "memory");
                kvm->arch.tlbie_lock = 0;
        } else {
 
        return va;
 }
 
+static inline void fixup_tlbie(unsigned long vpn, int psize, int apsize, int ssize)
+{
+       if (cpu_has_feature(CPU_FTR_P9_TLBIE_BUG)) {
+               /* Need the extra ptesync to ensure we don't reorder tlbie*/
+               asm volatile("ptesync": : :"memory");
+               ___tlbie(vpn, psize, apsize, ssize);
+       }
+}
+
 static inline void __tlbie(unsigned long vpn, int psize, int apsize, int ssize)
 {
        unsigned long rb;
                asm volatile("ptesync": : :"memory");
        } else {
                __tlbie(vpn, psize, apsize, ssize);
+               fixup_tlbie(vpn, psize, apsize, ssize);
                asm volatile("eieio; tlbsync; ptesync": : :"memory");
        }
        if (lock_tlbie && !use_local)
  */
 static void native_flush_hash_range(unsigned long number, int local)
 {
-       unsigned long vpn;
+       unsigned long vpn = 0;
        unsigned long hash, index, hidx, shift, slot;
        struct hash_pte *hptep;
        unsigned long hpte_v;
                                __tlbie(vpn, psize, psize, ssize);
                        } pte_iterate_hashed_end();
                }
+               /*
+                * Just do one more with the last used values.
+                */
+               fixup_tlbie(vpn, psize, psize, ssize);
                asm volatile("eieio; tlbsync; ptesync":::"memory");
 
                if (lock_tlbie)
 
                             "r" (TLBIEL_INVAL_SET_LPID), "r" (lpid));
                trace_tlbie(lpid, 0, TLBIEL_INVAL_SET_LPID, lpid, 2, 0, 0);
        }
+       /* do we need fixup here ?*/
        asm volatile("eieio; tlbsync; ptesync" : : : "memory");
 }
 EXPORT_SYMBOL_GPL(mmu_partition_table_set_entry);
 
        trace_tlbie(0, 0, rb, rs, ric, prs, r);
 }
 
+static inline void fixup_tlbie(void)
+{
+       unsigned long pid = 0;
+       unsigned long va = ((1UL << 52) - 1);
+
+       if (cpu_has_feature(CPU_FTR_P9_TLBIE_BUG)) {
+               asm volatile("ptesync": : :"memory");
+               __tlbie_va(va, pid, mmu_get_ap(MMU_PAGE_64K), RIC_FLUSH_TLB);
+       }
+}
+
 /*
  * We use 128 set in radix mode and 256 set in hpt mode.
  */
        default:
                __tlbie_pid(pid, RIC_FLUSH_ALL);
        }
+       fixup_tlbie();
        asm volatile("eieio; tlbsync; ptesync": : :"memory");
 }
 
 
        asm volatile("ptesync": : :"memory");
        __tlbie_va(va, pid, ap, ric);
+       fixup_tlbie();
        asm volatile("eieio; tlbsync; ptesync": : :"memory");
 }
 
        if (also_pwc)
                __tlbie_pid(pid, RIC_FLUSH_PWC);
        __tlbie_va_range(start, end, pid, page_size, psize);
+       fixup_tlbie();
        asm volatile("eieio; tlbsync; ptesync": : :"memory");
 }
 
                        if (hflush)
                                __tlbie_va_range(hstart, hend, pid,
                                                HPAGE_PMD_SIZE, MMU_PAGE_2M);
+                       fixup_tlbie();
                        asm volatile("eieio; tlbsync; ptesync": : :"memory");
                }
        }