[v2] arm64: jump_label: use constraints "Si" instead of "i"

Message ID 20240206074552.541154-1-maskray@google.com
State New
Headers
Series [v2] arm64: jump_label: use constraints "Si" instead of "i" |

Commit Message

Fangrui Song Feb. 6, 2024, 7:45 a.m. UTC
  The generic constraint "i" seems to be copied from x86 or arm (and with
a redundant generic operand modifier "c"). It works with -fno-PIE but
not with -fPIE/-fPIC in GCC's aarch64 port.

The machine constraint "S", which denotes a symbol or label reference
with a constant offset, supports PIC and has been available in GCC since
2012 and in Clang since 7.0. However, Clang before 19 does not support
"S" on a symbol with a constant offset [1] (e.g.
`static_key_false(&nf_hooks_needed[pf][hook])` in
include/linux/netfilter.h), so we use "i" as a fallback.

Suggested-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Fangrui Song <maskray@google.com>
Link: https://github.com/llvm/llvm-project/pull/80255 [1]

---
Changes from
arm64: jump_label: use constraint "S" instead of "i" (https://lore.kernel.org/all/20240131065322.1126831-1-maskray@google.com/)

* Use "Si" as Ard suggested to support Clang<19
* Make branch a separate operand

Changes from v1:

* Use asmSymbolicName for readability
---
 arch/arm64/include/asm/jump_label.h | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
  

Comments

Will Deacon Feb. 9, 2024, 6:31 p.m. UTC | #1
On Mon, 5 Feb 2024 23:45:52 -0800, Fangrui Song wrote:
> The generic constraint "i" seems to be copied from x86 or arm (and with
> a redundant generic operand modifier "c"). It works with -fno-PIE but
> not with -fPIE/-fPIC in GCC's aarch64 port.
> 
> The machine constraint "S", which denotes a symbol or label reference
> with a constant offset, supports PIC and has been available in GCC since
> 2012 and in Clang since 7.0. However, Clang before 19 does not support
> "S" on a symbol with a constant offset [1] (e.g.
> `static_key_false(&nf_hooks_needed[pf][hook])` in
> include/linux/netfilter.h), so we use "i" as a fallback.
> 
> [...]

Applied to arm64 (for-next/fixes), thanks!

[1/1] arm64: jump_label: use constraints "Si" instead of "i"
      https://git.kernel.org/arm64/c/f9daab0ad01c

Cheers,
  
Arnd Bergmann Feb. 19, 2024, 5:06 p.m. UTC | #2
On Mon, Feb 19, 2024, at 16:41, Ard Biesheuvel wrote:
> On Mon, 19 Feb 2024 at 15:43, Geert Uytterhoeven <geert@linux-m68k.org> wrote:
>> On Mon, Feb 19, 2024 at 11:57 AM Ard Biesheuvel <ardb@kernel.org> wrote:
>> > On Mon, 19 Feb 2024 at 11:56, Ard Biesheuvel <ardb@kernel.org> wrote:

>> > https://godbolt.org/z/GTnf3vPaT
>>
>> I could reproduce the issue on v6.8-rc5 using arm64 defconfig
>> and x86_64-gcc-5.5.0-nolibc-aarch64-linux.tar.xz from
>> https://cdn.kernel.org/pub/tools/crosstool/files/bin/x86_64/5.5.0/:
>>
>
> OK, I managed to do so as well.
>
> And GCC 6.4 from the same source works correctly.
>
> Not sure whether there are any plans to bump the minimal GCC version
> any time soon (cc'ing Arnd), but we should probably drop this change
> until that happens.

From what I can tell, we may as well formally raise the minimum
gcc version to 8.1+ already, as that is a version that is
actually used in distros, and we have been on 5.1+ for a few
years already.

Not sure if there are any other benefits to gcc-8 besides
allowing minor cleanups.

gcc-9 would bring --std=gnu2x support, but it may be too
early for that.

      Arnd
  
Ard Biesheuvel Feb. 20, 2024, 8:49 a.m. UTC | #3
On Tue, 20 Feb 2024 at 08:55, Ard Biesheuvel <ardb@kernel.org> wrote:
>
> On Mon, 19 Feb 2024 at 19:22, Mark Rutland <mark.rutland@arm.com> wrote:
> >
> > On Mon, Feb 19, 2024 at 06:06:19PM +0100, Arnd Bergmann wrote:
> > > On Mon, Feb 19, 2024, at 16:41, Ard Biesheuvel wrote:
> > > > On Mon, 19 Feb 2024 at 15:43, Geert Uytterhoeven <geert@linux-m68k.org> wrote:
> > > >> On Mon, Feb 19, 2024 at 11:57 AM Ard Biesheuvel <ardb@kernel.org> wrote:
> > > >> > On Mon, 19 Feb 2024 at 11:56, Ard Biesheuvel <ardb@kernel.org> wrote:
> > >
> > > >> > https://godbolt.org/z/GTnf3vPaT
> > > >>
> > > >> I could reproduce the issue on v6.8-rc5 using arm64 defconfig
> > > >> and x86_64-gcc-5.5.0-nolibc-aarch64-linux.tar.xz from
> > > >> https://cdn.kernel.org/pub/tools/crosstool/files/bin/x86_64/5.5.0/:
> > > >>
> > > >
> > > > OK, I managed to do so as well.
> > > >
> > > > And GCC 6.4 from the same source works correctly.
> > > >
> > > > Not sure whether there are any plans to bump the minimal GCC version
> > > > any time soon (cc'ing Arnd), but we should probably drop this change
> > > > until that happens.
> > >
> > > From what I can tell, we may as well formally raise the minimum
> > > gcc version to 8.1+ already, as that is a version that is
> > > actually used in distros, and we have been on 5.1+ for a few
> > > years already.
> > >
> > > Not sure if there are any other benefits to gcc-8 besides
> > > allowing minor cleanups.
> >
> > Arguably a minor cleanup, but on arm64 that'd allow us to get rid of the old
> > mcount-based ftrace implementation and rely on -fpatchable-function-entry.
> > On its own that'd save ~130 lines of asm and ~70 lines of C, but it'd also
> > remove some constraints on other features (e.g. the mcount-based form's graph
> > tracer isn't compatible with pointer authentication), it would simplify a few
> > things going forwards (e.g. the implementation of RELIABLE_STACKTRACE, since we
> > could rely on having ftrace_regs and a single trampoline), and the remaining
> > support would be better tested.
> >
> > I've wanted to remove the old ftrace implementation for a while, but on its own
> > it was never important/urgent enough to justify bumping to GCC 8+.
> >
>
> I don't think this is minor, tbh. Supporting two versions of the
> highly complex tracing infrastructure for a toolchain that is only
> used in CI seems like a waste of time and effort.
>
> I checked x86, and it needs at least GCC 7 for retpoline support, so I
> reckon at least GCC 5/6 support might be dropped there as well.

Another data point: __GCC_ASM_FLAG_OUTPUTS__ needs GCC 6 or later on x86.
  

Patch

diff --git a/arch/arm64/include/asm/jump_label.h b/arch/arm64/include/asm/jump_label.h
index 48ddc0f45d22..b7716b215f91 100644
--- a/arch/arm64/include/asm/jump_label.h
+++ b/arch/arm64/include/asm/jump_label.h
@@ -15,6 +15,10 @@ 
 
 #define JUMP_LABEL_NOP_SIZE		AARCH64_INSN_SIZE
 
+/*
+ * Prefer the constraint "S" to support PIC with GCC. Clang before 19 does not
+ * support "S" on a symbol with a constant offset, so we use "i" as a fallback.
+ */
 static __always_inline bool arch_static_branch(struct static_key * const key,
 					       const bool branch)
 {
@@ -23,9 +27,9 @@  static __always_inline bool arch_static_branch(struct static_key * const key,
 		 "	.pushsection	__jump_table, \"aw\"	\n\t"
 		 "	.align		3			\n\t"
 		 "	.long		1b - ., %l[l_yes] - .	\n\t"
-		 "	.quad		%c0 - .			\n\t"
+		 "	.quad		(%[key] - .) + %[bit0]  \n\t"
 		 "	.popsection				\n\t"
-		 :  :  "i"(&((char *)key)[branch]) :  : l_yes);
+		 :  :  [key]"Si"(key), [bit0]"i"(branch) :  : l_yes);
 
 	return false;
 l_yes:
@@ -40,9 +44,9 @@  static __always_inline bool arch_static_branch_jump(struct static_key * const ke
 		 "	.pushsection	__jump_table, \"aw\"	\n\t"
 		 "	.align		3			\n\t"
 		 "	.long		1b - ., %l[l_yes] - .	\n\t"
-		 "	.quad		%c0 - .			\n\t"
+		 "	.quad		(%[key] - .) + %[bit0]  \n\t"
 		 "	.popsection				\n\t"
-		 :  :  "i"(&((char *)key)[branch]) :  : l_yes);
+		 :  :  [key]"Si"(key), [bit0]"i"(branch) :  : l_yes);
 
 	return false;
 l_yes: