Skip to content

Commit c27cd08

Browse files
mrutland-armctmarinas
authored andcommitted
Compiler attributes: GCC cold function alignment workarounds
Contemporary versions of GCC (e.g. GCC 12.2.0) drop the alignment specified by '-falign-functions=N' for functions marked with the __cold__ attribute, and potentially for callees of __cold__ functions as these may be implicitly marked as __cold__ by the compiler. LLVM appears to respect '-falign-functions=N' in such cases. This has been reported to GCC in bug 88345: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88345 ... which also covers alignment being dropped when '-Os' is used, which will be addressed in a separate patch. Currently, use of '-falign-functions=N' is limited to CONFIG_FUNCTION_ALIGNMENT, which is largely used for performance and/or analysis reasons (e.g. with CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B), but isn't necessary for correct functionality. However, this dropped alignment isn't great for the performance and/or analysis cases. Subsequent patches will use CONFIG_FUNCTION_ALIGNMENT as part of arm64's ftrace implementation, which will require all instrumented functions to be aligned to at least 8-bytes. This patch works around the dropped alignment by avoiding the use of the __cold__ attribute when CONFIG_FUNCTION_ALIGNMENT is non-zero, and by specifically aligning abort(), which GCC implicitly marks as __cold__. As the __cold macro is now dependent upon config options (which is against the policy described at the top of compiler_attributes.h), it is moved into compiler_types.h. I've tested this by building and booting a kernel configured with defconfig + CONFIG_EXPERT=y + CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B=y, and looking for misaligned text symbols in /proc/kallsyms: * arm64: Before: # uname -rm 6.2.0-rc3 aarch64 # grep ' [Tt] ' /proc/kallsyms | grep -iv '[048c]0 [Tt] ' | wc -l 5009 After: # uname -rm 6.2.0-rc3-00001-g2a2bedf8bfa9 aarch64 # grep ' [Tt] ' /proc/kallsyms | grep -iv '[048c]0 [Tt] ' | wc -l 919 * x86_64: Before: # uname -rm 6.2.0-rc3 x86_64 # grep ' [Tt] ' /proc/kallsyms | grep -iv '[048c]0 [Tt] ' | wc -l 11537 After: # uname -rm 6.2.0-rc3-00001-g2a2bedf8bfa9 x86_64 # grep ' [Tt] ' /proc/kallsyms | grep -iv '[048c]0 [Tt] ' | wc -l 2805 There's clearly a substantial reduction in the number of misaligned symbols. From manual inspection, the remaining unaligned text labels are a combination of ACPICA functions (due to the use of '-Os'), static call trampolines, and non-function labels in assembly, which will be dealt with in subsequent patches. Signed-off-by: Mark Rutland <[email protected]> Cc: Florent Revest <[email protected]> Cc: Masami Hiramatsu <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Steven Rostedt <[email protected]> Cc: Will Deacon <[email protected]> Cc: Miguel Ojeda <[email protected]> Cc: Nick Desaulniers <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]>
1 parent cbad0fb commit c27cd08

File tree

3 files changed

+35
-7
lines changed

3 files changed

+35
-7
lines changed

include/linux/compiler_attributes.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,6 @@
7575
# define __assume_aligned(a, ...)
7676
#endif
7777

78-
/*
79-
* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-cold-function-attribute
80-
* gcc: https://gcc.gnu.org/onlinedocs/gcc/Label-Attributes.html#index-cold-label-attribute
81-
*/
82-
#define __cold __attribute__((__cold__))
83-
8478
/*
8579
* Note the long name.
8680
*

include/linux/compiler_types.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,33 @@ static inline void __chk_io_ptr(const volatile void __iomem *ptr) { }
7979
/* Attributes */
8080
#include <linux/compiler_attributes.h>
8181

82+
#if CONFIG_FUNCTION_ALIGNMENT > 0
83+
#define __function_aligned __aligned(CONFIG_FUNCTION_ALIGNMENT)
84+
#else
85+
#define __function_aligned
86+
#endif
87+
88+
/*
89+
* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-cold-function-attribute
90+
* gcc: https://gcc.gnu.org/onlinedocs/gcc/Label-Attributes.html#index-cold-label-attribute
91+
*
92+
* When -falign-functions=N is in use, we must avoid the cold attribute as
93+
* contemporary versions of GCC drop the alignment for cold functions. Worse,
94+
* GCC can implicitly mark callees of cold functions as cold themselves, so
95+
* it's not sufficient to add __function_aligned here as that will not ensure
96+
* that callees are correctly aligned.
97+
*
98+
* See:
99+
*
100+
* https://lore.kernel.org/lkml/Y77%2FqVgvaJidFpYt@FVFF77S0Q05N
101+
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88345#c9
102+
*/
103+
#if !defined(CONFIG_CC_IS_GCC) || (CONFIG_FUNCTION_ALIGNMENT == 0)
104+
#define __cold __attribute__((__cold__))
105+
#else
106+
#define __cold
107+
#endif
108+
82109
/* Builtins */
83110

84111
/*

kernel/exit.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1898,7 +1898,14 @@ bool thread_group_exited(struct pid *pid)
18981898
}
18991899
EXPORT_SYMBOL(thread_group_exited);
19001900

1901-
__weak void abort(void)
1901+
/*
1902+
* This needs to be __function_aligned as GCC implicitly makes any
1903+
* implementation of abort() cold and drops alignment specified by
1904+
* -falign-functions=N.
1905+
*
1906+
* See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88345#c11
1907+
*/
1908+
__weak __function_aligned void abort(void)
19021909
{
19031910
BUG();
19041911

0 commit comments

Comments
 (0)