[PATCH] arm64: Work around broken GCC handling of "S" constraint
Ard Biesheuvel
ardb at kernel.org
Mon Dec 7 12:17:54 EST 2020
On Mon, 7 Dec 2020 at 16:43, Marc Zyngier <maz at kernel.org> wrote:
>
> GCC 4.9 seems to have a problem with the "S" asm constraint
> when the symbol lives in the same compilation unit, and pretends
> the constraint is impossible:
>
> $ cat x.c
> void *foo(void)
> {
> static int x;
> int *addr;
> asm("adrp %0, %1" : "=r" (addr) : "S" (&x));
> return addr;
> }
>
> $ ~/Work/gcc-linaro-aarch64-linux-gnu-4.9-2014.09_linux/bin/aarch64-linux-gnu-gcc -S -x c -O2 x.c
> x.c: In function ‘foo’:
> x.c:5:2: error: impossible constraint in ‘asm’
> asm("adrp %0, %1" : "=r" (addr) : "S" (&x));
> ^
>
> Boo. Following revisions of the compiler work just fine, though.
>
> We can fallback to the "i" constraint in that case, which
> *seems* to do the right thing. Hopefully we will be able to
> remove this at some point, but in the meantime this gets us going.
>
> Signed-off-by: Marc Zyngier <maz at kernel.org>
> ---
> arch/arm64/Makefile | 9 +++++++++
> arch/arm64/include/asm/kvm_asm.h | 8 +++++++-
> 2 files changed, 16 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
> index 5789c2d18d43..c4ee8e64ad1a 100644
> --- a/arch/arm64/Makefile
> +++ b/arch/arm64/Makefile
> @@ -44,12 +44,21 @@ cc_has_k_constraint := $(call try-run,echo \
> return 0; \
> }' | $(CC) -S -x c -o "$$TMP" -,,-DCONFIG_CC_HAS_K_CONSTRAINT=1)
>
> +cc_has_broken_s_constraint := $(call try-run,echo \
> + 'void *foo(void) { \
> + static int x; \
> + int *addr; \
> + asm("adrp %0, %1" : "=r" (addr) : "S" (&x)); \
> + return addr; \
> + }' | $(CC) -S -x c -c -O2 -o "$$TMP" -,,-DCONFIG_CC_HAS_BROKEN_S_CONSTRAINT=1)
> +
> ifeq ($(CONFIG_BROKEN_GAS_INST),y)
> $(warning Detected assembler with broken .inst; disassembly will be unreliable)
> endif
>
> KBUILD_CFLAGS += -mgeneral-regs-only \
> $(compat_vdso) $(cc_has_k_constraint)
> +KBUILD_CFLAGS += $(cc_has_broken_s_constraint)
> KBUILD_CFLAGS += $(call cc-disable-warning, psabi)
> KBUILD_AFLAGS += $(compat_vdso)
>
> diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
> index 7ccf770c53d9..fa8e886998a3 100644
> --- a/arch/arm64/include/asm/kvm_asm.h
> +++ b/arch/arm64/include/asm/kvm_asm.h
> @@ -199,6 +199,12 @@ extern void __vgic_v3_init_lrs(void);
>
> extern u32 __kvm_get_mdcr_el2(void);
>
> +#ifdef CONFIG_CC_HAS_BROKEN_S_CONSTRAINT
> +#define SYM_CONSTRAINT "i"
> +#else
> +#define SYM_CONSTRAINT "S"
> +#endif
> +
Could we just check GCC_VERSION here?
> /*
> * Obtain the PC-relative address of a kernel symbol
> * s: symbol
> @@ -215,7 +221,7 @@ extern u32 __kvm_get_mdcr_el2(void);
> typeof(s) *addr; \
> asm("adrp %0, %1\n" \
> "add %0, %0, :lo12:%1\n" \
> - : "=r" (addr) : "S" (&s)); \
> + : "=r" (addr) : SYM_CONSTRAINT (&s)); \
> addr; \
> })
>
> --
> 2.29.2
>
More information about the linux-arm-kernel
mailing list