From 0c85ec84d1b0fc03b7593cd155a401192cec6264 Mon Sep 17 00:00:00 2001 From: Simon Xue Date: Tue, 14 Apr 2020 16:13:47 +0800 Subject: [PATCH] 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 Signed-off-by: Tao Huang --- include/linux/bootmem.h | 3 +++ init/main.c | 4 ++++ mm/nobootmem.c | 50 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index 42515195d7d8..12fd6ad17e6e 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h @@ -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, diff --git a/init/main.c b/init/main.c index a2d8596fea02..0e4eb2f02d23 100644 --- a/init/main.c +++ b/init/main.c @@ -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(); diff --git a/mm/nobootmem.c b/mm/nobootmem.c index 439af3b765a7..8d90c896da4e 100644 --- a/mm/nobootmem.c +++ b/mm/nobootmem.c @@ -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;