From: Jingxian He hejingxian@huawei.com
euleros inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I4REE5 CVE: NA
------------ 1.Refactor pin memory mem reserve: Move the memory reserve functions to pin_mem.c, and avoid using unnecessary macros.
2.Refactor pid reserve code: In oder to avoid using unnecessary compile macros in pid.c, add stub functions for free_reserved_pid and reserve_pids.
Signed-off-by: Jingxian He hejingxian@huawei.com Reviewed-by: Kefeng Wangwangkefeng.wang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/arm64/kernel/setup.c | 8 +-- arch/arm64/mm/init.c | 53 +----------------- include/linux/pin_mem.h | 34 +++++++++--- kernel/pid.c | 12 ++--- mm/pin_mem.c | 110 ++++++++++++++++++++++++++++++-------- 5 files changed, 119 insertions(+), 98 deletions(-)
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 92d75e381bb1..58d69e2e7538 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -30,9 +30,7 @@ #include <linux/psci.h> #include <linux/sched/task.h> #include <linux/mm.h> -#ifdef CONFIG_PIN_MEMORY #include <linux/pin_mem.h> -#endif
#include <asm/acpi.h> #include <asm/fixmap.h> @@ -297,11 +295,7 @@ static void __init request_standard_resources(void) request_resource(res, &quick_kexec_res); #endif
-#ifdef CONFIG_PIN_MEMORY - if (pin_memory_resource.end && pin_memory_resource.start >= res->start && - pin_memory_resource.end <= res->end) - request_resource(res, &pin_memory_resource); -#endif + request_pin_mem_res(res); } }
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 6ebfabde16f3..1364d52cbaa8 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -30,9 +30,7 @@ #include <linux/crash_dump.h> #include <linux/hugetlb.h> #include <linux/acpi_iort.h> -#ifdef CONFIG_PIN_MEMORY #include <linux/pin_mem.h> -#endif
#include <asm/boot.h> #include <asm/fixmap.h> @@ -56,52 +54,6 @@ s64 memstart_addr __ro_after_init = -1; EXPORT_SYMBOL(memstart_addr);
-#ifdef CONFIG_PIN_MEMORY -struct resource pin_memory_resource = { - .name = "Pin memory", - .start = 0, - .end = 0, - .flags = IORESOURCE_MEM, - .desc = IORES_DESC_RESERVED -}; - -static void __init reserve_pin_memory_res(void) -{ - unsigned long long mem_start, mem_len; - int ret; - - ret = parse_pin_memory(boot_command_line, memblock_phys_mem_size(), - &mem_len, &mem_start); - if (ret || !mem_len) - return; - - mem_len = PAGE_ALIGN(mem_len); - - if (!memblock_is_region_memory(mem_start, mem_len)) { - pr_warn("cannot reserve for pin memory: region is not memory!\n"); - return; - } - - if (memblock_is_region_reserved(mem_start, mem_len)) { - pr_warn("cannot reserve for pin memory: region overlaps reserved memory!\n"); - return; - } - - if (!IS_ALIGNED(mem_start, SZ_2M)) { - pr_warn("cannot reserve for pin memory: base address is not 2MB aligned\n"); - return; - } - - memblock_reserve(mem_start, mem_len); - pin_memory_resource.start = mem_start; - pin_memory_resource.end = mem_start + mem_len - 1; -} -#else -static void __init reserve_pin_memory_res(void) -{ -} -#endif /* CONFIG_PIN_MEMORY */ - /* * If the corresponding config options are enabled, we create both ZONE_DMA * and ZONE_DMA32. By default ZONE_DMA covers the 32-bit addressable memory @@ -729,11 +681,8 @@ void __init mem_init(void) /* this will put all unused low memory onto the freelists */ memblock_free_all();
-#ifdef CONFIG_PIN_MEMORY /* pre alloc the pages for pin memory */ - init_reserve_page_map((unsigned long)pin_memory_resource.start, - (unsigned long)(pin_memory_resource.end - pin_memory_resource.start)); -#endif + init_reserve_page_map();
mem_init_print_info(NULL);
diff --git a/include/linux/pin_mem.h b/include/linux/pin_mem.h index 6c54482a42a1..24e64efe4e51 100644 --- a/include/linux/pin_mem.h +++ b/include/linux/pin_mem.h @@ -83,17 +83,35 @@ extern int pagemap_get(struct mm_struct *mm, void *mem_walk, unsigned long *pte_entry, unsigned int *count);
extern int init_pagemap_read(void); -/* reserve space for pin memory*/ -#ifdef CONFIG_ARM64 -extern struct resource pin_memory_resource; -#endif -extern void init_reserve_page_map(unsigned long map_addr, unsigned long map_size); + +extern void __init reserve_pin_memory_res(void); + +extern void request_pin_mem_res(struct resource *res); + +extern void init_reserve_page_map(void); + +#else + +static inline void __init reserve_pin_memory_res(void) {} + +static inline void request_pin_mem_res(struct resource *res) {} + +static inline void init_reserve_page_map(void) {} + +#endif /* CONFIG_PIN_MEMORY */
#ifdef CONFIG_PID_RESERVE -extern bool is_need_reserve_pids(void); + extern void free_reserved_pid(struct idr *idr, int pid); + extern void reserve_pids(struct idr *idr, int pid_max); -#endif
-#endif /* CONFIG_PIN_MEMORY */ +#else + +static inline void free_reserved_pid(struct idr *idr, int pid) {} + +static inline void reserve_pids(struct idr *idr, int pid_max) {} + +#endif /* CONFIG_PID_RESERVE */ + #endif /* _LINUX_PIN_MEMORY_H */ diff --git a/kernel/pid.c b/kernel/pid.c index 28fdf3dc1005..3f9490082180 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -45,9 +45,7 @@ #include <net/sock.h> #include <linux/kmemleak.h> #include <uapi/linux/pidfd.h> -#ifdef CONFIG_PID_RESERVE #include <linux/pin_mem.h> -#endif
struct pid init_struct_pid = { .count = REFCOUNT_INIT(1), @@ -212,9 +210,8 @@ struct pid *alloc_pid(struct pid_namespace *ns, pid_t *set_tid, spin_lock_irq(&pidmap_lock);
if (tid) { -#ifdef CONFIG_PID_RESERVE free_reserved_pid(&tmp->idr, tid); -#endif + nr = idr_alloc(&tmp->idr, NULL, tid, tid + 1, GFP_ATOMIC); /* @@ -659,10 +656,9 @@ void __init pid_idr_init(void)
init_pid_ns.pid_cachep = KMEM_CACHE(pid, SLAB_HWCACHE_ALIGN | SLAB_PANIC | SLAB_ACCOUNT); -#ifdef CONFIG_PID_RESERVE - if (is_need_reserve_pids()) - reserve_pids(&init_pid_ns.idr, pid_max); -#endif + + reserve_pids(&init_pid_ns.idr, pid_max); + hdr = register_sysctl_paths(pid_kern_path, pid_ctl_table); kmemleak_not_leak(hdr); } diff --git a/mm/pin_mem.c b/mm/pin_mem.c index ff6ddd3a47f9..c158b7768d67 100644 --- a/mm/pin_mem.c +++ b/mm/pin_mem.c @@ -17,6 +17,7 @@ #include <linux/ctype.h> #include <linux/highmem.h> #include <crypto/sha2.h> +#include <linux/memblock.h>
#define MAX_PIN_PID_NUM 128 #define DEFAULT_REDIRECT_SPACE_SIZE 0x100000 @@ -1023,22 +1024,6 @@ vm_fault_t do_mem_remap(int pid, struct mm_struct *mm) } EXPORT_SYMBOL_GPL(do_mem_remap);
-#if defined(CONFIG_ARM64) -void init_reserve_page_map(unsigned long map_addr, unsigned long map_size) -{ - void *addr; - - if (!map_addr || !map_size) - return; - addr = phys_to_virt(map_addr); - init_page_map_info((struct pin_mem_dump_info *)addr, map_size); -} -#else -void init_reserve_page_map(unsigned long map_addr, unsigned long map_size) -{ -} -#endif - static void free_all_reserved_pages(void) { unsigned int i, j, index, order; @@ -1088,14 +1073,92 @@ void clear_pin_memory_record(void) } EXPORT_SYMBOL_GPL(clear_pin_memory_record);
-#ifdef CONFIG_PID_RESERVE -struct idr *reserve_idr; +static struct resource pin_memory_resource = { + .name = "Pin memory", + .start = 0, + .end = 0, + .flags = IORESOURCE_MEM, + .desc = IORES_DESC_RESERVED +}; + +static unsigned long long pin_mem_start; +static unsigned long long pin_mem_len;
-/* test if there exist pin memory tasks */ -bool is_need_reserve_pids(void) +static int __init parse_pin_memory(char *cmdline) { - return (pin_pid_num > 0); + char *cur = cmdline; + + pin_mem_len = memparse(cmdline, &cur); + if (cmdline == cur) { + pr_warn("crashkernel: memory value expected\n"); + return -EINVAL; + } + + if (*cur == '@') + pin_mem_start = memparse(cur+1, &cur); + else if (*cur != ' ' && *cur != '\0') { + pr_warn("pinmem: unrecognized char: %c\n", *cur); + return -EINVAL; + } + + return 0; } +early_param("pinmemory", parse_pin_memory); + +void __init reserve_pin_memory_res(void) +{ + unsigned long long mem_start = pin_mem_start; + unsigned long long mem_len = pin_mem_len; + + if (!pin_mem_len) + return; + + mem_len = PAGE_ALIGN(mem_len); + + if (!memblock_is_region_memory(mem_start, mem_len)) { + pr_warn("cannot reserve for pin memory: region is not memory!\n"); + return; + } + + if (memblock_is_region_reserved(mem_start, mem_len)) { + pr_warn("cannot reserve for pin memory: region overlaps reserved memory!\n"); + return; + } + + memblock_reserve(mem_start, mem_len); + pr_debug("pin memory resource reserved: 0x%016llx - 0x%016llx (%lld MB)\n", + mem_start, mem_start + mem_len, mem_len >> 20); + + pin_memory_resource.start = mem_start; + pin_memory_resource.end = mem_start + mem_len - 1; +} + +void request_pin_mem_res(struct resource *res) +{ + if (pin_memory_resource.end && + pin_memory_resource.start >= res->start && + pin_memory_resource.end <= res->end) + request_resource(res, &pin_memory_resource); +} + +void init_reserve_page_map(void) +{ + void *addr; + unsigned long map_addr, map_size; + + map_addr = (unsigned long)pin_memory_resource.start; + map_size = (unsigned long)(pin_memory_resource.end - pin_memory_resource.start + 1); + if (!map_addr || !map_size) + return; + + addr = phys_to_virt(map_addr); + init_page_map_info((struct pin_mem_dump_info *)addr, map_size); +} + +#endif /* CONFIG_PIN_MEMORY */ + +#ifdef CONFIG_PID_RESERVE +struct idr *reserve_idr;
void free_reserved_pid(struct idr *idr, int pid) { @@ -1121,8 +1184,9 @@ void reserve_pids(struct idr *idr, int pid_max) unsigned int index; struct page_map_info *pmi;
- if (!max_pin_pid_num) + if (!pin_pid_num || !max_pin_pid_num) return; + reserve_idr = idr; for (index = 0; index < pin_pid_num; index++) { pmi = &(user_space_reserve_start[index]); @@ -1137,6 +1201,6 @@ void reserve_pids(struct idr *idr, int pid_max) } } } + #endif /* CONFIG_PID_RESERVE */
-#endif /* CONFIG_PIN_MEMORY */