qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH] hw/display/qxl: Suppress clang-7 warning about


From: Philippe Mathieu-Daudé
Subject: Re: [Qemu-devel] [PATCH] hw/display/qxl: Suppress clang-7 warning about misaligned atomic operation
Date: Thu, 27 Sep 2018 22:00:03 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.0

On 9/27/18 5:55 PM, Peter Maydell wrote:
> If QEMU is compiled with clang-7 it results in the warning:
> 
> hw/display/qxl.c:1884:19: error: misaligned or large atomic operation
> may incur significant performance penalty [-Werror,-Watomic-alignment]
>     old_pending = atomic_fetch_or(&d->ram->int_pending, le_events);
>                   ^
> 
> This is because the Spice headers forgot to define the QXLRam struct
> with the '__aligned__(4)' attribute.  clang 7 and newer will thus
> warn that the access here to int_pending might not be 4-aligned
> (because the QXLRam object d->ram points at might start at a
> misaligned address).  In fact we set up d->ram in init_qxl_ram() so
> it always starts at a 4K boundary, so we know the atomic access here
> is OK.
> 
> Newer Spice versions (with Spice commit
> beda5ec7a6848be20c0cac2a9a8ef2a41e8069c1) will fix the bug;
> for older Spice versions, work around it by telling the compiler
> explicitly that the alignment is OK using __builtin_assume_aligned().
> 
> Signed-off-by: Peter Maydell <address@hidden>

Thanks!

Reviewed-by: Philippe Mathieu-Daudé <address@hidden>
Tested-by: Philippe Mathieu-Daudé <address@hidden>

> ---
>  include/qemu/compiler.h |  9 +++++++++
>  hw/display/qxl.c        | 26 +++++++++++++++++++++++++-
>  2 files changed, 34 insertions(+), 1 deletion(-)
> 
> diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
> index 5843812710c..bf47e7bee4e 100644
> --- a/include/qemu/compiler.h
> +++ b/include/qemu/compiler.h
> @@ -122,6 +122,15 @@
>  #ifndef __has_feature
>  #define __has_feature(x) 0 /* compatibility with non-clang compilers */
>  #endif
> +
> +#ifndef __has_builtin
> +#define __has_builtin(x) 0 /* compatibility with non-clang compilers */
> +#endif
> +
> +#if __has_builtin(__builtin_assume_aligned) || QEMU_GNUC_PREREQ(4, 7)
> +#define HAS_ASSUME_ALIGNED
> +#endif
> +
>  /* Implement C11 _Generic via GCC builtins.  Example:
>   *
>   *    QEMU_GENERIC(x, (float, sinf), (long double, sinl), sin) (x)
> diff --git a/hw/display/qxl.c b/hw/display/qxl.c
> index 8e9135d9c67..5702e8645d3 100644
> --- a/hw/display/qxl.c
> +++ b/hw/display/qxl.c
> @@ -1881,7 +1881,31 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t 
> events)
>          trace_qxl_send_events_vm_stopped(d->id, events);
>          return;
>      }
> -    old_pending = atomic_fetch_or(&d->ram->int_pending, le_events);
> +    /*
> +     * Older versions of Spice forgot to define the QXLRam struct
> +     * with the '__aligned__(4)' attribute. clang 7 and newer will
> +     * thus warn that atomic_fetch_or(&d->ram->int_pending, ...)
> +     * might be a misaligned atomic access, and will generate an
> +     * out-of-line call for it, which results in a link error since
> +     * we don't currently link against libatomic.
> +     *
> +     * In fact we set up d->ram in init_qxl_ram() so it always starts
> +     * at a 4K boundary, so we know that &d->ram->int_pending is
> +     * naturally aligned for a uint32_t. Newer Spice versions
> +     * (with Spice commit beda5ec7a6848be20c0cac2a9a8ef2a41e8069c1)
> +     * will fix the bug directly. To deal with older versions,
> +     * we tell the compiler to assume the address really is aligned.
> +     * Any compiler which cares about the misalignment will have
> +     * __builtin_assume_aligned.
> +     */
> +#ifdef HAS_ASSUME_ALIGNED
> +#define ALIGNED_UINT32_PTR(P) ((uint32_t *)__builtin_assume_aligned(P, 4))
> +#else
> +#define ALIGNED_UINT32_PTR(P) ((uint32_t *)P)
> +#endif
> +
> +    old_pending = atomic_fetch_or(ALIGNED_UINT32_PTR(&d->ram->int_pending),
> +                                  le_events);
>      if ((old_pending & le_events) == le_events) {
>          return;
>      }
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]