smccc: Use separate variables for args and results
authorAndrew Scull <ascull@google.com>
Tue, 15 Sep 2020 10:46:40 +0000 (11:46 +0100)
committerMarc Zyngier <maz@kernel.org>
Tue, 15 Sep 2020 17:39:04 +0000 (18:39 +0100)
Using the same register-bound variable for both arguments and results
means these values share a type. That type must allow the arguments to
be assigned to it and must also be assignable to the unsigned long
fields of struct arm_smccc_res.

This restriction on types causes compiler warnings when the argument
cannot be implicitly assigned to an unsigned long, for example the
pointers that are used in the KVM hyp interface.

By separating the arguments and results into their own variables, the
type constraint is lifted allowing the arguments to avoid the need for
any type conversion.

Signed-off-by: Andrew Scull <ascull@google.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Cc: Sudeep Holla <sudeep.holla@arm.com>
Link: https://lore.kernel.org/r/20200915104643.2543892-17-ascull@google.com
include/linux/arm-smccc.h

index ee286f5..885c9ff 100644 (file)
@@ -228,87 +228,67 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
 #define __count_args(...)                                              \
        ___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
 
-#define __constraint_write_0                                           \
-       "+r" (r0), "=&r" (r1), "=&r" (r2), "=&r" (r3)
-#define __constraint_write_1                                           \
-       "+r" (r0), "+r" (r1), "=&r" (r2), "=&r" (r3)
-#define __constraint_write_2                                           \
-       "+r" (r0), "+r" (r1), "+r" (r2), "=&r" (r3)
-#define __constraint_write_3                                           \
-       "+r" (r0), "+r" (r1), "+r" (r2), "+r" (r3)
-#define __constraint_write_4   __constraint_write_3
-#define __constraint_write_5   __constraint_write_4
-#define __constraint_write_6   __constraint_write_5
-#define __constraint_write_7   __constraint_write_6
-
-#define __constraint_read_0
-#define __constraint_read_1
-#define __constraint_read_2
-#define __constraint_read_3
-#define __constraint_read_4    "r" (r4)
-#define __constraint_read_5    __constraint_read_4, "r" (r5)
-#define __constraint_read_6    __constraint_read_5, "r" (r6)
-#define __constraint_read_7    __constraint_read_6, "r" (r7)
+#define __constraint_read_0    "r" (arg0)
+#define __constraint_read_1    __constraint_read_0, "r" (arg1)
+#define __constraint_read_2    __constraint_read_1, "r" (arg2)
+#define __constraint_read_3    __constraint_read_2, "r" (arg3)
+#define __constraint_read_4    __constraint_read_3, "r" (arg4)
+#define __constraint_read_5    __constraint_read_4, "r" (arg5)
+#define __constraint_read_6    __constraint_read_5, "r" (arg6)
+#define __constraint_read_7    __constraint_read_6, "r" (arg7)
 
 #define __declare_arg_0(a0, res)                                       \
        struct arm_smccc_res   *___res = res;                           \
-       register unsigned long r0 asm("r0") = (u32)a0;                  \
-       register unsigned long r1 asm("r1");                            \
-       register unsigned long r2 asm("r2");                            \
-       register unsigned long r3 asm("r3")
+       register unsigned long arg0 asm("r0") = (u32)a0
 
 #define __declare_arg_1(a0, a1, res)                                   \
        typeof(a1) __a1 = a1;                                           \
        struct arm_smccc_res   *___res = res;                           \
-       register unsigned long r0 asm("r0") = (u32)a0;                  \
-       register unsigned long r1 asm("r1") = __a1;                     \
-       register unsigned long r2 asm("r2");                            \
-       register unsigned long r3 asm("r3")
+       register unsigned long arg0 asm("r0") = (u32)a0;                        \
+       register typeof(a1) arg1 asm("r1") = __a1
 
 #define __declare_arg_2(a0, a1, a2, res)                               \
        typeof(a1) __a1 = a1;                                           \
        typeof(a2) __a2 = a2;                                           \
        struct arm_smccc_res   *___res = res;                           \
-       register unsigned long r0 asm("r0") = (u32)a0;                  \
-       register unsigned long r1 asm("r1") = __a1;                     \
-       register unsigned long r2 asm("r2") = __a2;                     \
-       register unsigned long r3 asm("r3")
+       register unsigned long arg0 asm("r0") = (u32)a0;                        \
+       register typeof(a1) arg1 asm("r1") = __a1;                      \
+       register typeof(a2) arg2 asm("r2") = __a2
 
 #define __declare_arg_3(a0, a1, a2, a3, res)                           \
        typeof(a1) __a1 = a1;                                           \
        typeof(a2) __a2 = a2;                                           \
        typeof(a3) __a3 = a3;                                           \
        struct arm_smccc_res   *___res = res;                           \
-       register unsigned long r0 asm("r0") = (u32)a0;                  \
-       register unsigned long r1 asm("r1") = __a1;                     \
-       register unsigned long r2 asm("r2") = __a2;                     \
-       register unsigned long r3 asm("r3") = __a3
+       register unsigned long arg0 asm("r0") = (u32)a0;                        \
+       register typeof(a1) arg1 asm("r1") = __a1;                      \
+       register typeof(a2) arg2 asm("r2") = __a2;                      \
+       register typeof(a3) arg3 asm("r3") = __a3
 
 #define __declare_arg_4(a0, a1, a2, a3, a4, res)                       \
        typeof(a4) __a4 = a4;                                           \
        __declare_arg_3(a0, a1, a2, a3, res);                           \
-       register unsigned long r4 asm("r4") = __a4
+       register typeof(a4) arg4 asm("r4") = __a4
 
 #define __declare_arg_5(a0, a1, a2, a3, a4, a5, res)                   \
        typeof(a5) __a5 = a5;                                           \
        __declare_arg_4(a0, a1, a2, a3, a4, res);                       \
-       register unsigned long r5 asm("r5") = __a5
+       register typeof(a5) arg5 asm("r5") = __a5
 
 #define __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res)               \
        typeof(a6) __a6 = a6;                                           \
        __declare_arg_5(a0, a1, a2, a3, a4, a5, res);                   \
-       register unsigned long r6 asm("r6") = __a6
+       register typeof(a6) arg6 asm("r6") = __a6
 
 #define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6, a7, res)           \
        typeof(a7) __a7 = a7;                                           \
        __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res);               \
-       register unsigned long r7 asm("r7") = __a7
+       register typeof(a7) arg7 asm("r7") = __a7
 
 #define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__)
 #define __declare_args(count, ...)  ___declare_args(count, __VA_ARGS__)
 
 #define ___constraints(count)                                          \
-       : __constraint_write_ ## count                                  \
        : __constraint_read_ ## count                                   \
        : "memory"
 #define __constraints(count)   ___constraints(count)
@@ -320,8 +300,13 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
  */
 #define __arm_smccc_1_1(inst, ...)                                     \
        do {                                                            \
+               register unsigned long r0 asm("r0");                    \
+               register unsigned long r1 asm("r1");                    \
+               register unsigned long r2 asm("r2");                    \
+               register unsigned long r3 asm("r3");                    \
                __declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \
-               asm volatile(inst "\n"                                  \
+               asm volatile(inst "\n" :                                \
+                            "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3) \
                             __constraints(__count_args(__VA_ARGS__))); \
                if (___res)                                             \
                        *___res = (typeof(*___res)){r0, r1, r2, r3};    \
@@ -367,7 +352,7 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1,
 #define __fail_smccc_1_1(...)                                          \
        do {                                                            \
                __declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \
-               asm ("" __constraints(__count_args(__VA_ARGS__)));      \
+               asm ("" : __constraints(__count_args(__VA_ARGS__)));    \
                if (___res)                                             \
                        ___res->a0 = SMCCC_RET_NOT_SUPPORTED;           \
        } while (0)