init: defer free large memblock to Buddy allocator

The physical memory of a system is divided into several types, like
memory reserved for device, for kernel pagetable, etc. The remaining
area is for Buddy allocator. Normally, The memory for Buddy is consist
of different size blocks, so, under meeting the memory request of kernel
booting, we can defer free the large block size to Buddy which can be
done later in work queue in parallel to other kernel threads, and the
size of the large block can be defined in kernel command line

Save boot time about 6ms on 512MB rv1126 evb.

Change-Id: Ie7a8d3122d8d92ad918e8bf680f5949412709f37
Signed-off-by: Simon Xue <xxm@rock-chips.com>
Signed-off-by: Tao Huang <huangtao@rock-chips.com>
This commit is contained in:
Simon Xue 2020-04-14 16:13:47 +08:00 committed by Tao Huang
parent 74c472cfec
commit 0c85ec84d1
3 changed files with 57 additions and 0 deletions

View File

@ -71,6 +71,9 @@ extern void free_bootmem_node(pg_data_t *pgdat,
unsigned long size);
extern void free_bootmem(unsigned long physaddr, unsigned long size);
extern void free_bootmem_late(unsigned long physaddr, unsigned long size);
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
extern int defer_free_bootmem(void *unused);
#endif
/*
* Flags for reserve_bootmem (also if CONFIG_HAVE_ARCH_BOOTMEM_NODE,

View File

@ -1376,6 +1376,10 @@ static noinline void __init kernel_init_freeable(void)
smp_init();
sched_init_smp();
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
kthread_run(defer_free_bootmem, NULL, "defer_mem");
#endif
page_alloc_init_late();
/* Initialize page ext after all struct pages are initialized. */
page_ext_init();

View File

@ -32,6 +32,26 @@ struct pglist_data __refdata contig_page_data;
EXPORT_SYMBOL(contig_page_data);
#endif
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
static unsigned long defer_start __initdata;
static unsigned long defer_end __initdata;
#define DEFAULT_DEFER_FREE_BLOCK_SIZE SZ_256M
static unsigned long defer_free_block_size __initdata =
DEFAULT_DEFER_FREE_BLOCK_SIZE;
static int __init early_defer_free_block_size(char *p)
{
defer_free_block_size = memparse(p, &p);
pr_debug("defer_free_block_size = 0x%lx\n", defer_free_block_size);
return 0;
}
early_param("defer_free_block_size", early_defer_free_block_size);
#endif
unsigned long max_low_pfn;
unsigned long min_low_pfn;
unsigned long max_pfn;
@ -112,6 +132,28 @@ static void __init __free_pages_memory(unsigned long start, unsigned long end)
}
}
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
int __init defer_free_bootmem(void *unused)
{
if (defer_start == 0)
return 0;
pr_debug("start = %ld, end = %ld\n", defer_start, defer_end);
__free_pages_memory(defer_start, defer_end);
totalram_pages += defer_end - defer_start;
pr_info("%s: size %luM free %luM [%luM - %luM] total %luM\n", __func__,
defer_free_block_size >> 20,
(defer_end - defer_start) >> (20 - PAGE_SHIFT),
defer_end >> (20 - PAGE_SHIFT),
defer_start >> (20 - PAGE_SHIFT),
totalram_pages >> (20 - PAGE_SHIFT));
return 0;
}
#endif
static unsigned long __init __free_memory_core(phys_addr_t start,
phys_addr_t end)
{
@ -122,6 +164,14 @@ static unsigned long __init __free_memory_core(phys_addr_t start,
if (start_pfn >= end_pfn)
return 0;
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
if ((end - start) > defer_free_block_size) {
defer_start = start_pfn;
defer_end = end_pfn;
return 0;
}
#endif
__free_pages_memory(start_pfn, end_pfn);
return end_pfn - start_pfn;