[PATCH] LoongArch: align range before sizing in local_flush_tlb_kernel_range

Song Hu posted 1 patch 1 week, 1 day ago
arch/loongarch/mm/tlb.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
[PATCH] LoongArch: align range before sizing in local_flush_tlb_kernel_range
Posted by Song Hu 1 week, 1 day ago
local_flush_tlb_kernel_range() sizes the flush from the unaligned caller
range and aligns start/end only afterwards — the opposite order of its
sibling local_flush_tlb_range(), which aligns first.  Align start/end
first, then size, to match the sibling.

The order matters for unaligned ranges: the original size is derived from
the raw caller range, not the 2-page-aligned range the per-entry invtlb()
loop actually iterates, so it can fall one entry short, and the
tlbsize/8-vs-tlbsize/2 threshold may then pick the per-entry loop when a
full local_flush_tlb_kernel() would be cheaper.

Both strategies flush correctly; the change only makes the sizing heuristic
match the sibling and reflect the real flush count.

Signed-off-by: Song Hu <husong@kylinos.cn>
---
 arch/loongarch/mm/tlb.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/arch/loongarch/mm/tlb.c b/arch/loongarch/mm/tlb.c
index 4b3d7120da73..a3c90841edbd 100644
--- a/arch/loongarch/mm/tlb.c
+++ b/arch/loongarch/mm/tlb.c
@@ -90,16 +90,13 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
 	unsigned long size, flags;
 
 	local_irq_save(flags);
-	size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
-	size = (size + 1) >> 1;
+	start &= (PAGE_MASK << 1);
+	end += ((PAGE_SIZE << 1) - 1);
+	end &= (PAGE_MASK << 1);
+	size = (end - start) >> (PAGE_SHIFT + 1);
 	if (size <= (current_cpu_data.tlbsizestlbsets ?
 		     current_cpu_data.tlbsize / 8 :
 		     current_cpu_data.tlbsize / 2)) {
-
-		start &= (PAGE_MASK << 1);
-		end += ((PAGE_SIZE << 1) - 1);
-		end &= (PAGE_MASK << 1);
-
 		while (start < end) {
 			invtlb_addr(INVTLB_ADDR_GTRUE_OR_ASID, 0, start);
 			start += (PAGE_SIZE << 1);
-- 
2.43.0

Re: [PATCH] LoongArch: align range before sizing in local_flush_tlb_kernel_range
Posted by Huacai Chen 1 week, 1 day ago
Hi, Song,

On Fri, Jul 17, 2026 at 11:28 AM Song Hu <husong@kylinos.cn> wrote:
>
> local_flush_tlb_kernel_range() sizes the flush from the unaligned caller
> range and aligns start/end only afterwards — the opposite order of its
> sibling local_flush_tlb_range(), which aligns first.  Align start/end
> first, then size, to match the sibling.
>
> The order matters for unaligned ranges: the original size is derived from
> the raw caller range, not the 2-page-aligned range the per-entry invtlb()
> loop actually iterates, so it can fall one entry short, and the
> tlbsize/8-vs-tlbsize/2 threshold may then pick the per-entry loop when a
> full local_flush_tlb_kernel() would be cheaper.
>
> Both strategies flush correctly; the change only makes the sizing heuristic
> match the sibling and reflect the real flush count.
Don't fix fake bugs! You know both are correct, so don't change it.

Huacai

>
> Signed-off-by: Song Hu <husong@kylinos.cn>
> ---
>  arch/loongarch/mm/tlb.c | 11 ++++-------
>  1 file changed, 4 insertions(+), 7 deletions(-)
>
> diff --git a/arch/loongarch/mm/tlb.c b/arch/loongarch/mm/tlb.c
> index 4b3d7120da73..a3c90841edbd 100644
> --- a/arch/loongarch/mm/tlb.c
> +++ b/arch/loongarch/mm/tlb.c
> @@ -90,16 +90,13 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
>         unsigned long size, flags;
>
>         local_irq_save(flags);
> -       size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
> -       size = (size + 1) >> 1;
> +       start &= (PAGE_MASK << 1);
> +       end += ((PAGE_SIZE << 1) - 1);
> +       end &= (PAGE_MASK << 1);
> +       size = (end - start) >> (PAGE_SHIFT + 1);
>         if (size <= (current_cpu_data.tlbsizestlbsets ?
>                      current_cpu_data.tlbsize / 8 :
>                      current_cpu_data.tlbsize / 2)) {
> -
> -               start &= (PAGE_MASK << 1);
> -               end += ((PAGE_SIZE << 1) - 1);
> -               end &= (PAGE_MASK << 1);
> -
>                 while (start < end) {
>                         invtlb_addr(INVTLB_ADDR_GTRUE_OR_ASID, 0, start);
>                         start += (PAGE_SIZE << 1);
> --
> 2.43.0
>