diff options
author | Andi Kleen <ak@linux.intel.com> | 2014-02-08 03:01:08 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2014-02-13 23:24:13 -0500 |
commit | ef1b893c29d0dba778f67ad97b554b37f9108dcc (patch) | |
tree | c77e509d240979f0718d6778a6abfe42fc0b59c3 /include/linux/init.h | |
parent | 128ea04a9885af9629059e631ddf0cab4815b589 (diff) |
lto, workaround: Add workaround for initcall reordering
Work around a LTO gcc problem: when there is no reference to a variable
in a module it will be moved to the end of the program. This causes
reordering of initcalls which the kernel does not like.
Add a dummy reference function to avoid this. The function is
deleted by the linker.
This replaces a previous much slower workaround.
Thanks to Jan "Honza" Hubička for suggesting this technique.
Suggested-by: Jan Hubička <hubicka@ucw.cz>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Link: http://lkml.kernel.org/r/1391846481-31491-4-git-send-email-ak@linux.intel.com
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'include/linux/init.h')
-rw-r--r-- | include/linux/init.h | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/include/linux/init.h b/include/linux/init.h index e1688802964f..a3ba27076342 100644 --- a/include/linux/init.h +++ b/include/linux/init.h | |||
@@ -163,6 +163,23 @@ extern bool initcall_debug; | |||
163 | 163 | ||
164 | #ifndef __ASSEMBLY__ | 164 | #ifndef __ASSEMBLY__ |
165 | 165 | ||
166 | #ifdef CONFIG_LTO | ||
167 | /* Work around a LTO gcc problem: when there is no reference to a variable | ||
168 | * in a module it will be moved to the end of the program. This causes | ||
169 | * reordering of initcalls which the kernel does not like. | ||
170 | * Add a dummy reference function to avoid this. The function is | ||
171 | * deleted by the linker. | ||
172 | */ | ||
173 | #define LTO_REFERENCE_INITCALL(x) \ | ||
174 | ; /* yes this is needed */ \ | ||
175 | static __used __exit void *reference_##x(void) \ | ||
176 | { \ | ||
177 | return &x; \ | ||
178 | } | ||
179 | #else | ||
180 | #define LTO_REFERENCE_INITCALL(x) | ||
181 | #endif | ||
182 | |||
166 | /* initcalls are now grouped by functionality into separate | 183 | /* initcalls are now grouped by functionality into separate |
167 | * subsections. Ordering inside the subsections is determined | 184 | * subsections. Ordering inside the subsections is determined |
168 | * by link order. | 185 | * by link order. |
@@ -175,7 +192,8 @@ extern bool initcall_debug; | |||
175 | 192 | ||
176 | #define __define_initcall(fn, id) \ | 193 | #define __define_initcall(fn, id) \ |
177 | static initcall_t __initcall_##fn##id __used \ | 194 | static initcall_t __initcall_##fn##id __used \ |
178 | __attribute__((__section__(".initcall" #id ".init"))) = fn | 195 | __attribute__((__section__(".initcall" #id ".init"))) = fn; \ |
196 | LTO_REFERENCE_INITCALL(__initcall_##fn##id) | ||
179 | 197 | ||
180 | /* | 198 | /* |
181 | * Early initcalls run before initializing SMP. | 199 | * Early initcalls run before initializing SMP. |