FROMLIST: arm64: make mrs_s and msr_s macros work with LTO
authorAlex Matveev <alxmtvv@gmail.com>
Tue, 14 Nov 2017 23:06:17 +0000 (15:06 -0800)
committerSami Tolvanen <samitolvanen@google.com>
Thu, 26 Apr 2018 23:03:36 +0000 (16:03 -0700)
Clang's integrated assembler does not allow assembly macros defined
in one inline asm block using the .macro directive to be used across
separate asm blocks. LLVM developers consider this a feature and not a
bug, recommending code refactoring:

  https://bugs.llvm.org/show_bug.cgi?id=19749

As binutils doesn't allow macros to be redefined, this change uses
UNDEFINE_MRS_S and UNDEFINE_MSR_S to define corresponding macros
in-place and workaround gcc and clang limitations on redefining macros
across different assembler blocks.

Bug: 62093296
Bug: 67506682
Change-Id: I803fff57f639b0921ef81f90ec4befe802e7eecf
(am from https://patchwork.kernel.org/patch/10060343/)
Signed-off-by: Alex Matveev <alxmtvv@gmail.com>
Signed-off-by: Yury Norov <ynorov@caviumnetworks.com>
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
arch/arm64/include/asm/kvm_hyp.h
arch/arm64/include/asm/sysreg.h

index 4572a9b560fa3d73a7db4a850215bcbc9049c8f1..20bfb8e676e043236f63a0165eb78e63437284ac 100644 (file)
@@ -29,7 +29,9 @@
        ({                                                              \
                u64 reg;                                                \
                asm volatile(ALTERNATIVE("mrs %0, " __stringify(r##nvh),\
-                                        "mrs_s %0, " __stringify(r##vh),\
+                                        DEFINE_MRS_S                   \
+                                        "mrs_s %0, " __stringify(r##vh) "\n"\
+                                        UNDEFINE_MRS_S,                \
                                         ARM64_HAS_VIRT_HOST_EXTN)      \
                             : "=r" (reg));                             \
                reg;                                                    \
@@ -39,7 +41,9 @@
        do {                                                            \
                u64 __val = (u64)(v);                                   \
                asm volatile(ALTERNATIVE("msr " __stringify(r##nvh) ", %x0",\
-                                        "msr_s " __stringify(r##vh) ", %x0",\
+                                        DEFINE_MSR_S                   \
+                                        "msr_s " __stringify(r##vh) ", %x0\n"\
+                                        UNDEFINE_MSR_S,                \
                                         ARM64_HAS_VIRT_HOST_EXTN)      \
                                         : : "rZ" (__val));             \
        } while (0)
index ede80d47d0effdb749a51df45d39dd576611fc9c..3bdec2f5cbb423bbdce450375e492ac45c2be1f7 100644 (file)
 
 #include <linux/types.h>
 
-asm(
-"      .irp    num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30\n"
-"      .equ    .L__reg_num_x\\num, \\num\n"
-"      .endr\n"
+#define __DEFINE_MRS_MSR_S_REGNUM                              \
+"      .irp    num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30\n" \
+"      .equ    .L__reg_num_x\\num, \\num\n"                    \
+"      .endr\n"                                                \
 "      .equ    .L__reg_num_xzr, 31\n"
-"\n"
-"      .macro  mrs_s, rt, sreg\n"
-       __emit_inst(0xd5200000|(\\sreg)|(.L__reg_num_\\rt))
+
+#define DEFINE_MRS_S                                           \
+       __DEFINE_MRS_MSR_S_REGNUM                               \
+"      .macro  mrs_s, rt, sreg\n"                              \
+"      .inst 0xd5200000|(\\sreg)|(.L__reg_num_\\rt)\n" \
 "      .endm\n"
-"\n"
-"      .macro  msr_s, sreg, rt\n"
-       __emit_inst(0xd5000000|(\\sreg)|(.L__reg_num_\\rt))
+
+#define DEFINE_MSR_S                                           \
+       __DEFINE_MRS_MSR_S_REGNUM                               \
+"      .macro  msr_s, sreg, rt\n"                              \
+"      .inst 0xd5000000|(\\sreg)|(.L__reg_num_\\rt)\n"         \
 "      .endm\n"
-);
+
+#define UNDEFINE_MRS_S                                         \
+"      .purgem mrs_s\n"
+
+#define UNDEFINE_MSR_S                                         \
+"      .purgem msr_s\n"
+
+#define __mrs_s(r, v)                                          \
+       DEFINE_MRS_S                                            \
+"      mrs_s %0, " __stringify(r) "\n"                         \
+       UNDEFINE_MRS_S : "=r" (v)
+
+#define __msr_s(r, v)                                          \
+       DEFINE_MSR_S                                            \
+"      msr_s " __stringify(r) ", %x0\n"                        \
+       UNDEFINE_MSR_S : : "rZ" (v)
 
 /*
  * Unlike read_cpuid, calls to read_sysreg are never expected to be
@@ -504,15 +523,15 @@ asm(
  * For registers without architectural names, or simply unsupported by
  * GAS.
  */
-#define read_sysreg_s(r) ({                                            \
-       u64 __val;                                                      \
-       asm volatile("mrs_s %0, " __stringify(r) : "=r" (__val));       \
-       __val;                                                          \
+#define read_sysreg_s(r) ({                                    \
+       u64 __val;                                              \
+       asm volatile(__mrs_s(r, __val));                        \
+       __val;                                                  \
 })
 
-#define write_sysreg_s(v, r) do {                                      \
-       u64 __val = (u64)(v);                                           \
-       asm volatile("msr_s " __stringify(r) ", %x0" : : "rZ" (__val)); \
+#define write_sysreg_s(v, r) do {                              \
+       u64 __val = (u64)(v);                                   \
+       asm volatile(__msr_s(r, __val));                        \
 } while (0)
 
 static inline void config_sctlr_el1(u32 clear, u32 set)