]> xenbits.xensource.com Git - people/andrewcoop/xen-test-framework.git/commitdiff
hypercall: Work around Clang code generation bug
authorAndrew Cooper <andrew.cooper3@citrix.com>
Fri, 6 Nov 2020 18:53:39 +0000 (18:53 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Fri, 6 Nov 2020 19:23:17 +0000 (19:23 +0000)
_hypercall64_4() is mis-compiled by some versions of Clang (5 is ok, 9 and
later not), in a way which breaks the XSA-286 PoC.

Clang loses the association between argument 4 being in %r10 between the input
"a" (_a4) and the output "=&r" (__ign4), so while the input is handled
correctly, the clobber on the output is missed.

In the XSA-286, PoC, this causes clang to hoist the setting of DOMID_SELF out
of the loop, and the test subsequently to malfunction on debug versions of Xen
which intentionally clobber the hypercall parameters.

Rewrite the hypercall macros to a single "+r" parameter form, rather than dual
input/output form, which causes all tested versions of Clang to set up %r10 on
each loop iteration.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
arch/x86/include/arch/hypercall-x86_32.h
arch/x86/include/arch/hypercall-x86_64.h

index 9bb72ef08094be8c6629cac00698fc0ec099764c..bf1d4f1dd530ffc77d673e851cdff294e1a8fa34 100644 (file)
@@ -9,52 +9,49 @@
 
 #define _hypercall32_1(type, hcall, a1)                                 \
     ({                                                                  \
-        long __res, __ign1;                                             \
+        long _res = (long)(hcall), _a1 = (long)(a1);                    \
         asm volatile (                                                  \
             "call hypercall_page + %c[offset]"                          \
-            : "=a" (__res), "=b" (__ign1)                               \
-            : [offset] "i" (hcall * 32),                                \
-              "1" ((long)(a1))                                          \
+            : "+a" (_res), "+b" (_a1)                                   \
+            : [offset] "i" (hcall * 32)                                 \
             : "memory" );                                               \
-        (type)__res;                                                    \
+        (type)_res;                                                     \
     })
 
 #define _hypercall32_2(type, hcall, a1, a2)                             \
     ({                                                                  \
-        long __res, __ign1, __ign2;                                     \
+        long _res = (long)(hcall), _a1 = (long)(a1), _a2 = (long)(a2);  \
         asm volatile (                                                  \
             "call hypercall_page + %c[offset]"                          \
-            : "=a" (__res), "=b" (__ign1), "=c" (__ign2)                \
-            : [offset] "i" (hcall * 32),                                \
-              "1" ((long)(a1)), "2" ((long)(a2))                        \
+            : "+a" (_res), "+b" (_a1), "+c" (_a2)                       \
+            : [offset] "i" (hcall * 32)                                 \
             : "memory" );                                               \
-        (type)__res;                                                    \
+        (type)_res;                                                     \
     })
 
 #define _hypercall32_3(type, hcall, a1, a2, a3)                         \
     ({                                                                  \
-        long __res, __ign1, __ign2, __ign3;                             \
+        long _res = (long)(hcall), _a1 = (long)(a1), _a2 = (long)(a2),  \
+            _a3 = (long)(a3);                                           \
         asm volatile (                                                  \
             "call hypercall_page + %c[offset]"                          \
-            : "=a" (__res), "=b" (__ign1), "=c" (__ign2), "=d" (__ign3) \
-            : [offset] "i" (hcall * 32),                                \
-              "1" ((long)(a1)), "2" ((long)(a2)), "3" ((long)(a3))      \
+            : "+a" (_res), "+b" (_a1), "+c" (_a2), "+d" (_a3)           \
+            : [offset] "i" (hcall * 32)                                 \
             : "memory" );                                               \
-        (type)__res;                                                    \
+        (type)_res;                                                     \
     })
 
 #define _hypercall32_4(type, hcall, a1, a2, a3, a4)                     \
     ({                                                                  \
-        long __res, __ign1, __ign2, __ign3, __ign4;                     \
+        long _res = (long)(hcall), _a1 = (long)(a1), _a2 = (long)(a2),  \
+            _a3 = (long)(a3), _a4 = (long)(a4);                         \
         asm volatile (                                                  \
             "call hypercall_page + %c[offset]"                          \
-            : "=a" (__res), "=b" (__ign1), "=c" (__ign2), "=d" (__ign3),\
-              "=S" (__ign4)                                             \
-            : [offset] "i" (hcall * 32),                                \
-              "1" ((long)(a1)), "2" ((long)(a2)), "3" ((long)(a3)),     \
-              "4" ((long)(a4))                                          \
+            : "+a" (_res), "+b" (_a1), "+c" (_a2), "+d" (_a3),          \
+              "+S" (_a4)                                                \
+            : [offset] "i" (hcall * 32)                                 \
             : "memory" );                                               \
-        (type)__res;                                                    \
+        (type)_res;                                                     \
     })
 
 #endif /* XTF_X86_32_HYPERCALL_H */
index 885bd30ed9f61a6abf6f4426f4970b4dc0972835..d6db99fe2895e62f4ffa208fdb80c4568ef5b6c4 100644 (file)
@@ -9,53 +9,50 @@
 
 #define _hypercall64_1(type, hcall, a1)                                 \
     ({                                                                  \
-        long __res, __ign1;                                             \
+        long _res = (long)(hcall), _a1 = (long)(a1);                    \
         asm volatile (                                                  \
             "call hypercall_page + %c[offset]"                          \
-            : "=a" (__res), "=D" (__ign1)                               \
-            : [offset] "i" (hcall * 32),                                \
-              "1" ((long)(a1))                                          \
+            : "+a" (_res), "+D" (_a1)                                   \
+            : [offset] "i" (hcall * 32)                                 \
             : "memory" );                                               \
-        (type)__res;                                                    \
+        (type)_res;                                                     \
     })
 
 #define _hypercall64_2(type, hcall, a1, a2)                             \
     ({                                                                  \
-        long __res, __ign1, __ign2;                                     \
+        long _res = (long)(hcall), _a1 = (long)(a1), _a2 = (long)(a2);  \
         asm volatile (                                                  \
             "call hypercall_page + %c[offset]"                          \
-            : "=a" (__res), "=D" (__ign1), "=S" (__ign2)                \
-            : [offset] "i" (hcall * 32),                                \
-              "1" ((long)(a1)), "2" ((long)(a2))                        \
+            : "+a" (_res), "+D" (_a1), "+S" (_a2)                       \
+            : [offset] "i" (hcall * 32)                                 \
             : "memory" );                                               \
-        (type)__res;                                                    \
+        (type)_res;                                                     \
     })
 
 #define _hypercall64_3(type, hcall, a1, a2, a3)                         \
     ({                                                                  \
-        long __res, __ign1, __ign2, __ign3;                             \
+        long _res = (long)(hcall), _a1 = (long)(a1), _a2 = (long)(a2),  \
+            _a3 = (long)(a3);                                           \
         asm volatile (                                                  \
             "call hypercall_page + %c[offset]"                          \
-            : "=a" (__res), "=D" (__ign1), "=S" (__ign2), "=d" (__ign3) \
-            : [offset] "i" (hcall * 32),                                \
-              "1" ((long)(a1)), "2" ((long)(a2)), "3" ((long)(a3))      \
+            : "+a" (_res), "+D" (_a1), "+S" (_a2), "+d" (_a3)           \
+            : [offset] "i" (hcall * 32)                                 \
             : "memory" );                                               \
-        (type)__res;                                                    \
+        (type)_res;                                                     \
     })
 
 #define _hypercall64_4(type, hcall, a1, a2, a3, a4)                     \
     ({                                                                  \
-        long __res, __ign1, __ign2, __ign3, __ign4;                     \
-        register long _a4 asm ("r10") = ((long)(a4));                   \
+        long _res = (long)(hcall), _a1 = (long)(a1), _a2 = (long)(a2),  \
+            _a3 = (long)(a3);                                           \
+        register long _a4 asm ("r10") = (long)(a4);                     \
         asm volatile (                                                  \
             "call hypercall_page + %c[offset]"                          \
-            : "=a" (__res), "=D" (__ign1), "=S" (__ign2), "=d" (__ign3),\
-              "=&r" (__ign4)                                            \
-            : [offset] "i" (hcall * 32),                                \
-              "1" ((long)(a1)), "2" ((long)(a2)), "3" ((long)(a3)),     \
-              "4" (_a4)                                                 \
+            : "+a" (_res), "+D" (_a1), "+S" (_a2), "+d" (_a3),          \
+              "+r" (_a4)                                                \
+            : [offset] "i" (hcall * 32)                                 \
             : "memory" );                                               \
-        (type)__res;                                                    \
+        (type)_res;                                                     \
     })
 
 #endif /* XTF_X86_64_HYPERCALL_H */