From cfb6b026191eea8e703dcd0aa208dab3c5bef763 Mon Sep 17 00:00:00 2001 From: Dawid Wesierski Date: Wed, 1 Jul 2026 10:36:54 -0400 Subject: [PATCH] Fix: avx512 crash during loading mtl plugins Disable the -march=native flag in dpdk, so the compiler doesn't assume that the host CPU supports AVX512 instructions. --- ...ig-add-mtl-version-to-version-string.patch | 2 +- ...fault-cpu_instruction_set-to-generic.patch | 49 +++++++++++++ .../gstreamer/avx512_compat/__init__.py | 0 .../gstreamer/avx512_compat/conftest.py | 52 ++++++++++++++ .../avx512_compat/test_avx512_compat.py | 72 +++++++++++++++++++ versions.env | 2 +- 6 files changed, 175 insertions(+), 2 deletions(-) create mode 100644 patches/dpdk/26.03/0009-config-default-cpu_instruction_set-to-generic.patch create mode 100644 tests/validation/tests/single/gstreamer/avx512_compat/__init__.py create mode 100644 tests/validation/tests/single/gstreamer/avx512_compat/conftest.py create mode 100644 tests/validation/tests/single/gstreamer/avx512_compat/test_avx512_compat.py diff --git a/patches/dpdk/26.03/0007-config-add-mtl-version-to-version-string.patch b/patches/dpdk/26.03/0007-config-add-mtl-version-to-version-string.patch index 2f842c8c4..b95318980 100644 --- a/patches/dpdk/26.03/0007-config-add-mtl-version-to-version-string.patch +++ b/patches/dpdk/26.03/0007-config-add-mtl-version-to-version-string.patch @@ -24,7 +24,7 @@ index 98035c1..7527942 100644 +++ b/VERSION @@ -1 +1 @@ -26.03.0 -+26.03.90_mtl_ ++26.03.92_mtl_ diff --git a/config/meson.build b/config/meson.build index 9ba7b9a..0d59d76 100644 --- a/config/meson.build diff --git a/patches/dpdk/26.03/0009-config-default-cpu_instruction_set-to-generic.patch b/patches/dpdk/26.03/0009-config-default-cpu_instruction_set-to-generic.patch new file mode 100644 index 000000000..823ba695c --- /dev/null +++ b/patches/dpdk/26.03/0009-config-default-cpu_instruction_set-to-generic.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MTL +Date: Wed, 1 Jul 2026 00:00:00 -0400 +Subject: [PATCH] config: default cpu_instruction_set to generic instead of + native + +Building DPDK with the implicit 'auto' -> 'native' default bakes the +build host's full ISA (e.g. AVX-512) into ELF init constructors such as +dummy_queue_init() in librte_ethdev. Those constructors run at +dlopen()/exec time, before any of DPDK's own runtime CPU dispatch +(rte_cpu_get_flag_enabled(), compile_time_cpuflags) can gate on it, so +a shared library or app built on an AVX-512 host raises SIGILL the +moment it is loaded on any narrower target CPU -- this hit MTL's +GStreamer plugins when loaded via gst-inspect-1.0 on a non-AVX-512 +host/VM (see .github/avx512_crash.md). + +Default 'auto' to 'generic' (the portable per-arch baseline DPDK +already supports, e.g. 'corei7' on x86) instead of 'native'. This does +not remove AVX-512/AVX2 support: DPDK's own runtime CPU dispatch still +selects those code paths where it explicitly checks for them. Callers +that want the old native-optimized build can still opt back in with +-Dcpu_instruction_set=native. + +Signed-off-by: MTL +--- + config/meson.build | 8 +++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/config/meson.build b/config/meson.build +--- a/config/meson.build ++++ b/config/meson.build +@@ -132,7 +132,14 @@ else + endif + if platform == 'native' + if cpu_instruction_set == 'auto' +- cpu_instruction_set = 'native' ++ # MTL: default 'auto' to the portable 'generic' baseline rather ++ # than 'native'. -march=native bakes the build host's full ISA ++ # (e.g. AVX-512) into ELF init constructors that run before any ++ # runtime CPU dispatch can gate on it, crashing with SIGILL on ++ # narrower target CPUs. Runtime dispatch still selects AVX2/ ++ # AVX-512 code paths where DPDK explicitly checks for them. ++ # Pass -Dcpu_instruction_set=native to opt back in. ++ cpu_instruction_set = 'generic' + endif + endif + endif +-- +2.47.3 diff --git a/tests/validation/tests/single/gstreamer/avx512_compat/__init__.py b/tests/validation/tests/single/gstreamer/avx512_compat/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/validation/tests/single/gstreamer/avx512_compat/conftest.py b/tests/validation/tests/single/gstreamer/avx512_compat/conftest.py new file mode 100644 index 000000000..3e42044fd --- /dev/null +++ b/tests/validation/tests/single/gstreamer/avx512_compat/conftest.py @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2026 Intel Corporation +"""Shared fixtures for avx512_compat tests. + +These tests emulate a non-AVX-512 host via ``qemu-x86_64-static`` to catch +init-time SIGILL crashes caused by DPDK being built with an ISA baseline +that is wider than the CPU it eventually runs on (see +``.github/avx512_crash.md``). qemu-user is an optional resource: skip +cleanly instead of failing the suite when it cannot be made available. +""" +from __future__ import annotations + +import pytest + +QEMU_CACHE_PATH = "/tmp/mtl_validation_qemu-x86_64-static" +QEMU_DOWNLOAD_URL = ( + "https://github.com/multiarch/qemu-user-static/releases/download/" + "v7.2.0-1/qemu-x86_64-static" +) + + +@pytest.fixture(scope="session") +def qemu_x86_64_static(hosts): + """Return a path to a runnable ``qemu-x86_64-static`` binary, or skip.""" + host = list(hosts.values())[0] + + found = host.connection.execute_command( + "command -v qemu-x86_64-static", shell=True, expected_return_codes=None + ) + if found.return_code == 0 and found.stdout.strip(): + return found.stdout.strip() + + cached = host.connection.execute_command( + f"test -x {QEMU_CACHE_PATH}", shell=True, expected_return_codes=None + ) + if cached.return_code == 0: + return QEMU_CACHE_PATH + + downloaded = host.connection.execute_command( + f"curl -fsSL -o {QEMU_CACHE_PATH} {QEMU_DOWNLOAD_URL} " + f"&& chmod +x {QEMU_CACHE_PATH}", + shell=True, + expected_return_codes=None, + ) + if downloaded.return_code == 0: + return QEMU_CACHE_PATH + + pytest.skip( + "qemu-x86_64-static unavailable (not on PATH and download failed) - " + "install the 'qemu-user-static' package or see .github/avx512_crash.md " + "for a manual download command" + ) diff --git a/tests/validation/tests/single/gstreamer/avx512_compat/test_avx512_compat.py b/tests/validation/tests/single/gstreamer/avx512_compat/test_avx512_compat.py new file mode 100644 index 000000000..4f0555cfc --- /dev/null +++ b/tests/validation/tests/single/gstreamer/avx512_compat/test_avx512_compat.py @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2026 Intel Corporation +"""GStreamer plugin AVX-512 compatibility. + +Regression test for the crash described in ``.github/avx512_crash.md``: +DPDK built with an ISA baseline wider than the target CPU bakes AVX-512 +instructions into ELF constructors (e.g. ``dummy_queue_init`` in +``librte_ethdev.so``) that run unconditionally at ``dlopen()`` time, +crashing with SIGILL on hosts/VMs that lack AVX-512 -- with no way for +MTL's own runtime SIMD dispatch to intervene, since the crash happens +before any MTL code runs. + +The non-AVX-512 host is emulated locally with ``qemu-x86_64-static`` using +``QEMU_CPU=Skylake-Client`` (AVX2, no AVX-512; also satisfies glibc's +x86-64-v2 baseline, unlike older QEMU CPU models such as ``qemu64``). +""" + +import pytest +from mtl_engine.execute import log_fail + +GSTREAMER_PLUGINS = [ + "libgstmtl_st20p_rx.so", + "libgstmtl_st20p_tx.so", + "libgstmtl_st30p_rx.so", + "libgstmtl_st30p_tx.so", + "libgstmtl_st40p_rx.so", + "libgstmtl_st40p_tx.so", + "libgstmtl_st40_rx.so", +] + + +@pytest.mark.smoke +@pytest.mark.parametrize("plugin", GSTREAMER_PLUGINS) +def test_gstreamer_plugin_avx512_compat(hosts, mtl_path, qemu_x86_64_static, plugin): + host = list(hosts.values())[0] + plugin_path = f"{mtl_path}/.local_install/gstreamer/gstreamer-1.0/{plugin}" + ld_library_path = ( + f"{mtl_path}/.local_install/mtl/lib64:" f"{mtl_path}/.local_install/dpdk/lib64" + ) + + if ( + host.connection.execute_command( + f"test -f {plugin_path}", shell=True, expected_return_codes=None + ).return_code + != 0 + ): + pytest.skip(f"GStreamer plugin not built: {plugin_path}") + + native = host.connection.execute_command( + f"LD_LIBRARY_PATH={ld_library_path} gst-inspect-1.0 {plugin_path}", + shell=True, + expected_return_codes=None, + ) + if native.return_code != 0: + log_fail(f"Native gst-inspect-1.0 failed for {plugin}: {native.stdout}") + assert native.return_code == 0, f"Native load of {plugin} failed unexpectedly" + + emulated = host.connection.execute_command( + f"LD_LIBRARY_PATH={ld_library_path} QEMU_CPU=Skylake-Client " + f"{qemu_x86_64_static} $(command -v gst-inspect-1.0) {plugin_path}", + shell=True, + expected_return_codes=None, + ) + if emulated.return_code != 0: + log_fail( + f"{plugin} crashed under emulated non-AVX-512 CPU " + f"(rc={emulated.return_code}): {emulated.stdout}" + ) + assert emulated.return_code == 0, ( + f"{plugin} must load on a non-AVX-512 CPU without SIGILL " + f"(rc={emulated.return_code}, expected 132 before the DPDK ISA-baseline fix)" + ) diff --git a/versions.env b/versions.env index db4a5e41a..100e2d9ad 100644 --- a/versions.env +++ b/versions.env @@ -1,5 +1,5 @@ DPDK_VER=26.03 -DPDK_MTL_MINOR_VER=90 +DPDK_MTL_MINOR_VER=92 ICE_VER=2.6.6 ICE_DMID=921605 ONE_API_GPU_VER=1.22.3