All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 1/1] pgo: Fix allocate_node() v2
@ 2021-06-04 16:58 Jarmo Tiitto
  2021-06-04 17:04 ` Nathan Chancellor
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Jarmo Tiitto @ 2021-06-04 16:58 UTC (permalink / raw)
  To: Sami Tolvanen, Bill Wendling, Kees Cook, Nathan Chancellor,
	Nick Desaulniers, clang-built-linux, linux-kernel
  Cc: Jarmo Tiitto, morbo

When clang instrumentation eventually calls allocate_node()
the struct llvm_prf_data *p argument tells us from what section
we should reserve the vnode: It either points into vmlinux's
core __llvm_prf_data section or some loaded module's
__llvm_prf_data section.

But since we don't have access to corresponding
__llvm_prf_vnds section(s) for any module, the function
should return just NULL and ignore any profiling attempts
from modules for now.

Signed-off-by: Jarmo Tiitto <jarmo.tiitto@gmail.com>
---
Based on Kees and others feedback here is v3 patch
that clarifies why the current checks in allocate_node()
are flawed. I did fair amount of KGDB time on it.

The commit is based on kees/for-next/clang/features tree,
hopefully this is ok. Should I have based it on linux-next
instead?

I grep -R'd where the memory_contains() can be found and it is only
found in #include <asm-generic/sections.h>

I cross my fingers and await if this is my first accepted patch. :-)
---
 kernel/pgo/instrument.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/kernel/pgo/instrument.c b/kernel/pgo/instrument.c
index 0e07ee1b17d9..c69b4f7ebaad 100644
--- a/kernel/pgo/instrument.c
+++ b/kernel/pgo/instrument.c
@@ -18,6 +18,7 @@
 
 #define pr_fmt(fmt)	"pgo: " fmt
 
+#include <asm-generic/sections.h>
 #include <linux/bitops.h>
 #include <linux/kernel.h>
 #include <linux/export.h>
@@ -55,17 +56,21 @@ void prf_unlock(unsigned long flags)
 static struct llvm_prf_value_node *allocate_node(struct llvm_prf_data *p,
 						 u32 index, u64 value)
 {
-	if (&__llvm_prf_vnds_start[current_node + 1] >= __llvm_prf_vnds_end)
-		return NULL; /* Out of nodes */
-
-	current_node++;
-
-	/* Make sure the node is entirely within the section */
-	if (&__llvm_prf_vnds_start[current_node] >= __llvm_prf_vnds_end ||
-	    &__llvm_prf_vnds_start[current_node + 1] > __llvm_prf_vnds_end)
+	const int max_vnds = prf_vnds_count();
+
+	/*
+	 * Check that p is within vmlinux __llvm_prf_data section.
+	 * If not, don't allocate since we can't handle modules yet.
+	 */
+	if (!memory_contains(__llvm_prf_data_start,
+		__llvm_prf_data_end, p, sizeof(*p)))
 		return NULL;
 
-	return &__llvm_prf_vnds_start[current_node];
+	if (WARN_ON_ONCE(current_node >= max_vnds))
+		return NULL; /* Out of nodes */
+
+	/* reserve vnode for vmlinux */
+	return &__llvm_prf_vnds_start[current_node++];
 }
 
 /*

base-commit: 5d0cda65918279ada060417c5fecb7e86ccb3def
-- 
2.31.1


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

* Re: [PATCH v3 1/1] pgo: Fix allocate_node() v2
  2021-06-04 16:58 [PATCH v3 1/1] pgo: Fix allocate_node() v2 Jarmo Tiitto
@ 2021-06-04 17:04 ` Nathan Chancellor
  2021-06-04 17:28 ` Nick Desaulniers
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Nathan Chancellor @ 2021-06-04 17:04 UTC (permalink / raw)
  To: Jarmo Tiitto, Sami Tolvanen, Bill Wendling, Kees Cook,
	Nick Desaulniers, clang-built-linux, linux-kernel
  Cc: morbo

On 6/4/2021 9:58 AM, Jarmo Tiitto wrote:
> When clang instrumentation eventually calls allocate_node()
> the struct llvm_prf_data *p argument tells us from what section
> we should reserve the vnode: It either points into vmlinux's
> core __llvm_prf_data section or some loaded module's
> __llvm_prf_data section.
> 
> But since we don't have access to corresponding
> __llvm_prf_vnds section(s) for any module, the function
> should return just NULL and ignore any profiling attempts
> from modules for now.
> 
> Signed-off-by: Jarmo Tiitto <jarmo.tiitto@gmail.com>

Reviewed-by: Nathan Chancellor <nathan@kernel.org>

> ---
> Based on Kees and others feedback here is v3 patch
> that clarifies why the current checks in allocate_node()
> are flawed. I did fair amount of KGDB time on it.
> 
> The commit is based on kees/for-next/clang/features tree,
> hopefully this is ok. Should I have based it on linux-next
> instead?
> 
> I grep -R'd where the memory_contains() can be found and it is only
> found in #include <asm-generic/sections.h>
> 
> I cross my fingers and await if this is my first accepted patch. :-)
> ---
>   kernel/pgo/instrument.c | 23 ++++++++++++++---------
>   1 file changed, 14 insertions(+), 9 deletions(-)
> 
> diff --git a/kernel/pgo/instrument.c b/kernel/pgo/instrument.c
> index 0e07ee1b17d9..c69b4f7ebaad 100644
> --- a/kernel/pgo/instrument.c
> +++ b/kernel/pgo/instrument.c
> @@ -18,6 +18,7 @@
>   
>   #define pr_fmt(fmt)	"pgo: " fmt
>   
> +#include <asm-generic/sections.h>
>   #include <linux/bitops.h>
>   #include <linux/kernel.h>
>   #include <linux/export.h>
> @@ -55,17 +56,21 @@ void prf_unlock(unsigned long flags)
>   static struct llvm_prf_value_node *allocate_node(struct llvm_prf_data *p,
>   						 u32 index, u64 value)
>   {
> -	if (&__llvm_prf_vnds_start[current_node + 1] >= __llvm_prf_vnds_end)
> -		return NULL; /* Out of nodes */
> -
> -	current_node++;
> -
> -	/* Make sure the node is entirely within the section */
> -	if (&__llvm_prf_vnds_start[current_node] >= __llvm_prf_vnds_end ||
> -	    &__llvm_prf_vnds_start[current_node + 1] > __llvm_prf_vnds_end)
> +	const int max_vnds = prf_vnds_count();
> +
> +	/*
> +	 * Check that p is within vmlinux __llvm_prf_data section.
> +	 * If not, don't allocate since we can't handle modules yet.
> +	 */
> +	if (!memory_contains(__llvm_prf_data_start,
> +		__llvm_prf_data_end, p, sizeof(*p)))
>   		return NULL;
>   
> -	return &__llvm_prf_vnds_start[current_node];
> +	if (WARN_ON_ONCE(current_node >= max_vnds))
> +		return NULL; /* Out of nodes */
> +
> +	/* reserve vnode for vmlinux */
> +	return &__llvm_prf_vnds_start[current_node++];
>   }
>   
>   /*
> 
> base-commit: 5d0cda65918279ada060417c5fecb7e86ccb3def
> 


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

* Re: [PATCH v3 1/1] pgo: Fix allocate_node() v2
  2021-06-04 16:58 [PATCH v3 1/1] pgo: Fix allocate_node() v2 Jarmo Tiitto
  2021-06-04 17:04 ` Nathan Chancellor
@ 2021-06-04 17:28 ` Nick Desaulniers
  2021-06-04 17:58 ` Kees Cook
  2021-06-04 18:06 ` Kees Cook
  3 siblings, 0 replies; 7+ messages in thread
From: Nick Desaulniers @ 2021-06-04 17:28 UTC (permalink / raw)
  To: Jarmo Tiitto
  Cc: Sami Tolvanen, Bill Wendling, Kees Cook, Nathan Chancellor,
	clang-built-linux, LKML, Bill Wendling

On Fri, Jun 4, 2021 at 10:03 AM Jarmo Tiitto <jarmo.tiitto@gmail.com> wrote:
>
> When clang instrumentation eventually calls allocate_node()
> the struct llvm_prf_data *p argument tells us from what section
> we should reserve the vnode: It either points into vmlinux's
> core __llvm_prf_data section or some loaded module's
> __llvm_prf_data section.
>
> But since we don't have access to corresponding
> __llvm_prf_vnds section(s) for any module, the function
> should return just NULL and ignore any profiling attempts
> from modules for now.
>
> Signed-off-by: Jarmo Tiitto <jarmo.tiitto@gmail.com>
> ---
> Based on Kees and others feedback here is v3 patch
> that clarifies why the current checks in allocate_node()
> are flawed. I did fair amount of KGDB time on it.
>
> The commit is based on kees/for-next/clang/features tree,
> hopefully this is ok. Should I have based it on linux-next
> instead?
>
> I grep -R'd where the memory_contains() can be found and it is only
> found in #include <asm-generic/sections.h>
>
> I cross my fingers and await if this is my first accepted patch. :-)
> ---
>  kernel/pgo/instrument.c | 23 ++++++++++++++---------
>  1 file changed, 14 insertions(+), 9 deletions(-)
>
> diff --git a/kernel/pgo/instrument.c b/kernel/pgo/instrument.c
> index 0e07ee1b17d9..c69b4f7ebaad 100644
> --- a/kernel/pgo/instrument.c
> +++ b/kernel/pgo/instrument.c
> @@ -18,6 +18,7 @@
>
>  #define pr_fmt(fmt)    "pgo: " fmt
>
> +#include <asm-generic/sections.h>

^ What about Nathan's feedback on this being just `<asm/sections.h>`?

>  #include <linux/bitops.h>
>  #include <linux/kernel.h>
>  #include <linux/export.h>
> @@ -55,17 +56,21 @@ void prf_unlock(unsigned long flags)
>  static struct llvm_prf_value_node *allocate_node(struct llvm_prf_data *p,
>                                                  u32 index, u64 value)
>  {
> -       if (&__llvm_prf_vnds_start[current_node + 1] >= __llvm_prf_vnds_end)
> -               return NULL; /* Out of nodes */
> -
> -       current_node++;
> -
> -       /* Make sure the node is entirely within the section */
> -       if (&__llvm_prf_vnds_start[current_node] >= __llvm_prf_vnds_end ||
> -           &__llvm_prf_vnds_start[current_node + 1] > __llvm_prf_vnds_end)
> +       const int max_vnds = prf_vnds_count();
> +
> +       /*
> +        * Check that p is within vmlinux __llvm_prf_data section.
> +        * If not, don't allocate since we can't handle modules yet.
> +        */
> +       if (!memory_contains(__llvm_prf_data_start,
> +               __llvm_prf_data_end, p, sizeof(*p)))
>                 return NULL;
>
> -       return &__llvm_prf_vnds_start[current_node];
> +       if (WARN_ON_ONCE(current_node >= max_vnds))
> +               return NULL; /* Out of nodes */
> +
> +       /* reserve vnode for vmlinux */
> +       return &__llvm_prf_vnds_start[current_node++];
>  }
>
>  /*
>
> base-commit: 5d0cda65918279ada060417c5fecb7e86ccb3def
> --
> 2.31.1
>


-- 
Thanks,
~Nick Desaulniers

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

* Re: [PATCH v3 1/1] pgo: Fix allocate_node() v2
  2021-06-04 16:58 [PATCH v3 1/1] pgo: Fix allocate_node() v2 Jarmo Tiitto
  2021-06-04 17:04 ` Nathan Chancellor
  2021-06-04 17:28 ` Nick Desaulniers
@ 2021-06-04 17:58 ` Kees Cook
  2021-06-04 18:06 ` Kees Cook
  3 siblings, 0 replies; 7+ messages in thread
From: Kees Cook @ 2021-06-04 17:58 UTC (permalink / raw)
  To: Bill Wendling, Nathan Chancellor, Jarmo Tiitto, linux-kernel,
	clang-built-linux, Nick Desaulniers, Sami Tolvanen
  Cc: Kees Cook, morbo

On Fri, 4 Jun 2021 19:58:20 +0300, Jarmo Tiitto wrote:
> When clang instrumentation eventually calls allocate_node()
> the struct llvm_prf_data *p argument tells us from what section
> we should reserve the vnode: It either points into vmlinux's
> core __llvm_prf_data section or some loaded module's
> __llvm_prf_data section.
> 
> But since we don't have access to corresponding
> __llvm_prf_vnds section(s) for any module, the function
> should return just NULL and ignore any profiling attempts
> from modules for now.

Thanks for working on this! I tweaked the commit title, reflowed the
commit log to 80 columns, and adjusted asm-generic to asm.

Applied to for-next/clang/features, thanks!

[1/1] pgo: Limit allocate_node() to vmlinux sections
      https://git.kernel.org/kees/c/46773f32ddf1

-- 
Kees Cook


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

* Re: [PATCH v3 1/1] pgo: Fix allocate_node() v2
  2021-06-04 16:58 [PATCH v3 1/1] pgo: Fix allocate_node() v2 Jarmo Tiitto
                   ` (2 preceding siblings ...)
  2021-06-04 17:58 ` Kees Cook
@ 2021-06-04 18:06 ` Kees Cook
  2021-06-05 17:15   ` Jarmo Tiitto
  3 siblings, 1 reply; 7+ messages in thread
From: Kees Cook @ 2021-06-04 18:06 UTC (permalink / raw)
  To: Jarmo Tiitto
  Cc: Sami Tolvanen, Bill Wendling, Nathan Chancellor,
	Nick Desaulniers, clang-built-linux, linux-kernel, morbo

On Fri, Jun 04, 2021 at 07:58:20PM +0300, Jarmo Tiitto wrote:
> When clang instrumentation eventually calls allocate_node()
> the struct llvm_prf_data *p argument tells us from what section
> we should reserve the vnode: It either points into vmlinux's
> core __llvm_prf_data section or some loaded module's
> __llvm_prf_data section.
> 
> But since we don't have access to corresponding
> __llvm_prf_vnds section(s) for any module, the function
> should return just NULL and ignore any profiling attempts
> from modules for now.
> 
> Signed-off-by: Jarmo Tiitto <jarmo.tiitto@gmail.com>
> ---
> Based on Kees and others feedback here is v3 patch
> that clarifies why the current checks in allocate_node()
> are flawed. I did fair amount of KGDB time on it.
> 
> The commit is based on kees/for-next/clang/features tree,
> hopefully this is ok. Should I have based it on linux-next
> instead?
> 
> I grep -R'd where the memory_contains() can be found and it is only
> found in #include <asm-generic/sections.h>

That's true, but the way to use "asm-generic" is to include the
top-level "asm" file, so that architectures can override things as
needed.

> I cross my fingers and await if this is my first accepted patch. :-)

I tweaked it a bit and applied it (see the separate email).

Thank you!

-Kees

-- 
Kees Cook

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

* Re: [PATCH v3 1/1] pgo: Fix allocate_node() v2
  2021-06-04 18:06 ` Kees Cook
@ 2021-06-05 17:15   ` Jarmo Tiitto
  2021-06-05 23:45     ` Fangrui Song
  0 siblings, 1 reply; 7+ messages in thread
From: Jarmo Tiitto @ 2021-06-05 17:15 UTC (permalink / raw)
  To: Jarmo Tiitto, Kees Cook
  Cc: Sami Tolvanen, Bill Wendling, Nathan Chancellor,
	Nick Desaulniers, clang-built-linux, linux-kernel, morbo

> Kees Cook wrote perjantaina 4. kesäkuuta 2021 21.06.37 EEST:
> > 
> > I grep -R'd where the memory_contains() can be found and it is only
> > found in #include <asm-generic/sections.h>
> 
> That's true, but the way to use "asm-generic" is to include the
> top-level "asm" file, so that architectures can override things as
> needed.
> 
Thanks, I didn't know that.

> > I cross my fingers and await if this is my first accepted patch. :-)
> 
> I tweaked it a bit and applied it (see the separate email).
> 
> Thank you!
> 
> -Kees
> 
> -- 
> Kees Cook
> 

Whoa! 
Thanks, I'm glad it worked out. :-)

Btw. I have almost forgotten that I once wrote code 
(that I didn't send) for the GCC gcov subsystem that also enabled 
-fprofile-generate/use for the kernel.
However the Clang PGO looks much more approachable and
easier to hack on since the profile data format is simpler.

So starting to work on this felt just natural to me. :-)

-Jarmo




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

* Re: [PATCH v3 1/1] pgo: Fix allocate_node() v2
  2021-06-05 17:15   ` Jarmo Tiitto
@ 2021-06-05 23:45     ` Fangrui Song
  0 siblings, 0 replies; 7+ messages in thread
From: Fangrui Song @ 2021-06-05 23:45 UTC (permalink / raw)
  To: Jarmo Tiitto
  Cc: Kees Cook, Sami Tolvanen, Bill Wendling, Nathan Chancellor,
	Nick Desaulniers, clang-built-linux, linux-kernel, morbo

On 2021-06-05, Jarmo Tiitto wrote:
>> Kees Cook wrote perjantaina 4. kesäkuuta 2021 21.06.37 EEST:
>> >
>> > I grep -R'd where the memory_contains() can be found and it is only
>> > found in #include <asm-generic/sections.h>
>>
>> That's true, but the way to use "asm-generic" is to include the
>> top-level "asm" file, so that architectures can override things as
>> needed.
>>
>Thanks, I didn't know that.
>
>> > I cross my fingers and await if this is my first accepted patch. :-)
>>
>> I tweaked it a bit and applied it (see the separate email).
>>
>> Thank you!
>>
>> -Kees
>>
>> --
>> Kees Cook
>>
>
>Whoa!
>Thanks, I'm glad it worked out. :-)
>
>Btw. I have almost forgotten that I once wrote code
>(that I didn't send) for the GCC gcov subsystem that also enabled
>-fprofile-generate/use for the kernel.
>However the Clang PGO looks much more approachable and
>easier to hack on since the profile data format is simpler.
>
>So starting to work on this felt just natural to me. :-)
>
>-Jarmo

Right, __llvm_prf_vnodes reserves space for static allocation.
There is no relocation referencing __llvm_prf_vnodes so there is
no straightforward way using the space for the kernel.

In userspace shared objects, the scheme works by linking
libclang_rt.profile-*.a into every shared object.  The
__start___llvm_prf_vnodes/__stop___llvm_prf_vnodes symbols are
delieberately hidden in compiler-rt InstrProfilingPlatformLinux.c.

The GCC gcov format is definitely simpler than the LLVM format:)

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

end of thread, other threads:[~2021-06-05 23:46 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-04 16:58 [PATCH v3 1/1] pgo: Fix allocate_node() v2 Jarmo Tiitto
2021-06-04 17:04 ` Nathan Chancellor
2021-06-04 17:28 ` Nick Desaulniers
2021-06-04 17:58 ` Kees Cook
2021-06-04 18:06 ` Kees Cook
2021-06-05 17:15   ` Jarmo Tiitto
2021-06-05 23:45     ` Fangrui Song

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.