[PATCH 4/6] meson: allow configuring the x86-64 baseline

Paolo Bonzini posted 6 patches 6 months, 1 week ago
[PATCH 4/6] meson: allow configuring the x86-64 baseline
Posted by Paolo Bonzini 6 months, 1 week ago
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 meson.build                   | 41 ++++++++++++++++++++++++++++-------
 meson_options.txt             |  3 +++
 scripts/meson-buildoptions.sh |  3 +++
 3 files changed, 39 insertions(+), 8 deletions(-)

diff --git a/meson.build b/meson.build
index 97e00d6f59b..6e694ecd9fe 100644
--- a/meson.build
+++ b/meson.build
@@ -336,15 +336,40 @@ if host_arch == 'i386' and not cc.links('''
   qemu_common_flags = ['-march=i486'] + qemu_common_flags
 endif
 
-# Assume x86-64-v2 (minus CMPXCHG16B for 32-bit code)
-if host_arch == 'i386'
-  qemu_common_flags = ['-mfpmath=sse'] + qemu_common_flags
-endif
+# Pick x86-64 baseline version
 if host_arch in ['i386', 'x86_64']
-  qemu_common_flags = ['-mpopcnt', '-msse4.2'] + qemu_common_flags
-endif
-if host_arch == 'x86_64'
-  qemu_common_flags = ['-mcx16'] + qemu_common_flags
+  if get_option('x86_version') == '0' and host_arch == 'x86_64'
+    error('x86_64-v1 required for x86-64 hosts')
+  endif
+
+  # add flags for individual instruction set extensions
+  if get_option('x86_version') >= '1'
+    if host_arch == 'i386'
+      qemu_common_flags = ['-mfpmath=sse'] + qemu_common_flags
+    else
+      # present on basically all processors but technically not part of
+      # x86-64-v1, so only include -mneeded for x86-64 version 2 and above
+      qemu_common_flags = ['-mcx16'] + qemu_common_flags
+    endif
+  endif
+  if get_option('x86_version') >= '2'
+    qemu_common_flags = ['-mpopcnt'] + qemu_common_flags
+    qemu_common_flags = cc.get_supported_arguments('-mneeded') + qemu_common_flags
+  endif
+  if get_option('x86_version') >= '3'
+    qemu_common_flags = ['-mmovbe', '-mabm', '-mbmi1', '-mbmi2', '-mfma', '-mf16c'] + qemu_common_flags
+  endif
+
+  # add required vector instruction set (each level implies those below)
+  if get_option('x86_version') == '1'
+    qemu_common_flags = ['-msse2'] + qemu_common_flags
+  elif get_option('x86_version') == '2'
+    qemu_common_flags = ['-msse4.2'] + qemu_common_flags
+  elif get_option('x86_version') == '3'
+    qemu_common_flags = ['-mavx2'] + qemu_common_flags
+  elif get_option('x86_version') == '4'
+    qemu_common_flags = ['-mavx512f', '-mavx512bw', '-mavx512cd', '-mavx512dq', '-mavx512vl'] + qemu_common_flags
+  endif
 endif
 
 if get_option('prefer_static')
diff --git a/meson_options.txt b/meson_options.txt
index 7a79dd89706..6065ed2d352 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -370,3 +370,6 @@ option('qemu_ga_version', type: 'string', value: '',
 
 option('hexagon_idef_parser', type : 'boolean', value : true,
        description: 'use idef-parser to automatically generate TCG code for the Hexagon frontend')
+
+option('x86_version', type : 'combo', choices : ['0', '1', '2', '3', '4'], value: '1',
+       description: 'tweak required x86_64 architecture version beyond compiler default')
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
index 58d49a447d5..62842d47e88 100644
--- a/scripts/meson-buildoptions.sh
+++ b/scripts/meson-buildoptions.sh
@@ -82,6 +82,8 @@ meson_options_help() {
   printf "%s\n" '  --with-suffix=VALUE      Suffix for QEMU data/modules/config directories'
   printf "%s\n" '                           (can be empty) [qemu]'
   printf "%s\n" '  --with-trace-file=VALUE  Trace file prefix for simple backend [trace]'
+  printf "%s\n" '  --x86-version=CHOICE     tweak required x86_64 architecture version beyond'
+  printf "%s\n" '                           compiler default [1] (choices: 0/1/2/3)'
   printf "%s\n" ''
   printf "%s\n" 'Optional features, enabled with --enable-FEATURE and'
   printf "%s\n" 'disabled with --disable-FEATURE, default is enabled if available'
@@ -552,6 +554,7 @@ _meson_option_parse() {
     --disable-werror) printf "%s" -Dwerror=false ;;
     --enable-whpx) printf "%s" -Dwhpx=enabled ;;
     --disable-whpx) printf "%s" -Dwhpx=disabled ;;
+    --x86-version=*) quote_sh "-Dx86_version=$2" ;;
     --enable-xen) printf "%s" -Dxen=enabled ;;
     --disable-xen) printf "%s" -Dxen=disabled ;;
     --enable-xen-pci-passthrough) printf "%s" -Dxen_pci_passthrough=enabled ;;
-- 
2.45.2
Re: [PATCH 4/6] meson: allow configuring the x86-64 baseline
Posted by Richard Henderson 6 months, 1 week ago
On 6/20/24 06:02, Paolo Bonzini wrote:
> Signed-off-by: Paolo Bonzini<pbonzini@redhat.com>
> ---
>   meson.build                   | 41 ++++++++++++++++++++++++++++-------
>   meson_options.txt             |  3 +++
>   scripts/meson-buildoptions.sh |  3 +++
>   3 files changed, 39 insertions(+), 8 deletions(-)

Acked-by: Richard Henderson <richard.henderson@linaro.org>

For -mneeded, we need gcc 11 and for enforcing GNU_PROPERTY_X86_ISA_1_NEEDED we need glibc 
2.33, so:

   debian 12
   fedora 34
   ubuntu 2204
   suse leap 15.6 or tumbleweed.
   centos stream 9

I believe the -mneeded option will be accepted by FreeBSD's clang, but the note will not 
be enforced by the dynamic linker at startup.

However, since this is all optional, requiring an explicit configure option, I don't think 
any of this versioning should stand in the way.


r~
Re: [PATCH 4/6] meson: allow configuring the x86-64 baseline
Posted by Daniel P. Berrangé 6 months, 1 week ago
On Thu, Jun 20, 2024 at 03:02:52PM +0200, Paolo Bonzini wrote:
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  meson.build                   | 41 ++++++++++++++++++++++++++++-------
>  meson_options.txt             |  3 +++
>  scripts/meson-buildoptions.sh |  3 +++
>  3 files changed, 39 insertions(+), 8 deletions(-)
> 
> diff --git a/meson.build b/meson.build
> index 97e00d6f59b..6e694ecd9fe 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -336,15 +336,40 @@ if host_arch == 'i386' and not cc.links('''
>    qemu_common_flags = ['-march=i486'] + qemu_common_flags
>  endif
>  
> -# Assume x86-64-v2 (minus CMPXCHG16B for 32-bit code)
> -if host_arch == 'i386'
> -  qemu_common_flags = ['-mfpmath=sse'] + qemu_common_flags
> -endif
> +# Pick x86-64 baseline version
>  if host_arch in ['i386', 'x86_64']
> -  qemu_common_flags = ['-mpopcnt', '-msse4.2'] + qemu_common_flags
> -endif
> -if host_arch == 'x86_64'
> -  qemu_common_flags = ['-mcx16'] + qemu_common_flags
> +  if get_option('x86_version') == '0' and host_arch == 'x86_64'
> +    error('x86_64-v1 required for x86-64 hosts')
> +  endif
> +
> +  # add flags for individual instruction set extensions
> +  if get_option('x86_version') >= '1'
> +    if host_arch == 'i386'
> +      qemu_common_flags = ['-mfpmath=sse'] + qemu_common_flags
> +    else
> +      # present on basically all processors but technically not part of
> +      # x86-64-v1, so only include -mneeded for x86-64 version 2 and above
> +      qemu_common_flags = ['-mcx16'] + qemu_common_flags
> +    endif
> +  endif
> +  if get_option('x86_version') >= '2'
> +    qemu_common_flags = ['-mpopcnt'] + qemu_common_flags
> +    qemu_common_flags = cc.get_supported_arguments('-mneeded') + qemu_common_flags
> +  endif
> +  if get_option('x86_version') >= '3'
> +    qemu_common_flags = ['-mmovbe', '-mabm', '-mbmi1', '-mbmi2', '-mfma', '-mf16c'] + qemu_common_flags
> +  endif
> +
> +  # add required vector instruction set (each level implies those below)
> +  if get_option('x86_version') == '1'
> +    qemu_common_flags = ['-msse2'] + qemu_common_flags
> +  elif get_option('x86_version') == '2'
> +    qemu_common_flags = ['-msse4.2'] + qemu_common_flags
> +  elif get_option('x86_version') == '3'
> +    qemu_common_flags = ['-mavx2'] + qemu_common_flags
> +  elif get_option('x86_version') == '4'
> +    qemu_common_flags = ['-mavx512f', '-mavx512bw', '-mavx512cd', '-mavx512dq', '-mavx512vl'] + qemu_common_flags
> +  endif
>  endif


Any particular reason you chose to list various instructions individually
rather than just ask GCC for the full ABI ? I'd think all of the above
condences down to just

  # add flags for individual instruction set extensions
  if get_option('x86_version') >= '1'
    if host_arch == 'i386'
      qemu_common_flags = ['-mfpmath=sse'] + qemu_common_flags
    else
      # present on basically all processors but technically not part of
      # x86-64-v1, so only include -mneeded for x86-64 version 2 and above
      qemu_common_flags = ['-mcx16'] + qemu_common_flags
    endif
  endif
  if get_option('x86_version') >= '2'
    qemu_common_flags = ['-march=x86-64-v' + get_option('x86_version'), '-mneeded'] + qemu_common_flags
  endif


With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|
Re: [PATCH 4/6] meson: allow configuring the x86-64 baseline
Posted by Paolo Bonzini 6 months, 1 week ago
On Thu, Jun 20, 2024 at 4:55 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
> Any particular reason you chose to list various instructions individually
> rather than just ask GCC for the full ABI ? I'd think all of the above
> condences down to just

To avoid that the default ('1') forces a lower level than the compiler default.

Something like what you propose below could work by adding a 'default'
value to the x86_version option, that leaves the flags entirely alone
apart from -mcx16.

However, doing so would prevent QEMU from changing the default to
x86-64-v2 in meson_options.txt, because then even a compiler that
defaults to x86-64-v3 would build a QEMU with AVX2 disabled.

For AVX2 specifically this is not a huge deal because the decision to
use AVX2 code is mostly done at runtime; but it would be a problem for
future integer instruction set extensions---for example if the distro
compiler uses APX you don't want to disable it.

>   # add flags for individual instruction set extensions
>   if get_option('x86_version') >= '1'
>     if host_arch == 'i386'
>       qemu_common_flags = ['-mfpmath=sse'] + qemu_common_flags

Also -msse2 here, but yes.

Paolo