[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen stable-4.19] x86/altcall: fix clang code-gen when using altcall in loop constructs



commit 9d7f7e3444bcd85b73a8a152b26b22821275a156
Author:     Roger Pau Monné <roger.pau@xxxxxxxxxx>
AuthorDate: Tue Jul 23 14:07:54 2024 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Tue Jul 23 14:07:54 2024 +0200

    x86/altcall: fix clang code-gen when using altcall in loop constructs
    
    Yet another clang code generation issue when using altcalls.
    
    The issue this time is with using loop constructs around 
alternative_{,v}call
    instances using parameter types smaller than the register size.
    
    Given the following example code:
    
    static void bar(bool b)
    {
        unsigned int i;
    
        for ( i = 0; i < 10; i++ )
        {
            int ret_;
            register union {
                bool e;
                unsigned long r;
            } di asm("rdi") = { .e = b };
            register unsigned long si asm("rsi");
            register unsigned long dx asm("rdx");
            register unsigned long cx asm("rcx");
            register unsigned long r8 asm("r8");
            register unsigned long r9 asm("r9");
            register unsigned long r10 asm("r10");
            register unsigned long r11 asm("r11");
    
            asm volatile ( "call %c[addr]"
                           : "+r" (di), "=r" (si), "=r" (dx),
                             "=r" (cx), "=r" (r8), "=r" (r9),
                             "=r" (r10), "=r" (r11), "=a" (ret_)
                           : [addr] "i" (&(func)), "g" (func)
                           : "memory" );
        }
    }
    
    See: https://godbolt.org/z/qvxMGd84q
    
    Clang will generate machine code that only resets the low 8 bits of %rdi
    between loop calls, leaving the rest of the register possibly containing
    garbage from the use of %rdi inside the called function.  Note also that 
clang
    doesn't truncate the input parameters at the callee, thus breaking the 
psABI.
    
    Fix this by turning the `e` element in the anonymous union into an array 
that
    consumes the same space as an unsigned long, as this forces clang to reset 
the
    whole %rdi register instead of just the low 8 bits.
    
    Fixes: 2ce562b2a413 ('x86/altcall: use a union as register type for 
function parameters on clang')
    Suggested-by: Jan Beulich <jbeulich@xxxxxxxx>
    Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
    Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
    Release-Acked-By: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
    master commit: d51b2f5ea1915fe058f730b0ec542cf84254fca0
    master date: 2024-07-23 13:59:30 +0200
---
 xen/arch/x86/include/asm/alternative.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/xen/arch/x86/include/asm/alternative.h 
b/xen/arch/x86/include/asm/alternative.h
index 0d3697f1de..e63b459276 100644
--- a/xen/arch/x86/include/asm/alternative.h
+++ b/xen/arch/x86/include/asm/alternative.h
@@ -185,10 +185,10 @@ extern void alternative_branches(void);
  */
 #define ALT_CALL_ARG(arg, n)                                            \
     register union {                                                    \
-        typeof(arg) e;                                                  \
+        typeof(arg) e[sizeof(long) / sizeof(arg)];                      \
         unsigned long r;                                                \
     } a ## n ## _ asm ( ALT_CALL_arg ## n ) = {                         \
-        .e = ({ BUILD_BUG_ON(sizeof(arg) > sizeof(void *)); (arg); })   \
+        .e[0] = ({ BUILD_BUG_ON(sizeof(arg) > sizeof(void *)); (arg); })\
     }
 #else
 #define ALT_CALL_ARG(arg, n) \
--
generated by git-patchbot for /home/xen/git/xen.git#stable-4.19



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.