Re: [PATCH v7 7/8] execmem: add support for cache of large ROX pages

2025-02-27 Thread Ryan Roberts
Hi Mike,

Drive by review comments below...


On 23/10/2024 17:27, Mike Rapoport wrote:
> From: "Mike Rapoport (Microsoft)" 
> 
> Using large pages to map text areas reduces iTLB pressure and improves
> performance.
> 
> Extend execmem_alloc() with an ability to use huge pages with ROX
> permissions as a cache for smaller allocations.
> 
> To populate the cache, a writable large page is allocated from vmalloc with
> VM_ALLOW_HUGE_VMAP, filled with invalid instructions and then remapped as
> ROX.
> 
> The direct map alias of that large page is exculded from the direct map.
> 
> Portions of that large page are handed out to execmem_alloc() callers
> without any changes to the permissions.
> 
> When the memory is freed with execmem_free() it is invalidated again so
> that it won't contain stale instructions.
> 
> An architecture has to implement execmem_fill_trapping_insns() callback
> and select ARCH_HAS_EXECMEM_ROX configuration option to be able to use
> the ROX cache.
> 
> The cache is enabled on per-range basis when an architecture sets
> EXECMEM_ROX_CACHE flag in definition of an execmem_range.
> 
> Signed-off-by: Mike Rapoport (Microsoft) 
> Reviewed-by: Luis Chamberlain 
> Tested-by: kdevops 
> ---

[...]

> +
> +static int execmem_cache_populate(struct execmem_range *range, size_t size)
> +{
> + unsigned long vm_flags = VM_ALLOW_HUGE_VMAP;
> + unsigned long start, end;
> + struct vm_struct *vm;
> + size_t alloc_size;
> + int err = -ENOMEM;
> + void *p;
> +
> + alloc_size = round_up(size, PMD_SIZE);
> + p = execmem_vmalloc(range, alloc_size, PAGE_KERNEL, vm_flags);

Shouldn't this be passing PAGE_KERNEL_ROX? Otherwise I don't see how the
allocated memory is ROX? I don't see any call below where you change the 
permission.

Given the range has the pgprot in it, you could just drop passing the pgprot
explicitly here and have execmem_vmalloc() use range->pgprot directly?

Thanks,
Ryan

> + if (!p)
> + return err;
> +
> + vm = find_vm_area(p);
> + if (!vm)
> + goto err_free_mem;
> +
> + /* fill memory with instructions that will trap */
> + execmem_fill_trapping_insns(p, alloc_size, /* writable = */ true);
> +
> + start = (unsigned long)p;
> + end = start + alloc_size;
> +
> + vunmap_range(start, end);
> +
> + err = execmem_set_direct_map_valid(vm, false);
> + if (err)
> + goto err_free_mem;
> +
> + err = vmap_pages_range_noflush(start, end, range->pgprot, vm->pages,
> +PMD_SHIFT);
> + if (err)
> + goto err_free_mem;
> +
> + err = execmem_cache_add(p, alloc_size);
> + if (err)
> + goto err_free_mem;
> +
> + return 0;
> +
> +err_free_mem:
> + vfree(p);
> + return err;
> +}

[...]


___
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc


Re: [PATCH RFC v2 03/29] mm: asi: Introduce ASI core API

2025-02-27 Thread Borislav Petkov
On Wed, Feb 19, 2025 at 02:53:03PM +0100, Brendan Jackman wrote:
> Argh, sorry, GMail switched back to HTML mode somehow. Maybe I have to
> get a proper mail client after all.

Yap, wouldn't be such a bad idea. And yes, it ain't easy - we have a whole doc
about it:

Documentation/process/email-clients.rst

> OK, sounds like I need to rewrite this explanation! It's only been
> read before by people who already knew how this thing worked so this
> might take a few attempts to make it clear.
> 
> Maybe the best way to make it clear is to explain this with reference
> to KVM. At a super high level, That looks like:
> 
> ioctl(KVM_RUN) {
> enter_from_user_mode()
> while !need_userspace_handling() {
> asi_enter();  // part 1
> vmenter();  // part 2
> asi_relax(); // part 3
> }
> asi _exit(); // part 4b
> exit_to_user_mode()
> }
> 
> So part 4a is just referring to continuation of the loop.
> 
> This explanation was written when that was the only user of this API
> so it was probably clearer, now we have userspace it seems a bit odd.
> 
> With my pseudocode above, does it make more sense? If so I'll try to
> think of a better way to explain it.

Well, it is still confusing. I would expect to see:

ioctl(KVM_RUN) {
enter_from_user_mode()
while !need_userspace_handling() {
asi_enter();  // part 1
vmenter();  // part 2
asi_exit(); // part 3
}
asi_switch(); // part 4b
exit_to_user_mode()
}

Because then it is ballanced: you enter the restricted address space, do stuff
and then you exit it without switching address space. But then you need to
switch address space so you have to do asi_exit or asi_switch or wnatnot. And
that's still unbalanced.

So from *only* looking at the usage, it'd be a lot more balanced if all calls
were paired:

ioctl(KVM_RUN) {
enter_from_user_mode()
asi_switch_to();<---+
while !need_userspace_handling() {  |
asi_enter();  // part 1 <---+   |
vmenter();  // part 2   |   |
asi_exit(); // part 3   <---+   |
}   |
asi_switch_back(); // part 4b   <---+
exit_to_user_mode()
}

(look at me doing ascii paintint :-P)

Naming is awful but it should illustrate what I mean:

asi_switch_to
  asi_enter
  asi_exit
asi_switch_back

Does that make more sense?

> asi_enter() is actually balanced with asi_relax(). The comment says
> "if we are in it" because technically if you call this asi_relax()
> outside of the critical section, it's a nop. But, there's no reason to
> do that, so we could definitely change the comment and WARN if that
> happens.

See above.

> 
> >
> > > +#define ASI_TAINT_OTHER_MM_CONTROL   ((asi_taints_t)BIT(6))
> > > +#define ASI_NUM_TAINTS   6
> > > +static_assert(BITS_PER_BYTE * sizeof(asi_taints_t) >= ASI_NUM_TAINTS);
> >
> > Why is this a typedef at all to make the code more unreadable than it needs 
> > to
> > be? Why not a simple unsigned int or char or whatever you need?
> 
> 
> My thinking was just that it's nicer to see asi_taints_t and know that
> it means "it holds taint flags and it's big enough" instead of having
> to remember the space needed for these flags. But yeah I'm fine with
> making it a raw integer type.

You're thinking of some of those rules here perhaps?

https://kernel.org/doc/html/latest/process/coding-style.html#typedefs

Probably but then you're using casts (asi_taints_t) to put in integers in it.
Does it matter then?

Might as well use a plain int and avoid the casts, no? Unless there's a real
good reason to have a special type and it is really really good this way...?

> Well it needs to be disambiguated from the field below (currently
> protect_data) but it could be control_to_flush (and data_to_flush).
> 
> The downside of that is that having one say "prevent" and one say
> "protect" is quite meaningful. prevent_control is describing things we
> need to do to protect the system from this domain, protect_data is
> about protecting the domain from the system. However, while that
> difference is meaningful it might not actually be helpful for the
> reader of the code so I'm not wed to it.
> 
> Also worth noting that we could just combine these fields. At present
> they should have disjoint bits set. But, they're used in separate
> contexts and have separate (although conceptually very similar)
> meanings, so I think that would reduce clarity.

Ok, I guess it'll tell us what is better once we stare at that code more. :)

> Ack, I've set up a local thingy to spellcheck all my commits so
> hopefully you should encounter less of that noise in future.

Yeah, I use the default vim spellchecker and it simply works.
 
> For the pronouns stuff I will do my best but you might still spot
> violations in older text, sorry about that.

No worries.

> What this field is describing i