hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I6DAD6
--------------------------------
After I add a 10GB pmem device, I got the following error message when insert module:
insmod: vmalloc error: size 16384, vm_struct allocation failed, mode:0xcc0(GFP_KERNEL), nodemask=(null),cpuset=/,mems_allowed=0
If CONFIG_RANDOMIZE_BASE is set, the module region can be located in the vmalloc region entirely. Although module_alloc() can fall back to a 2GB window if ARM64_MODULE_PLTS is set, the module region is still easily exhausted because the module region is located at bottom of vmalloc region and the vmalloc region is allocated from bottom to top.
Skip module region if not calling from module_alloc().
Signed-off-by: Liu Shixin liushixin2@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com [cherry-pick from devel-6.1] Signed-off-by: Liu Shixin liushixin2@huawei.com --- arch/arm64/include/asm/vmalloc.h | 26 ++++++++++++++++++++++++++ include/linux/vmalloc.h | 9 +++++++++ mm/vmalloc.c | 4 ++++ 3 files changed, 39 insertions(+)
diff --git a/arch/arm64/include/asm/vmalloc.h b/arch/arm64/include/asm/vmalloc.h index 38fafffe699f..4feff546b11b 100644 --- a/arch/arm64/include/asm/vmalloc.h +++ b/arch/arm64/include/asm/vmalloc.h @@ -31,4 +31,30 @@ static inline pgprot_t arch_vmap_pgprot_tagged(pgprot_t prot) return pgprot_tagged(prot); }
+#ifdef CONFIG_RANDOMIZE_BASE +extern u64 module_alloc_base; +#define arch_vmap_skip_module_region arch_vmap_skip_module_region +static inline void arch_vmap_skip_module_region(unsigned long *addr, + unsigned long vstart, + unsigned long size, + unsigned long align) +{ + u64 module_alloc_end = module_alloc_base + MODULES_VSIZE; + + if (vstart == module_alloc_base) + return; + + if (IS_ENABLED(CONFIG_KASAN_GENERIC) || + IS_ENABLED(CONFIG_KASAN_SW_TAGS)) + /* don't exceed the static module region - see module_alloc() */ + module_alloc_end = MODULES_END; + + if ((module_alloc_base >= *addr + size) || + (module_alloc_end <= *addr)) + return; + + *addr = ALIGN(module_alloc_end, align); +} +#endif + #endif /* _ASM_ARM64_VMALLOC_H */ diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index c720be70c8dd..a7b6c2183d55 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -124,6 +124,15 @@ static inline pgprot_t arch_vmap_pgprot_tagged(pgprot_t prot) } #endif
+#ifndef arch_vmap_skip_module_region +static inline void arch_vmap_skip_module_region(unsigned long *addr, + unsigned long vstart, + unsigned long size, + unsigned long align) +{ +} +#endif + /* * Highlevel APIs for driver use */ diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 1d13d71687d7..afab3c7295b4 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -1230,6 +1230,8 @@ is_within_this_va(struct vmap_area *va, unsigned long size, else nva_start_addr = ALIGN(vstart, align);
+ arch_vmap_skip_module_region(&nva_start_addr, vstart, size, align); + /* Can be overflowed due to big size or alignment. */ if (nva_start_addr + size < nva_start_addr || nva_start_addr < vstart) @@ -1517,6 +1519,8 @@ __alloc_vmap_area(struct rb_root *root, struct list_head *head, else nva_start_addr = ALIGN(vstart, align);
+ arch_vmap_skip_module_region(&nva_start_addr, vstart, size, align); + /* Check the "vend" restriction. */ if (nva_start_addr + size > vend) return vend;
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/1449 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/N...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/1449 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/N...