]>
Commit | Line | Data |
---|---|---|
5b0b9568 GKH |
1 | From 7b0eb6b41a08fa1fa0d04b1c53becd62b5fbfaee Mon Sep 17 00:00:00 2001 |
2 | From: Johannes Weiner <hannes@cmpxchg.org> | |
3 | Date: Mon, 23 Jul 2018 10:18:23 -0400 | |
4 | Subject: arm64: fix vmemmap BUILD_BUG_ON() triggering on !vmemmap setups | |
5 | ||
6 | From: Johannes Weiner <hannes@cmpxchg.org> | |
7 | ||
8 | commit 7b0eb6b41a08fa1fa0d04b1c53becd62b5fbfaee upstream. | |
9 | ||
10 | Arnd reports the following arm64 randconfig build error with the PSI | |
11 | patches that add another page flag: | |
12 | ||
13 | /git/arm-soc/arch/arm64/mm/init.c: In function 'mem_init': | |
14 | /git/arm-soc/include/linux/compiler.h:357:38: error: call to | |
15 | '__compiletime_assert_618' declared with attribute error: BUILD_BUG_ON | |
16 | failed: sizeof(struct page) > (1 << STRUCT_PAGE_MAX_SHIFT) | |
17 | ||
18 | The additional page flag causes other information stored in | |
19 | page->flags to get bumped into their own struct page member: | |
20 | ||
21 | #if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT+LAST_CPUPID_SHIFT <= | |
22 | BITS_PER_LONG - NR_PAGEFLAGS | |
23 | #define LAST_CPUPID_WIDTH LAST_CPUPID_SHIFT | |
24 | #else | |
25 | #define LAST_CPUPID_WIDTH 0 | |
26 | #endif | |
27 | ||
28 | #if defined(CONFIG_NUMA_BALANCING) && LAST_CPUPID_WIDTH == 0 | |
29 | #define LAST_CPUPID_NOT_IN_PAGE_FLAGS | |
30 | #endif | |
31 | ||
32 | which in turn causes the struct page size to exceed the size set in | |
33 | STRUCT_PAGE_MAX_SHIFT. This value is an an estimate used to size the | |
34 | VMEMMAP page array according to address space and struct page size. | |
35 | ||
36 | However, the check is performed - and triggers here - on a !VMEMMAP | |
37 | config, which consumes an additional 22 page bits for the sparse | |
38 | section id. When VMEMMAP is enabled, those bits are returned, cpupid | |
39 | doesn't need its own member, and the page passes the VMEMMAP check. | |
40 | ||
41 | Restrict that check to the situation it was meant to check: that we | |
42 | are sizing the VMEMMAP page array correctly. | |
43 | ||
44 | Says Arnd: | |
45 | ||
46 | Further experiments show that the build error already existed before, | |
47 | but was only triggered with larger values of CONFIG_NR_CPU and/or | |
48 | CONFIG_NODES_SHIFT that might be used in actual configurations but | |
49 | not in randconfig builds. | |
50 | ||
51 | With longer CPU and node masks, I could recreate the problem with | |
52 | kernels as old as linux-4.7 when arm64 NUMA support got added. | |
53 | ||
54 | Reported-by: Arnd Bergmann <arnd@arndb.de> | |
55 | Tested-by: Arnd Bergmann <arnd@arndb.de> | |
56 | Cc: stable@vger.kernel.org | |
57 | Fixes: 1a2db300348b ("arm64, numa: Add NUMA support for arm64 platforms.") | |
58 | Fixes: 3e1907d5bf5a ("arm64: mm: move vmemmap region right below the linear region") | |
59 | Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> | |
60 | Signed-off-by: Will Deacon <will.deacon@arm.com> | |
61 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
62 | ||
63 | --- | |
64 | arch/arm64/mm/init.c | 4 +++- | |
65 | 1 file changed, 3 insertions(+), 1 deletion(-) | |
66 | ||
67 | --- a/arch/arm64/mm/init.c | |
68 | +++ b/arch/arm64/mm/init.c | |
69 | @@ -651,11 +651,13 @@ void __init mem_init(void) | |
70 | BUILD_BUG_ON(TASK_SIZE_32 > TASK_SIZE_64); | |
71 | #endif | |
72 | ||
73 | +#ifdef CONFIG_SPARSEMEM_VMEMMAP | |
74 | /* | |
75 | * Make sure we chose the upper bound of sizeof(struct page) | |
76 | - * correctly. | |
77 | + * correctly when sizing the VMEMMAP array. | |
78 | */ | |
79 | BUILD_BUG_ON(sizeof(struct page) > (1 << STRUCT_PAGE_MAX_SHIFT)); | |
80 | +#endif | |
81 | ||
82 | if (PAGE_SIZE >= 16384 && get_num_physpages() <= 128) { | |
83 | extern int sysctl_overcommit_memory; |