LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH v2] powerpc/32: Don't use a struct based type for pte_t
@ 2021-09-17 13:57 Christophe Leroy
  2021-09-17 14:32 ` David Laight
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Christophe Leroy @ 2021-09-17 13:57 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
  Cc: Christophe Leroy, linux-kernel, linuxppc-dev

Long time ago we had a config item called STRICT_MM_TYPECHECKS
to build the kernel with pte_t defined as a structure in order
to perform additional build checks or build it with pte_t
defined as a simple type in order to get simpler generated code.

Commit 670eea924198 ("powerpc/mm: Always use STRICT_MM_TYPECHECKS")
made the struct based definition the only one, considering that the
generated code was similar in both cases.

That's right on ppc64 because the ABI is such that the content of a
struct having a single simple type element is passed as register,
but on ppc32 such a structure is passed via the stack like any
structure.

Simple test function:

	pte_t test(pte_t pte)
	{
		return pte;
	}

Before this patch we get

	c00108ec <test>:
	c00108ec:	81 24 00 00 	lwz     r9,0(r4)
	c00108f0:	91 23 00 00 	stw     r9,0(r3)
	c00108f4:	4e 80 00 20 	blr

So, for PPC32, restore the simple type behaviour we got before
commit 670eea924198, but instead of adding a config option to
activate type check, do it when __CHECKER__ is set so that type
checking is performed by 'sparse' and provides feedback like:

	arch/powerpc/mm/pgtable.c:466:16: warning: incorrect type in return expression (different base types)
	arch/powerpc/mm/pgtable.c:466:16:    expected unsigned long
	arch/powerpc/mm/pgtable.c:466:16:    got struct pte_t [usertype] x

With this patch we now get

	c0010890 <test>:
	c0010890:	4e 80 00 20 	blr

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
v2: Properly handle 8xx 16k pages
---
 arch/powerpc/include/asm/nohash/32/pgtable.h |  2 +-
 arch/powerpc/include/asm/pgtable-types.h     | 14 +++++++++++++-
 arch/powerpc/mm/pgtable.c                    |  2 +-
 3 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/include/asm/nohash/32/pgtable.h b/arch/powerpc/include/asm/nohash/32/pgtable.h
index f06ae00f2a65..34ce50da1850 100644
--- a/arch/powerpc/include/asm/nohash/32/pgtable.h
+++ b/arch/powerpc/include/asm/nohash/32/pgtable.h
@@ -245,7 +245,7 @@ static int number_of_cells_per_pte(pmd_t *pmd, pte_basic_t val, int huge)
 static inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, pte_t *p,
 				     unsigned long clr, unsigned long set, int huge)
 {
-	pte_basic_t *entry = &p->pte;
+	pte_basic_t *entry = (pte_basic_t *)p;
 	pte_basic_t old = pte_val(*p);
 	pte_basic_t new = (old & ~(pte_basic_t)clr) | set;
 	int num, i;
diff --git a/arch/powerpc/include/asm/pgtable-types.h b/arch/powerpc/include/asm/pgtable-types.h
index d11b4c61d686..c60199fc6fa6 100644
--- a/arch/powerpc/include/asm/pgtable-types.h
+++ b/arch/powerpc/include/asm/pgtable-types.h
@@ -5,14 +5,26 @@
 /* PTE level */
 #if defined(CONFIG_PPC_8xx) && defined(CONFIG_PPC_16K_PAGES)
 typedef struct { pte_basic_t pte, pte1, pte2, pte3; } pte_t;
-#else
+#elif defined(__CHECKER__) || !defined(CONFIG_PPC32)
 typedef struct { pte_basic_t pte; } pte_t;
+#else
+typedef pte_basic_t pte_t;
 #endif
+
+#if defined(__CHECKER__) || !defined(CONFIG_PPC32) || \
+    (defined(CONFIG_PPC_8xx) && defined(CONFIG_PPC_16K_PAGES))
 #define __pte(x)	((pte_t) { (x) })
 static inline pte_basic_t pte_val(pte_t x)
 {
 	return x.pte;
 }
+#else
+#define __pte(x)	((pte_t)(x))
+static inline pte_basic_t pte_val(pte_t x)
+{
+	return x;
+}
+#endif
 
 /* PMD level */
 #ifdef CONFIG_PPC64
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c
index cd16b407f47e..ce9482383144 100644
--- a/arch/powerpc/mm/pgtable.c
+++ b/arch/powerpc/mm/pgtable.c
@@ -271,7 +271,7 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_
 {
 	pmd_t *pmd = pmd_off(mm, addr);
 	pte_basic_t val;
-	pte_basic_t *entry = &ptep->pte;
+	pte_basic_t *entry = (pte_basic_t *)ptep;
 	int num, i;
 
 	/*
-- 
2.31.1


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

* RE: [PATCH v2] powerpc/32: Don't use a struct based type for pte_t
  2021-09-17 13:57 [PATCH v2] powerpc/32: Don't use a struct based type for pte_t Christophe Leroy
@ 2021-09-17 14:32 ` David Laight
  2021-09-18  8:47   ` Christophe Leroy
  2021-09-18  3:26 ` Michael Ellerman
  2021-11-02 10:11 ` Michael Ellerman
  2 siblings, 1 reply; 6+ messages in thread
From: David Laight @ 2021-09-17 14:32 UTC (permalink / raw)
  To: 'Christophe Leroy',
	Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
  Cc: linuxppc-dev, linux-kernel

From: Christophe Leroy
> Sent: 17 September 2021 14:58
> 
> Long time ago we had a config item called STRICT_MM_TYPECHECKS
> to build the kernel with pte_t defined as a structure in order
> to perform additional build checks or build it with pte_t
> defined as a simple type in order to get simpler generated code.
> 
...
> diff --git a/arch/powerpc/include/asm/pgtable-types.h b/arch/powerpc/include/asm/pgtable-types.h
> index d11b4c61d686..c60199fc6fa6 100644
> --- a/arch/powerpc/include/asm/pgtable-types.h
> +++ b/arch/powerpc/include/asm/pgtable-types.h
> @@ -5,14 +5,26 @@
>  /* PTE level */
>  #if defined(CONFIG_PPC_8xx) && defined(CONFIG_PPC_16K_PAGES)
>  typedef struct { pte_basic_t pte, pte1, pte2, pte3; } pte_t;
> -#else
> +#elif defined(__CHECKER__) || !defined(CONFIG_PPC32)
>  typedef struct { pte_basic_t pte; } pte_t;
> +#else
> +typedef pte_basic_t pte_t;
>  #endif
> +
> +#if defined(__CHECKER__) || !defined(CONFIG_PPC32) || \
> +    (defined(CONFIG_PPC_8xx) && defined(CONFIG_PPC_16K_PAGES))
>  #define __pte(x)	((pte_t) { (x) })
>  static inline pte_basic_t pte_val(pte_t x)
>  {
>  	return x.pte;
>  }
> +#else
> +#define __pte(x)	((pte_t)(x))
> +static inline pte_basic_t pte_val(pte_t x)
> +{
> +	return x;
> +}
> +#endif

Would it be better to define:
static inline pte_basic_*pte_basic(pte_t *x)
{
#if xxx
	return x;
#else
	return &x->pte;
#endif
}

Then pte_val(x) is always *pt_basic(x)
and the casts like:

> -	pte_basic_t *entry = &ptep->pte;
> +	pte_basic_t *entry = (pte_basic_t *)ptep;

can go away.

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)


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

* Re: [PATCH v2] powerpc/32: Don't use a struct based type for pte_t
  2021-09-17 13:57 [PATCH v2] powerpc/32: Don't use a struct based type for pte_t Christophe Leroy
  2021-09-17 14:32 ` David Laight
@ 2021-09-18  3:26 ` Michael Ellerman
  2021-09-18  8:37   ` Christophe Leroy
  2021-11-02 10:11 ` Michael Ellerman
  2 siblings, 1 reply; 6+ messages in thread
From: Michael Ellerman @ 2021-09-18  3:26 UTC (permalink / raw)
  To: Christophe Leroy, Benjamin Herrenschmidt, Paul Mackerras
  Cc: Christophe Leroy, linux-kernel, linuxppc-dev

Christophe Leroy <christophe.leroy@csgroup.eu> writes:
> Long time ago we had a config item called STRICT_MM_TYPECHECKS
> to build the kernel with pte_t defined as a structure in order
> to perform additional build checks or build it with pte_t
> defined as a simple type in order to get simpler generated code.
>
> Commit 670eea924198 ("powerpc/mm: Always use STRICT_MM_TYPECHECKS")
> made the struct based definition the only one, considering that the
> generated code was similar in both cases.
>
> That's right on ppc64 because the ABI is such that the content of a
> struct having a single simple type element is passed as register,
> but on ppc32 such a structure is passed via the stack like any
> structure.
>
> Simple test function:
>
> 	pte_t test(pte_t pte)
> 	{
> 		return pte;
> 	}
>
> Before this patch we get
>
> 	c00108ec <test>:
> 	c00108ec:	81 24 00 00 	lwz     r9,0(r4)
> 	c00108f0:	91 23 00 00 	stw     r9,0(r3)
> 	c00108f4:	4e 80 00 20 	blr
>
> So, for PPC32, restore the simple type behaviour we got before
> commit 670eea924198, but instead of adding a config option to
> activate type check, do it when __CHECKER__ is set so that type
> checking is performed by 'sparse' and provides feedback like:
>
> 	arch/powerpc/mm/pgtable.c:466:16: warning: incorrect type in return expression (different base types)
> 	arch/powerpc/mm/pgtable.c:466:16:    expected unsigned long
> 	arch/powerpc/mm/pgtable.c:466:16:    got struct pte_t [usertype] x

OK that's a good trade off.

One question below ...

> diff --git a/arch/powerpc/include/asm/pgtable-types.h b/arch/powerpc/include/asm/pgtable-types.h
> index d11b4c61d686..c60199fc6fa6 100644
> --- a/arch/powerpc/include/asm/pgtable-types.h
> +++ b/arch/powerpc/include/asm/pgtable-types.h
> @@ -5,14 +5,26 @@
>  /* PTE level */
>  #if defined(CONFIG_PPC_8xx) && defined(CONFIG_PPC_16K_PAGES)
>  typedef struct { pte_basic_t pte, pte1, pte2, pte3; } pte_t;
> -#else
> +#elif defined(__CHECKER__) || !defined(CONFIG_PPC32)

It would be nicer if this logic was in Kconfig.

eg. restore config STRICT_MM_TYPECHECKS but make it always enabled for
64-bit, and depend on CHECKER for 32-bit.

The only thing is I'm not sure if we can test __CHECKER__ in Kconfig?

cheers

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

* Re: [PATCH v2] powerpc/32: Don't use a struct based type for pte_t
  2021-09-18  3:26 ` Michael Ellerman
@ 2021-09-18  8:37   ` Christophe Leroy
  0 siblings, 0 replies; 6+ messages in thread
From: Christophe Leroy @ 2021-09-18  8:37 UTC (permalink / raw)
  To: Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras
  Cc: linux-kernel, linuxppc-dev



Le 18/09/2021 à 05:26, Michael Ellerman a écrit :
> Christophe Leroy <christophe.leroy@csgroup.eu> writes:
>> Long time ago we had a config item called STRICT_MM_TYPECHECKS
>> to build the kernel with pte_t defined as a structure in order
>> to perform additional build checks or build it with pte_t
>> defined as a simple type in order to get simpler generated code.
>>
>> Commit 670eea924198 ("powerpc/mm: Always use STRICT_MM_TYPECHECKS")
>> made the struct based definition the only one, considering that the
>> generated code was similar in both cases.
>>
>> That's right on ppc64 because the ABI is such that the content of a
>> struct having a single simple type element is passed as register,
>> but on ppc32 such a structure is passed via the stack like any
>> structure.
>>
>> Simple test function:
>>
>> 	pte_t test(pte_t pte)
>> 	{
>> 		return pte;
>> 	}
>>
>> Before this patch we get
>>
>> 	c00108ec <test>:
>> 	c00108ec:	81 24 00 00 	lwz     r9,0(r4)
>> 	c00108f0:	91 23 00 00 	stw     r9,0(r3)
>> 	c00108f4:	4e 80 00 20 	blr
>>
>> So, for PPC32, restore the simple type behaviour we got before
>> commit 670eea924198, but instead of adding a config option to
>> activate type check, do it when __CHECKER__ is set so that type
>> checking is performed by 'sparse' and provides feedback like:
>>
>> 	arch/powerpc/mm/pgtable.c:466:16: warning: incorrect type in return expression (different base types)
>> 	arch/powerpc/mm/pgtable.c:466:16:    expected unsigned long
>> 	arch/powerpc/mm/pgtable.c:466:16:    got struct pte_t [usertype] x
> 
> OK that's a good trade off.
> 
> One question below ...
> 
>> diff --git a/arch/powerpc/include/asm/pgtable-types.h b/arch/powerpc/include/asm/pgtable-types.h
>> index d11b4c61d686..c60199fc6fa6 100644
>> --- a/arch/powerpc/include/asm/pgtable-types.h
>> +++ b/arch/powerpc/include/asm/pgtable-types.h
>> @@ -5,14 +5,26 @@
>>   /* PTE level */
>>   #if defined(CONFIG_PPC_8xx) && defined(CONFIG_PPC_16K_PAGES)
>>   typedef struct { pte_basic_t pte, pte1, pte2, pte3; } pte_t;
>> -#else
>> +#elif defined(__CHECKER__) || !defined(CONFIG_PPC32)
> 
> It would be nicer if this logic was in Kconfig.
> 
> eg. restore config STRICT_MM_TYPECHECKS but make it always enabled for
> 64-bit, and depend on CHECKER for 32-bit.
> 
> The only thing is I'm not sure if we can test __CHECKER__ in Kconfig?


I think Kconfig doesn't see __CHECKER__, otherwise it would mean that a 
build may get different whether you build with C=1/2 or not.

__CHECKER__ is a define added by sparse when doing the CHECK on a per 
object basis.

What I can do is to add:

#if defined(__CHECKER__) || !defined(CONFIG_PPC32)
#define STRICT_MM_TYPECHECKS
#endif

Christophe

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

* Re: [PATCH v2] powerpc/32: Don't use a struct based type for pte_t
  2021-09-17 14:32 ` David Laight
@ 2021-09-18  8:47   ` Christophe Leroy
  0 siblings, 0 replies; 6+ messages in thread
From: Christophe Leroy @ 2021-09-18  8:47 UTC (permalink / raw)
  To: David Laight, Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
  Cc: linuxppc-dev, linux-kernel



Le 17/09/2021 à 16:32, David Laight a écrit :
> From: Christophe Leroy
>> Sent: 17 September 2021 14:58
>>
>> Long time ago we had a config item called STRICT_MM_TYPECHECKS
>> to build the kernel with pte_t defined as a structure in order
>> to perform additional build checks or build it with pte_t
>> defined as a simple type in order to get simpler generated code.
>>
> ...
>> diff --git a/arch/powerpc/include/asm/pgtable-types.h b/arch/powerpc/include/asm/pgtable-types.h
>> index d11b4c61d686..c60199fc6fa6 100644
>> --- a/arch/powerpc/include/asm/pgtable-types.h
>> +++ b/arch/powerpc/include/asm/pgtable-types.h
>> @@ -5,14 +5,26 @@
>>   /* PTE level */
>>   #if defined(CONFIG_PPC_8xx) && defined(CONFIG_PPC_16K_PAGES)
>>   typedef struct { pte_basic_t pte, pte1, pte2, pte3; } pte_t;
>> -#else
>> +#elif defined(__CHECKER__) || !defined(CONFIG_PPC32)
>>   typedef struct { pte_basic_t pte; } pte_t;
>> +#else
>> +typedef pte_basic_t pte_t;
>>   #endif
>> +
>> +#if defined(__CHECKER__) || !defined(CONFIG_PPC32) || \
>> +    (defined(CONFIG_PPC_8xx) && defined(CONFIG_PPC_16K_PAGES))
>>   #define __pte(x)	((pte_t) { (x) })
>>   static inline pte_basic_t pte_val(pte_t x)
>>   {
>>   	return x.pte;
>>   }
>> +#else
>> +#define __pte(x)	((pte_t)(x))
>> +static inline pte_basic_t pte_val(pte_t x)
>> +{
>> +	return x;
>> +}
>> +#endif
> 
> Would it be better to define:
> static inline pte_basic_*pte_basic(pte_t *x)
> {
> #if xxx
> 	return x;
> #else
> 	return &x->pte;
> #endif
> }
> 
> Then pte_val(x) is always *pt_basic(x)
> and the casts like:
> 
>> -	pte_basic_t *entry = &ptep->pte;
>> +	pte_basic_t *entry = (pte_basic_t *)ptep;
> 
> can go away.
> 


I don't like that idea too much, because it means going through a 
pointer of something which is not in memory at the begining. Doing that 
forces GCC to put the pte_t object on stack. And that's exactly the 
purpose of this patch: avoid having to go via memory. Allthough recent 
versions of GCC optimise it away at the end, I don't like it in principle.

And the only two places (pte_update() and set_huge_pte_at() where this 
cast is required are really two places very special which deal with real 
page tables. So IMHO it makes sense to explicitely show that what we use 
is the address of the entry in the page table.

Christophe

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

* Re: [PATCH v2] powerpc/32: Don't use a struct based type for pte_t
  2021-09-17 13:57 [PATCH v2] powerpc/32: Don't use a struct based type for pte_t Christophe Leroy
  2021-09-17 14:32 ` David Laight
  2021-09-18  3:26 ` Michael Ellerman
@ 2021-11-02 10:11 ` Michael Ellerman
  2 siblings, 0 replies; 6+ messages in thread
From: Michael Ellerman @ 2021-11-02 10:11 UTC (permalink / raw)
  To: Michael Ellerman, Paul Mackerras, Christophe Leroy,
	Benjamin Herrenschmidt
  Cc: linux-kernel, linuxppc-dev

On Fri, 17 Sep 2021 15:57:31 +0200, Christophe Leroy wrote:
> Long time ago we had a config item called STRICT_MM_TYPECHECKS
> to build the kernel with pte_t defined as a structure in order
> to perform additional build checks or build it with pte_t
> defined as a simple type in order to get simpler generated code.
> 
> Commit 670eea924198 ("powerpc/mm: Always use STRICT_MM_TYPECHECKS")
> made the struct based definition the only one, considering that the
> generated code was similar in both cases.
> 
> [...]

Applied to powerpc/next.

[1/1] powerpc/32: Don't use a struct based type for pte_t
      https://git.kernel.org/powerpc/c/c7d19189d7241e135cd2e450a7fbc77cb7bd40ee

cheers

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

end of thread, other threads:[~2021-11-02 11:39 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-17 13:57 [PATCH v2] powerpc/32: Don't use a struct based type for pte_t Christophe Leroy
2021-09-17 14:32 ` David Laight
2021-09-18  8:47   ` Christophe Leroy
2021-09-18  3:26 ` Michael Ellerman
2021-09-18  8:37   ` Christophe Leroy
2021-11-02 10:11 ` Michael Ellerman

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).