[PATCH] powerpc/32s: Don't flush all TLBs when flushing one page

Subsystems: linux for powerpc (32-bit and 64-bit), the rest

STALE2397d

8 messages, 2 authors, 2020-02-01 · open the first message on its own page

[PATCH] powerpc/32s: Don't flush all TLBs when flushing one page

From: Christophe Leroy <hidden>
Date: 2020-01-31 15:37:37

When flushing a range, the flushing function flushes all TLBs.

When the range is a single page, do a page flush instead.

Signed-off-by: Christophe Leroy <redacted>
---
 arch/powerpc/mm/book3s32/tlb.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/mm/book3s32/tlb.c b/arch/powerpc/mm/book3s32/tlb.c
index 2fcd321040ff..8e0089065a7e 100644
--- a/arch/powerpc/mm/book3s32/tlb.c
+++ b/arch/powerpc/mm/book3s32/tlb.c
@@ -79,14 +79,17 @@ static void flush_range(struct mm_struct *mm, unsigned long start,
 	int count;
 	unsigned int ctx = mm->context.id;
 
+	start &= PAGE_MASK;
+	end = (end - 1) | ~PAGE_MASK;
 	if (!Hash) {
-		_tlbia();
+		if (end - start == PAGE_SIZE)
+			_tlbie(start);
+		else
+			_tlbia();
 		return;
 	}
-	start &= PAGE_MASK;
 	if (start >= end)
 		return;
-	end = (end - 1) | ~PAGE_MASK;
 	pmd = pmd_offset(pud_offset(pgd_offset(mm, start), start), start);
 	for (;;) {
 		pmd_end = ((start + PGDIR_SIZE) & PGDIR_MASK) - 1;
-- 
2.25.0

Re: [PATCH] powerpc/32s: Don't flush all TLBs when flushing one page

From: Segher Boessenkool <hidden>
Date: 2020-01-31 15:52:16

On Fri, Jan 31, 2020 at 03:37:34PM +0000, Christophe Leroy wrote:
When the range is a single page, do a page flush instead.
+	start &= PAGE_MASK;
+	end = (end - 1) | ~PAGE_MASK;
 	if (!Hash) {
-		_tlbia();
+		if (end - start == PAGE_SIZE)
+			_tlbie(start);
+		else
+			_tlbia();
 		return;
 	}
For just one page, you get  end - start == 0  actually?


Segher

Re: [PATCH] powerpc/32s: Don't flush all TLBs when flushing one page

From: Christophe Leroy <hidden>
Date: 2020-01-31 16:15:31


Le 31/01/2020 à 16:51, Segher Boessenkool a écrit :
On Fri, Jan 31, 2020 at 03:37:34PM +0000, Christophe Leroy wrote:
quoted
When the range is a single page, do a page flush instead.
quoted
+	start &= PAGE_MASK;
+	end = (end - 1) | ~PAGE_MASK;
  	if (!Hash) {
-		_tlbia();
+		if (end - start == PAGE_SIZE)
+			_tlbie(start);
+		else
+			_tlbia();
  		return;
  	}
For just one page, you get  end - start == 0  actually?
Oops, good catch.

Indeed you don't get PAGE_SIZE but (PAGE_SIZE - 1) for just one page.

Christophe

Re: [PATCH] powerpc/32s: Don't flush all TLBs when flushing one page

From: Segher Boessenkool <hidden>
Date: 2020-01-31 19:39:04

On Fri, Jan 31, 2020 at 05:15:20PM +0100, Christophe Leroy wrote:
Le 31/01/2020 à 16:51, Segher Boessenkool a écrit :
quoted
On Fri, Jan 31, 2020 at 03:37:34PM +0000, Christophe Leroy wrote:
quoted
When the range is a single page, do a page flush instead.
quoted
+	start &= PAGE_MASK;
+	end = (end - 1) | ~PAGE_MASK;
 	if (!Hash) {
-		_tlbia();
+		if (end - start == PAGE_SIZE)
+			_tlbie(start);
+		else
+			_tlbia();
 		return;
 	}
For just one page, you get  end - start == 0  actually?
Oops, good catch.

Indeed you don't get PAGE_SIZE but (PAGE_SIZE - 1) for just one page.
You have all low bits masked off in both start and end, so you get zero.
You could make the condion read "if (start == end)?

Maybe a nicer way to describe what you do is "if start and end are on the
same memory page, flush that page."


Segher

Re: [PATCH] powerpc/32s: Don't flush all TLBs when flushing one page

From: Christophe Leroy <hidden>
Date: 2020-02-01 07:27:10


Le 31/01/2020 à 20:38, Segher Boessenkool a écrit :
On Fri, Jan 31, 2020 at 05:15:20PM +0100, Christophe Leroy wrote:
quoted
Le 31/01/2020 à 16:51, Segher Boessenkool a écrit :
quoted
On Fri, Jan 31, 2020 at 03:37:34PM +0000, Christophe Leroy wrote:
quoted
When the range is a single page, do a page flush instead.
quoted
+	start &= PAGE_MASK;
+	end = (end - 1) | ~PAGE_MASK;
  	if (!Hash) {
-		_tlbia();
+		if (end - start == PAGE_SIZE)
+			_tlbie(start);
+		else
+			_tlbia();
  		return;
  	}
For just one page, you get  end - start == 0  actually?
Oops, good catch.

Indeed you don't get PAGE_SIZE but (PAGE_SIZE - 1) for just one page.
You have all low bits masked off in both start and end, so you get zero.
You could make the condion read "if (start == end)?
No, in end the low bits are set, that's a BIT OR with ~PAGE_MASK, so it 
sets all low bits to 1.

Christophe

Re: [PATCH] powerpc/32s: Don't flush all TLBs when flushing one page

From: Segher Boessenkool <hidden>
Date: 2020-02-01 14:07:09

On Sat, Feb 01, 2020 at 08:27:03AM +0100, Christophe Leroy wrote:
Le 31/01/2020 à 20:38, Segher Boessenkool a écrit :
quoted
On Fri, Jan 31, 2020 at 05:15:20PM +0100, Christophe Leroy wrote:
quoted
Le 31/01/2020 à 16:51, Segher Boessenkool a écrit :
quoted
On Fri, Jan 31, 2020 at 03:37:34PM +0000, Christophe Leroy wrote:
quoted
When the range is a single page, do a page flush instead.
quoted
+	start &= PAGE_MASK;
+	end = (end - 1) | ~PAGE_MASK;
 	if (!Hash) {
-		_tlbia();
+		if (end - start == PAGE_SIZE)
+			_tlbie(start);
+		else
+			_tlbia();
 		return;
 	}
For just one page, you get  end - start == 0  actually?
Oops, good catch.

Indeed you don't get PAGE_SIZE but (PAGE_SIZE - 1) for just one page.
You have all low bits masked off in both start and end, so you get zero.
You could make the condion read "if (start == end)?
No, in end the low bits are set, that's a BIT OR with ~PAGE_MASK, so it 
sets all low bits to 1.
Oh, wow, yes, I cannot read apparently.

Maybe there are some ROUND_DOWN and ROUND_UP macros you could use?


Segher

Re: [PATCH] powerpc/32s: Don't flush all TLBs when flushing one page

From: Christophe Leroy <hidden>
Date: 2020-02-01 14:53:17


Le 01/02/2020 à 15:06, Segher Boessenkool a écrit :
On Sat, Feb 01, 2020 at 08:27:03AM +0100, Christophe Leroy wrote:
quoted
Le 31/01/2020 à 20:38, Segher Boessenkool a écrit :
quoted
On Fri, Jan 31, 2020 at 05:15:20PM +0100, Christophe Leroy wrote:
quoted
Le 31/01/2020 à 16:51, Segher Boessenkool a écrit :
quoted
On Fri, Jan 31, 2020 at 03:37:34PM +0000, Christophe Leroy wrote:
quoted
When the range is a single page, do a page flush instead.
quoted
+	start &= PAGE_MASK;
+	end = (end - 1) | ~PAGE_MASK;
  	if (!Hash) {
-		_tlbia();
+		if (end - start == PAGE_SIZE)
+			_tlbie(start);
+		else
+			_tlbia();
  		return;
  	}
For just one page, you get  end - start == 0  actually?
Oops, good catch.

Indeed you don't get PAGE_SIZE but (PAGE_SIZE - 1) for just one page.
You have all low bits masked off in both start and end, so you get zero.
You could make the condion read "if (start == end)?
No, in end the low bits are set, that's a BIT OR with ~PAGE_MASK, so it
sets all low bits to 1.
Oh, wow, yes, I cannot read apparently.

Maybe there are some ROUND_DOWN and ROUND_UP macros you could use?
Yes but my intention was to modify the existing code as less as possible.
What do you think about version v2 of the patch ?

Christophe

Re: [PATCH] powerpc/32s: Don't flush all TLBs when flushing one page

From: Segher Boessenkool <hidden>
Date: 2020-02-01 16:18:07

On Sat, Feb 01, 2020 at 03:53:12PM +0100, Christophe Leroy wrote:
quoted
quoted
No, in end the low bits are set, that's a BIT OR with ~PAGE_MASK, so it
sets all low bits to 1.
Oh, wow, yes, I cannot read apparently.

Maybe there are some ROUND_DOWN and ROUND_UP macros you could use?
Yes but my intention was to modify the existing code as less as possible.
What do you think about version v2 of the patch ?
It looked fine to me.

Add my

Reviewed-by: Segher Boessenkool <redacted>

if you want.


Segher
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help