Skip to content

Commit 4e5b0e8

Browse files
ubizjakIngo Molnar
authored andcommitted
x86/percpu: Unify arch_raw_cpu_ptr() defines
When building a 32-bit vDSO for a 64-bit kernel, games are played with CONFIG_X86_64. {this,raw}_cpu_read_8() macros are conditionally defined on CONFIG_X86_64 and when CONFIG_X86_64 is undefined in fake_32bit_build.h various build failures in generic percpu header files can happen. To make things worse, the build of 32-bit vDSO for a 64-bit kernel grew dependency on arch_raw_cpu_ptr() macro and the build fails if arch_raw_cpu_ptr() macro is not defined. To mitigate these issues, x86 carefully defines arch_raw_cpu_ptr() to avoid any dependency on raw_cpu_read_8() and thus CONFIG_X86_64. W/o segment register support, the definition uses size-agnostic MOV asm mnemonic and hopes that _ptr argument won't ever be 64-bit size on 32-bit targets (although newer GCCs warn for this situation with "unsupported size for integer register"), and w/ segment register support the definition uses size-agnostic __raw_cpu_read() macro. Fortunately, raw_cpu_read() is not used in 32-bit vDSO for a 64-bit kernel. However, we can't simply omit the definition of arch_raw_cpu_read(), since the build will fail when building vdso/vdso32/vclock_gettime.o. The patch defines arch_raw_cpu_ptr to BUILD_BUG() when BUILD_VDSO32_64 macro is defined. This way, we are sure that arch_raw_cpu_ptr() won't actually be used in 32-bit VDSO for a 64-bit kernel, but it is still defined to prevent build failure. Finally, we can unify arch_raw_cpu_ptr() between builds w/ and w/o x86 segment register support, substituting two tricky macro definitions with a straightforward implementation. There is no size difference and no difference in number of this_cpu_off accesses between patched and unpatched kernel when the kernel is built either w/ and w/o segment register support. Signed-off-by: Uros Bizjak <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Cc: Andy Lutomirski <[email protected]> Cc: Linus Torvalds <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent b429eaf commit 4e5b0e8

File tree

1 file changed

+18
-24
lines changed

1 file changed

+18
-24
lines changed

arch/x86/include/asm/percpu.h

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -59,36 +59,30 @@
5959
#define __force_percpu_prefix "%%"__stringify(__percpu_seg)":"
6060
#define __my_cpu_offset this_cpu_read(this_cpu_off)
6161

62-
#ifdef CONFIG_USE_X86_SEG_SUPPORT
63-
/*
64-
* Efficient implementation for cases in which the compiler supports
65-
* named address spaces. Allows the compiler to perform additional
66-
* optimizations that can save more instructions.
67-
*/
68-
#define arch_raw_cpu_ptr(ptr) \
69-
({ \
70-
unsigned long tcp_ptr__; \
71-
tcp_ptr__ = __raw_cpu_read(, this_cpu_off); \
72-
\
73-
tcp_ptr__ += (unsigned long)(ptr); \
74-
(typeof(*(ptr)) __kernel __force *)tcp_ptr__; \
75-
})
76-
#else /* CONFIG_USE_X86_SEG_SUPPORT */
62+
#ifdef CONFIG_X86_64
63+
#define __raw_my_cpu_offset raw_cpu_read_8(this_cpu_off);
64+
#else
65+
#define __raw_my_cpu_offset raw_cpu_read_4(this_cpu_off);
66+
#endif
67+
7768
/*
7869
* Compared to the generic __my_cpu_offset version, the following
7970
* saves one instruction and avoids clobbering a temp register.
71+
*
72+
* arch_raw_cpu_ptr should not be used in 32-bit VDSO for a 64-bit
73+
* kernel, because games are played with CONFIG_X86_64 there and
74+
* sizeof(this_cpu_off) becames 4.
8075
*/
81-
#define arch_raw_cpu_ptr(ptr) \
76+
#ifndef BUILD_VDSO32_64
77+
#define arch_raw_cpu_ptr(_ptr) \
8278
({ \
83-
unsigned long tcp_ptr__; \
84-
asm ("mov " __percpu_arg(1) ", %0" \
85-
: "=r" (tcp_ptr__) \
86-
: "m" (__my_cpu_var(this_cpu_off))); \
87-
\
88-
tcp_ptr__ += (unsigned long)(ptr); \
89-
(typeof(*(ptr)) __kernel __force *)tcp_ptr__; \
79+
unsigned long tcp_ptr__ = __raw_my_cpu_offset; \
80+
tcp_ptr__ += (unsigned long)(_ptr); \
81+
(typeof(*(_ptr)) __kernel __force *)tcp_ptr__; \
9082
})
91-
#endif /* CONFIG_USE_X86_SEG_SUPPORT */
83+
#else
84+
#define arch_raw_cpu_ptr(_ptr) ({ BUILD_BUG(); (typeof(_ptr))0; })
85+
#endif
9286

9387
#define PER_CPU_VAR(var) %__percpu_seg:(var)__percpu_rel
9488

0 commit comments

Comments
 (0)