Re: [PATCH v3 03/13] mm/execmem, arch: convert simple overrides of module_alloc to execmem

2023-10-26 Thread Mike Rapoport
Hi Rick,

Sorry for the delay, I was a bit preoccupied with $stuff.

On Thu, Oct 05, 2023 at 06:09:07PM +, Edgecombe, Rick P wrote:
> On Thu, 2023-10-05 at 08:26 +0300, Mike Rapoport wrote:
> > On Wed, Oct 04, 2023 at 03:39:26PM +, Edgecombe, Rick P wrote:
> > > On Tue, 2023-10-03 at 17:29 -0700, Rick Edgecombe wrote:
> > > > It seems a bit weird to copy all of this. Is it trying to be
> > > > faster
> > > > or
> > > > something?
> > > > 
> > > > Couldn't it just check r->start in execmem_text/data_alloc() path
> > > > and
> > > > switch to EXECMEM_DEFAULT if needed then? The
> > > > execmem_range_is_data()
> > > > part that comes later could be added to the logic there too. So
> > > > this
> > > > seems like unnecessary complexity to me or I don't see the
> > > > reason.
> > > 
> > > I guess this is a bad idea because if you have the full size array
> > > sitting around anyway you might as well use it and reduce the
> > > exec_mem_alloc() logic.
> > 
> > That's was the idea, indeed. :)
> > 
> > > Just looking at it from the x86 side (and
> > > similar) though, where there is actually only one execmem_range and
> > > it
> > > building this whole array with identical data and it seems weird.
> > 
> > Right, most architectures have only one range, but to support all
> > variants
> > that we have, execmem has to maintain the whole array.
> 
> What about just having an index into a smaller set of ranges. The
> module area and the extra JIT area. So ->ranges can be size 3
> (statically allocated in the arch code) for three areas and then the
> index array can be size EXECMEM_TYPE_MAX. The default 0 value of the
> indexing array will point to the default area and any special areas can
> be set in the index point to the desired range.
> 
> Looking at how it would do for x86 and arm64, it looks maybe a bit
> better to me. A little bit less code and memory usage, and a bit easier
> to trace the configuration through to the final state (IMO). What do
> you think? Very rough, on top of this series, below.

I like your suggestion to only have definitions of actual ranges in arch
code and index array to redirect allocation requests to the right range.
I'll make the next version along the lines of your patch.

> As I was playing around with this, I was also wondering why it needs
> two copies of struct execmem_params: one returned from the arch code
> and one in exec mem. 

No actual reason, one copy is enough, thanks for catching this.

> And why the temporary arch copy is ro_after_init,
> but the final execmem.c copy is not ro_after_init?

I just missed it, thanks for pointing out.
 
-- 
Sincerely yours,
Mike.


Re: [PATCH v3 03/13] mm/execmem, arch: convert simple overrides of module_alloc to execmem

2023-10-05 Thread Edgecombe, Rick P
On Mon, 2023-09-18 at 10:29 +0300, Mike Rapoport wrote:
> +/**
> + * struct execmem_range - definition of a memory range suitable for
> code and
> + *   related data allocations
> + * @start: address space start
> + * @end:   address space end (inclusive)
> + * @pgprot:permissions for memory in this address space
> + * @alignment: alignment required for text allocations
> + */
> +struct execmem_range {
> +   unsigned long   start;
> +   unsigned long   end;
> +   pgprot_t    pgprot;
> +   unsigned intalignment;
> +};

Not a strong opinion, but range doesn't seem an appropriate name. It
*has* a range, but also other allocation configuration. It gets
especially confusing when multiple "ranges" have the same range. Maybe
execmem_alloc_params?


Re: [PATCH v3 03/13] mm/execmem, arch: convert simple overrides of module_alloc to execmem

2023-10-05 Thread Edgecombe, Rick P
On Thu, 2023-10-05 at 08:26 +0300, Mike Rapoport wrote:
> On Wed, Oct 04, 2023 at 03:39:26PM +, Edgecombe, Rick P wrote:
> > On Tue, 2023-10-03 at 17:29 -0700, Rick Edgecombe wrote:
> > > It seems a bit weird to copy all of this. Is it trying to be
> > > faster
> > > or
> > > something?
> > > 
> > > Couldn't it just check r->start in execmem_text/data_alloc() path
> > > and
> > > switch to EXECMEM_DEFAULT if needed then? The
> > > execmem_range_is_data()
> > > part that comes later could be added to the logic there too. So
> > > this
> > > seems like unnecessary complexity to me or I don't see the
> > > reason.
> > 
> > I guess this is a bad idea because if you have the full size array
> > sitting around anyway you might as well use it and reduce the
> > exec_mem_alloc() logic.
> 
> That's was the idea, indeed. :)
> 
> > Just looking at it from the x86 side (and
> > similar) though, where there is actually only one execmem_range and
> > it
> > building this whole array with identical data and it seems weird.
> 
> Right, most architectures have only one range, but to support all
> variants
> that we have, execmem has to maintain the whole array.

What about just having an index into a smaller set of ranges. The
module area and the extra JIT area. So ->ranges can be size 3
(statically allocated in the arch code) for three areas and then the
index array can be size EXECMEM_TYPE_MAX. The default 0 value of the
indexing array will point to the default area and any special areas can
be set in the index point to the desired range.

Looking at how it would do for x86 and arm64, it looks maybe a bit
better to me. A little bit less code and memory usage, and a bit easier
to trace the configuration through to the final state (IMO). What do
you think? Very rough, on top of this series, below.

As I was playing around with this, I was also wondering why it needs
two copies of struct execmem_params: one returned from the arch code
and one in exec mem. And why the temporary arch copy is ro_after_init,
but the final execmem.c copy is not ro_after_init?

 arch/arm64/mm/init.c| 67 ++---
--
 arch/x86/mm/init.c  | 24 +---
 include/linux/execmem.h |  5 +++--
 mm/execmem.c| 61 -

 4 files changed, 70 insertions(+), 87 deletions(-)

diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 9b7716b4d84c..7df119101f20 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -633,49 +633,58 @@ static int __init module_init_limits(void)
return 0;
 }
 
-static struct execmem_params execmem_params __ro_after_init = {
-   .ranges = {
-   [EXECMEM_DEFAULT] = {
-   .flags = EXECMEM_KASAN_SHADOW,
-   .alignment = MODULE_ALIGN,
-   },
-   [EXECMEM_KPROBES] = {
-   .start = VMALLOC_START,
-   .end = VMALLOC_END,
-   .alignment = 1,
-   },
-   [EXECMEM_BPF] = {
-   .start = VMALLOC_START,
-   .end = VMALLOC_END,
-   .alignment = 1,
-   },
+static struct execmem_range[2] ranges __ro_after_init = {
+   /* Module area */
+   [0] = {
+   .flags = EXECMEM_KASAN_SHADOW,
+   .alignment = MODULE_ALIGN,
+   },
+   /* Kprobes area */
+   [1] = {
+   .start = VMALLOC_START,
+   .end = VMALLOC_END,
+   .alignment = 1,
+   },
+   /* BPF area */
+   [2] = {
+   .start = VMALLOC_START,
+   .end = VMALLOC_END,
+   .alignment = 1,
},
 };
 
-struct execmem_params __init *execmem_arch_params(void)
+void __init execmem_arch_params(struct execmem_params *p)
 {
-   struct execmem_range *r =
_params.ranges[EXECMEM_DEFAULT];
+   struct execmem_range *default;
+   struct execmem_range *jit;
+
+   p->ranges = 
 
module_init_limits();
 
-   r->pgprot = PAGE_KERNEL;
-
+   /* Default area */
+   default = [0];
+   default->pgprot = PAGE_KERNEL;
if (module_direct_base) {
-   r->start = module_direct_base;
-   r->end = module_direct_base + SZ_128M;
+   default->start = module_direct_base;
+   default->end = module_direct_base + SZ_128M;
 
if (module_plt_base) {
-   r->fallback_start = module_plt_base;
-   r->fallback_end = module_plt_base + SZ_2G;
+   default->fallback_start = module_plt_base;
+   default->fallback_end = module_plt_base +
SZ_2G;
}
} else if (module_plt_base) {
-   r->start = module_plt_base;
-   r->end = module_plt_base + SZ_2G;
+   default->start = 

Re: [PATCH v3 03/13] mm/execmem, arch: convert simple overrides of module_alloc to execmem

2023-10-04 Thread Mike Rapoport
On Wed, Oct 04, 2023 at 03:39:26PM +, Edgecombe, Rick P wrote:
> On Tue, 2023-10-03 at 17:29 -0700, Rick Edgecombe wrote:
> > It seems a bit weird to copy all of this. Is it trying to be faster
> > or
> > something?
> > 
> > Couldn't it just check r->start in execmem_text/data_alloc() path and
> > switch to EXECMEM_DEFAULT if needed then? The execmem_range_is_data()
> > part that comes later could be added to the logic there too. So this
> > seems like unnecessary complexity to me or I don't see the reason.
> 
> I guess this is a bad idea because if you have the full size array
> sitting around anyway you might as well use it and reduce the
> exec_mem_alloc() logic.

That's was the idea, indeed. :)

> Just looking at it from the x86 side (and
> similar) though, where there is actually only one execmem_range and it
> building this whole array with identical data and it seems weird.

Right, most architectures have only one range, but to support all variants
that we have, execmem has to maintain the whole array.

-- 
Sincerely yours,
Mike.


Re: [PATCH v3 03/13] mm/execmem, arch: convert simple overrides of module_alloc to execmem

2023-10-04 Thread Edgecombe, Rick P
On Tue, 2023-10-03 at 17:29 -0700, Rick Edgecombe wrote:
> It seems a bit weird to copy all of this. Is it trying to be faster
> or
> something?
> 
> Couldn't it just check r->start in execmem_text/data_alloc() path and
> switch to EXECMEM_DEFAULT if needed then? The execmem_range_is_data()
> part that comes later could be added to the logic there too. So this
> seems like unnecessary complexity to me or I don't see the reason.

I guess this is a bad idea because if you have the full size array
sitting around anyway you might as well use it and reduce the
exec_mem_alloc() logic. Just looking at it from the x86 side (and
similar) though, where there is actually only one execmem_range and it
building this whole array with identical data and it seems weird.



Re: [PATCH v3 03/13] mm/execmem, arch: convert simple overrides of module_alloc to execmem

2023-10-03 Thread Edgecombe, Rick P
On Mon, 2023-09-18 at 10:29 +0300, Mike Rapoport wrote:
> +
> +static void execmem_init_missing(struct execmem_params *p)
> +{
> +   struct execmem_range *default_range = 
> >ranges[EXECMEM_DEFAULT];
> +
> +   for (int i = EXECMEM_DEFAULT + 1; i < EXECMEM_TYPE_MAX; i++)
> {
> +   struct execmem_range *r = >ranges[i];
> +
> +   if (!r->start) {
> +   r->pgprot = default_range->pgprot;
> +   r->alignment = default_range->alignment;
> +   r->start = default_range->start;
> +   r->end = default_range->end;
> +   }
> +   }
> +}
> +

It seems a bit weird to copy all of this. Is it trying to be faster or
something?

Couldn't it just check r->start in execmem_text/data_alloc() path and
switch to EXECMEM_DEFAULT if needed then? The execmem_range_is_data()
part that comes later could be added to the logic there too. So this
seems like unnecessary complexity to me or I don't see the reason.