From eda025141354a0fa2b0d1ec89dc95d2b4b299aa0 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Thu, 17 Dec 2020 11:11:35 +0000 Subject: [PATCH] BACKPORT: arm64: Work around broken GCC 4.9 handling of "S" constraint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 for GCC version prior to 5.0, 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 Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20201217111135.1536658-1-maz@kernel.org Signed-off-by: Catalin Marinas (cherry picked from commit 9fd339a45be5c06e239d45a042eab9d25de87882) [will: Fixed trivial conflict due to removal of __smccc_workaround_1_smc] Signed-off-by: Will Deacon Change-Id: I8ec0842eb50ee32eefaed947bf5dbf7a4892f3b4 Bug: 178098380 Test: atest VirtualizationHostTestCases on an EL2-enabled device --- arch/arm64/include/asm/kvm_asm.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index d67531c7317b..8c3547c8db30 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); +#if defined(GCC_VERSION) && GCC_VERSION < 50000 +#define SYM_CONSTRAINT "i" +#else +#define SYM_CONSTRAINT "S" +#endif + /* * 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; \ })