From 72fcf67f294d03d2276388af5590eb54f38aaa27 Mon Sep 17 00:00:00 2001 From: wanglongjie Date: Mon, 13 Oct 2025 21:06:35 +0800 Subject: [PATCH] embsys: free reserved memory Implemented the functionality of dynamically releasing reserved memory. Dynamically freeing up unused reserved memory addresses the issue of memory wastage after its use, thereby optimizing the system's memory utilization. Signed-off-by: wanglongjie Signed-off-by: Yang Yang Reviewed-by: Xuexin Jiang Link: https://gitee.com/anolis/embedded-kernel/pulls/1030 --- kernel/resource.c | 74 +++++++++++++++++++ nos/extend_features/free_reserved_mm/Kconfig | 5 ++ nos/extend_features/free_reserved_mm/Makefile | 1 + .../free_reserved_mm/free_reserved_mm.c | 74 +++++++++++++++++++ 4 files changed, 154 insertions(+) create mode 100644 nos/extend_features/free_reserved_mm/Kconfig create mode 100644 nos/extend_features/free_reserved_mm/Makefile create mode 100644 nos/extend_features/free_reserved_mm/free_reserved_mm.c diff --git a/kernel/resource.c b/kernel/resource.c index e3f5680a564c..4126827db0bf 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -2015,3 +2015,77 @@ static int __init iomem_init_inode(void) fs_initcall(iomem_init_inode); __setup("iomem=", strict_iomem); +#ifdef CONFIG_FREE_RESERVED_MM +int release_reserved_resource(resource_size_t start, resource_size_t end, + unsigned long flags, bool first_lvl) +{ + bool siblings_only = false; + struct resource *p; + struct resource *new_res = NULL; + + if (start >= end) + return -EINVAL; + + read_lock(&resource_lock); + + for (p = iomem_resource.child; p; p = next_resource(p)) { + if (p->start > end) { + p = NULL; + break; + } + + if (p->end < start) + continue; + + if (p->end > end && p->child) + continue; + + siblings_only = first_lvl; + + if ((p->flags & flags) != flags) + continue; + + break; + } + + read_unlock(&resource_lock); + + if (p) { + pr_info("p->start=%llx,p->end=%llx\n", p->start, p->end); + if (p->start == start && p->end == end) { + release_resource(p); + } else if (p->start == start && p->end != end) { + /* adjust the start */ + adjust_resource(p, end + 1, p->end - end); + } else if (p->start != start && p->end == end) { + /* adjust the end */ + adjust_resource(p, p->start, start - p->start); + } else { + /* split into entries - we need a new resource */ + read_lock(&resource_lock); + new_res = alloc_resource(GFP_KERNEL); + if (!new_res) + alloc_resource(GFP_ATOMIC); + if (!new_res) + alloc_resource(GFP_KERNEL | __GFP_NOFAIL); + new_res->name = p->name; + new_res->start = end + 1; + new_res->end = p->end; + new_res->flags = p->flags; + new_res->parent = p->parent; + new_res->sibling = p->sibling; + new_res->child = NULL; + read_unlock(&resource_lock); + + if (adjust_resource(p, p->start, start - p->start)) + goto out; + p->sibling = new_res; + new_res = NULL; + } + } + +out: + free_resource(new_res); + return p ? 0 : -ENODEV; +} +#endif diff --git a/nos/extend_features/free_reserved_mm/Kconfig b/nos/extend_features/free_reserved_mm/Kconfig new file mode 100644 index 000000000000..1dfa7f48c169 --- /dev/null +++ b/nos/extend_features/free_reserved_mm/Kconfig @@ -0,0 +1,5 @@ +config FREE_RESERVED_MM + bool "Free reserved memory after system start" + default n + help + Free reserved memory, while reserved memory must be mapped. \ No newline at end of file diff --git a/nos/extend_features/free_reserved_mm/Makefile b/nos/extend_features/free_reserved_mm/Makefile new file mode 100644 index 000000000000..73e4e6a466ff --- /dev/null +++ b/nos/extend_features/free_reserved_mm/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_FREE_RESERVED_MM) += free_reserved_mm.o \ No newline at end of file diff --git a/nos/extend_features/free_reserved_mm/free_reserved_mm.c b/nos/extend_features/free_reserved_mm/free_reserved_mm.c new file mode 100644 index 000000000000..982a3ecd224f --- /dev/null +++ b/nos/extend_features/free_reserved_mm/free_reserved_mm.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include +#include +#include +#include +#ifdef CONFIG_X86 +#include +#endif +#include + +extern int release_reserved_resource(resource_size_t start, resource_size_t end, + unsigned long flags, bool first_lvl); + +static unsigned long memblock_addrs_inlap(phys_addr_t base1, phys_addr_t size1, + phys_addr_t base2, phys_addr_t size2) +{ + return (base1 + size1) <= (base2 + size2) && base1 >= base2; +} + +static bool memblock_inlaps_region(struct memblock_type *type, + phys_addr_t base, phys_addr_t size) +{ + unsigned long i; + + for (i = 0; i < type->cnt; i++) + if (memblock_addrs_inlap(base, size, type->regions[i].base, + type->regions[i].size)) + break; + return i < type->cnt; +} + +static bool memblock_in_region_reserved(phys_addr_t base, phys_addr_t size) +{ + size = min(size, (phys_addr_t)ULLONG_MAX - base); + return memblock_inlaps_region(&memblock.reserved, base, size); +} + +int free_reserved_mm(unsigned long resv_start, unsigned long resv_size) +{ + unsigned long pfn_start_align, pfn_end_align; + void *start, *end; + + pfn_start_align = PFN_UP(resv_start); + pfn_end_align = PFN_DOWN(resv_start + resv_size); + +#ifdef CONFIG_X86 + if (!pfn_range_is_mapped(pfn_start_align, pfn_end_align)) { + pr_warn("[0x%lx, 0x%lx] is not mapped\n", + pfn_start_align << PAGE_SHIFT, + pfn_end_align << PAGE_SHIFT); + return -EINVAL; + } +#endif + + start = __va(pfn_start_align << PAGE_SHIFT); + end = __va(pfn_end_align << PAGE_SHIFT); + + if (!memblock_in_region_reserved(pfn_start_align << PAGE_SHIFT, + PAGE_ALIGN(resv_size))) { + pr_warn("[0x%lx, 0x%lx] is not all reserved\n", + pfn_start_align << PAGE_SHIFT, + pfn_end_align << PAGE_SHIFT); + return -EINVAL; + } + + free_reserved_area(start, end, 0, "reserve free"); + memblock_free(pfn_start_align << PAGE_SHIFT, + (pfn_end_align << PAGE_SHIFT) - (pfn_start_align << PAGE_SHIFT)); + + return release_reserved_resource(pfn_start_align << PAGE_SHIFT, + (pfn_end_align << PAGE_SHIFT) - 1, + IORESOURCE_MEM, false); +} +EXPORT_SYMBOL(free_reserved_mm); \ No newline at end of file -- Gitee