@@ -66,9 +66,15 @@ static inline void invlpgb_flush_user(unsigned long pcid,
static inline void __invlpgb_flush_user_nr_nosync(unsigned long pcid,
unsigned long addr,
u16 nr,
- bool pmd_stride)
+ bool pmd_stride,
+ bool freed_tables)
{
- __invlpgb(0, pcid, addr, nr - 1, pmd_stride, INVLPGB_PCID | INVLPGB_VA);
+ u8 flags = INVLPGB_PCID | INVLPGB_VA;
+
+ if (!freed_tables)
+ flags |= INVLPGB_FINAL_ONLY;
+
+ __invlpgb(0, pcid, addr, nr - 1, pmd_stride, flags);
}
/* Flush all mappings for a given PCID, not including globals. */
@@ -498,9 +498,10 @@ static inline void tlbsync(void)
static inline void invlpgb_flush_user_nr_nosync(unsigned long pcid,
unsigned long addr,
- u16 nr, bool pmd_stride)
+ u16 nr, bool pmd_stride,
+ bool freed_tables)
{
- __invlpgb_flush_user_nr_nosync(pcid, addr, nr, pmd_stride);
+ __invlpgb_flush_user_nr_nosync(pcid, addr, nr, pmd_stride, freed_tables);
if (!this_cpu_read(cpu_tlbstate.need_tlbsync))
this_cpu_write(cpu_tlbstate.need_tlbsync, true);
}
@@ -549,10 +550,10 @@ static void broadcast_tlb_flush(struct flush_tlb_info *info)
nr = min(maxnr, (info->end - addr) >> info->stride_shift);
nr = max(nr, 1);
- invlpgb_flush_user_nr_nosync(kern_pcid(asid), addr, nr, pmd);
+ invlpgb_flush_user_nr_nosync(kern_pcid(asid), addr, nr, pmd, info->freed_tables);
/* Do any CPUs supporting INVLPGB need PTI? */
if (static_cpu_has(X86_FEATURE_PTI))
- invlpgb_flush_user_nr_nosync(user_pcid(asid), addr, nr, pmd);
+ invlpgb_flush_user_nr_nosync(user_pcid(asid), addr, nr, pmd, info->freed_tables);
addr += nr << info->stride_shift;
} while (addr < info->end);
@@ -1715,10 +1716,10 @@ void arch_tlbbatch_add_pending(struct arch_tlbflush_unmap_batch *batch,
u16 asid = mm_global_asid(mm);
if (asid) {
- invlpgb_flush_user_nr_nosync(kern_pcid(asid), uaddr, 1, false);
+ invlpgb_flush_user_nr_nosync(kern_pcid(asid), uaddr, 1, false, false);
/* Do any CPUs supporting INVLPGB need PTI? */
if (static_cpu_has(X86_FEATURE_PTI))
- invlpgb_flush_user_nr_nosync(user_pcid(asid), uaddr, 1, false);
+ invlpgb_flush_user_nr_nosync(user_pcid(asid), uaddr, 1, false, false);
/*
* Some CPUs might still be using a local ASID for this