On 09/07/2024 12:57, Will Deacon wrote: > On Mon, Jul 01, 2024 at 10:54:58AM +0100, Steven Price wrote: >> When __change_memory_common() is purely setting the valid bit on a PTE >> (e.g. via the set_memory_valid() call) there is no need for a TLBI as >> either the entry isn't changing (the valid bit was already set) or the >> entry was invalid and so should not have been cached in the TLB. >> >> Signed-off-by: Steven Price <steven.price@xxxxxxx> >> --- >> v4: New patch >> --- >> arch/arm64/mm/pageattr.c | 8 +++++++- >> 1 file changed, 7 insertions(+), 1 deletion(-) >> >> diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c >> index 0e270a1c51e6..547a9e0b46c2 100644 >> --- a/arch/arm64/mm/pageattr.c >> +++ b/arch/arm64/mm/pageattr.c >> @@ -60,7 +60,13 @@ static int __change_memory_common(unsigned long start, unsigned long size, >> ret = apply_to_page_range(&init_mm, start, size, change_page_range, >> &data); >> >> - flush_tlb_kernel_range(start, start + size); >> + /* >> + * If the memory is being made valid without changing any other bits >> + * then a TLBI isn't required as a non-valid entry cannot be cached in >> + * the TLB. >> + */ >> + if (pgprot_val(set_mask) != PTE_VALID || pgprot_val(clear_mask)) >> + flush_tlb_kernel_range(start, start + size); >> return ret; > > Can you elaborate on when this actually happens, please? It feels like a > case of "Doctor, it hurts when I do this" rather than something we should > be trying to short-circuit in the low-level code. This is for the benefit of the following patch. When transitioning a page between shared and private we need to change the IPA (to set/clear the top bit). This requires a break-before-make - see __set_memory_enc_dec() in the following patch. The easiest way of implementing the code was to just call __change_memory_common() twice - once to make the entry invalid and then again to make it valid with the new IPA. But that led to a double TLBI which Catalin didn't like[1]. So this patch removes the unnecessary second TLBI by detecting that we're just making the entry valid. Or at least it would if I hadn't screwed up... I should have changed the following patch to ensure that the second call to __change_memory_common was only setting the PTE_VALID bit and not changing anything else (so that the TLBI could be skipped) and forgot to do that. So thanks for making me take a look at this again! Thanks, Steve [1] https://lore.kernel.org/lkml/Zmc3euO2YGh-g9Th@xxxxxxx/