Re: [PATCH v5 7/8] execmem: add support for cache of large ROX pages
Kees Bakker <[email protected]>
| Newsgroups | gmane.linux.ports.alpha,gmane.linux.kernel.bpf,gmane.linux.kernel.cross-arch,gmane.linux.ports.arm.kernel,gmane.linux.ports.hexagon,gmane.linux.kernel,gmane.linux.ports.mips,gmane.linux.kernel.mm,gmane.linux.kernel.modules,gmane.linux.ports.parisc,gmane.linux.ports.riscv,gmane.linux.ports.sh.devel,gmane.linux.kernel.arc,gmane.linux.uml.devel,gmane.linux.ports.ppc64.devel,gmane.linux.ports.sparc |
|---|---|
| Message-ID | <[email protected]> |
Op 09-10-2024 om 20:08 schreef Mike Rapoport: > From: "Mike Rapoport (Microsoft)" <[email protected]> > > 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. > > 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. > > The cache is enabled when an architecture sets EXECMEM_ROX_CACHE flag in > definition of an execmem_range. > > Signed-off-by: Mike Rapoport (Microsoft) <[email protected]> > --- > include/linux/execmem.h | 2 + > mm/execmem.c | 317 +++++++++++++++++++++++++++++++++++++++- > mm/internal.h | 1 + > mm/vmalloc.c | 5 + > 4 files changed, 320 insertions(+), 5 deletions(-) > [...] > +static void execmem_cache_clean(struct work_struct *work) > +{ > + struct maple_tree *free_areas = &execmem_cache.free_areas; > + struct mutex *mutex = &execmem_cache.mutex; > + MA_STATE(mas, free_areas, 0, ULONG_MAX); > + void *area; > + > + mutex_lock(mutex); > + mas_for_each(&mas, area, ULONG_MAX) { > + size_t size; > + No need to check for !area, because it is already guaranteed by the while loop condition (mas_for_each) > + if (!area) > + continue; > + > + size = mas_range_len(&mas); > + > + if (IS_ALIGNED(size, PMD_SIZE) && > + IS_ALIGNED(mas.index, PMD_SIZE)) { > + struct vm_struct *vm = find_vm_area(area); > + > + execmem_set_direct_map_valid(vm, true); > + mas_store_gfp(&mas, NULL, GFP_KERNEL); > + vfree(area); > + } > + } > + mutex_unlock(mutex); > +} >