ANDROID: memblock: track kernel size on memsize
Some memory regions are already being tracked by previous patches. But there are many memory allocations from memblock and frees to memblock during the boot time. This patch tracks the memblock size used for the common kernel. To to this, tracking memblock size is disabled for some memory handling logics like early param, device tree, and default cma size. For precise kernel size, this patch counts not actually freed size to buddy at boot time, and does not count freed size from ramdisk and init section. Additionally this patch does one important thing. This patch blocks memblock_add_range of memblock_remove_range not to update memsize if free pages were already released to the buddy allocator. This is an example. The kernel size is newly added by this patch. .kernel : 135137 KB .unusable : 788073 KB .reusable : 294912 KB Bug: 340432773 Signed-off-by: Jaewon Kim <jaewon31.kim@samsung.com> Link: https://lore.kernel.org/linux-mm/20240521023957.2587005-8-jaewon31.kim@samsung.com/ Change-Id: Ice0c2aa568385490a3468f7567b4b8c083e043ec
This commit is contained in:
committed by
Suren Baghdasaryan
parent
e8e18b40c0
commit
75fe456d4e
@@ -504,6 +504,7 @@ void __init early_init_fdt_scan_reserved_mem(void)
|
||||
return;
|
||||
|
||||
memblock_memsize_detect_hole();
|
||||
memblock_memsize_disable_tracking();
|
||||
|
||||
fdt_scan_reserved_mem();
|
||||
fdt_reserve_elfcorehdr();
|
||||
@@ -516,6 +517,7 @@ void __init early_init_fdt_scan_reserved_mem(void)
|
||||
memblock_reserve(base, size);
|
||||
memblock_memsize_record("memreserve", base, size, false, false);
|
||||
}
|
||||
memblock_memsize_enable_tracking();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -597,10 +597,16 @@ static inline void memtest_report_meminfo(struct seq_file *m) { }
|
||||
extern void __init_memblock memblock_memsize_record(const char *name,
|
||||
phys_addr_t base, phys_addr_t size, bool nomap, bool reusable);
|
||||
extern void __init memblock_memsize_detect_hole(void);
|
||||
extern void __init memblock_memsize_enable_tracking(void);
|
||||
extern void __init memblock_memsize_disable_tracking(void);
|
||||
extern void memblock_memsize_mod_kernel_size(long size);
|
||||
#else
|
||||
static inline void __init_memblock memblock_memsize_record(const char *name,
|
||||
phys_addr_t base, phys_addr_t size, bool nomap, bool reusable) { }
|
||||
static inline void __init memblock_memsize_detect_hole(void) { }
|
||||
static inline void __init memblock_memsize_enable_tracking(void) { }
|
||||
static inline void __init memblock_memsize_disable_tracking(void) { }
|
||||
static inline void memblock_memsize_mod_kernel_size(long size) { }
|
||||
#endif
|
||||
|
||||
#endif /* _LINUX_MEMBLOCK_H */
|
||||
|
||||
@@ -278,10 +278,11 @@ int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base,
|
||||
{
|
||||
int ret;
|
||||
|
||||
memblock_memsize_disable_tracking();
|
||||
ret = cma_declare_contiguous(base, size, limit, 0, 0, fixed,
|
||||
"reserved", res_cma);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
/* Architecture specific contiguous memory fixup. */
|
||||
dma_contiguous_early_fixup(cma_get_base(*res_cma),
|
||||
@@ -289,7 +290,9 @@ int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base,
|
||||
|
||||
memblock_memsize_record("dma_cma", cma_get_base(*res_cma),
|
||||
cma_get_size(*res_cma), false, true);
|
||||
return 0;
|
||||
out:
|
||||
memblock_memsize_enable_tracking();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+57
-1
@@ -134,6 +134,11 @@ struct memblock_type physmem = {
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MEMBLOCK_MEMSIZE
|
||||
static long memsize_kinit;
|
||||
static bool memblock_memsize_tracking __initdata_memblock = true;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* keep a pointer to &memblock.memory in the text section to use it in
|
||||
* __next_mem_range() and its helpers.
|
||||
@@ -690,6 +695,15 @@ repeat:
|
||||
memblock_merge_regions(type, start_rgn, end_rgn);
|
||||
}
|
||||
done:
|
||||
#ifdef CONFIG_MEMBLOCK_MEMSIZE
|
||||
if (memblock_memsize_tracking) {
|
||||
if (new_size && type == &memblock.reserved) {
|
||||
memblock_dbg("%s: kernel %lu %+ld\n", __func__,
|
||||
memsize_kinit, (unsigned long)new_size);
|
||||
memsize_kinit += size;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -861,6 +875,15 @@ static int __init_memblock memblock_remove_range(struct memblock_type *type,
|
||||
|
||||
for (i = end_rgn - 1; i >= start_rgn; i--)
|
||||
memblock_remove_region(type, i);
|
||||
#ifdef CONFIG_MEMBLOCK_MEMSIZE
|
||||
if (memblock_memsize_tracking) {
|
||||
if (type == &memblock.reserved) {
|
||||
memblock_dbg("%s: kernel %lu %+ld\n", __func__,
|
||||
memsize_kinit, (unsigned long)size);
|
||||
memsize_kinit -= size;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2057,6 +2080,21 @@ struct memsize_rgn_struct {
|
||||
static struct memsize_rgn_struct memsize_rgn[CONFIG_MAX_MEMBLOCK_MEMSIZE] __initdata_memblock;
|
||||
static int memsize_rgn_count __initdata_memblock;
|
||||
|
||||
void __init memblock_memsize_enable_tracking(void)
|
||||
{
|
||||
memblock_memsize_tracking = true;
|
||||
}
|
||||
|
||||
void __init memblock_memsize_disable_tracking(void)
|
||||
{
|
||||
memblock_memsize_tracking = false;
|
||||
}
|
||||
|
||||
void memblock_memsize_mod_kernel_size(long size)
|
||||
{
|
||||
memsize_kinit += size;
|
||||
}
|
||||
|
||||
static void __init_memblock memsize_get_valid_name(char *valid_name, const char *name)
|
||||
{
|
||||
char *head, *tail, *found;
|
||||
@@ -2367,6 +2405,19 @@ static unsigned long __init __free_memory_core(phys_addr_t start,
|
||||
unsigned long end_pfn = min_t(unsigned long,
|
||||
PFN_DOWN(end), max_low_pfn);
|
||||
|
||||
#ifdef CONFIG_MEMBLOCK_MEMSIZE
|
||||
unsigned long start_align_up = PFN_ALIGN(start);
|
||||
unsigned long end_align_down = PFN_PHYS(end_pfn);
|
||||
|
||||
if (start_pfn >= end_pfn) {
|
||||
memblock_memsize_mod_kernel_size(end - start);
|
||||
} else {
|
||||
if (start_align_up > start)
|
||||
memblock_memsize_mod_kernel_size(start_align_up - start);
|
||||
if (end_pfn != max_low_pfn && end_align_down < end)
|
||||
memblock_memsize_mod_kernel_size(end - end_align_down);
|
||||
}
|
||||
#endif
|
||||
if (start_pfn >= end_pfn)
|
||||
return 0;
|
||||
|
||||
@@ -2471,6 +2522,8 @@ void __init memblock_free_all(void)
|
||||
|
||||
pages = free_low_memory_core_early();
|
||||
totalram_pages_add(pages);
|
||||
|
||||
memblock_memsize_disable_tracking();
|
||||
}
|
||||
|
||||
/* Keep a table to reserve named memory */
|
||||
@@ -2694,7 +2747,6 @@ static inline void memblock_memsize_check_size(struct memsize_rgn_struct *rgn)
|
||||
if (rgn->reusable || rgn->nomap)
|
||||
return;
|
||||
|
||||
/* check the first page of each 1 MB */
|
||||
phy = rgn->base;
|
||||
end = rgn->base + rgn->size;
|
||||
while (phy < end) {
|
||||
@@ -2713,6 +2765,8 @@ static inline void memblock_memsize_check_size(struct memsize_rgn_struct *rgn)
|
||||
|
||||
if (has_freed && (phy + SZ_64K >= end))
|
||||
memblock_memsize_free(freed, end - freed);
|
||||
|
||||
/* check the first page only */
|
||||
phy += SZ_64K;
|
||||
}
|
||||
}
|
||||
@@ -2748,6 +2802,8 @@ static int memblock_memsize_show(struct seq_file *m, void *private)
|
||||
}
|
||||
|
||||
seq_puts(m, "\n");
|
||||
seq_printf(m, " .kernel : %7lu KB\n",
|
||||
DIV_ROUND_UP(memsize_kinit, SZ_1K));
|
||||
seq_printf(m, " .unusable : %7lu KB\n",
|
||||
DIV_ROUND_UP(reserved, SZ_1K));
|
||||
seq_printf(m, " .reusable : %7lu KB\n",
|
||||
|
||||
+9
-1
@@ -20,6 +20,7 @@
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kasan.h>
|
||||
@@ -6147,8 +6148,15 @@ unsigned long free_reserved_area(void *start, void *end, int poison, const char
|
||||
free_reserved_page(page);
|
||||
}
|
||||
|
||||
if (pages && s)
|
||||
if (pages && s) {
|
||||
pr_info("Freeing %s memory: %ldK\n", s, K(pages));
|
||||
if (!strcmp(s, "initrd") || !strcmp(s, "unused kernel")) {
|
||||
long size;
|
||||
|
||||
size = -1 * (long)(pages << PAGE_SHIFT);
|
||||
memblock_memsize_mod_kernel_size(size);
|
||||
}
|
||||
}
|
||||
|
||||
return pages;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user