Messages in this thread Patch in this message | | | Date | Fri, 31 Mar 2023 16:48:16 -0500 | Subject | Re: [PATCH v2] arm64: mm: Increase MODULES_VSIZE to 2GB | From | Shanker Donthineni <> |
| |
Hi Ard,
On 3/30/23 09:04, Shanker Donthineni wrote: > The allocation of modules occurs in two regions. The first region > is MODULES_VSIZE, which is 128MB in size and shared with the core > kernel when the KASLR feature is unavailable or disabled through > a boot parameter. The second region, which is 2GB in size, is > shared with the other vmalloc callers. Depending on the size of > the core kernel, the 128MB region may quickly fill up after > loading a few modules, causing the system to switch to the 2GB > region. Unfortunately, even the 2GB region can run out of space > if previously loaded modules and other kernel subsystems consume > the entire area, leaving no space for additional modules. > > This issue usually occurs when the system has a large number of > CPU cores, PCIe host-brigde controllers, and I/O devices. For > instance, the ECAM region of one host-bridge controller can use > up to 256MB of vmalloc space, while eight controllers can occupy > the entire 2GB. > > To address this problem, a possible solution would be to increase > the MODULES_VSIZE to 2GB. This would improve the system's ability > to accommodate a greater number of dynamically loaded modules and > drivers when KASLR is not enabled. However, prior to switching to > the 2GB region, it is advisable to allocate modules within the > 128MB space that covers the core kernel, in order to benefit from > the direct branches. > > Signed-off-by: Shanker Donthineni <sdonthineni@nvidia.com> > --- > Changes since v1: > - Included Ard's recommendations. > - Revised the commit message. > > dmesg: > On a NVIDIA T241 system with Ubuntu-22.04, hitting boot failures > due to vmalloc/vmap allocation errors when loading modules. > > [ 64.181308] ipmi_ssif: IPMI SSIF Interface driver > [ 64.184494] usbcore: registered new interface driver r8152 > [ 64.242492] vmap allocation for size 393216 failed: use vmalloc=<size> to increase size > [ 64.242499] systemd-udevd: vmalloc error: size 327680, vm_struct allocation failed, mode:0xcc0(GFP_KERNEL), nodemask=(null),cpuset=/,mems_allowed=0-3 > [ 64.242510] CPU: 32 PID: 2910 Comm: systemd-udevd Tainted: G OE 6.2-generic-64k > [ 64.242513] Hardware name: NVIDIA T241, BIOS v1.1.0 2023-03-18T21:32:31+00:00 > [ 64.242515] Call trace: > [ 64.242516] dump_backtrace+0xe0/0x130 > [ 64.242523] show_stack+0x20/0x60 > [ 64.242525] dump_stack_lvl+0x68/0x84 > [ 64.242530] dump_stack+0x18/0x34 > [ 64.242532] warn_alloc+0x11c/0x1b0 > [ 64.242537] __vmalloc_node_range+0xe0/0x20c > [ 64.242540] module_alloc+0x118/0x160 > [ 64.242543] move_module+0x2c/0x190 > [ 64.242546] layout_and_allocate+0xfc/0x160 > [ 64.242548] load_module+0x260/0xbc4 > [ 64.242549] __do_sys_finit_module+0xac/0x130 > [ 64.242551] __arm64_sys_finit_module+0x28/0x34 > [ 64.242552] invoke_syscall+0x78/0x100 > [ 64.242553] el0_svc_common.constprop.0+0x170/0x194 > [ 64.242555] do_el0_svc+0x38/0x4c > [ 64.242556] el0_svc+0x2c/0xc0 > [ 64.242558] el0t_64_sync_handler+0xbc/0x13c > [ 64.242560] el0t_64_sync+0x1a0/0x1a4 > > Documentation/arm64/memory.rst | 8 ++++---- > arch/arm64/include/asm/memory.h | 2 +- > arch/arm64/kernel/module.c | 2 +- > 3 files changed, 6 insertions(+), 6 deletions(-) > > diff --git a/Documentation/arm64/memory.rst b/Documentation/arm64/memory.rst > index 2a641ba7be3b..55a55f30eed8 100644 > --- a/Documentation/arm64/memory.rst > +++ b/Documentation/arm64/memory.rst > @@ -33,8 +33,8 @@ AArch64 Linux memory layout with 4KB pages + 4 levels (48-bit):: > 0000000000000000 0000ffffffffffff 256TB user > ffff000000000000 ffff7fffffffffff 128TB kernel logical memory map > [ffff600000000000 ffff7fffffffffff] 32TB [kasan shadow region] > - ffff800000000000 ffff800007ffffff 128MB modules > - ffff800008000000 fffffbffefffffff 124TB vmalloc > + ffff800000000000 ffff80007fffffff 2GB modules > + ffff800080000000 fffffbffefffffff 124TB vmalloc > fffffbfff0000000 fffffbfffdffffff 224MB fixed mappings (top down) > fffffbfffe000000 fffffbfffe7fffff 8MB [guard region] > fffffbfffe800000 fffffbffff7fffff 16MB PCI I/O space > @@ -50,8 +50,8 @@ AArch64 Linux memory layout with 64KB pages + 3 levels (52-bit with HW support): > 0000000000000000 000fffffffffffff 4PB user > fff0000000000000 ffff7fffffffffff ~4PB kernel logical memory map > [fffd800000000000 ffff7fffffffffff] 512TB [kasan shadow region] > - ffff800000000000 ffff800007ffffff 128MB modules > - ffff800008000000 fffffbffefffffff 124TB vmalloc > + ffff800000000000 ffff80007fffffff 2GB modules > + ffff800080000000 fffffbffefffffff 124TB vmalloc > fffffbfff0000000 fffffbfffdffffff 224MB fixed mappings (top down) > fffffbfffe000000 fffffbfffe7fffff 8MB [guard region] > fffffbfffe800000 fffffbffff7fffff 16MB PCI I/O space > diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h > index 78e5163836a0..b58c3127323e 100644 > --- a/arch/arm64/include/asm/memory.h > +++ b/arch/arm64/include/asm/memory.h > @@ -46,7 +46,7 @@ > #define KIMAGE_VADDR (MODULES_END) > #define MODULES_END (MODULES_VADDR + MODULES_VSIZE) > #define MODULES_VADDR (_PAGE_END(VA_BITS_MIN)) > -#define MODULES_VSIZE (SZ_128M) > +#define MODULES_VSIZE (SZ_2G) > #define VMEMMAP_START (-(UL(1) << (VA_BITS - VMEMMAP_SHIFT))) > #define VMEMMAP_END (VMEMMAP_START + VMEMMAP_SIZE) > #define PCI_IO_END (VMEMMAP_START - SZ_8M) > diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c > index 5af4975caeb5..b4affe775f23 100644 > --- a/arch/arm64/kernel/module.c > +++ b/arch/arm64/kernel/module.c > @@ -37,7 +37,7 @@ void *module_alloc(unsigned long size) > /* don't exceed the static module region - see below */ > module_alloc_end = MODULES_END; > > - p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base, > + p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_end - SZ_128M, > module_alloc_end, gfp_mask, PAGE_KERNEL, VM_DEFER_KMEMLEAK, > NUMA_NO_NODE, __builtin_return_address(0)); > Occasionally encountering the "overflow in relocation type 261" error suggests that the expression 'module_alloc_end - SZ_128M' may be outside the 2GB range starting from the beginning of _stext. Used the following code to resolve the issue And also enable randomization of module base within 128MB if CONFIG_RANDOMIZE_MODULE_REGION_FULL is not defined.
--- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -46,7 +46,7 @@ #define KIMAGE_VADDR (MODULES_END) #define MODULES_END (MODULES_VADDR + MODULES_VSIZE) #define MODULES_VADDR (_PAGE_END(VA_BITS_MIN)) -#define MODULES_VSIZE (SZ_128M) +#define MODULES_VSIZE (SZ_2G) #define VMEMMAP_START (-(UL(1) << (VA_BITS - VMEMMAP_SHIFT))) #define VMEMMAP_END (VMEMMAP_START + VMEMMAP_SIZE) #define PCI_IO_END (VMEMMAP_START - SZ_8M) diff --git a/arch/arm64/kernel/kaslr.c b/arch/arm64/kernel/kaslr.c index e7477f21a4c9..4f92fc511b85 100644 @@ -70,18 +70,19 @@ static int __init kaslr_init(void) * resolved normally.) */ module_range = SZ_2G - (u64)(_end - _stext); - module_alloc_base = max((u64)_end - SZ_2G, (u64)MODULES_VADDR); + module_alloc_base = max((u64)_etext - SZ_2G, (u64)MODULES_VADDR); } else { /* * Randomize the module region by setting module_alloc_base to - * a PAGE_SIZE multiple in the range [_etext - MODULES_VSIZE, + * a PAGE_SIZE multiple in the range [_etext - SZ_128M, * _stext) . This guarantees that the resulting region still * covers [_stext, _etext], and that all relative branches can * be resolved without veneers unless this region is exhausted * and we fall back to a larger 2GB window in module_alloc() * when ARM64_MODULE_PLTS is enabled. */ - module_range = MODULES_VSIZE - (u64)(_etext - _stext); + module_range = SZ_128M - (u64)(_etext - _stext); + module_alloc_base = (u64)_etext - SZ_128M; }
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c index 5af4975caeb5..b4affe775f23 100644 @@ -37,7 +37,7 @@ void *module_alloc(unsigned long size) /* don't exceed the static module region - see below */ module_alloc_end = MODULES_END;
- p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base, + p = __vmalloc_node_range(size, MODULE_ALIGN, kaslr_enabled() ? + module_alloc_base : module_alloc_end - SZ_128M, module_alloc_end, gfp_mask, PAGE_KERNEL, VM_DEFER_KMEMLEAK, NUMA_NO_NODE, __builtin_return_address(0));
| |