treewide: Backport new vmalloc for large performance benefits
This is a backport from Linux 5.2-rc1 of a patch series to greatly enhance vmalloc's performance especially on embedded systems, plus all of its dependencies that were missing in kernel 4.9. For all the informations, refer to LKML: https://lkml.org/lkml/2018/10/19/786 Brief informations: Currently an allocation of the new VA area is done over busy list iteration until a suitable hole is found between two busy areas. Therefore each new allocation causes the list being grown. Due to long list and different permissive parameters an allocation can take a long time on embedded devices(milliseconds). This patch organizes the vmalloc memory layout into free areas of the VMALLOC_START-VMALLOC_END range. It uses a red-black tree that keeps blocks sorted by their offsets in pair with linked list keeping the free space in order of increasing addresses. Quote Phoronix: With this patch from Uladzislau Rezki, calling vmalloc() can take up to 67% less time compared to the behavior on Linux 5.1 and prior, at least with tests done by the developer under QEMU. Personal tests are showing that the device is more responsive when memory pressure is high and when huge allocations are to be done, it's also noticeably faster in this case, like when starting Chrome with more than 100 opened tabs after a system reboot (so, an uncached complete load of it). Shameless kanged from: https://github.com/sonyxperiadev/kernel / Pull Request 2016 Signed-off-by: sweetyicecare <gabrielseedev@outlook.com> Signed-off-by: Aoihara <veronicadisa6@gmail.com> Signed-off-by: KangMamles <imzea69@gmail.com> Signed-off-by: Sorayukii <sorayukii69@gmail.com>
This commit is contained in:
parent
05b528d2bb
commit
24b59982a7
126 changed files with 2219 additions and 812 deletions
|
|
@ -150,6 +150,7 @@ See the include/linux/kmemleak.h header for the functions prototype.
|
|||
- ``kmemleak_init`` - initialize kmemleak
|
||||
- ``kmemleak_alloc`` - notify of a memory block allocation
|
||||
- ``kmemleak_alloc_percpu`` - notify of a percpu memory block allocation
|
||||
- ``kmemleak_vmalloc`` - notify of a vmalloc() memory allocation
|
||||
- ``kmemleak_free`` - notify of a memory block freeing
|
||||
- ``kmemleak_free_part`` - notify of a partial memory block freeing
|
||||
- ``kmemleak_free_percpu`` - notify of a percpu memory block freeing
|
||||
|
|
|
|||
|
|
@ -227,6 +227,9 @@ config ARCH_HAS_FORTIFY_SOURCE
|
|||
An architecture should select this when it can successfully
|
||||
build and run with CONFIG_FORTIFY_SOURCE.
|
||||
|
||||
config ARCH_HAS_SET_MEMORY
|
||||
bool
|
||||
|
||||
config FORTIFY_COMPILE_CHECK
|
||||
depends on ARCH_HAS_FORTIFY_SOURCE
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include <asm/shmparam.h>
|
||||
#include <asm/cachetype.h>
|
||||
#include <asm/outercache.h>
|
||||
#include <asm/set_memory.h>
|
||||
|
||||
#define CACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
|
||||
|
||||
|
|
|
|||
32
arch/arm/include/asm/set_memory.h
Normal file
32
arch/arm/include/asm/set_memory.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (C) 1999-2002 Russell King
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _ASMARM_SET_MEMORY_H
|
||||
#define _ASMARM_SET_MEMORY_H
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
int set_memory_ro(unsigned long addr, int numpages);
|
||||
int set_memory_rw(unsigned long addr, int numpages);
|
||||
int set_memory_x(unsigned long addr, int numpages);
|
||||
int set_memory_nx(unsigned long addr, int numpages);
|
||||
#else
|
||||
static inline int set_memory_ro(unsigned long addr, int numpages) { return 0; }
|
||||
static inline int set_memory_rw(unsigned long addr, int numpages) { return 0; }
|
||||
static inline int set_memory_x(unsigned long addr, int numpages) { return 0; }
|
||||
static inline int set_memory_nx(unsigned long addr, int numpages) { return 0; }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STRICT_KERNEL_RWX
|
||||
void set_kernel_text_rw(void);
|
||||
void set_kernel_text_ro(void);
|
||||
#else
|
||||
static inline void set_kernel_text_rw(void) { }
|
||||
static inline void set_kernel_text_ro(void) { }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -92,8 +92,7 @@ void __init add_static_vm_early(struct static_vm *svm)
|
|||
void *vaddr;
|
||||
|
||||
vm = &svm->vm;
|
||||
if (!vm_area_check_early(vm))
|
||||
vm_area_add_early(vm);
|
||||
vm_area_add_early(vm);
|
||||
vaddr = vm->addr;
|
||||
|
||||
list_for_each_entry(curr_svm, &static_vmlist, list) {
|
||||
|
|
|
|||
|
|
@ -1449,21 +1449,12 @@ static void __init map_lowmem(void)
|
|||
phys_addr_t kernel_x_start = round_down(__pa(_stext), SECTION_SIZE);
|
||||
#endif
|
||||
phys_addr_t kernel_x_end = round_up(__pa(__init_end), SECTION_SIZE);
|
||||
struct static_vm *svm;
|
||||
phys_addr_t start;
|
||||
phys_addr_t end;
|
||||
unsigned long vaddr;
|
||||
unsigned long pfn;
|
||||
unsigned long length;
|
||||
unsigned int type;
|
||||
int nr = 0;
|
||||
|
||||
/* Map all the lowmem memory banks. */
|
||||
for_each_memblock(memory, reg) {
|
||||
phys_addr_t start = reg->base;
|
||||
phys_addr_t end = start + reg->size;
|
||||
struct map_desc map;
|
||||
start = reg->base;
|
||||
end = start + reg->size;
|
||||
nr++;
|
||||
|
||||
if (memblock_is_nomap(reg))
|
||||
continue;
|
||||
|
|
@ -1515,34 +1506,6 @@ static void __init map_lowmem(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
svm = early_alloc_aligned(sizeof(*svm) * nr, __alignof__(*svm));
|
||||
|
||||
for_each_memblock(memory, reg) {
|
||||
struct vm_struct *vm;
|
||||
|
||||
start = reg->base;
|
||||
end = start + reg->size;
|
||||
|
||||
if (end > arm_lowmem_limit)
|
||||
end = arm_lowmem_limit;
|
||||
if (start >= end)
|
||||
break;
|
||||
|
||||
vm = &svm->vm;
|
||||
pfn = __phys_to_pfn(start);
|
||||
vaddr = __phys_to_virt(start);
|
||||
length = end - start;
|
||||
type = MT_MEMORY_RW;
|
||||
|
||||
vm->addr = (void *)(vaddr & PAGE_MASK);
|
||||
vm->size = PAGE_ALIGN(length + (vaddr & ~PAGE_MASK));
|
||||
vm->phys_addr = __pfn_to_phys(pfn);
|
||||
vm->flags = VM_LOWMEM;
|
||||
vm->flags |= VM_ARM_MTYPE(type);
|
||||
vm->caller = map_lowmem;
|
||||
add_static_vm_early(svm++);
|
||||
mark_vmalloc_reserved_area(vm->addr, vm->size);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM_PV_FIXUP
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ config ARM64
|
|||
select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
|
||||
select ARCH_WANT_FRAME_POINTERS
|
||||
select ARCH_HAS_UBSAN_SANITIZE_ALL
|
||||
select ARCH_HAS_SET_MEMORY
|
||||
select ARM_AMBA
|
||||
select ARM_ARCH_TIMER
|
||||
select ARM_GIC
|
||||
|
|
|
|||
|
|
@ -243,6 +243,7 @@ CONFIG_HAVE_DMA_CONTIGUOUS=y
|
|||
CONFIG_GENERIC_SMP_IDLE_THREAD=y
|
||||
CONFIG_GENERIC_IDLE_POLL_SETUP=y
|
||||
CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
|
||||
CONFIG_ARCH_HAS_SET_MEMORY=y
|
||||
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
|
||||
CONFIG_HAVE_CLK=y
|
||||
CONFIG_HAVE_DMA_API_DEBUG=y
|
||||
|
|
|
|||
|
|
@ -243,6 +243,7 @@ CONFIG_HAVE_DMA_CONTIGUOUS=y
|
|||
CONFIG_GENERIC_SMP_IDLE_THREAD=y
|
||||
CONFIG_GENERIC_IDLE_POLL_SETUP=y
|
||||
CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
|
||||
CONFIG_ARCH_HAS_SET_MEMORY=y
|
||||
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
|
||||
CONFIG_HAVE_CLK=y
|
||||
CONFIG_HAVE_DMA_API_DEBUG=y
|
||||
|
|
|
|||
|
|
@ -243,6 +243,7 @@ CONFIG_HAVE_DMA_CONTIGUOUS=y
|
|||
CONFIG_GENERIC_SMP_IDLE_THREAD=y
|
||||
CONFIG_GENERIC_IDLE_POLL_SETUP=y
|
||||
CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
|
||||
CONFIG_ARCH_HAS_SET_MEMORY=y
|
||||
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
|
||||
CONFIG_HAVE_CLK=y
|
||||
CONFIG_HAVE_DMA_API_DEBUG=y
|
||||
|
|
|
|||
|
|
@ -243,6 +243,7 @@ CONFIG_HAVE_DMA_CONTIGUOUS=y
|
|||
CONFIG_GENERIC_SMP_IDLE_THREAD=y
|
||||
CONFIG_GENERIC_IDLE_POLL_SETUP=y
|
||||
CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
|
||||
CONFIG_ARCH_HAS_SET_MEMORY=y
|
||||
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
|
||||
CONFIG_HAVE_CLK=y
|
||||
CONFIG_HAVE_DMA_API_DEBUG=y
|
||||
|
|
|
|||
|
|
@ -243,6 +243,7 @@ CONFIG_HAVE_DMA_CONTIGUOUS=y
|
|||
CONFIG_GENERIC_SMP_IDLE_THREAD=y
|
||||
CONFIG_GENERIC_IDLE_POLL_SETUP=y
|
||||
CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
|
||||
CONFIG_ARCH_HAS_SET_MEMORY=y
|
||||
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
|
||||
CONFIG_HAVE_CLK=y
|
||||
CONFIG_HAVE_DMA_API_DEBUG=y
|
||||
|
|
|
|||
|
|
@ -243,6 +243,7 @@ CONFIG_HAVE_DMA_CONTIGUOUS=y
|
|||
CONFIG_GENERIC_SMP_IDLE_THREAD=y
|
||||
CONFIG_GENERIC_IDLE_POLL_SETUP=y
|
||||
CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
|
||||
CONFIG_ARCH_HAS_SET_MEMORY=y
|
||||
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
|
||||
CONFIG_HAVE_CLK=y
|
||||
CONFIG_HAVE_DMA_API_DEBUG=y
|
||||
|
|
|
|||
|
|
@ -243,6 +243,7 @@ CONFIG_HAVE_DMA_CONTIGUOUS=y
|
|||
CONFIG_GENERIC_SMP_IDLE_THREAD=y
|
||||
CONFIG_GENERIC_IDLE_POLL_SETUP=y
|
||||
CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
|
||||
CONFIG_ARCH_HAS_SET_MEMORY=y
|
||||
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
|
||||
CONFIG_HAVE_CLK=y
|
||||
CONFIG_HAVE_DMA_API_DEBUG=y
|
||||
|
|
|
|||
|
|
@ -243,6 +243,7 @@ CONFIG_HAVE_DMA_CONTIGUOUS=y
|
|||
CONFIG_GENERIC_SMP_IDLE_THREAD=y
|
||||
CONFIG_GENERIC_IDLE_POLL_SETUP=y
|
||||
CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
|
||||
CONFIG_ARCH_HAS_SET_MEMORY=y
|
||||
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
|
||||
CONFIG_HAVE_CLK=y
|
||||
CONFIG_HAVE_DMA_API_DEBUG=y
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ generic-y += rwsem.h
|
|||
generic-y += segment.h
|
||||
generic-y += sembuf.h
|
||||
generic-y += serial.h
|
||||
generic-y += set_memory.h
|
||||
generic-y += shmbuf.h
|
||||
generic-y += simd.h
|
||||
generic-y += sizes.h
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#define __ASM_CACHEFLUSH_H
|
||||
|
||||
#include <linux/mm.h>
|
||||
#include <asm/set_memory.h>
|
||||
|
||||
/*
|
||||
* This flag is used to indicate that the page pointed to by a pte is clean
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ void free_init_pages(const char *what, unsigned long begin, unsigned long end)
|
|||
ClearPageReserved(virt_to_page(addr));
|
||||
init_page_count(virt_to_page(addr));
|
||||
free_page(addr);
|
||||
totalram_pages++;
|
||||
totalram_pages_inc();
|
||||
}
|
||||
|
||||
printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ void *module_alloc(unsigned long size)
|
|||
* easier than trying to map the text, data, init_text and
|
||||
* init_data correctly */
|
||||
return __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END,
|
||||
GFP_KERNEL | __GFP_HIGHMEM,
|
||||
GFP_KERNEL,
|
||||
PAGE_KERNEL_RWX, 0, NUMA_NO_NODE,
|
||||
__builtin_return_address(0));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ static long cmm_alloc_pages(long nr)
|
|||
|
||||
pa->page[pa->index++] = addr;
|
||||
loaned_pages++;
|
||||
totalram_pages--;
|
||||
totalram_pages_dec();
|
||||
spin_unlock(&cmm_lock);
|
||||
nr--;
|
||||
}
|
||||
|
|
@ -213,7 +213,7 @@ static long cmm_free_pages(long nr)
|
|||
free_page(addr);
|
||||
loaned_pages--;
|
||||
nr--;
|
||||
totalram_pages++;
|
||||
totalram_pages_inc();
|
||||
}
|
||||
spin_unlock(&cmm_lock);
|
||||
cmm_dbg("End request with %ld pages unfulfilled\n", nr);
|
||||
|
|
@ -257,7 +257,7 @@ static void cmm_get_mpp(void)
|
|||
int rc;
|
||||
struct hvcall_mpp_data mpp_data;
|
||||
signed long active_pages_target, page_loan_request, target;
|
||||
signed long total_pages = totalram_pages + loaned_pages;
|
||||
signed long total_pages = totalram_pages() + loaned_pages;
|
||||
signed long min_mem_pages = (min_mem_mb * 1024 * 1024) / PAGE_SIZE;
|
||||
|
||||
rc = h_get_mpp(&mpp_data);
|
||||
|
|
@ -288,7 +288,7 @@ static void cmm_get_mpp(void)
|
|||
|
||||
cmm_dbg("delta = %ld, loaned = %lu, target = %lu, oom = %lu, totalram = %lu\n",
|
||||
page_loan_request, loaned_pages, loaned_pages_target,
|
||||
oom_freed_pages, totalram_pages);
|
||||
oom_freed_pages, totalram_pages());
|
||||
}
|
||||
|
||||
static struct notifier_block cmm_oom_nb = {
|
||||
|
|
@ -552,7 +552,7 @@ static int cmm_mem_going_offline(void *arg)
|
|||
free_page(pa_curr->page[idx]);
|
||||
freed++;
|
||||
loaned_pages--;
|
||||
totalram_pages++;
|
||||
totalram_pages_inc();
|
||||
pa_curr->page[idx] = pa_last->page[--pa_last->index];
|
||||
if (pa_last->index == 0) {
|
||||
if (pa_curr == pa_last)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue