Skip to content

Commit ab51301

Browse files
rpedgecoPeter Zijlstra
authored andcommitted
x86/mm/cpa: Flush direct map alias during cpa
As an optimization, cpa_flush() was changed to optionally only flush the range in @cpa if it was small enough. However, this range does not include any direct map aliases changed in cpa_process_alias(). So small set_memory_() calls that touch that alias don't get the direct map changes flushed. This situation can happen when the virtual address taking variants are passed an address in vmalloc or modules space. In these cases, force a full TLB flush. Note this issue does not extend to cases where the set_memory_() calls are passed a direct map address, or page array, etc, as the primary target. In those cases the direct map would be flushed. Fixes: 935f583 ("x86/mm/cpa: Optimize cpa_flush_array() TLB invalidation") Signed-off-by: Rick Edgecombe <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 53fb6e9 commit ab51301

File tree

1 file changed

+8
-4
lines changed

1 file changed

+8
-4
lines changed

arch/x86/mm/pat/set_memory.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ struct cpa_data {
4343
unsigned long pfn;
4444
unsigned int flags;
4545
unsigned int force_split : 1,
46-
force_static_prot : 1;
46+
force_static_prot : 1,
47+
force_flush_all : 1;
4748
struct page **pages;
4849
};
4950

@@ -355,10 +356,10 @@ static void cpa_flush(struct cpa_data *data, int cache)
355356
return;
356357
}
357358

358-
if (cpa->numpages <= tlb_single_page_flush_ceiling)
359-
on_each_cpu(__cpa_flush_tlb, cpa, 1);
360-
else
359+
if (cpa->force_flush_all || cpa->numpages > tlb_single_page_flush_ceiling)
361360
flush_tlb_all();
361+
else
362+
on_each_cpu(__cpa_flush_tlb, cpa, 1);
362363

363364
if (!cache)
364365
return;
@@ -1598,6 +1599,8 @@ static int cpa_process_alias(struct cpa_data *cpa)
15981599
alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
15991600
alias_cpa.curpage = 0;
16001601

1602+
cpa->force_flush_all = 1;
1603+
16011604
ret = __change_page_attr_set_clr(&alias_cpa, 0);
16021605
if (ret)
16031606
return ret;
@@ -1618,6 +1621,7 @@ static int cpa_process_alias(struct cpa_data *cpa)
16181621
alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
16191622
alias_cpa.curpage = 0;
16201623

1624+
cpa->force_flush_all = 1;
16211625
/*
16221626
* The high mapping range is imprecise, so ignore the
16231627
* return value.

0 commit comments

Comments
 (0)