linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] powerpc: mm: radix_tlb: rearrange the if-else block
@ 2021-11-25 15:44 Anders Roxell
  2021-11-26 13:43 ` Christophe Leroy
  0 siblings, 1 reply; 5+ messages in thread
From: Anders Roxell @ 2021-11-25 15:44 UTC (permalink / raw)
  To: benh, paulus
  Cc: nathan, ndesaulniers, linuxppc-dev, linux-kernel, llvm,
	Anders Roxell, Arnd Bergmann

Clang warns:

arch/powerpc/mm/book3s64/radix_tlb.c:1191:23: error: variable 'hstart' is uninitialized when used here [-Werror,-Wuninitialized]
                                __tlbiel_va_range(hstart, hend, pid,
                                                  ^~~~~~
arch/powerpc/mm/book3s64/radix_tlb.c:1175:23: note: initialize the variable 'hstart' to silence this warning
                unsigned long hstart, hend;
                                    ^
                                     = 0
arch/powerpc/mm/book3s64/radix_tlb.c:1191:31: error: variable 'hend' is uninitialized when used here [-Werror,-Wuninitialized]
                                __tlbiel_va_range(hstart, hend, pid,
                                                          ^~~~
arch/powerpc/mm/book3s64/radix_tlb.c:1175:29: note: initialize the variable 'hend' to silence this warning
                unsigned long hstart, hend;
                                          ^
                                           = 0
2 errors generated.

Rework the if-else to pull the 'IS_ENABLE(CONFIG_TRANSPARENT_HUGEPAGE)'
check one level up, this will silent the warnings. That will also
simplify the 'else' path. Clang is getting confused with these warnings,
but the warnings is a false-positive.

Suggested-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Anders Roxell <anders.roxell@linaro.org>
---
 arch/powerpc/mm/book3s64/radix_tlb.c | 31 +++++++++++++++++++++-------
 1 file changed, 24 insertions(+), 7 deletions(-)

diff --git a/arch/powerpc/mm/book3s64/radix_tlb.c b/arch/powerpc/mm/book3s64/radix_tlb.c
index 7724af19ed7e..e494a45ce1b4 100644
--- a/arch/powerpc/mm/book3s64/radix_tlb.c
+++ b/arch/powerpc/mm/book3s64/radix_tlb.c
@@ -1170,16 +1170,14 @@ static inline void __radix__flush_tlb_range(struct mm_struct *mm,
 				_tlbiel_pid_multicast(mm, pid, RIC_FLUSH_ALL);
 			}
 		}
-	} else {
+	} else if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {
 		bool hflush = false;
 		unsigned long hstart, hend;
 
-		if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {
-			hstart = (start + PMD_SIZE - 1) & PMD_MASK;
-			hend = end & PMD_MASK;
-			if (hstart < hend)
-				hflush = true;
-		}
+		hstart = (start + PMD_SIZE - 1) & PMD_MASK;
+		hend = end & PMD_MASK;
+		if (hstart < hend)
+			hflush = true;
 
 		if (type == FLUSH_TYPE_LOCAL) {
 			asm volatile("ptesync": : :"memory");
@@ -1207,6 +1205,25 @@ static inline void __radix__flush_tlb_range(struct mm_struct *mm,
 				_tlbiel_va_range_multicast(mm,
 					hstart, hend, pid, PMD_SIZE, MMU_PAGE_2M, flush_pwc);
 		}
+	} else {
+
+		if (type == FLUSH_TYPE_LOCAL) {
+			asm volatile("ptesync" : : : "memory");
+			if (flush_pwc)
+				/* For PWC, only one flush is needed */
+				__tlbiel_pid(pid, 0, RIC_FLUSH_PWC);
+			__tlbiel_va_range(start, end, pid, page_size, mmu_virtual_psize);
+			ppc_after_tlbiel_barrier();
+		} else if (cputlb_use_tlbie()) {
+			asm volatile("ptesync" : : : "memory");
+			if (flush_pwc)
+				__tlbie_pid(pid, RIC_FLUSH_PWC);
+			__tlbie_va_range(start, end, pid, page_size, mmu_virtual_psize);
+			asm volatile("eieio; tlbsync; ptesync" : : : "memory");
+		} else {
+			_tlbiel_va_range_multicast(mm,
+					start, end, pid, page_size, mmu_virtual_psize, flush_pwc);
+		}
 	}
 out:
 	preempt_enable();
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] powerpc: mm: radix_tlb: rearrange the if-else block
  2021-11-25 15:44 [PATCH] powerpc: mm: radix_tlb: rearrange the if-else block Anders Roxell
@ 2021-11-26 13:43 ` Christophe Leroy
  2021-11-26 13:59   ` Arnd Bergmann
  0 siblings, 1 reply; 5+ messages in thread
From: Christophe Leroy @ 2021-11-26 13:43 UTC (permalink / raw)
  To: Anders Roxell, benh, paulus
  Cc: Arnd Bergmann, llvm, ndesaulniers, linux-kernel, nathan, linuxppc-dev



Le 25/11/2021 à 16:44, Anders Roxell a écrit :
> Clang warns:
> 
> arch/powerpc/mm/book3s64/radix_tlb.c:1191:23: error: variable 'hstart' is uninitialized when used here [-Werror,-Wuninitialized]
>                                  __tlbiel_va_range(hstart, hend, pid,
>                                                    ^~~~~~
> arch/powerpc/mm/book3s64/radix_tlb.c:1175:23: note: initialize the variable 'hstart' to silence this warning
>                  unsigned long hstart, hend;
>                                      ^
>                                       = 0
> arch/powerpc/mm/book3s64/radix_tlb.c:1191:31: error: variable 'hend' is uninitialized when used here [-Werror,-Wuninitialized]
>                                  __tlbiel_va_range(hstart, hend, pid,
>                                                            ^~~~
> arch/powerpc/mm/book3s64/radix_tlb.c:1175:29: note: initialize the variable 'hend' to silence this warning
>                  unsigned long hstart, hend;
>                                            ^
>                                             = 0
> 2 errors generated.
> 
> Rework the if-else to pull the 'IS_ENABLE(CONFIG_TRANSPARENT_HUGEPAGE)'
> check one level up, this will silent the warnings. That will also
> simplify the 'else' path. Clang is getting confused with these warnings,
> but the warnings is a false-positive.

But you are duplicating a significant part of the code by doing that, 
and duplicated code generaly leads to bugs.

And we already have redundant stuff between FLUSH_TYPE_LOCAL leg and 
cputlb_use_tlbie() leg.

Can't you fix CLANG instead :) ?

Or just add an else to the IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) that 
sets hstart and hend to 0 ?

Or just put hstart and hend calculation outside the IS_ENABLED() ? After 
all GCC should drop the calculation when not used.


> 
> Suggested-by: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Anders Roxell <anders.roxell@linaro.org>
> ---
>   arch/powerpc/mm/book3s64/radix_tlb.c | 31 +++++++++++++++++++++-------
>   1 file changed, 24 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/powerpc/mm/book3s64/radix_tlb.c b/arch/powerpc/mm/book3s64/radix_tlb.c
> index 7724af19ed7e..e494a45ce1b4 100644
> --- a/arch/powerpc/mm/book3s64/radix_tlb.c
> +++ b/arch/powerpc/mm/book3s64/radix_tlb.c
> @@ -1170,16 +1170,14 @@ static inline void __radix__flush_tlb_range(struct mm_struct *mm,
>   				_tlbiel_pid_multicast(mm, pid, RIC_FLUSH_ALL);
>   			}
>   		}
> -	} else {
> +	} else if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {
>   		bool hflush = false;
>   		unsigned long hstart, hend;
>   
> -		if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {
> -			hstart = (start + PMD_SIZE - 1) & PMD_MASK;
> -			hend = end & PMD_MASK;
> -			if (hstart < hend)
> -				hflush = true;
> -		}
> +		hstart = (start + PMD_SIZE - 1) & PMD_MASK;
> +		hend = end & PMD_MASK;
> +		if (hstart < hend)
> +			hflush = true;
>   
>   		if (type == FLUSH_TYPE_LOCAL) {
>   			asm volatile("ptesync": : :"memory");
> @@ -1207,6 +1205,25 @@ static inline void __radix__flush_tlb_range(struct mm_struct *mm,
>   				_tlbiel_va_range_multicast(mm,
>   					hstart, hend, pid, PMD_SIZE, MMU_PAGE_2M, flush_pwc);
>   		}
> +	} else {
> +
> +		if (type == FLUSH_TYPE_LOCAL) {
> +			asm volatile("ptesync" : : : "memory");
> +			if (flush_pwc)
> +				/* For PWC, only one flush is needed */
> +				__tlbiel_pid(pid, 0, RIC_FLUSH_PWC);
> +			__tlbiel_va_range(start, end, pid, page_size, mmu_virtual_psize);
> +			ppc_after_tlbiel_barrier();
> +		} else if (cputlb_use_tlbie()) {
> +			asm volatile("ptesync" : : : "memory");
> +			if (flush_pwc)
> +				__tlbie_pid(pid, RIC_FLUSH_PWC);
> +			__tlbie_va_range(start, end, pid, page_size, mmu_virtual_psize);
> +			asm volatile("eieio; tlbsync; ptesync" : : : "memory");
> +		} else {
> +			_tlbiel_va_range_multicast(mm,
> +					start, end, pid, page_size, mmu_virtual_psize, flush_pwc);
> +		}
>   	}
>   out:
>   	preempt_enable();
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] powerpc: mm: radix_tlb: rearrange the if-else block
  2021-11-26 13:43 ` Christophe Leroy
@ 2021-11-26 13:59   ` Arnd Bergmann
  2021-11-26 15:46     ` Nathan Chancellor
  0 siblings, 1 reply; 5+ messages in thread
From: Arnd Bergmann @ 2021-11-26 13:59 UTC (permalink / raw)
  To: Christophe Leroy
  Cc: Anders Roxell, Benjamin Herrenschmidt, Paul Mackerras,
	Arnd Bergmann, llvm, Nick Desaulniers, Linux Kernel Mailing List,
	Nathan Chancellor, linuxppc-dev

On Fri, Nov 26, 2021 at 2:43 PM Christophe Leroy
<christophe.leroy@csgroup.eu> wrote:
> Le 25/11/2021 à 16:44, Anders Roxell a écrit :
> Can't you fix CLANG instead :) ?
>
> Or just add an else to the IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) that
> sets hstart and hend to 0 ?

That doesn't sound any less risky than duplicating the code, it can lead to
incorrect changes just as easily if a patch ends up actually flushing at the
wrong address, and the compiler fails to complain because of the bogus
initialization.

> Or just put hstart and hend calculation outside the IS_ENABLED() ? After
> all GCC should drop the calculation when not used.

I like this one. I'm still unsure how clang can get so confused about whether
the variables are initialized or not, usually it handles this much better than
gcc. My best guess is that one of the memory clobbers makes it conclude
that 'hflush' can be true when it gets written to by an inline asm.

        Arnd

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] powerpc: mm: radix_tlb: rearrange the if-else block
  2021-11-26 13:59   ` Arnd Bergmann
@ 2021-11-26 15:46     ` Nathan Chancellor
  2021-11-26 16:25       ` Christophe Leroy
  0 siblings, 1 reply; 5+ messages in thread
From: Nathan Chancellor @ 2021-11-26 15:46 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Christophe Leroy, Anders Roxell, Benjamin Herrenschmidt,
	Paul Mackerras, llvm, Nick Desaulniers,
	Linux Kernel Mailing List, linuxppc-dev

On Fri, Nov 26, 2021 at 02:59:29PM +0100, Arnd Bergmann wrote:
> On Fri, Nov 26, 2021 at 2:43 PM Christophe Leroy
> <christophe.leroy@csgroup.eu> wrote:
> > Le 25/11/2021 à 16:44, Anders Roxell a écrit :
> > Can't you fix CLANG instead :) ?
> >
> > Or just add an else to the IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) that
> > sets hstart and hend to 0 ?
> 
> That doesn't sound any less risky than duplicating the code, it can lead to
> incorrect changes just as easily if a patch ends up actually flushing at the
> wrong address, and the compiler fails to complain because of the bogus
> initialization.
> 
> > Or just put hstart and hend calculation outside the IS_ENABLED() ? After
> > all GCC should drop the calculation when not used.
> 
> I like this one. I'm still unsure how clang can get so confused about whether
> the variables are initialized or not, usually it handles this much better than
> gcc. My best guess is that one of the memory clobbers makes it conclude
> that 'hflush' can be true when it gets written to by an inline asm.

As far as I am aware, clang's analysis does not evaluate variables when
generating a control flow graph and using that for static analysis:

https://godbolt.org/z/PdGxoq9j7

Based on the control flow graph, it knows that hstart and hend are
uninitialized because IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) gets
expanded to 0 by the preprocessor but it does not seem like it can piece
together that hflush's value of false is only changed to true under the
now 'if (0) {' branch, meaning that all the calls to __tlbiel_va_range()
never get evaluated. That may or may not be easy to fix in clang but we
run into issues like this so infrequently.

At any rate, the below diff works for me.

Cheers,
Nathan

diff --git a/arch/powerpc/mm/book3s64/radix_tlb.c b/arch/powerpc/mm/book3s64/radix_tlb.c
index 7724af19ed7e..156a631df976 100644
--- a/arch/powerpc/mm/book3s64/radix_tlb.c
+++ b/arch/powerpc/mm/book3s64/radix_tlb.c
@@ -1174,12 +1174,10 @@ static inline void __radix__flush_tlb_range(struct mm_struct *mm,
 		bool hflush = false;
 		unsigned long hstart, hend;
 
-		if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {
-			hstart = (start + PMD_SIZE - 1) & PMD_MASK;
-			hend = end & PMD_MASK;
-			if (hstart < hend)
-				hflush = true;
-		}
+		hstart = (start + PMD_SIZE - 1) & PMD_MASK;
+		hend = end & PMD_MASK;
+		if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && hstart < hend)
+			hflush = true;
 
 		if (type == FLUSH_TYPE_LOCAL) {
 			asm volatile("ptesync": : :"memory");

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] powerpc: mm: radix_tlb: rearrange the if-else block
  2021-11-26 15:46     ` Nathan Chancellor
@ 2021-11-26 16:25       ` Christophe Leroy
  0 siblings, 0 replies; 5+ messages in thread
From: Christophe Leroy @ 2021-11-26 16:25 UTC (permalink / raw)
  To: Nathan Chancellor, Arnd Bergmann
  Cc: Anders Roxell, Benjamin Herrenschmidt, Paul Mackerras, llvm,
	Nick Desaulniers, Linux Kernel Mailing List, linuxppc-dev



Le 26/11/2021 à 16:46, Nathan Chancellor a écrit :
> On Fri, Nov 26, 2021 at 02:59:29PM +0100, Arnd Bergmann wrote:
>> On Fri, Nov 26, 2021 at 2:43 PM Christophe Leroy
>> <christophe.leroy@csgroup.eu> wrote:
>>> Le 25/11/2021 à 16:44, Anders Roxell a écrit :
>>> Can't you fix CLANG instead :) ?
>>>
>>> Or just add an else to the IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) that
>>> sets hstart and hend to 0 ?
>>
>> That doesn't sound any less risky than duplicating the code, it can lead to
>> incorrect changes just as easily if a patch ends up actually flushing at the
>> wrong address, and the compiler fails to complain because of the bogus
>> initialization.
>>
>>> Or just put hstart and hend calculation outside the IS_ENABLED() ? After
>>> all GCC should drop the calculation when not used.
>>
>> I like this one. I'm still unsure how clang can get so confused about whether
>> the variables are initialized or not, usually it handles this much better than
>> gcc. My best guess is that one of the memory clobbers makes it conclude
>> that 'hflush' can be true when it gets written to by an inline asm.
> 
> As far as I am aware, clang's analysis does not evaluate variables when
> generating a control flow graph and using that for static analysis:
> 
> https://godbolt.org/z/PdGxoq9j7
> 
> Based on the control flow graph, it knows that hstart and hend are
> uninitialized because IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) gets
> expanded to 0 by the preprocessor but it does not seem like it can piece
> together that hflush's value of false is only changed to true under the
> now 'if (0) {' branch, meaning that all the calls to __tlbiel_va_range()
> never get evaluated. That may or may not be easy to fix in clang but we
> run into issues like this so infrequently.
> 
> At any rate, the below diff works for me.
> 
> Cheers,
> Nathan
> 
> diff --git a/arch/powerpc/mm/book3s64/radix_tlb.c b/arch/powerpc/mm/book3s64/radix_tlb.c
> index 7724af19ed7e..156a631df976 100644
> --- a/arch/powerpc/mm/book3s64/radix_tlb.c
> +++ b/arch/powerpc/mm/book3s64/radix_tlb.c
> @@ -1174,12 +1174,10 @@ static inline void __radix__flush_tlb_range(struct mm_struct *mm,
>   		bool hflush = false;
>   		unsigned long hstart, hend;
>   
> -		if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {
> -			hstart = (start + PMD_SIZE - 1) & PMD_MASK;
> -			hend = end & PMD_MASK;
> -			if (hstart < hend)
> -				hflush = true;
> -		}
> +		hstart = (start + PMD_SIZE - 1) & PMD_MASK;
> +		hend = end & PMD_MASK;
> +		if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && hstart < hend)
> +			hflush = true;

Yes I like that much better.

Maybe even better with

	hflush = IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && hstart < hend;

(And remove default false value at declaration).

>   
>   		if (type == FLUSH_TYPE_LOCAL) {
>   			asm volatile("ptesync": : :"memory");
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-11-26 16:27 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-25 15:44 [PATCH] powerpc: mm: radix_tlb: rearrange the if-else block Anders Roxell
2021-11-26 13:43 ` Christophe Leroy
2021-11-26 13:59   ` Arnd Bergmann
2021-11-26 15:46     ` Nathan Chancellor
2021-11-26 16:25       ` Christophe Leroy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).