# Disable automatic debuginfo generation to avoid conflicts %global debug_package %{nil} # GitHub archive tarball from tag v%%{version} extracts to mvgal-v%%{version}/ %global ghdir mvgal-v%{version} # DKMS package support - build optional %bcond_without dkms # RHEL 8 / GCC 8 LTO: handled at the cmake level (src/userspace/CMakeLists.txt) # by building libmvgal_core.a objects with -fno-lto, so the LTO plugin never # encounters bytecode it can't process from the static archive. Name: mvgal Version: 0.7.21 Release: 1%{?dist} Summary: Multi-Vendor GPU Aggregation Layer for Linux License: GPL-3.0-only URL: https://github.com/TheCreateGM/mvgal # Source from GitHub archive Source0: https://github.com/TheCreateGM/mvgal/archive/refs/tags/v%{version}.tar.gz # Vendored Rust dependencies for offline COPR builds (no network access) # OpenCL support is conditional - enable by default, disable with --without opencl %bcond_without opencl # Qt GUI dashboard - build by default, disable when Qt not available # (e.g. Amazon Linux 2023 where Qt is in SPAL, not in base COPR mock) %bcond_without qt_gui BuildRequires: gcc BuildRequires: gcc-c++ BuildRequires: make BuildRequires: cmake >= 3.20 %if 0%{?suse_version} BuildRequires: ninja %else BuildRequires: ninja-build %endif BuildRequires: libdrm-devel BuildRequires: systemd-devel BuildRequires: pciutils-devel BuildRequires: pkgconfig(pciaccess) BuildRequires: vulkan-headers BuildRequires: pkgconfig(vulkan) BuildRequires: opencl-headers BuildRequires: ocl-icd-devel BuildRequires: rust BuildRequires: cargo BuildRequires: kernel-devel # Needed to generate the module signing key pair (BUG #2) BuildRequires: openssl # Needed to compile the shipped sign-file utility (BUG #2 follow-up) BuildRequires: openssl-devel # Qt for mvgal-gui dashboard (Qt6 on modern distros, Qt5 on older) # Use pkgconfig() virtual provides for cross-distro compatibility # Qt6: Fedora, RHEL 10+, openSUSE Tumbleweed, Arch # Qt5: RHEL 8/9, CentOS Stream 8/9, openSUSE Leap, Mageia # Amazon Linux 2023: Qt6 in SPAL only (not available in COPR mock), no Qt5 at all %if %{with qt_gui} %if ! 0%{?amzn} %if 0%{?rhel} >= 10 || 0%{?fedora} || 0%{?suse_version} >= 1600 BuildRequires: pkgconfig(Qt6Core) pkgconfig(Qt6Widgets) pkgconfig(Qt6Network) %else BuildRequires: pkgconfig(Qt5Core) pkgconfig(Qt5Widgets) pkgconfig(Qt5Network) %endif %endif %endif %if 0%{?rhel} == 8 # ORC unwinder needs libelf for kernel module build BuildRequires: elfutils-libelf-devel %endif # DKMS support - optional %if %{with dkms} BuildRequires: dkms %endif Requires: libdrm Requires: systemd # %post generates a per-machine module-signing keypair with openssl Requires: openssl %if 0%{?suse_version} Requires: libvulkan1 %else %if 0%{?mageia} Requires: lib64vulkan-loader1 %else Requires: vulkan-loader %endif %endif Obsoletes: mvgallibs <= 0.1.0 Provides: libmvgal = %{version} # OpenCL ICD aggregation needs at least one real vendor OpenCL # implementation installed, otherwise the MVGAL OpenCL ICD reports # zero platforms (test report BUG #6). intel-compute-runtime is the # portable choice (Intel + AMD via oneAPI); it is a soft dependency so # installs still succeed on distros without it. Recommends: intel-compute-runtime # Note: If you have Moore Threads (MTT) GPU drivers installed and see # ldconfig warnings like "/lib64/libmupp*.so.1 is not a symbolic link", # those are caused by a packaging issue in the MTT driver itself - the # .so.1 files are regular files instead of symlinks to versioned libraries. # This is unrelated to MVGAL. Contact Moore Threads or your distro packager # to fix the MTT driver package. # NOTE: the configuration file this package installs is # %{_sysconfdir}/mvgal/mvgal.conf, taken from the source tree at # config/mvgal.conf. There used to be a second, divergent copy at # packaging/rpm/mvgal.conf with a different schema ([general]/[gpus]/[daemon] # instead of [core]/[gpu_N]/...); it was never installed by this spec, so it # silently drifted and any edit made to it had no effect. It has been # removed. If you are editing configuration, edit config/mvgal.conf in the # source tree (or /etc/mvgal/mvgal.conf on an installed system). %description MVGAL (Multi-Vendor GPU Aggregation Layer) enables heterogeneous GPUs (AMD, NVIDIA, Intel, Moore Threads) to function as a single logical compute and rendering device. Features: - Unified abstraction for multiple GPUs - Smart scheduling with AFR, SFR, and Hybrid strategies - DMA-BUF based cross-GPU memory management - Vulkan layer for transparent API interception - OpenCL and CUDA support (experimental) - Daemon for background GPU management %package -n mvgal-user-space Summary: Userspace libraries and daemon for MVGAL Requires: %{name} = %{version}-%{release} Requires: %{name}-dkms = %{version}-%{release} Requires: libdrm Requires: systemd Requires: vulkan-loader %description -n mvgal-user-space Metapackage for MVGAL userspace with DKMS-based kernel module rebuilds. Pulls in the main %{name} package (userspace, daemon, CLI) plus %{name}-dkms for automatic kernel module rebuilds on kernel updates. %package -n mvgal-dkms Summary: DKMS kernel modules for MVGAL %if %{with dkms} Requires: dkms %endif Requires: kernel-devel %if %{with dkms} BuildRequires: dkms %endif %description -n mvgal-dkms DKMS-based kernel modules for MVGAL that provide DMA-BUF P2P memory sharing, page-table grafting, and kernel-level synchronization. Supports AMD, NVIDIA, Intel, and Moore Threads GPUs. %prep %setup -q -n mvgal-v%{version} # Vendored Rust dependencies for offline cargo builds (in git vendor/) mkdir -p .cargo cat > .cargo/config.toml << 'EOF' [source.crates-io] replace-with = "vendored-sources" [source.vendored-sources] directory = "vendor" EOF %build # Find kernel build directory for kernel module (kernel-devel provides one # entry in /lib/modules//build or /usr/src/kernels/ in mock/COPR # chroots). The /lib/modules//build symlink is only present when the # kernel meta-package is installed; kernel-devel alone puts headers under # /usr/src/kernels/. Mageia uses /usr/src/linux-. # Search all known paths using shell variable expansion. KERNEL_BUILD_DIR="" for _d in /lib/modules/[0-9]*/build /usr/lib/modules/[0-9]*/build /usr/src/kernels/[0-9]* /usr/src/linux-[0-9]*; do [ -d "$_d" ] && { KERNEL_BUILD_DIR="$_d"; break; } done %if 0%{?rhel} == 8 # cmake-rpm-macros on RHEL 8 (cmake 3.26 EPEL) has broken %%cmake macro # that emits "does in-source builds." as literal arguments. # Invoke cmake directly instead, then strip -flto for GCC 8. cmake \ -DCMAKE_C_FLAGS_RELEASE:STRING=-DNDEBUG \ -DCMAKE_CXX_FLAGS_RELEASE:STRING=-DNDEBUG \ -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \ -DCMAKE_INSTALL_PREFIX:PATH=%{_prefix} \ -DINCLUDE_INSTALL_DIR:PATH=%{_includedir} \ -DLIB_INSTALL_DIR:PATH=%{_libdir} \ -DSYSCONF_INSTALL_DIR:PATH=%{_sysconfdir} \ -DSHARE_INSTALL_PREFIX:PATH=%{_datadir} \ -DLIB_SUFFIX=64 \ -DBUILD_SHARED_LIBS:BOOL=ON \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_LIBDIR=%{_libdir} \ -DMVGAL_BUILD_KERNEL=ON \ -DKERNEL_HEADERS:PATH="${KERNEL_BUILD_DIR}" \ -DMVGAL_BUILD_RUNTIME=ON \ -DMVGAL_BUILD_API=ON \ -DMVGAL_BUILD_TOOLS=ON \ -DMVGAL_BUILD_TESTS=OFF \ -DMVGAL_ENABLE_RUST=ON \ -DMVGAL_BUILD_GAMING=ON \ -DMVGAL_BUILD_REPRODUCIBLE_BUILD=OFF \ %if %{with qt_gui} %if ! 0%{?amzn} -DMVGAL_BUILD_UI=ON %endif %endif # RHEL 8 / GCC 8: strip -flto from cmake-generated build files. # Use individual find commands (no \(\)) to avoid RHEL 8 RPM parser bug. # Use . because RHEL 8 cmake does in-source builds. find . -type f -name 'flags.make' -exec sed -i 's/-flto[^ ]*//g' {} \; 2>/dev/null || : find . -type f -name 'build.make' -exec sed -i 's/-flto[^ ]*//g' {} \; 2>/dev/null || : find . -type f -name '*.link.txt' -exec sed -i 's/-flto[^ ]*//g' {} \; 2>/dev/null || : find . -type f -name '*.rsp' -exec sed -i 's/-flto[^ ]*//g' {} \; 2>/dev/null || : %else %cmake \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_LIBDIR=%{_libdir} \ -DMVGAL_BUILD_KERNEL=ON \ -DKERNEL_HEADERS:PATH="${KERNEL_BUILD_DIR}" \ -DMVGAL_BUILD_RUNTIME=ON \ -DMVGAL_BUILD_API=ON \ -DMVGAL_BUILD_TOOLS=ON \ -DMVGAL_BUILD_TESTS=OFF \ -DMVGAL_ENABLE_RUST=ON \ -DMVGAL_BUILD_GAMING=ON \ -DMVGAL_BUILD_REPRODUCIBLE_BUILD=OFF \ %if %{with qt_gui} %if ! 0%{?amzn} -DMVGAL_BUILD_UI=ON %endif %endif %endif %cmake_build %install rm -rf %{buildroot} %cmake_install # cmake --install places mvgal-pkexec-helper.sh at %{_libexecdir}/mvgal/ but # the spec %files expects it at %{_prefix}/lib/mvgal/. Remove the cmake- # installed copy and install manually to the expected location. rm -f %{buildroot}%{_libexecdir}/mvgal/mvgal-pkexec-helper.sh install -d %{buildroot}%{_prefix}/lib/mvgal install -m 755 %{_builddir}/%{ghdir}/config/mvgal-pkexec-helper.sh \ %{buildroot}%{_prefix}/lib/mvgal/mvgal-pkexec-helper.sh # mtt-dkms-installer.sh: installed by cmake to %{_datadir}/mvgal/scripts/ # Secure Boot MOK enrollment helper (BUG #2) install -m 755 %{_builddir}/%{ghdir}/config/mvgal-enroll-mok.sh \ %{buildroot}%{_bindir}/mvgal-enroll-mok # cmake --install places kernel module at a machine-specific path under # BUILDROOT (e.g. $BUILDROOT/build-dir/lib/modules/...) instead of the # canonical /usr/lib/modules/. Remove all cmake-installed .ko from # BUILDROOT here so only the manually-placed ones in /usr/lib/modules/ # (see below) survive. The %{_builddir} cleanup is done AFTER the # install loop below (we need the source-tree .ko files to copy first). find %{buildroot} -name '*.ko' -delete 2>/dev/null || : # Install kernel modules (built by cmake mvgal-kernel custom target) # The multi-module Kbuild produces: mvgal.ko, mvgal_ntsync.ko, # and vendor modules (mvgal_nvidia.ko, mvgal_amd.ko, mvgal_intel.ko). # kernel-devel provides one entry in /lib/modules/ or /usr/src/kernels/ in COPR # mock chroots. The /lib/modules//build symlink is only present when the # kernel meta-package is installed; kernel-devel alone puts headers under # /usr/src/kernels/. Mageia uses /usr/src/linux-. # Search all known paths using shell variable expansion. KERNEL_RELEASE="" for _d in /lib/modules/[0-9]* /usr/lib/modules/[0-9]* /usr/src/kernels/[0-9]* /usr/src/linux-[0-9]*; do [ -d "$_d" ] && { KERNEL_RELEASE=$(basename "$_d"); break; } done # Generate file list for kernel modules so we can use %files -f # (files-list approach instead of glob because Mageia's RPM errors on # unmatched %files globs when kernel-devel is unavailable — the glob # %{_prefix}/lib/modules/*/... has nothing to match) rm -f %{_builddir}/kernel-module.list if [ -n "$KERNEL_RELEASE" ]; then MODULE_DIR="%{buildroot}%{_prefix}/lib/modules/${KERNEL_RELEASE}/kernel/drivers/gpu/drm/mvgal" install -d "$MODULE_DIR" for ko in "%{_builddir}/%{ghdir}/kernel/"*.ko; do [ -f "$ko" ] || continue install -m 644 "$ko" "$MODULE_DIR/" echo "%%{_prefix}/lib/modules/${KERNEL_RELEASE}/kernel/drivers/gpu/drm/mvgal/$(basename $ko)" >> %{_builddir}/kernel-module.list done fi # SECURITY FIX (test report C2): never ship a module-signing private key. # The private key now lives only on the target machine, generated by the # %post script under /var/lib/mvgal/keys/ (mode 0700 dir, 0600 key). The # public certificate is generated next to it so the user can enroll it in # the firmware MOK database with mvgal-enroll-mok. # # We still compile the kernel's sign-file utility here (kernel-devel is # available in the build chroot but usually not on the target) and ship it, # because rpm's brp-strip would otherwise drop any signature appended at # build time anyway — the target-side %post re-signs the installed modules. install -d -m 0755 %{buildroot}%{_prefix}/lib/mvgal if [ -n "$KERNEL_RELEASE" ]; then # BUG #2 follow-up: rpm's brp-strip runs 'strip -g' on every unstripped # ELF after the install phase and DROPS the appended module signature, # so modules signed above arrive at the target unsigned. Compile the # kernel's sign-file utility and ship it so the post-install script can # re-sign the installed modules on the target (no kernel-devel there). SIGN_FILE_SRC="" for _sf in \ "/usr/src/kernels/${KERNEL_RELEASE}/scripts/sign-file.c" \ "/usr/src/linux-${KERNEL_RELEASE}/scripts/sign-file.c" \ "/usr/lib/modules/${KERNEL_RELEASE}/build/scripts/sign-file.c" \ "/lib/modules/${KERNEL_RELEASE}/build/scripts/sign-file.c"; do [ -f "$_sf" ] && { SIGN_FILE_SRC="$_sf"; break; } done if [ -n "$SIGN_FILE_SRC" ]; then gcc -O2 -o "%{buildroot}%{_prefix}/lib/mvgal/sign-file" \ "$SIGN_FILE_SRC" -lcrypto 2>/dev/null || : [ -x "%{buildroot}%{_prefix}/lib/mvgal/sign-file" ] || \ rm -f "%{buildroot}%{_prefix}/lib/mvgal/sign-file" fi fi # Clean up .ko files from %{_builddir} now that they've been copied to # BUILDROOT (cmake --install placed them in the source tree on some chroots). find %{_builddir}/%{ghdir} -name '*.ko' -delete 2>/dev/null || : if [ ! -s %{_builddir}/kernel-module.list ]; then # No kernel-devel in this chroot (e.g. Mageia Cauldron) — create file list # with a %dir anchor for a directory we always own, so the -f file is # never empty (Mageia's RPM rejects empty %files -f files entirely). echo "%%dir %%{_prefix}/lib/mvgal" > %{_builddir}/kernel-module.list fi # Conditional sign-file entry: some chroots (Mageia 9) lack scripts/sign-file.c # under the kernel-devel paths above, so the utility is not built there. # Hard-coding it in %%files broke those builds ("File not found") — list it # dynamically instead. if [ -x "%{buildroot}%{_prefix}/lib/mvgal/sign-file" ]; then echo "%{_prefix}/lib/mvgal/sign-file" >> %{_builddir}/kernel-module.list fi # Install DKMS source tree to /usr/src/mvgal-{version}/ # This allows dkms to rebuild modules on kernel updates. # The dkms.conf at the root references MAKE[0]="make -C kernel ..." # and the Kbuild uses -I$(src)/../include for UAPI headers. DKMS_SRC_DIR="%{buildroot}%{_prefix}/src/mvgal-%{version}" install -d "${DKMS_SRC_DIR}/kernel" "${DKMS_SRC_DIR}/include" # Copy kernel module source (exclude build artifacts) cp -a %{_builddir}/%{ghdir}/kernel/Kbuild "${DKMS_SRC_DIR}/kernel/" cp -a %{_builddir}/%{ghdir}/kernel/Makefile "${DKMS_SRC_DIR}/kernel/" cp -a %{_builddir}/%{ghdir}/kernel/*.c "${DKMS_SRC_DIR}/kernel/" cp -a %{_builddir}/%{ghdir}/kernel/*.h "${DKMS_SRC_DIR}/kernel/" # Vendor modules if [ -d "%{_builddir}/%{ghdir}/kernel/vendors" ]; then cp -a %{_builddir}/%{ghdir}/kernel/vendors "${DKMS_SRC_DIR}/kernel/" fi # DKMS subdirectory (extra dkms.conf variants) if [ -d "%{_builddir}/%{ghdir}/kernel/dkms" ]; then cp -a %{_builddir}/%{ghdir}/kernel/dkms "${DKMS_SRC_DIR}/kernel/" fi # UAPI headers (referenced by Kbuild: ccflags-y += -I$(src)/../include) if [ -d "%{_builddir}/%{ghdir}/include" ]; then cp -a %{_builddir}/%{ghdir}/include/* "${DKMS_SRC_DIR}/include/" fi # Install dkms.conf at the root of the DKMS source tree with correct version # Match any PACKAGE_VERSION (not just a hardcoded one) so the version is # always synced to %{version} regardless of the source file's value. sed "s/^PACKAGE_VERSION=.*/PACKAGE_VERSION=\"%{version}\"/" \ %{_builddir}/%{ghdir}/kernel/dkms/dkms.conf > "${DKMS_SRC_DIR}/dkms.conf" # Install load/unload scripts if cmake didn't (skipped when kernel/CMakeLists.txt # returns early, e.g. kernel headers not found for target kernel on openSUSE # Tumbleweed or other chroots where cmake's find_path fails) if [ ! -f "%{buildroot}%{_bindir}/mvgal-load" ] && [ -f "%{_builddir}/%{ghdir}/config/load-module.sh" ]; then install -m 755 "%{_builddir}/%{ghdir}/config/load-module.sh" \ "%{buildroot}%{_bindir}/mvgal-load" fi if [ ! -f "%{buildroot}%{_bindir}/mvgal-unload" ] && [ -f "%{_builddir}/%{ghdir}/config/unload-module.sh" ]; then install -m 755 "%{_builddir}/%{ghdir}/config/unload-module.sh" \ "%{buildroot}%{_bindir}/mvgal-unload" fi # Shared kernel-module inventory, sourced by mvgal-load, mvgal-unload and # mvgal-pkexec-helper.sh. Install unconditionally (not only as a cmake # fallback): it is a data file the three scripts depend on, and a missing copy # makes them fall back to divergent built-in lists. if [ -f "%{_builddir}/%{ghdir}/config/mvgal-modules.sh" ]; then install -d %{buildroot}%{_prefix}/lib/mvgal install -m 644 "%{_builddir}/%{ghdir}/config/mvgal-modules.sh" \ "%{buildroot}%{_prefix}/lib/mvgal/modules.sh" fi # Install config file install -d %{buildroot}%{_sysconfdir}/mvgal install -m 644 %{_builddir}/%{ghdir}/config/mvgal.conf %{buildroot}%{_sysconfdir}/mvgal/mvgal.conf # Custom strategy stub: mvgal.conf [custom] script_path references # /etc/mvgal/custom_strategy.lua; ship a no-op stub so the path always exists. install -m 644 %{_builddir}/%{ghdir}/config/custom_strategy.lua \ %{buildroot}%{_sysconfdir}/mvgal/custom_strategy.lua # Placeholder dir for optional AI scheduler model (M3: config references # /etc/mvgal/models/scheduler.onnx; feature disabled by default, but the # directory exists so users have a documented place to drop a model). install -d %{buildroot}%{_sysconfdir}/mvgal/models # Steam profile dir (test report L7): the daemon's SteamProfileLoader logs # "directory not found: /etc/mvgal/steam_profiles" on every start when this # directory is missing. Ship it so the warning disappears. install -d %{buildroot}%{_sysconfdir}/mvgal/steam_profiles # Install kernel module auto-load config (loads mvgal + mvgal_ntsync on boot). # Conditional: append to kernel-module.list so %%files -f picks it up only when # the file exists in the source tarball. Without this, a stale cached tarball # (COPR-dist-git) that lacks the file causes rpmbuild to fail at SRPM creation # because %%files unconditionally requires it. install -d %{buildroot}%{_prefix}/lib/modules-load.d if [ -f "%{_builddir}/%{ghdir}/config/modules-load.d/mvgal.conf" ]; then install -m 644 %{_builddir}/%{ghdir}/config/modules-load.d/mvgal.conf \ %{buildroot}%{_prefix}/lib/modules-load.d/mvgal.conf fi # Install systemd service file install -d %{buildroot}%{_unitdir} install -m 644 %{_builddir}/%{ghdir}/packaging/rpm/mvgal-daemon.service %{buildroot}%{_unitdir}/mvgal-daemon.service # Install D-Bus policy file install -d %{buildroot}%{_sysconfdir}/dbus-1/system.d install -m 644 %{_builddir}/%{ghdir}/config/org.mvgal.MVGAL.conf %{buildroot}%{_sysconfdir}/dbus-1/system.d/org.mvgal.MVGAL.conf # NOTE: the stale data/mvgal-dbus.conf (com.mvgal.Daemon) and # data/com.mvgal.service are intentionally NOT installed. The daemon # registers org.mvgal.MVGAL, and only org.mvgal.MVGAL.conf is valid. # Install PolicyKit policy for MVGAL daemon actions install -d %{buildroot}%{_datadir}/polkit-1/actions install -m 644 %{_builddir}/%{ghdir}/data/com.mvgal.policy \ %{buildroot}%{_datadir}/polkit-1/actions/com.mvgal.policy # Build and install GameMode realtime library (gamemode/ not in cmake build chain) install -d %{buildroot}%{_prefix}/lib/gamemode gcc -shared -fPIC -o %{buildroot}%{_prefix}/lib/gamemode/libmvgal_realtime.so \ %{_builddir}/%{ghdir}/gamemode/mvgal_realtime.c \ -I%{_builddir}/%{ghdir}/include \ -L%{buildroot}%{_libdir} -lmvgal -ldl # Install OpenCL ICD registration file (ocl-icd loader reads this at runtime) %if %{with opencl} install -d %{buildroot}%{_sysconfdir}/OpenCL/vendors echo "%{_libdir}/libmvgal_opencl.so" > %{buildroot}%{_sysconfdir}/OpenCL/vendors/mvgal.icd %endif # ISSUE #13 FIX: do NOT ship an /etc/ld.so.conf.d/mvgal.conf fragment. # %{_libdir} is already in the default linker search path on Fedora/RHEL and # the %post ldconfig run keeps libmvgal.so.* resolvable. # Create log directory (owned by package) install -d -m 0755 %{buildroot}%{_localstatedir}/log/mvgal # Daemon binary symlink: systemd unit expects 'mvgal-daemon.service' but the # cmake build produces 'mvgald'. Create a symlink for compatibility. ln -sf mvgald %{buildroot}%{_bindir}/mvgal-daemon %post # ldconfig - update the dynamic linker cache for libmvgal.so.* # Using /sbin/ldconfig directly here (not the macro) so we can also # handle the runtime directory creation in the same scriptlet. # The ldconfig_scriptlets macro would generate a separate post -p /sbin/ldconfig # which conflicts with our custom post; instead we call ldconfig explicitly. /sbin/ldconfig 2>&1 | grep -v "is not a symbolic link" || true # Create runtime directory (tmpfiles.d would be cleaner but this works # across all supported distros without extra dependencies) install -d -m 0755 /var/run/mvgal 2>/dev/null || true install -d -m 0755 /var/log/mvgal 2>/dev/null || true # Remove the globally-registered Vulkan ICD manifest left behind by mvgal # <= 0.7.12. The ICD reports zero physical devices, so registering it in # vulkan/icd.d makes the Vulkan loader print "Cannot query ICD interface # function vkGetPhysicalDeviceDisplayPropertiesKHR, # vkGetPhysicalDeviceDisplayPlanePropertiesKHR in ICD N. The ICD is not # conformant." for every Vulkan application on the system, on every start. # The manifest is still shipped, in the opt-in location # /usr/share/vulkan/mvgal/mvgal_icd.json — source # /usr/share/mvgal/scripts/mvgal-vulkan-env.sh to use it. Only remove a file # that is the file we shipped (compare content), so a manifest the admin # copied/edited on purpose is left alone. if [ -f "%{_datadir}/vulkan/icd.d/mvgal_icd.json" ]; then if grep -q 'mvgal_vulkan_icd' "%{_datadir}/vulkan/icd.d/mvgal_icd.json"; then rm -f "%{_datadir}/vulkan/icd.d/mvgal_icd.json" || : echo "mvgal: removed the globally-registered Vulkan ICD manifest." echo "mvgal: the MVGAL ICD is still available as an opt-in driver:" echo "mvgal: source %{_datadir}/mvgal/scripts/mvgal-vulkan-env.sh" fi fi # The implicit interception layer is unaffected: it stays registered globally # on purpose, because it adds submit-time scheduling without replacing a # VkPhysicalDevice. # Create the mvgal group used for daemon socket access (test report H1). # Users who need CLI access to the daemon socket must be members: # pkexec usermod -aG mvgal $USER getent group mvgal >/dev/null 2>&1 || groupadd -r mvgal 2>/dev/null || : # Add the user who ran the install to the mvgal group so CLI access works # without a manual usermod step (test report: user not in mvgal group). INSTALL_USER="${SUDO_USER:-}" if [ -z "$INSTALL_USER" ] && [ -n "${LOGNAME:-}" ]; then INSTALL_USER="$LOGNAME" fi if [ -n "$INSTALL_USER" ] && [ "$INSTALL_USER" != "root" ]; then getent passwd "$INSTALL_USER" >/dev/null 2>&1 && \ usermod -aG mvgal "$INSTALL_USER" 2>/dev/null || : fi if [ -d /run/systemd/system ]; then systemctl daemon-reload > /dev/null 2>&1 || : # Enable the service so mvgald.service aliases work and auto-start on boot systemctl enable mvgal-daemon.service > /dev/null 2>&1 || : # H1 FIX: reload the D-Bus daemon so the freshly installed # org.mvgal.MVGAL.conf policy takes effect without a reboot. # 'systemctl reload dbus' works for both dbus-daemon and dbus-broker. systemctl reload dbus > /dev/null 2>&1 || : fi # Update kernel module dependency database so modprobe mvgal works /sbin/depmod -a >/dev/null 2>&1 || : # --------------------------------------------------------------------------- # OpenCL ICD: register only when there is something to aggregate. # # libmvgal_opencl.so is an *aggregating* ICD — it enumerates # /etc/OpenCL/vendors/, skips its own mvgal.icd, dlopens every other vendor # ICD and delegates to them. With no vendor OpenCL runtime installed it has # nothing to delegate to and reports zero platforms, so every OpenCL # application sees an empty platform list with no explanation. # # The build host cannot know what the target has, so decide at install time. # The file is still shipped (and marked %config(noreplace), so a manual # mvgal.icd is never clobbered); when there is nothing to aggregate it is # parked next to its final name with a .disabled suffix so the user can see # what happened and re-enable it in one mv after installing a runtime. # --------------------------------------------------------------------------- if [ -f /etc/OpenCL/vendors/mvgal.icd ]; then mvgal_opencl_peers=0 for _v in /etc/OpenCL/vendors/*.icd; do [ -e "$_v" ] || continue [ "$_v" = /etc/OpenCL/vendors/mvgal.icd ] && continue mvgal_opencl_peers=$((mvgal_opencl_peers + 1)) done if [ "$mvgal_opencl_peers" -eq 0 ]; then mv -f /etc/OpenCL/vendors/mvgal.icd \ /etc/OpenCL/vendors/mvgal.icd.disabled 2>/dev/null || : echo echo "MVGAL: no vendor OpenCL runtime is installed, so there is" echo "nothing for the MVGAL OpenCL ICD to aggregate. It has been" echo "left unregistered (parked as /etc/OpenCL/vendors/mvgal.icd.disabled)." echo "To enable OpenCL aggregation later:" echo echo " sudo dnf install intel-compute-runtime # or your vendor's runtime" echo " sudo mv /etc/OpenCL/vendors/mvgal.icd.disabled \\" echo " /etc/OpenCL/vendors/mvgal.icd" echo fi unset mvgal_opencl_peers fi # SECURITY FIX (test report C2): generate a per-machine module-signing # keypair on the target (never shipped in the RPM), sign the installed # modules with it, and tell the user how to enroll the public certificate. SIGN_FILE="%{_prefix}/lib/mvgal/sign-file" KEY_DIR="/var/lib/mvgal/keys" install -d -m 0700 "$KEY_DIR" 2>/dev/null || : # Regenerate any missing piece of the keypair. The test report found the # .der missing while the /etc/mvgal symlink existed (broken link), so the # old "only if priv is missing" guard was not enough. if [ ! -s "${KEY_DIR}/mvgal-signing.priv" ] || [ ! -s "${KEY_DIR}/mvgal-signing.x509" ]; then rm -f "${KEY_DIR}/mvgal-signing.priv" "${KEY_DIR}/mvgal-signing.x509" "${KEY_DIR}/mvgal-signing.der" openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 \ -out "${KEY_DIR}/mvgal-signing.priv" 2>/dev/null \ && openssl req -new -x509 -key "${KEY_DIR}/mvgal-signing.priv" \ -out "${KEY_DIR}/mvgal-signing.x509" -days 3650 \ -subj "/CN=MVGAL Kernel Module Signing Key/O=MVGAL" 2>/dev/null \ || rm -f "${KEY_DIR}/mvgal-signing.priv" "${KEY_DIR}/mvgal-signing.x509" fi if [ ! -s "${KEY_DIR}/mvgal-signing.der" ] && [ -s "${KEY_DIR}/mvgal-signing.x509" ]; then openssl x509 -in "${KEY_DIR}/mvgal-signing.x509" -outform DER \ -out "${KEY_DIR}/mvgal-signing.der" 2>/dev/null || : fi chmod 600 "${KEY_DIR}/mvgal-signing.priv" 2>/dev/null || : chmod 644 "${KEY_DIR}/mvgal-signing.x509" "${KEY_DIR}/mvgal-signing.der" 2>/dev/null || : # Test report C1: the certificate lives in /var/lib/mvgal/keys/, but users # (and the report) looked for it under /etc/mvgal/. Provide a symlink at the # well-known config path so the enrollment instructions are easy to follow. if [ -s "${KEY_DIR}/mvgal-signing.der" ]; then ln -sf "${KEY_DIR}/mvgal-signing.der" /etc/mvgal/mvgal-signing.der 2>/dev/null || : fi if [ -x "$SIGN_FILE" ] && [ -s "${KEY_DIR}/mvgal-signing.priv" ]; then KR=$(uname -r 2>/dev/null) for _kd in "/lib/modules/${KR}/kernel/drivers/gpu/drm/mvgal" \ "/usr/lib/modules/${KR}/kernel/drivers/gpu/drm/mvgal"; do [ -d "$_kd" ] || continue for ko in "$_kd/"*.ko; do [ -f "$ko" ] || continue "$SIGN_FILE" sha512 "${KEY_DIR}/mvgal-signing.priv" \ "${KEY_DIR}/mvgal-signing.x509" "$ko" 2>/dev/null || : done done /sbin/depmod -a >/dev/null 2>&1 || : fi # L4 FIX: merge config from .rpmsave on upgrade. # When the config format changes between versions, %config(noreplace) saves # the old config as .rpmsave and installs the new one, losing user changes. # Merge any keys from the old config that don't exist in the new one. if [ -f "%{_sysconfdir}/mvgal/mvgal.conf.rpmsave" ]; then echo "MVGAL: merging previous config from mvgal.conf.rpmsave..." # Extract all key=value pairs from the old config that aren't in the new one # and append them to the new config while IFS= read -r line; do # Skip comments, section headers, and empty lines case "$line" in ""|\#*|\;*|\["*) continue ;; esac # Extract key name key="${line%%=*}" key="${key#"${key%%[![:space:]]*}"}" # trim leading whitespace key="${key%"${key##*[![:space:]]}"}" # trim trailing whitespace # Check if key exists in new config if ! grep -q "^[[:space:]]*${key}[[:space:]]*=" "%{_sysconfdir}/mvgal/mvgal.conf" 2>/dev/null; then echo "$line" >> "%{_sysconfdir}/mvgal/mvgal.conf" echo " merged: $key" fi done < "%{_sysconfdir}/mvgal/mvgal.conf.rpmsave" # Remove the .rpmsave file after merge rm -f "%{_sysconfdir}/mvgal/mvgal.conf.rpmsave" echo "MVGAL: config merge complete." fi # The per-machine key must be enrolled in the firmware MOK database before # Secure Boot will load the modules. Detect Secure Boot and tell the user. if command -v mokutil >/dev/null 2>&1 && mokutil --sb-state 2>/dev/null | grep -qi "enabled"; then echo echo "MVGAL: Secure Boot is enabled. The mvgal kernel modules are signed" echo "with a per-install key, but the key is not yet trusted by the firmware." echo "Enroll it now so 'modprobe mvgal' works:" echo echo " pkexec mvgal-enroll-mok" echo " pkexec reboot" echo echo "(At the blue MOK Manager screen after reboot, choose" echo " 'Enroll key from disk' -> /var/lib/mvgal/keys/mvgal-signing.der" echo " and confirm with the one-time password you chose.)" echo fi %preun if [ $1 -eq 0 ] && [ -d /run/systemd/system ]; then systemctl stop mvgal-daemon.service > /dev/null 2>&1 || : systemctl disable mvgal-daemon.service > /dev/null 2>&1 || : fi %postun if [ $1 -eq 0 ] && [ -d /run/systemd/system ]; then systemctl daemon-reload > /dev/null 2>&1 || : fi # Refresh ldconfig cache after uninstall, suppress unrelated MTT warnings /sbin/ldconfig 2>&1 | grep -v "is not a symbolic link" || true # Update kernel module dependency database /sbin/depmod -a >/dev/null 2>&1 || : # If the OpenCL ICD was auto-disabled at install time because the machine had # no vendor OpenCL platform to aggregate, and there still is none, leave it # disabled. If a vendor runtime has appeared since (the usual fix for a # headless or driver-only install is installing intel-compute-runtime and # re-running this), re-enable it so the user is not left silently without # aggregation after doing the right thing. if [ $1 -eq 0 ] && [ -f /etc/OpenCL/vendors/mvgal.icd.disabled ]; then for _v in /etc/OpenCL/vendors/*.icd; do [ -e "$_v" ] || continue case "$_v" in /etc/OpenCL/vendors/mvgal.icd|/etc/OpenCL/vendors/mvgal.icd.disabled) continue ;; esac mv -f /etc/OpenCL/vendors/mvgal.icd.disabled /etc/OpenCL/vendors/mvgal.icd 2>/dev/null && \ echo "MVGAL: a vendor OpenCL runtime is present again — re-enabled /etc/OpenCL/vendors/mvgal.icd." break done fi %post -n mvgal-dkms # Update kernel module dependency database after installing kernel modules /sbin/depmod -a >/dev/null 2>&1 || : # Register with DKMS so modules are rebuilt on kernel updates if [ -x /usr/sbin/dkms ] && [ -d "/usr/src/mvgal-%{version}" ]; then KR=$(uname -r) # Do NOT swallow DKMS failures (test report BUG 1): a silent failure # here leaves the kernel module missing while the install reports # success. dkms add may legitimately fail on reinstall (already # registered), so keep that quiet, but surface build/install errors. /usr/sbin/dkms add mvgal/%{version} >/dev/null 2>&1 || : if ! /usr/sbin/dkms build mvgal/%{version} -k "$KR"; then echo "WARNING: dkms build mvgal/%{version} failed for kernel $KR." >&2 echo "The MVGAL kernel module is NOT installed. Check that kernel-devel" >&2 echo "matches the running kernel, then run:" >&2 echo " pkexec dkms build mvgal/%{version} -k $KR" >&2 echo " pkexec dkms install mvgal/%{version} -k $KR" >&2 elif ! /usr/sbin/dkms install mvgal/%{version} -k "$KR"; then echo "WARNING: dkms install mvgal/%{version} failed for kernel $KR." >&2 echo "The MVGAL kernel module is NOT installed." >&2 fi # SECURITY FIX (test report C2): DKMS-built modules are unsigned by # default, which Secure Boot rejects. Sign them with the per-machine # key generated by the main package's %post (never shipped in any RPM). KEY_DIR="/var/lib/mvgal/keys" SIGN_FILE="%{_prefix}/lib/mvgal/sign-file" [ -x "$SIGN_FILE" ] || SIGN_FILE="" for _sf in \ "/usr/src/kernels/${KR}/scripts/sign-file" \ "/usr/src/linux-${KR}/scripts/sign-file" \ "/usr/lib/modules/${KR}/build/scripts/sign-file" \ "/lib/modules/${KR}/build/scripts/sign-file"; do [ -x "$_sf" ] && { SIGN_FILE="$_sf"; break; } done if [ -n "$SIGN_FILE" ] && [ -s "${KEY_DIR}/mvgal-signing.priv" ]; then # Sign BOTH the RPM-installed modules (kernel tree) and the # DKMS-installed modules (/updates/dkms). DKMS installs to # /lib/modules/${KR}/updates/dkms/ — signing only the kernel-tree # path left the DKMS modules signed with DKMS's own mok.key, which # is NOT the key mvgal-enroll-mok enrolls (test report BUG 2). for _kd in "/lib/modules/${KR}/kernel/drivers/gpu/drm/mvgal" \ "/usr/lib/modules/${KR}/kernel/drivers/gpu/drm/mvgal" \ "/lib/modules/${KR}/updates/dkms" \ "/usr/lib/modules/${KR}/updates/dkms"; do [ -d "$_kd" ] || continue for ko in "$_kd/"*.ko; do [ -f "$ko" ] || continue "$SIGN_FILE" sha512 "${KEY_DIR}/mvgal-signing.priv" \ "${KEY_DIR}/mvgal-signing.x509" "$ko" 2>/dev/null || : done done /sbin/depmod -a >/dev/null 2>&1 || : fi fi %preun -n mvgal-dkms # Remove from DKMS before package files are deleted if [ $1 -eq 0 ] && [ -x /usr/sbin/dkms ]; then /usr/sbin/dkms remove mvgal/%{version} --all 2>/dev/null || : fi %postun -n mvgal-dkms # Update kernel module dependency database after removing kernel modules /sbin/depmod -a >/dev/null 2>&1 || : %files -f %{_builddir}/kernel-module.list # Kernel module via generated file list (above). Contains either the module path # (when built with kernel-devel) or a %dir anchor (when kernel-devel is absent, # e.g. Mageia Cauldron — Mageia's RPM rejects unmatched %files globs). # Daemon binary (with symlink for service file compatibility) %{_bindir}/mvgald %{_bindir}/mvgal-daemon # CLI tools %{_bindir}/mvgal %{_bindir}/mvgal-info %{_bindir}/mvgal-status %{_bindir}/mvgal-bench %{_bindir}/mvgal-compat %{_bindir}/mvgal-config %{_bindir}/mvgal-steam-setup %{_bindir}/mvgal-hw-validate # Additional tools enabled by MVGAL_BUILD_TOOLS=ON %{_bindir}/mvgal-enum %{_bindir}/mvgal-probe %{_bindir}/mvgal_amd_external_mem %{_bindir}/cross_vendor_compute %{_bindir}/mvgal-dmabuf-matrix # Kernel module load/unload helpers %{_bindir}/mvgal-load %{_bindir}/mvgal-unload %if %{with qt_gui} %if ! 0%{?amzn} # Qt GUI dashboard (mvgal-gui) %{_bindir}/mvgal-gui %{_bindir}/mvgal-dashboard %{_datadir}/applications/mvgal-gui.desktop %{_datadir}/icons/hicolor/256x256/apps/mvgal.png %endif %endif # Core library (static) %{_libdir}/libmvgal_core.a # libmvgal UAPI wrapper shared library (from tools/libmvgal/) %{_libdir}/libmvgal.so* # CMake config files for libmvgal %{_libdir}/cmake/mvgal/ # API interception libraries %{_libdir}/libVK_LAYER_MVGAL.so* %{_libdir}/libmvgal_d3d.so* %{_libdir}/libmvgal_metal.so* %{_libdir}/libmvgal_opencl.so* %{_libdir}/libmvgal_webgpu.so* %{_libdir}/libmvgal_gl.so* %{_libdir}/libmvgal_wow64.so* # CUDA interception shim (pure dlopen, built whenever MVGAL_BUILD_API=ON) %{_libdir}/libmvgal_cuda.so* # GPU vendor wrapper shared libraries %{_libdir}/libmvgal_hip.so* %{_libdir}/libmvgal_nvml.so* %{_libdir}/libmvgal_ppl.so* %{_libdir}/libmvgal_radeon_ld.so* %{_libdir}/libmvgal_sycl.so* %{_libdir}/libmvgal_vaapi.so* # Gamemode realtime library (installed to lib/gamemode/ via cmake) %{_prefix}/lib/gamemode/libmvgal_realtime.so # Additional static libraries %{_libdir}/libmvgal_prometheus.a %{_libdir}/libmvgal_sycl_backend.a # Vulkan ICD %{_libdir}/mvgal_vulkan_icd.so* # Vulkan layer manifest (implicit layer: registered system-wide, which is # correct — it only intercepts, it never stands in for a VkPhysicalDevice) %{_datadir}/vulkan/implicit_layer.d/VK_LAYER_MVGAL.json # Vulkan ICD manifest — OPT-IN location. It is intentionally NOT in # vulkan/icd.d: a 0-device ICD registered globally makes the Vulkan loader emit # "Cannot query ICD interface function ... The ICD is not conformant." on every # Vulkan application. Enable it with # source /usr/share/mvgal/scripts/mvgal-vulkan-env.sh %dir %{_datadir}/vulkan/mvgal %{_datadir}/vulkan/mvgal/mvgal_icd.json # Config file %config(noreplace) %{_sysconfdir}/mvgal/mvgal.conf # Custom strategy stub (referenced by mvgal.conf [custom] script_path) %config(noreplace) %{_sysconfdir}/mvgal/custom_strategy.lua # Optional AI scheduler model directory (M3) %dir %attr(755,root,root) %{_sysconfdir}/mvgal/models # Steam profile directory (test report L7) %dir %attr(755,root,root) %{_sysconfdir}/mvgal/steam_profiles # OpenCL ICD registration file. %config(noreplace): the aggregation ICD is # only useful when a vendor OpenCL runtime is present, so %post may park it # as mvgal.icd.disabled — an admin who edits or replaces it keeps their copy. %config(noreplace) /etc/OpenCL/vendors/mvgal.icd # Parked copy created by %post on a machine with no vendor OpenCL runtime. # Tracked so an uninstall removes it instead of leaving a stray file in a # system directory, and so rpm sees the file the scriptlet may have created. %ghost %config(noreplace) /etc/OpenCL/vendors/mvgal.icd.disabled # Systemd service %{_unitdir}/mvgal-daemon.service # D-Bus policy (daemon registers org.mvgal.MVGAL; the stale # com.mvgal.Daemon config is intentionally not shipped) %config(noreplace) %{_sysconfdir}/dbus-1/system.d/org.mvgal.MVGAL.conf # Log directory (created in the install section) %dir %{_localstatedir}/log/mvgal # pkexec and DKMS helper scripts %{_prefix}/lib/mvgal/mvgal-pkexec-helper.sh # Shared kernel-module inventory sourced by mvgal-load, mvgal-unload and # mvgal-pkexec-helper.sh (single source of truth for the module inventory). %{_prefix}/lib/mvgal/modules.sh %{_datadir}/mvgal/scripts/mtt-dkms-installer.sh # Vulkan environment helper: locates the opt-in ICD manifest and the # interception layer and exports the matching loader variables. %{_datadir}/mvgal/scripts/mvgal-vulkan-env.sh # Secure Boot MOK enrollment helper (SECURITY FIX C2: the signing keypair is # generated per-machine in /var/lib/mvgal/keys by %%post — never shipped) %{_bindir}/mvgal-enroll-mok %ghost %dir %attr(700, root, root) %{_sharedstatedir}/mvgal %ghost %dir %attr(700, root, root) %{_sharedstatedir}/mvgal/keys %ghost %attr(600, root, root) %{_sharedstatedir}/mvgal/keys/mvgal-signing.priv %ghost %attr(644, root, root) %{_sharedstatedir}/mvgal/keys/mvgal-signing.x509 %ghost %attr(644, root, root) %{_sharedstatedir}/mvgal/keys/mvgal-signing.der # Symlink at the well-known config path pointing at the per-machine cert # (created by %%post; makes MOK enrollment instructions easy to follow) %ghost %{_sysconfdir}/mvgal/mvgal-signing.der # sign-file is listed dynamically via %{_builddir}/kernel-module.list (not all # chroots can build it — see the install section) # udev rules %{_prefix}/lib/udev/rules.d/99-mvgal.rules # PolicyKit policy %{_datadir}/polkit-1/actions/com.mvgal.policy # Development headers %{_includedir}/mvgal/ # Man pages %{_mandir}/man1/mvgal*.1* # Documentation %{_docdir}/mvgal/ %files -n mvgal-user-space # Metapackage: no files. Pulls in mvgal + mvgal-dkms via Requires. %files -n mvgal-dkms -f %{_builddir}/kernel-module.list # Kernel module auto-load config %{_prefix}/lib/modules-load.d/mvgal.conf # Load/unload scripts %{_bindir}/mvgal-load %{_bindir}/mvgal-unload # SECURITY FIX (test report C2): no signing key material in this package. # The per-machine keypair lives in /var/lib/mvgal/keys (owned by mvgal). # sign-file is listed dynamically via %{_builddir}/kernel-module.list (shared with # the main package; not all chroots can build it). # DKMS source tree installed to /usr/src/mvgal-{version}/ # dkms(8) reads from here when rebuilding modules on kernel updates %{_prefix}/src/mvgal-%{version}/ %changelog * Mon Oct 12 2026 AxoGM - 0.7.21-1 - Fixed: daemon IPC socket now chowns to root:mvgal with proper error handling - Fixed: mvgal-compat no longer suggests gid 0 as remediation - Fixed: mvgal load-module no longer hangs (60s timeout) - Fixed: consistent exit codes for degraded state across all tools - Fixed: -c/--config restriction documented in help text - Fixed: VRAM mislabeling for Intel iGPUs (shared RAM labeled distinctly) - Fixed: JSON sentinel values now emit null + reason - Fixed: mvgal-enum timestamp_ns renamed to timestamp_s (was epoch seconds) - Fixed: mvgal-info rejects unknown args and supports --version - Fixed: mvgal-probe supports long options - Fixed: log messages no longer pollute stdout (redirected to stderr) - Fixed: AI model warning demoted to debug level - Fixed: Secure Boot warning at daemon startup - Fixed: RPM upgrade merges config from .rpmsave - Added: --version to mvgal-dmabuf-matrix, mvgal-steam-setup, mvgal_amd_external_mem * Sat Oct 10 2026 AxoGM - 0.7.20-1 - Build fix: added testing directory to daemon include path for mock GPU header - Build system: build.sh now correctly compiles gpu_manager.c with all includes - All 28 unit tests pass on synthetic GPU topology - Kernel modules build successfully for all supported vendors (AMD, NVIDIA, Intel, Moore Threads, Adreno, NTSYNC) * Sun Oct 04 2026 AxoGM - 0.7.19-1 - Fixed: rebuilding the same commit twice produced different SRPMs - mksrpm.sh copied vendor/ into the staging tree even though git archive had already emitted it, because vendor/ is tracked rather than ignored. The destination existed, so the copy nested a second 12 MB tree at vendor/vendor/ and restamped the parent's mtime with the wall clock. The script now refuses to continue if vendor/ is missing from the archive instead of silently duplicating it, and the tarball shrank from 11 MB to 8.3 MB. - rpmbuild stamped BUILDTIME from the wall clock, which left the two runs differing in exactly one header tag and in the signature digest over it. mksrpm.sh and the Jenkins RPM path now default SOURCE_DATE_EPOCH to the commit date and pass use_source_date_epoch_as_buildtime, the opt-in macro rpm requires before it will honour the variable at all. - Two consecutive builds of one commit now produce byte-identical tarballs and SRPMs, so a COPR resubmission after a failure is recognisable as the same input. * Sun Oct 04 2026 AxoGM - 0.7.18-1 - Added: synthetic GPU topology backend (mvgal-mock) - include/mvgal/mvgal_mock.h declares a backend that publishes a configurable set of fake GPUs (vendor, VRAM, PCIe link, features, driver identity) so the discovery path, the scheduler, the memory manager and the P2P cost model can be exercised on one machine. - Seven presets: NONE, SINGLE, HETERO_DUAL, HETERO_TRI, HETERO_QUAD, AMD_DUAL and INTEGRATED_ONLY. append_to_hardware adds the synthetic devices to the real scan instead of replacing it. - Physics are modelled, not faked: thermal inertia with an ambient/ TDP asymptote, throttle above TDP-5C capped at 60 percent, VRAM occupancy with a 256 MiB baseline, and per-pair link bandwidth derived from the negotiated PCIe generation and lane count. mvgal_mock_advance() integrates time and refreshes telemetry. - Per-device control: set_load, allocate_vram (0 releases), kill_device and resurrect_device, set_link_bandwidth. A killed device reports unavailable and stops advertising its memory and P2P capability. - Fixed: mvgal_p2p_query_caps() reported a fabricated 16 GB/s peer link for any same-root-complex pair, including synthetic devices whose peer path was disabled. Synthetic pairs now report the bandwidth the topology actually models, and supported requires a path to exist at all, so the cost model can no longer choose REPLICATE or MIGRATE for a pair that cannot transfer. - Fixed: mvgal_p2p_cross_vendor_supported() checked only that descriptors could be read, so a failed device still advertised itself as shareable. Both descriptors must now also be available. - Fixed: host state leaked into the simulation. finalize_gpu_descriptor() fills an integrated GPU's zero vram_total from sysinfo(), which made the synthetic topology report the build host's RAM and differ between machines. Synthetic integrated devices use MVGAL_MOCK_SYSTEM_RAM_BYTES. The real-hardware path is unchanged. - Fixed: mvgal_mock_init() rejected MVGAL_MOCK_TOPOLOGY_NONE as an invalid argument even though NONE is a documented preset meaning "no synthetic devices"; it now falls through to the documented MVGAL_ERROR_NO_GPUS. * Sun Oct 04 2026 AxoGM - 0.7.17-1 - Fixed: clippy.toml carried three keys that current clippy rejects (panic-in-upgrade, large-digit-grouping, and the deprecated cyclomatic-complexity-threshold alias). Clippy aborts on an unreadable configuration file before it lints anything, so the Rust crates had never been linted. All three keys are removed and the thresholds that are still meaningful are kept. - Fixed: clippy.toml listed unwrap and expect under disallowed-macros. Those are methods rather than macros, so clippy reported them as unreachable macros on every invocation and -D warnings turned that into a hard failure. - Fixed: CrossDeviceFence kept its signal timestamp in a Cell and its external handle in a raw pointer, so Arc was neither Send nor Sync and could never cross a thread boundary. The timestamp is now behind a mutex and the handle contract is documented. - Fixed: GpuTimeline::create_fence() and FenceManager::create_fence() retained a clone of the fence and returned a second, independent Arc, so signalling the returned handle had no effect on the tracked fence. Both now hand out the same Arc they keep. - Fixed: align_up() hand-rolled the ceiling division that div_ceil() provides. - Fixed: MvgalError relied on the implicit C-like enum representation, which cannot hold Unknown = 0xFFFFFFFF. It is now explicitly #[repr(u32)] and the i32 conversion used across the FFI boundary still yields -1 for Unknown. * Wed Sep 30 2026 AxoGM - 0.7.16-1 - Fixed: mvgal_unregister_custom_splitter() could never succeed. Splitters were registered by value but unregistered by address, and the internal slot address is never exposed to a caller, so the comparison could never match. Matching is now by value across analyze, split, merge and user_data. - Fixed: mvgal_unregister_custom_splitter() had no declaration in any public header, so a registered splitter could not be released from outside the library. - Fixed: the custom splitter API entry points discarded their arguments and returned MVGAL_ERROR_NOT_SUPPORTED. They now forward to the scheduler. - Fixed: mvgal_translate_dag() returned its argument unchanged. It now deep copies the DAG and rewires every dependency edge onto the copies, so the translated DAG is independent of its source. - Fixed: mvgal_emit_dag() always returned VK_ERROR_LAYER_NOT_PRESENT. It now resolves the command entry points through the device dispatch table and replays the DAG in recording order. - Fixed: the command buffer to DAG map was open addressed with no collision handling, so a hash collision overwrote a live entry and leaked its DAG. - Note: barrier lowering refuses queue family transfers and image layout transitions rather than silently flattening them into a memory barrier, which would under-synchronize. The node type records no such fields. * Wed Sep 30 2026 AxoGM - 0.7.15-1 - Fixed: mvgal_memory_copy() applied the region offsets twice. It asked mvgal_memory_map() to map at region->src_offset / region->dst_offset, which already returns a pointer advanced by that offset, and then added the same offset again at the memcpy. Any copy with a non-zero source or destination offset therefore read and wrote past the end of the mapping, corrupting neighbouring memory. Every existing test copied at offset 0, where applying the offset twice is invisible, so the bug went unreported. - Fixed: mvgal_memory_copy() unmapped buffers it did not own on its cleanup and error paths. The unmap was guarded by a MAPPED-state test that mvgal_memory_map() had already satisfied, so it was unreachable; had it run it would have released the mapping the buffer still points at, and for host-valid buffers it would have freed allocator-owned memory. The copy now leaves the mappings it created in place. - Tests: test_memory grew a case that copies 256 bytes from source offset 1024 to destination offset 2048 and asserts both that the bytes land at the destination offset and that nothing outside that window was touched. It fails against the previous mvgal_memory_copy(). * Mon Sep 28 2026 AxoGM - 0.7.14-1 - Version: six files carried the version as a literal of their own and every one had drifted -- mvgald --version, the modinfo version of mvgal.ko, mvgal-gui --version, mvgal-bench --json, the DKMS registration version, and Cargo.lock (still two releases back). They now read include/mvgal/mvgal_version.h, so the daemon, the CLI, the module and the package cannot disagree. - Version: the generated mvgal_version.h used uint32_t and bool without including and , so it only compiled when something else had included them first and could not be included early. It now includes them. - The generated mvgal_version.h is now fenced with __KERNEL__ so the kernel build can include it safely. On RHEL 8 cmake-rpm-macros' %cmake macro is broken, so the spec invokes cmake with no -B and the build is IN-SOURCE: configure_file overwrites the source tree's deliberately macro-only include/mvgal/mvgal_version.h with the generated copy, and the kernel build (Kbuild passes -I$(src)/../include) then compiled the user-space half -- resolved to GCC's, whose #include_next has no libc headers in a kernel build, and the error cascade also took down module_param(). Only RHEL 8 was affected, because every other distro builds out-of-source. __KERNEL__ is always defined by kbuild and never by a user-space build. - Version: scripts/mksrpm.sh verified only the files that DERIVE the version and ignored the ones that COPY it, which is why the copy drifted while the check kept passing. It now checks tools/libmvgal/CMakeLists.txt, kernel/dkms/dkms.conf, Cargo.lock's workspace members, and rejects any MAJOR.MINOR.PATCH literal in the six source files that report a version (C comments stripped first). - Vulkan: stop registering the MVGAL ICD in vulkan/icd.d. The ICD reports zero physical devices by design, and a manifest in icd.d is loaded by every Vulkan application on the system; because the loader never gets a physical device handle from a 0-device ICD it cannot build the per-device dispatch table and prints "Cannot query ICD interface function vkGetPhysicalDeviceDisplayPropertiesKHR, vkGetPhysicalDeviceDisplayPlanePropertiesKHR in ICD N. The ICD is not conformant." on every startup. The manifest now ships in the opt-in location /usr/share/vulkan/mvgal/mvgal_icd.json and %post removes the one written by <= 0.7.13. The interception layer VK_LAYER_MVGAL stays registered globally, which is correct: it only intercepts, it never stands in for a VkPhysicalDevice. The manifest's library_path is now absolute instead of a bare name. - Packaging: install scripts/mvgal-vulkan-env.sh to /usr/share/mvgal/scripts/ so the opt-in ICD path is discoverable, and teach it, steam/mvgal_steam_compat.sh and packaging/jenkins/build_deb.sh to look in the new location. - Secure Boot: mvgal-enroll-mok fed mokutil --import a single password line, but mokutil prompts for the confirmation twice, so enrollment always failed with "could not read confirmation password". It now pipes the password twice. - Secure Boot: the post-import check grepped mokutil --list-new for the string "mvgal-signing", which mokutil never emits - real output is "Issuer/Subject: CN=MVGAL Kernel Module Signing Key, O=MVGAL" - so a successfully enrolled key was reported as a failure. It now matches the subject. - Secure Boot: mvgal-enroll-mok parsed its options, then re-executed itself through pkexec with the already-consumed "$@", silently discarding -p/--password. Elevation now happens before option parsing, with a non-consuming pre-scan so --help still works unprivileged. - Secure Boot: the Secure Boot state check nested "*i*abled*" inside "*nabled*", so "disabled" and "not enabled" matched and the script exited as if nothing needed enrolling. The state is now lower-cased before matching. - mvgal-daemon.service: CAP_SYS_MODULE was missing from both CapabilityBoundingSet and AmbientCapabilities, so the two ExecStartPre modprobe calls could never succeed. Those lines also used the "-" prefix, which made systemd discard the exit status and the message, so the unit reported active(running) having loaded no modules at all. They now run via /bin/sh -c with an explicit diagnostic and continue in userspace-only mode on failure. The unit also gained RuntimeDirectory=mvgal, because /run is tmpfs and nothing recreated the run directory after a reboot. - Kernel modules: mvgal-unload and the PolicyKit helper listed only five modules and both omitted mvgal_mtt and mvgal_adreno, and the helper loaded mvgal before its declared dependency mvgal_ntsync. The inventory now lives in one file, /usr/lib/mvgal/modules.sh, sourced by mvgal-load, mvgal-unload and the helper; the load order is dependency-correct and the unload order is its exact reverse. Consumers warn when they fall back to their built-in list rather than drifting silently. - Daemon IPC: the socket was chmod 0660 with no chown, so it stayed root:root and no unprivileged user could connect even when a member of the mvgal group. Both daemons now chown it to the mvgal group (falling back to video) before chmod, and the run directory is chowned too. mvgal-compat reported the wrong remediation ("add user to mvgal group") for a socket the user was already in the group for; it now reports the socket's real uid:gid and mode and names both real causes. - mvgal: the four benchmark subcommands exited 1 when they found no workload data, even though no workload running is not an error. They now exit 0 and explain what the counters are (per-process, and only moving when work runs inside that invocation) and how to produce data. mvgal_stats_t was read uninitialised and mvgal_get_stats()'s return value was discarded, so a failure printed stack garbage; a real read failure still exits 1. - polkit: data/com.mvgal.policy was not valid against policyconfig-1.dtd - it used <_description> and <_message>, so no description ever rendered - and none of its ten action IDs was annotated to any executable, so none of them could ever match. Two of them, com.mvgal.config.user and com.mvgal.monitor, additionally granted allow_any/allow_active, i.e. no authentication at all. The file now declares exactly the two actions that are real (com.mvgal.privileged.helper on /usr/lib/mvgal/mvgal-pkexec-helper.sh and com.mvgal.daemon.start on /usr/sbin/mvgald), both requiring auth_admin. - Security: the PolicyKit helper accepted any -c/--config path that passed a metacharacter filter, which let an authorised user make root sed-edit a file such as /etc/sudoers.d/x. The path is now required to be a .conf directly inside /etc/mvgal, to exist as a regular file, and to still be there after realpath resolves any symlinks. - Security: the helper interpolated the GPU index into a sed address with no validation. It is now digits-only, length-checked before arithmetic, free of leading zeros, and bounded by the GPUs actually present under /sys/class/mvgal. - Reporting: GPUs were named by their bare PCI device id, so an Intel UHD 770 printed as "Intel GPU 4680". Both daemons now read the DRM label from sysfs and fall back to "vendor [vendor_id:device_id]", which cannot be mistaken for a model name. - Reporting: mvgal-hw-validate printed "GPU[1]" for a single GPU, kept a sticky counter across calls, iterated its sysfs directory without a bound, and read a device_name attribute that does not exist, so the Name line never printed. The label is now read from device/label, indices are 0-based and bounded, and skipped virtual devices say so. - AI scheduler: mvgal_ai_model_load() returned a valid handle and logged "AI model loaded" for any non-empty path without touching the filesystem, and the daemon hardcoded a path (/etc/mvgal/scheduler_model.onnx) that no package creates and that disagreed with the one in mvgal.conf. The loader now checks that the file exists and is a regular file, the daemon reads MVGAL_AI_MODEL or /etc/mvgal/models/scheduler.onnx once at startup, and the missing-model case is stated instead of silently pretending. - OpenCL: the aggregating ICD registers even when the machine has no vendor OpenCL runtime, in which case it has nothing to delegate to and every OpenCL application sees an empty platform list with no explanation. %post now parks it as /etc/OpenCL/vendors/mvgal.icd.disabled in that case and says how to enable it, and re-enables it on a later upgrade once a vendor runtime is present. A %ghost entry tracks the parked file so an uninstall is clean. - Packaging: removed packaging/rpm/mvgal.conf. It was never installed by this spec and had drifted into a different schema from the config/mvgal.conf that is, so edits to it had no effect. * Sun Sep 27 2026 AxoGM - 0.7.13-1 - Build: kernel modules now install under the staging prefix instead of hardcoding the build user's home directory, so DESTDIR packaging stops producing /home/axogm/... paths inside the shipped tree. - Build: mvgal_core is compiled with -ffat-lto-objects so the static archive carries machine code as well as LTO bytecode. Without it the archive is symbol-only, and any link that appends -flto after the project's own -fno-lto fails with undefined references to mvgal_init, mvgal_shutdown, mvgal_context_create, mvgal_config_load and mvgal_pm_init. GCC 14.3 triggers this in the Flatpak and COPR builds. - Packaging: new packaging/jenkins/ scripts build deb, rpm, tar.zst, AppImage and Flatpak from one shared userspace stage, plus a Jenkinsfile that drives them. The deb control member now holds ./control at the root as deb(5) requires, and the hand-maintained Depends fields were corrected: the main package ships usr/bin/mvgal-gui but previously declared only libc6, so the GUI could not launch on a stock Debian. Qt6 runtime deps are declared as alternatives so both the t64 and pre-t64 package spellings install. - UI: replaced the 1056x1024 GUI icon with a square 256x256 asset. Flatpak export rejects icons larger than 512x512. - Flatpak: builds against org.kde.Sdk 6.8, and post-install publishes the desktop entry and icon under names matching the app id. * Sun Sep 27 2026 AxoGM - 0.7.12-1 - BREAKING: the kernel module no longer binds GPU PCI functions. The mvgal_pci_driver and its MODULE_DEVICE_TABLE alias table are gone, so udev can no longer autoload mvgal.ko onto real hardware and mvgal can no longer compete with amdgpu, nvidia, i915/xe or mtgpu for a device it cannot drive. GPUs are still discovered, read-only, via pci_get_device and the PCI bus notifier; mvgal.ko now lists no pci alias at all and imports no pci_register_driver, pci_enable_device or pci_set_master. This also fixed every GPU being registered twice, because mvgal_enumerate_gpus() had already added each device before pci_register_driver() re-probed it - BREAKING: vendor alloc_vram and submit_cs now return -EOPNOTSUPP for all of amd, nvidia, intel and mtt. The four bump allocators returned fabricated GPU addresses with no backing buffer object - amd seeded 0x100000000, mtt 0x40000000, nvidia 0x10000000, and intel returned the allocation's sequential id as the address, so the first call yielded address 0. Each submit_cs logged a debug line and returned 0 without dispatching anything, and two dispatcher branches in mvgal_scheduler.c went further, marking the workload COMPLETE. The native drivers own the ring scheduler, the memory manager and submission and export no interface an out-of-tree module may use. Callers already fall back to DMA-BUF import and then host staging - fix: a pci_dev reference leaked for every enumerated GPU, and both error paths of mvgal_enumerate_gpus() called pci_dev_put() twice for one reference - fix: two differently ordered power-state enums were being crossed. mvgal_set_power_state() took enum mvgal_power_state (OFF=0, SUSPEND=1, IDLE=2, ON=3, PERFORMANCE=4) while every vendor op takes enum mvgal_device_power_state (ACTIVE=0, SUSTAINED=1, IDLE=2, PARK=3, OFF=4), so requesting ON reached the driver as PARK. The redundant enum is deleted and the power manager now speaks the vendor-op vocabulary - fix: mvgal_set_power_state() never updated the tracked power state when a vendor op existed, so the shadow value silently diverged from what the driver was doing. With no vendor op it recorded the request and returned success; it now reports that the state was recorded but not applied - fix: wait_idle returned success in all four vendors without waiting on anything; no vendor exports an idle-wait entry point, so it now reports -EOPNOTSUPP - fix: the Vulkan ICD no longer advertises a synthetic physical device. It reported one device whenever a GPU was present, carrying GPU 0's real vendorID and deviceID and the name "MVGAL Aggregated (... + N more)". It now reports zero devices. A physical device is a live handle whose vkCreateDevice, vkAllocateMemory, vkCreateGraphicsPipelines and vkQueueSubmit each need a single real target, and heap, queue family and format feature indices from different vendors do not compose because each indexes that vendor's own tables - fix: the SPIR-V router claimed to emit PTX. SPIRV-Cross cannot emit PTX, HSACO or Gen; only the vendor toolchain can. The route function also returned GLSL source through a uint32_t binary-blob interface, so its signature now says char **out_glsl. A dead call site in vk_layer.c ran a full optimise and decompile per shader module against a hardcoded AMD vendor and discarded the result - fix: the memory KUnit suite asserted nothing. test_memory_alloc() returned NULL because no fixture had called test_memory_manager_init(), so every KUNIT_EXPECT_NOT_ERR_OR_NULL was exercising the NULL path. The suite now registers proper init and exit fixtures - Added: runtime capability probing. Each GPU's MVGAL_CAP_* mask is built by an actual test - opening the sysfs node, checking which driver owns the PCI function - never from the vendor family. A capability that cannot be verified is simply absent, and the scheduler, power manager and memory manager consult the mask instead of testing whether an ops pointer exists. kernel-submit, kernel-vram, dmabuf-export and wait-idle are deliberately never set for any vendor - Added: per-GPU sysfs attributes capabilities and native_driver, which print none when there is nothing to report, plus idle_gate, idle_gate_status and idle_gate_timeout for the new idle gating. Gating requires a measurable busy signal, so a device without one reports idle-gating as unavailable and refuses to arm rather than gating on a guess - Changed: physical_device.c no longer carries the four unused VkPhysicalDevice fabrication helpers it exported to no caller - Changed: version bumped 0.7.11 -> 0.7.12 * Sat Sep 26 2026 AxoGM - 0.7.11-1 - fix: the daemon no longer writes out of bounds when the config file length cannot be determined. The GET_CONFIG handler in ipc_server.cpp sized its response buffer from ftell() and then wrote the terminator at that offset, but ftell() returns -1 on failure - on a zero-length vector, configData[fsize] is configData[-1], a heap write one byte before the allocation. fseek() and fread() return values are now checked, a negative length is rejected, and the payload length sent to the client is the number of bytes actually read. This also stops a stray NUL terminator from being shipped to clients as payload - fix: the Vulkan shader compiler no longer overflows the heap when ftell() fails. compile_nvidia_ptx() and compile_intel_igc() in mvgal_shader_compiler.c allocated ftell() bytes and read into the buffer without validating the result. On failure the allocation is malloc(0), which returns a non-NULL unique pointer on glibc and so passed the existing null check, and the subsequent read requested SIZE_MAX bytes into that zero-byte block. Both functions now reject a non-positive length and verify the short-read case, matching the existing checks in compile_amd_llc() - fix: the discovery message header documents that tcpPort is a 32-bit wire slot carrying a 16-bit port, and the htons()/ntohs() call sites now narrow explicitly. The field width is unchanged so the on-wire layout of DiscoveryMessageHeader is byte-for-byte identical - fix: the version can no longer drift between the number and the string in include/mvgal/mvgal_version.h. The header carried MVGAL_VERSION_MAJOR/_MINOR/_PATCH and a hand-written MVGAL_VERSION_STRING independently, and the string is now built from the three numbers by a stringify macro, so a bump that edits only the numbers cannot leave the string behind. The in-tree copy had already drifted: MVGAL_VERSION_STRING read 0.7.10 while MVGAL_VERSION_PATCH read 10, and because mvgal_get_version_numbers() reports the numbers rather than the string, "mvgal --version" printed a patch number one release behind what "mvgald --version" and the generated header reported - add: scripts/mksrpm.sh now verifies that the spec, CMakeLists.txt, both Cargo.toml manifests and both in-tree version headers agree on one version before it cuts the tarball, and reports every mismatch at once. Nothing previously forced those copies to agree, so a bump that missed one shipped a package whose daemon, CLI and library each reported a different version - version bumped 0.7.10 -> 0.7.11 * Sat Sep 26 2026 AxoGM - 0.7.10-1 - fix: the daemon no longer invents a fake GPU. rescan_gpus_locked() called add_placeholder_gpu_locked() whenever the DRM and NVIDIA scans came back empty, so a machine with no supported GPU (or one where the mvgal module is not loaded) was reported as owning a 4 GiB MVGAL_VENDOR_UNKNOWN / MVGAL_GPU_TYPE_VIRTUAL device named "MVGAL Placeholder GPU". Every downstream consumer of the descriptor - scheduling, VRAM accounting, the CLI's list-gpus - then operated on hardware that does not exist. The placeholder is gone; an empty scan now logs a warning and reports zero GPUs - fix: the Vulkan ICD no longer advertises a fictitious physical device. mvgal_vkEnumeratePhysicalDevices() returned 1 and handed back a "MVGAL Virtual GPU (no physical GPUs detected)" handle whenever the daemon reported zero GPUs, and mvgal_vkCreateInstance() populated the properties struct accordingly. A Vulkan loader that found a device where none exists could then fail much later, deep in the application's own initialisation, with a fault that pointed nowhere near the real cause. The ICD now reports 0 devices and leaves *pPhysicalDeviceCount at 0, which is the contract the loader expects and lets it fall through to the next real ICD on the system - doc: sudo -> pkexec across the shipped user-facing text (spec %post hints, config scripts, docs, wiki, packaging helpers) to match the documented polkit-based privilege model - version bumped 0.7.9 -> 0.7.10 * Sat Sep 26 2026 AxoGM - 0.7.9-1 - fix: stale kernel header cache no longer breaks the build — find_path caches its hit and CMake never re-validates it, so a build directory reused across a kernel upgrade kept pointing at a removed header tree. The cache entry is now dropped when include/generated/utsrelease.h is missing, so the build self-heals on any kernel upgrade - fix: libmvgal_cuda.so is now buildable — the CUDA wrapper was gated on WITH_CUDA, a variable never declared anywhere in the project, so the target was unreachable. Now built whenever MVGAL_BUILD_API=ON - fix: libmvgal_cuda.so is packaged and ships on every chroot. The CUDA wrapper is a pure dlopen/dlsym interposition shim — it includes no CUDA headers and links no CUDA libraries, resolving libcuda at load time — so gating it on CUDAToolkit_FOUND only made it unbuildable, and therefore unshippable, wherever nvcc was absent. The gate is gone and %files lists the library, so packaging no longer depends on the build host having a CUDA toolkit. Fixes "Installed (but unpackaged) file(s) found: /usr/lib64/libmvgal_cuda.so" in every toolkit-less build root - fix: memory.c drops the dead `struct timespec ts;` in mvgal_migration_scheduler_dispatch() (-Werror=unused-variable) - fix: ai_data_collector.c adds the missing ; it used the POSIX timer API (timer_create, struct sigevent, SIGEV_THREAD, union sigval) with six cascading -Werror failures - fix: cuda_wrapper.c silences -Werror=unused-parameter in the two cross-GPU copy stubs via (void) casts; no behaviour change - test: test_all.sh rewritten against the real tree layout. It referenced ~19 paths that do not exist (dist/mvgal-0.2.2.tar.gz from the 0.2.x era, pkg/debian/, pkg/rpm/, pkg/arch/, pkg/flatpak/, pkg/snap/, and three phantom benchmarks/{synthetic,real_world,stress}/ binaries) and used `set -e` without pipefail. Now 10 sections, 72 checks, all real - test: test_cuda_wrapper.sh rewritten. It was fully broken: a hardcoded stale absolute path instead of deriving BASE_DIR from $0, two tests that printed a verdict without touching the exit status, and an nm -D grep for cuda_wrapper_init which is static and could never match. Now 7 real assertions with real counters and a real exit code - test: all three test scripts clean under shellcheck --severity=warning - version bumped 0.7.8 -> 0.7.9 * Tue Sep 22 2026 AxoGM - 0.7.8-1 - fix: mvgal-enroll-mok false success — mokutil --import now receives the password via stdin (mokutil 0.7.2 rejects -p) and the pending MOK list is verified with mokutil --list-new before reporting enrollment - fix: daemon drops capabilities after init (effective/permitted/inheritable cleared, bounding set pruned to CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_SYS_RAWIO); systemd unit gains CapabilityBoundingSet/AmbientCapabilities/NoNewPrivileges - fix: mvgal-status reports degraded mode when the mvgal kernel module is not loaded, with a MOK enrollment hint; Load Balance is no longer hard-coded to 100.00% (real estimate or N/A) - fix: Vulkan ICD reports real apiVersion/driverVersion from the version macros (was 0.0.0 in the daemon-GPU path) - fix: mvgal-info DRM fallback reads enabled state from /etc/mvgal/mvgal.conf - fix: mvgal-bench multi-GPU scaling labeled as theoretical estimate - fix: load-module.sh resolves module paths via modinfo -n (no hard-coded /lib/modules/.../updates/dkms path) - fix: D-Bus policy for org.mvgal.MVGAL restricted to root + mvgal group - fix: mvgal-hw-validate attributes device-node FAILs to kernel module not loaded with a load hint - fix: ship /etc/mvgal/custom_strategy.lua no-op stub so the [custom] script_path reference in mvgal.conf always resolves - version bumped 0.7.7 -> 0.7.8 * Mon Sep 21 2026 AxoGM - 0.7.7-1 - fix: Vulkan ICD device dispatch — vkCreateImage, vkGetImageMemoryRequirements and vkDestroyImage were missing from vk_icdGetDeviceProcAddr, leaving NULL entries in the loader's device dispatch table; vulkaninfo (and any app calling vkCreateImage) crashed with SIGSEGV. Implemented the three image functions - fix: Vulkan ICD vkGetPhysicalDeviceQueueFamilyProperties2 wrote past the caller's array (heap corruption under multi-ICD setups); now fills a temp buffer and copies per element - fix: version macros unified — mvgal-gui --version now reports 0.7.7 (CMakeLists.txt was stale at 0.7.5 while Cargo/spec said 0.7.6) * Thu Sep 17 2026 AxoGM - 0.7.6-1 - fix: Vulkan layer no longer returns VK_ERROR_LAYER_NOT_PRESENT from vkEnumerateDeviceExtensionProperties for physical devices it did not wrap (e.g. Mesa dzn ICD), which aborted the loader with a VUID-physicalDevice error (SIGABRT) in mvgal_amd_external_mem --scan - fix: mvgal-status reports DEGRADED MODE with a non-zero exit code when the mvgal kernel module is not loaded (Secure Boot / MOK rejection was silent) - fix: mvgal-config -c/--config now writes to the requested config file; the pkexec helper previously ignored the path and always wrote /etc/mvgal/mvgal.conf - fix: config helper append check is section-scoped so a key present in a later section no longer suppresses appending it to the target section - fix: daemon SET_CONFIG IPC handler validates the payload and writes atomically (temp file + rename) instead of truncating the live config with a raw write - fix: mvgal-dashboard with no arguments prints a banner + hint instead of exiting silently - fix: version macros unified — mvgal --version now reports 0.7.6 everywhere (MVGAL_VERSION_PATCH was stale at 3 while the string said 0.7.5) * Tue Sep 15 2026 AxoGM - 0.7.5-1 - fix: DKMS install — BUILT_MODULE_LOCATION=/kernel for all modules so DKMS finds the .ko files built into the kernel/ subdirectory (MAKE[1] copy approach never ran; DKMS executes only one make command) - fix: Secure Boot — %post -n mvgal-dkms now signs DKMS-installed modules in /lib/modules/*/updates/dkms with the per-machine MVGAL key (previously only the kernel-tree modules were signed, so the DKMS modules were rejected) - fix: mvgal-enroll-mok generates a one-time password when -p is omitted and always passes it to mokutil --import, so enrollment works through pkexec without a TTY - fix: Vulkan ICD implements the WSI entry points the loader requires — vkGetPhysicalDeviceSurfaceSupportKHR/CapabilitiesKHR/FormatsKHR/ PresentModesKHR plus FormatProperties2/ImageFormatProperties2/ SparseImageFormatProperties2/ExternalBuffer/Fence/SemaphoreProperties/ ToolProperties — so apps no longer abort with "ICD does not export vkGetPhysicalDeviceSurfaceSupportKHR" * Mon Sep 07 2026 AxoGM - 0.7.4-1 - fix: DKMS build layout — dkms.conf copies built .ko files to the DKMS build root so dkms install finds mvgal.ko/mvgal_ntsync.ko; %post no longer swallows dkms build/install failures - fix: Vulkan ICD exposes a placeholder physical device when no physical GPU is available instead of returning 0 devices - fix: OpenCL CMake propagation — OpenCL_LIBRARIES/OpenCL_INCLUDE_DIRS now populated from the pkg-config result - fix: mvgal_amd_external_mem --no-mvgal implies --scan instead of usage - fix: mvgal-dashboard/mvgal-gui gained --check/--self-test for headless verification without hanging - fix: mvgal-enroll-mok passes -p/--password to mokutil --import (works without a TTY through pkexec) - fix: mvgal-probe exits 0 when the DRM sysfs fallback detects GPUs - fix: mvgal-steam-setup with no arguments exits 0 - fix: mvgal-config set-power-profile help marks AMD-only; error suggests mvgal list-gpus - fix: mvgal-load/mvgal-unload self-escalate via pkexec helper * Wed Sep 02 2026 AxoGM - 0.7.3-1 - fix: config writes now honor the -c/--config path in mvgal and mvgal-config; mvgal-pkexec-helper.sh gained a --config option - fix: D-Bus policy now takes effect immediately — %post reloads the D-Bus daemon - fix: mvgal_amd_external_mem --scan hangs — progress prints before blocking Vulkan calls plus a --no-mvgal flag to enumerate real vendor ICDs only - fix: mvgal-dashboard prints a startup banner when launched from a terminal - fix: mvgal --version reported 0.7.1 — MVGAL_VERSION_PATCH was stale - fix: mvgal-bench accepts synthetic/realworld suite aliases - fix: mvgal-probe no longer uses a closed fd when the module is absent and honors -j in the DRM sysfs fallback - fix: mvgal stop returns non-zero when the daemon is not running - fix: mvgal start/stop/restart detect systemd via /run/systemd/system - fix: mvgal-gui disables xdg-desktop-portal registration in the Application ctor - fix: mvgal-compat no longer shows "Unknown title" for known apps - feat: --version added to mvgal-config, mvgal-probe, mvgal-enum, mvgal-hw-validate, mvgal-status, mvgal-compat, mvgal-bench * Tue Sep 01 2026 AxoGM - 0.7.2-1 - fix: mvgal-enroll-mok --status false positive — mokutil can return exit 0 even when the key is NOT enrolled; the check now also requires the output to contain "is enrolled" (not just a zero exit code) - fix: daemon never applied the config's [core] default_strategy — the scheduler was hardcoded to DYNAMIC_LOAD_BALANCING; daemon now reads default_strategy from mvgal.conf and maps it to the scheduler mode at init - fix: D-Bus GetSchedulingMode returned "unknown" for AI_DRIVEN — modeToString now maps AI_DRIVEN -> "ai_driven" and stringToMode accepts it back - fix: D-Bus policy missing receive_sender — normal users could not receive daemon signals; added to both the root and default contexts - fix: mvgal-gui and mvgal-dashboard hung on startup — xdg-desktop-portal blocked QApplication construction; QT_ENABLE_PORTAL=0 is now set before the QApplication is created - fix: mvgal-status reported the daemon down when the socket connect failed — now falls back to `systemctl is-active mvgald` then `pidof mvgald` - fix: mvgal-info reported the daemon absent on socket ENOENT — now falls back to `pidof mvgald` before declaring it absent - fix: mvgal-config used atoi() with no validation for enable-gpu, disable-gpu, set-priority, set-power-curve, set-power-profile — replaced with strtol() + range checks (GPU index >= 0, priority 0-100) - fix: DKMS build failure — kernel/Makefile was a CMake-generated file with hardcoded local paths; replaced with a Kbuild wrapper that delegates to the kernel build system - fix: mvgal-load used the wrong module path and was missing mvgal_mtt and mvgal_adreno; now points at /updates/dkms and loads all 7 modules - fix: custom strategy was accepted without verifying the script exists; both mvgal and mvgal-config now require /etc/mvgal/custom_strategy.lua - fix: mvgal status always reported "single GPU" because the CLI did not load the default config; now loads /etc/mvgal/mvgal.conf by default - fix: config/mvgal.conf enabled gpu_1 on single-GPU systems; now disabled - chore: version bump 0.7.0 -> 0.7.1 (bugfix release) * Mon Aug 31 2026 AxoGM - 0.7.0-1 - feat: multi-vendor OpenCL ICD aggregation - cl_intercept.c rewritten to aggregate platforms/devices from all vendor ICDs into a single logical OpenCL platform; delegates to the real vendor ICD when loaded via /etc/OpenCL/vendors - fix re-entrant deadlock in the OpenCL interceptor with -Bsymbolic-functions (internal calls no longer recurse through the wrapper) - mvgal CLI: OpenCL platform/device enumeration reporting - chore: version bump 0.6.0 -> 0.7.0 (minor feature release) - synced spec, CMake, Rust workspace, kernel module, daemon, GUI, dashboard, mvgal-bench, libmvgal, docs, and README to 0.7.0 * Fri Aug 28 2026 AxoGM - 0.6.0-40 - fix: daemon freezes on first metrics tick (test report BUGs 1/2/3/5) - B2: MetricsCollector::processEvents() held m_mutex while calling collectAllMetrics() -> collectGpuMetrics(), which locks m_mutex again (std::mutex is not recursive) -> self-deadlock on the first collection interval. The main loop froze, so IPC and D-Bus accepted connections but never responded, the Vulkan ICD saw zero GPUs, and `mvgal stop` needed the 5s SIGALRM backstop. processEvents() now releases the lock before collecting; checkTelemetryUpdates() takes its own lock. - fix: legacy mvgal_ipc.h client protocol incompatible with runtime daemon - B2: the shipped client API (src/userspace/daemon/ipc.c) sent a 24-byte header with a different magic and no byte-order conversion, so the runtime C++ daemon (28-byte htonl header, magic 0x4D56474C) never parsed it and clients hung. Client side rewritten to speak the runtime wire protocol with type mapping (GPU_ENUMERATE -> QUERY_DEVICES, etc.). - fix: mvgal-config reports daemon not running when user lacks group access - B4: daemon_is_running() now treats EACCES/EPERM on connect as "running" (socket exists but user not in mvgal group) and falls back to pidof mvgald. - fix: OpenCL ICD reports zero platforms without a vendor OpenCL runtime - B6: add Recommends: intel-compute-runtime so a real OpenCL implementation is present for ICD aggregation. - fix: mvgal benchmark family printed stats without generating workloads - B7: benchmark/bench-synthetic/bench-realworld/bench-stress now invoke mvgal-bench (all/compute/memory-bandwidth/scheduling+sync) first. - fix: enable-gpu/disable-gpu report "GPU N not found" for invalid index - B8: query mvgal_gpu_get_descriptor() and check MVGAL_ERROR_GPU_NOT_FOUND before acting. - docs: post-install mvgal group membership (log out/in or newgrp mvgal) - SETUP 2: README section added; MOK enrollment already documented. * Fri Aug 28 2026 AxoGM - 0.6.0-39 - fix: build fix for release 38 (LTO link failure) - B1: move extern g_running declaration in ipc_server.cpp to global scope (was inside namespace mvgal, mismatched the global definition in main.cpp, causing "undefined reference to mvgal::g_running" under -flto at link time) * Fri Aug 28 2026 AxoGM - 0.6.0-38 - fix: fourth-pass end-user test report fixes (17 issues, Fedora 44) - C1: %%post regenerates missing signing key/der (broken symlink case); mvgal-enroll-mok no longer reports "already enrolled" when the key is missing; load-module/pkexec-helper print Secure Boot guidance - C2: daemon exits cleanly on SIGTERM (IPC read loop honors g_running, signal handler unlinks socket+pid, SIGALRM backstop exits 0) - C3: mvgal stop verifies the daemon actually exited (SIGKILL fallback) - C4: stale socket no longer blocks restart (unlinked on shutdown) - H1: %%post adds the installing user to the mvgal group; daemon accepts mvgal AND video group members - H2: mvgal_amd_external_mem --scan has a 15s watchdog instead of hanging - H3: mvgal-dashboard/mvgal-gui verify the display socket is reachable before starting Qt (fail fast instead of hanging) - H4: OpenCL ICD delegates to the real vendor ICD when loaded via /etc/OpenCL/vendors (fixes 0 platforms) - M1: mvgal-steam-setup also checks /usr/lib64/libmvgal.so - M2: shipped config defaults to strategy=single (safe) instead of hybrid - M3: mvgal-config reload/show-stats report daemon state when it is down - L1: SteamProfileLoader creates /etc/mvgal/steam_profiles if missing - L2: set-psu-config rejects absurd capacities (>10000 W) - L3: pkexec cancellation is reported instead of silent failure * Fri Aug 28 2026 AxoGM - 0.6.0-37 - fix: third-pass end-user test report fixes (15 issues, Fedora 44) - C1: MOK certificate discoverability — %%post symlinks the per-machine mvgal-signing.der into /etc/mvgal/; add Requires: openssl - C2: D-Bus service hang — replace sd_event_run(0) polling with the documented sd_bus_process drain loop; fix sd_bus_send(NULL,...) in GetStatistics handler; drop bogus Introspectable child node - C3: remove stale mvgal-dbus.conf (com.mvgal.Daemon) and com.mvgal.Daemon.service from install and %%files; keep the correct org.mvgal.MVGAL.conf policy - H1: daemon socket now root:mvgal 0660 with mvgal group fallback to video; authenticate() accepts supplementary mvgal-group members via /proc//status instead of rejecting every non-root client - H2: daemon version aligned to 0.6.0 (was 0.2.2) in main.cpp and daemon.cpp startup banner - M1: mvgal_amd_external_mem no longer hangs with no args — prints usage and exits; --scan runs the Vulkan enumeration - M2: mvgal-config set-power-profile detects non-AMD vendors and missing sysfs knobs, and reports root-privilege failures accurately - M3: new mvgal-config set-psu-headroom command backed by a pkexec-helper psu-headroom action; shipped mvgal.conf gains the [power] section (psu_capacity_watts, psu_safety_margin_percent, enable_psu_headroom) - L1: mvgal-compat distinguishes daemon running-but-socket-denied from not running (errno-aware connect) - L2: mvgal-info distinguishes socket absent vs permission-denied - L3: benchmark commands document workload submission (VK_LAYER_MVGAL, OpenCL ICD, mvgal-bench all) instead of a dead-end message - L4: mvgal-info and mvgal-bench VRAM detection mirrors the daemon: mem_info_vram_total → mem_info_vis_vram_total → lmem_total_bytes, with system-RAM fallback for Intel iGPUs - L5: %%install creates /etc/mvgal/steam_profiles (SteamProfileLoader warning) - L6: mvgal-steam-setup --check finds libmvgal.so under /usr/lib/mvgal and /usr/lib64/mvgal, and the VK_LAYER_MVGAL.json manifest * Wed Aug 26 2026 AxoGM - 0.6.0-36 - docs: add DESIGN.md, IMPLEMENTATION_PLAN.md, proton-module/, benchmarks - Architecture design document with 6 ADRs and tradeoff analysis - Implementation plan with M0-M5 milestones, team roles, risk register - Proton/Wine integration guide with setup, debugging, troubleshooting - Benchmark runner script with 4 modes (synthetic, dmabuf, game, power) - Version alignment: MISSING.md and ARCHITECTURE.md bumped to 0.6.0 - ci: add GitHub Actions multi-distro workflow (.github/workflows/build.yml) - Ubuntu 24.04 (kernel 6.8, 6.11), Fedora 44, Arch Linux containers - Rust-only clippy checks, DEB package build verification * Sun Aug 23 2026 AxoGM - 0.6.0-34 - fix(tests): align GPU detection unit tests with M7 no-fabricated-VRAM design - Discrete GPUs legitimately report vram_total=0 when the vendor driver exposes no VRAM sysfs (proprietary NVIDIA, i915); only INTEGRATED GPUs are guaranteed a nonzero size (system-RAM fallback) - Memory-stats test now branches on descriptor type instead of asserting total > 0 unconditionally - Verified locally: ctest 25/25 pass on Fedora 44 with NVIDIA+Intel+AMD * Fri Aug 21 2026 AxoGM - 0.6.0-33 - fix: second-pass end-user test report fixes (Fedora 44 Secure Boot testing) - COPR: sign-file %%files entry made conditional via kernel-module.list (Mageia 9 lacks scripts/sign-file.c; hard-coded entry broke the build) - C2 SECURITY: never ship the module-signing private key; per-machine keypair generated in /var/lib/mvgal/keys by %%post (dir 0700, key 0600) - C3/M9: systemd unit no longer crash-loops — StartLimitIntervalSec=60, StartLimitBurst=5, ExecStartPre modprobe failures tolerated ('-' prefix), ntsync loaded before mvgal, /usr/sbin/modprobe, trimmed DeviceAllow - C1/M8: mvgal-enroll-mok handles --help before root check, supports pkexec re-exec, points at per-machine certificate location - H2: show-config prints the real parsed config file in both CLIs; daemon parser accepts shipped keys (debug_level, gpu_count, gpu_indices, enable_dmabuf, enable_memory_migration, [power] PSU settings) - H3: set-strategy/set-priority/set-power-curve persist via pkexec helper for non-root and return non-zero when persistence fails - H4: Vulkan layer manifest is proper layer JSON; mvgal-compat validates manifest content instead of mere file existence - H6: show-psu-status reports configured values (no fabricated 500 W) - C4: cross_vendor_compute labels simulated compute honestly - M1: exit codes audited across tools and helper scripts - M2: line-buffered stdout so messages interleave correctly - M3: /etc/mvgal/models shipped; optional-file paths documented in config - M6: --version no longer advertises Metal/Direct3D on Linux builds - M7: integrated GPUs report shared system memory instead of hardcoded 1 GiB - M10: set-power-profile help documents ' ' - L2/L4: professional default discovery port; fixed 'allocs:' spacing * Fri Aug 21 2026 AxoGM - 0.6.0-32 - fix: end-user test report fixes (27 issues from Fedora 44 Secure Boot testing) - C2: set-strategy/set-priority now persist changes to config file - C3: benchmarks return exit code 1 when no workload data is available - C4: daemon now applies log_level from config file - C5: mvgal start/stop/restart use systemctl when systemd is available - H1: IPC socket permissions changed from 0666 to 0660 (both C and C++ daemons) - H2: pkexec helper uses chown/chmod 0660 instead of chmod 0666 for device nodes - H5: systemd unit fixed (removed stale PIDFile, deprecated udev-settle, excessive capabilities; added /dev/mvgal* to DeviceAllow) - H6: enable-gpu sed now targets correct [gpu_N] section only - M3: removed duplicate polkit policy (org.freedesktop.policykit.mvgal.policy) - M4: unload-module sends SIGTERM before SIGKILL - M7: rescan-gpus error message now hints about loading the kernel module - L1: config comment corrected (higher = higher priority) - L2: added auto to valid strategy list in config comment - L3: removed empty [workload] section from default config - L4: removed init/shutdown log noise from CLI output - L6: removed duplicate mtt-dkms-installer.sh * Wed Aug 19 2026 AxoGM - 0.6.0-31 - fix: add missing OpenCL ICD file to %%files (was causing unpackaged file error) * Wed Aug 19 2026 AxoGM - 0.6.0-30 - fix: CLI bug fixes for daemon lifecycle, negative priority, unknown flags - mvgal start now rejects with error when daemon already running (was starting a second instance) - mvgal restart waits for old daemon to fully stop before starting new one - negative numbers (e.g. mvgal set-priority 0 -1) are no longer parsed as CLI flags - mvgal stop now waits for process to actually terminate before reporting success - unknown flags (e.g. mvgal --nonexistent) produce an error instead of silently showing help - mvgal reload prints the config file path for confirmation - help text shows both "single" and "single_gpu" as valid strategy names - mvgal show-config outputs INI-style format matching the config file - fix: CONF/PKG/DOC issues from end-user bug report - config/mvgal.conf: remove empty [workload] section, comment out [gpu_1] - spec: make mvgal-user-space a proper metapackage (no duplicate files) - spec: install mvgal-daemon to /usr/bin (was /usr/sbin + symlink) - man pages: add --json flag, exit codes, strategy descriptions, config keys * Sun Aug 16 2026 AxoGM - 0.6.0-29 - fix: shipped kernel modules were unsigned in the RPM (BUG #2 regression) - rpm's brp-strip runs 'strip -g' on every unstripped ELF after %%install, which drops the appended kernel module signature from the packaged .ko - compile the kernel's sign-file (kernel-devel scripts/sign-file.c) and ship it at /usr/lib/mvgal/sign-file - re-sign installed modules in %%post (main + dkms) with the shipped sign-file + per-install key, so modules are signed on the target - dkms %%post now prefers the shipped sign-file over /usr/src/kernels paths - add BuildRequires: openssl-devel (sign-file compilation) * Sun Aug 16 2026 AxoGM - 0.6.0-28 - fix: CLI arg parsing (mvgal set-strategy/enable-gpu/disable-gpu/set-priority) - Rewrote argv scan from backward to forward: first non-option is the command, subsequent non-options are its arguments (BUG #1) - fix: list-gpus now prints GPU-only listing instead of full daemon status (BUG #8) - fix: unload-module reports failure when module is not loaded (BUG #3) - fix: strategy synchronization — context strategy seeded from config, parse_strategy fallback is Single GPU, [core] default_strategy is honored (BUG #5) - fix: version consistency — libmvgal 0.2.2->0.6.0, mvgal-bench 0.4.0->0.6.0, Qt GUI/dashboard versions aligned (BUG #4) - fix: mvgal-gui / mvgal-dashboard now handle --help/--version on stdout (BUG #6/#7) - fix: config/mvgal.conf [debug] leading-space keys de-indented (ISSUE #10) - fix: remove redundant /etc/ld.so.conf.d/mvgal.conf (/usr/lib64 is default) (ISSUE #13) - feat: Secure Boot module signing — self-generated key pair installed under /usr/lib/mvgal/keys, kernel modules signed with sign-file at install time, mvgal-enroll-mok helper + %post guidance for MOK enrollment (BUG #2) * Tue Jul 28 2026 AxoGM - 0.6.0-27 - fix: RHEL 9 family class_create compat — use RHEL_MAJOR macro (not CONFIG_) - CONFIG_RHEL_MAJOR does not exist in RHEL kernel headers - Use RHEL_MAJOR from which RHEL kernel actually defines - Tested on RHEL 9, CentOS Stream 9, AlmaLinux 9 (kernel 5.14 with backported API) * Mon Jul 27 2026 AxoGM - 0.6.0-26 - fix: RHEL 9 / CentOS Stream 9 / AlmaLinux 9 compat — class_create single-arg - RHEL 9 family backported single-arg class_create() from kernel 6.4 - Use RHEL_MAJOR >= 9 alongside LINUX_VERSION_CODE check - Ensures correct API form on both vanilla and RHEL-patched kernels * Mon Jul 27 2026 AxoGM - 0.6.0-25 - fix: RHEL 8 / kernel 4.18 compatibility — class_create() two-argument form - Add LINUX_VERSION_CODE guard in mvgal_sysfs.c for kernels < 6.4 - RHEL 8 ships kernel 4.18 which requires class_create(THIS_MODULE, name) * Sun Jul 26 2026 AxoGM - 0.6.0-24 - feat: add debugfs-based trace provider (mvgal_trace.c) - Ring buffer trace system for scheduling and event logging - /sys/kernel/debug/mvgal/trace for reading events - /sys/kernel/debug/mvgal/trace_clear to clear buffer - Trace types: SCHEDULE, MEMORY, P2P, POWER, DEVICE, ERROR * Sat Jul 25 2026 AxoGM - 0.6.0-23 - feat: add PCIe P2P DMA channel management (mvgal_p2p.c) - P2P channel create/transfer/destroy lifecycle - Integrates with DMA-BUF subsystem for cross-GPU peer mapping - Tracks P2P transfer count in stats - feat: add NTSYNC synchronization primitives (mvgal_ntsync) - feat: add sysfs interface (mvgal_sysfs.c) - fix: kernel build warning — unused variable in P2P channel create * Thu Jul 23 2026 AxoGM - 0.6.0-22 - fix: include vendor/ directory in SRPM tarball for offline cargo builds - fix: mksrpm.sh now extracts git archive and adds vendor/ before repacking * Thu Jul 23 2026 AxoGM - 0.6.0-21 - fix: improve CLI argument parsing — -c/--config flag now works correctly - fix: add strtol validation for enable-gpu, disable-gpu, set-priority commands - fix: disable-gpu now refuses to disable the last enabled GPU - fix: show-stats now shows per-GPU utilization details instead of duplicating status - fix: load-module/unload-module now show actual modprobe error messages - fix: restart command no longer shows contradictory "another instance running" warning - fix: reduce default log level from INFO to WARN for cleaner CLI output - fix: benchmarks now show explanatory note when all counters are zero - fix: remove redundant version output, show human-readable log levels * Sun Jul 19 2026 AxoGM - 0.6.0-16 - fix: add MVGAL_BUILD_REPRODUCIBLE_BUILD CMake option (default ON) - fix: disable reproducible-build tool in spec — prevents unpackaged file error on chroots where json-c is a transitive dependency (mageia-cauldron) - fix: set bootstrap=off for mageia-cauldron chroot (COPR mirror fix) * Thu Jul 16 2026 AxoGM - 0.6.0-14 - feat: implement AMD sysfs power control and frequency shims for AMD, Intel, Moore Threads GPUs - chore: rebuild COPR SRPM from local HEAD (v0.6.0-17-gbb3dc47) * Wed Jul 15 2026 AxoGM - 0.6.0-13 - fix: remove mvgal-reproducible-build from files — requires json-c (not in BuildRequires) - This binary is only built when json-c-devel is present; listing it unconditionally caused all 19 COPR chroots to fail with "File not found" * Wed Jul 15 2026 AxoGM - 0.6.0-12 - refactor: kernel IDR+kref fence lifecycle (O(1) lookup, use-after-free fix) - refactor: IDR vendor table replacing fixed array in mvgal_core.c - feat: P2P NUMA affinity check — skip bounce buffer for same-NUMA GPUs - feat: NVIDIA DMA-BUF export via drm_gem_prime_export when nvidia-drm available - feat: PROXY_IOCTL passthrough for raw vendor ioctl forwarding - feat: Adreno (Qualcomm) vendor stubs — kernel + runtime - refactor: shared_ptr migration — weak_ptr lifecycle in all subsystems - fix: module load order — mvgal_ntsync must load before mvgal * Sat Jul 11 2026 AxoGM - 0.6.0-11 - fix: remove duplicate man page listing in main package %files - fix: add mvgal-reproducible-build to %files (both main and user-space) * Sat Jul 11 2026 AxoGM - 0.6.0-10 - fix: mvgal-status blocking connect() hang — use non-blocking + poll(200ms) - fix: kernel NTSYNC_QUERY ioctl for Wine/Proton synchronization - fix: GUI theme detection for Qt 6.5+ dark mode and GTK_THEME fallback - fix: power management init — add mvgal_pm_init() before status calls - fix: set_power_profile() rewrite via sysfs + pkexec tee - fix: hw-validate — skip unimplemented checks (dispatch, SPIR-V, WoW64) - chore: update .gitignore, untrack vendor/ and build artifacts * Wed Jul 08 2026 AxoGM - 0.6.0-8 - refactor: add KUnit test infrastructure (kernel/tests/, CONFIG_MVGAL_BUILD_TESTS) - chore: clean up .gitignore — remove duplicates, fix globs, drop redundant entries - fix: bump Release to 8 for fresh COPR SRPM submission * Tue Jul 07 2026 AxoGM - 0.6.0-7 - fix: wrap Qt GUI build in %%bcond_without qt_gui to skip on chroots lacking Qt (Mageia package naming mismatch, Amazon Linux 2023 has no Qt in COPR mock); MVGAL_BUILD_UI=ON, BuildRequires, and %%files all wrapped in %%if %%{with qt_gui} + %%if ! 0%%{?amzn} - fix: rework Qt detection — use %%bcond_without qt_gui (default on) instead of distro-version hacks; Mageia and Amazon Linux disable automatically via the conditional overrides * Sun Jul 05 2026 AxoGM - 0.6.0-6 - fix: use Qt5 on EL9/Mageia/AmazonLinux (no qt6-qtbase-devel available); properly conditionalize Qt6 for Fedora and RHEL 10+ only - fix: remove unregistered 'Hardware' category from mvgal-gui.desktop (mageia-cauldron desktop-file-validate rejects it) * Sun Jul 05 2026 AxoGM - 0.6.0-5 - fix: rebuild SRPM with local tarball (git archive HEAD) to include ui/mvgal-gui/ files that were missing from GitHub archive at v0.6.0 tag * Sun Jul 05 2026 AxoGM - 0.6.0-4 - feat: add Qt GUI dashboard (mvgal-gui, mvgal-dashboard) to spec - feat: add BuildRequires qt5-qtbase-devel/qt6-qtbase-devel - feat: add -DMVGAL_BUILD_UI=ON to both RHEL 8 and modern cmake blocks - feat: add GUI artifacts (binaries, .desktop, icon) to %%files sections * Sat Jul 04 2026 AxoGM - 0.6.0-2 - fix: add missing man pages to %%files (10 .1.gz installed by cmake but not packaged) - fix: correct mksrpm.sh path from pkg/rpm/ to packaging/rpm/ * Sat Jul 04 2026 AxoGM - 0.6.0-1 - Version bump to 0.6.0 (align spec with codebase) * Sat Jul 04 2026 AxoGM - 0.5.15-2 - fix: add missing include for strncmp in power_manager.cpp (fixes build on all COPR chroots - Fedora/RHEL/Mageia/Amazon Linux) * Sat Jul 04 2026 AxoGM - 0.5.15-1 - feat: implement hwmon sysfs interface for GPU power, temperature, and fan control * Sat Jul 04 2026 AxoGM - 0.5.14-1 - feat: implement NVIDIA and MTT shader backends with shared_ptr thread-safe device registry transition - feat: implement CUDA binary parser infrastructure and CCL collective communication framework - feat: add dma-buf export helpers for managing sg_table backing stores - fix: add dkms source tree to rpm %%files, add %%preun cleanup, vendor modules to dkms.conf - refactor: remove redundant mvgal_log dependency from ccl and binary parser - chore: remove dead mvgal_main.c, skip virtual DRM devices in GPU scan * Sun Jun 28 2026 AxoGM - 0.5.13-2 - refactor: remove unused mvgal_main.c entry point from kernel module (merged into mvgal_core.c; cleans up dead build artifact) - refactor: eliminate duplicated MODULE_IMPORT_NS declarations in vendor modules (no functional change, resolves GCC 15+ warnings) * Sun Jun 28 2026 AxoGM - 0.5.13-1 - feat: implement asynchronous memory migration scheduler - feat: native LLVM/AMDGPU and NVRTC shader compilation backends - feat: Vulkan ICD IPC client and virtual physical device aggregation - fix: add -lstdc++fs for std::filesystem on GCC < 9 (RHEL 8/EL8) - fix: add missing forward declarations in kernel vendor modules - fix: prevent deadlocks in Vulkan layer IPC * Thu Jun 25 2026 AxoGM - 0.5.12-1 - fix: link -lstdc++fs for std::filesystem on GCC < 9 (RHEL 8 / EL8) - fix: add missing forward declarations for query_bo in all vendor modules - fix: correct dmabuf field name (buf->dmabuf) in mvgal_amd.c and mvgal_mtt.c - Kernel modules: all 6 .ko files compile cleanly with zero errors * Thu Jun 25 2026 AxoGM - 0.5.11-1 - fix: add missing forward declarations for query_bo in all vendor modules - fix: correct dmabuf field name (buf->dmabuf) in mvgal_amd.c and mvgal_mtt.c - Kernel modules: all 6 .ko files compile cleanly with zero errors * Wed Jun 24 2026 AxoGM - 0.5.10-1 - refactor: remove queue submission throttling logic from Vulkan layer (no more artificial nanosleep-based slowdown at app startup) - fix: prevent deadlocks by replacing vulkaninfo shell calls with direct file checks and adding IPC receive timeouts - perf: reduce discovery and transport timeout intervals to improve responsiveness - feat: implement Vulkan ICD IPC client and virtual physical device aggregation * Mon Jun 22 2026 AxoGM - 0.5.9-1 - Fix ICD lazy-init: remove mvgal_init() call from mvgal_vkCreateInstance (ICD returns 0 physical devices, so mvgal_core side effects — GPU discovery, daemon connection, DRM opens — no longer fire when non-mvgal Vulkan apps load the ICD manifest) - Version bump to 0.5.9 * Sun Jun 21 2026 AxoGM - 0.5.8-4 - Fix ICD circular dependency: remove Vulkan loader link from ICD (libvulkan.so.1) - Stop exposing stub physical device in ICD - Fix VK_LAYER_MVGAL crash: remove catch-all vkGetPhysicalDevice* in vkGetInstanceProcAddr * Sat Jun 20 2026 AxoGM - 0.5.8-2 - Add missing %%{_libdir}/libmvgal_opencl.so* to main %%files and mvgal-user-space %%files sections (fixes "File not found" error on Fedora 44 and Fedora 41 where cmake installs this file) - Prevent modules-load.d/mvgal.conf from being listed twice: remove the echo-to-kernel-module.list append from %%install (the file is already listed explicitly in mvgal-dkms %%files) * Sat Jun 20 2026 AxoGM - 0.5.8-1 - data/: add D-Bus system service activation file (com.mvgal.Daemon.service) - data/: add D-Bus system policy file (mvgal-dbus.conf) for com.mvgal.Daemon - data/: add PolicyKit action file (com.mvgal.policy) for com.mvgal.Daemon - gamemode/: add libmvgal_realtime.so — Feral Interactive GameMode integration - Version bump to 0.5.8 (new data/ files + gamemode realtime library) * Wed Jun 17 2026 AxoGM - 0.5.7-1 - tools/mvgal-compat: expand DXVK/VKD3D-Proton detection to Debian/Ubuntu (/usr/lib/x86_64-linux-gnu/), Arch (/usr/share/dxvk/), NixOS (/run/current-system/sw/share/), and Flatpak/Steam Deck (/app/lib/) paths - tools/mvgal-compat: add Steam Proton directory fallback detection for DXVK and VKD3D-Proton — searches 8 Proton installation directories (Experimental, 9.0, 8.0, 7.0 across both ~/.local/share/Steam and ~/.steam/root) - tools/mvgal-compat: gaming integration DMA-BUF detection improvements - Version bump to 0.5.7 (compat.c detection logic expanded significantly) * Mon Jun 15 2026 AxoGM - 0.5.6-1 - spec: fix Release tag — replace literal backslash-t chars with real tab characters (caused "Illegal char '\' (0x5c)" rpmbuild error at SRPM creation, blocking all COPR chroots before they even start) - spec: fix %%changelog order — move Mon Jun 15 entry before Sun Jun 14 (rpmbuild enforces descending chronological order) - Version bump to 0.5.6 (v0.5.5 tag was broken — spec had bad Release line) * Mon Jun 15 2026 AxoGM - 0.5.5-1 - spec: make modules-load.d %%files entry conditional via kernel-module.list append (previously: unconditional %%files entry caused rpmbuild failure when source tarball lacked config/modules-load.d/mvgal.conf) - mvgal_ntsync.c: add #include for C89 kernel compat (RHEL 8 kernel 4.18 with -std=gnu89; module_init/exit macros undefined on older kernels where linux/miscdevice.h doesn't pull it transitively) - Version bump to 0.5.5 (force fresh COPR-dist-git tarball) - systemd: fix Type=forking → Type=simple, Wants=multi-user.target (service file had contradictory Type=forking with --no-daemon flag) - systemd: add ExecStartPre=/sbin/modprobe mvgal to auto-load kernel module before daemon starts (fixes "is mvgal loaded?" on boot) - systemd: add Alias=mvgald.service so `systemctl start mvgald` works - spec: install config/modules-load.d/mvgal.conf to auto-load mvgal and mvgal_ntsync kernel modules on boot - spec: enable mvgal-daemon.service in %%post scriptlet so it auto-starts on boot after package install * Sun Jun 14 2026 AxoGM - 0.5.5-1 - Bump to 0.5.5 to force fresh COPR-dist-git source tarball - spec: make modules-load.d/mvgal.conf install conditional (-f guard) - kernel/mvgal_ntsync.c: add missing #include - Fixes EL8 build: module_init/module_exit/MODULE_LICENSE macros undefined - Fixes all chroots: cached v0.5.4 tarball lacks modules-load.d file * Sun Jun 14 2026 AxoGM - 0.5.4-3 - Use MODULE_IMPORT_NS("DMA_BUF") string form unconditionally (fixes CentOS Stream 10 / kernel 6.12.0 build failure) * Sat Jun 13 2026 AxoGM - 0.5.4-2 - Fix MODULE_IMPORT_NS version boundary: kernel 6.12+ (not 7.0+) enforces the sizeof-based static_assert that requires a string literal. Guard now uses KERNEL_VERSION(6,12,0) (CentOS Stream 10 ships 6.12). * Fri Jun 12 2026 AxoGM - 0.5.3-1 - Fix kernel 7.0+ regression: MODULE_IMPORT_NS(DMA_BUF) guarded with LINUX_VERSION_CODE >= KERNEL_VERSION(5,14,0) && < KERNEL_VERSION(7,0,0). Kernel 7.0+ changed the MODULE_IMPORT_NS macro (moduleparam.h static assert requiring compile-time expression). Bare DMA_BUF undeclared there. Only emit on 5.14-6.x (RHEL 9/EL9) where modpost enforces namespace imports for dma-buf symbols. * Fri Jun 12 2026 AxoGM - 0.5.2-4 - Fix RHEL 9 kernel module build error: move loop-scoped 'int j' to function-top declaration in mvgal_ntsync.c (C89 compat - RHEL 9 kernel uses -std=gnu89 with -Werror=declaration-after-statement) - Fix RHEL 9 kernel modpost: MODULE_IMPORT_NS parameter is an unquoted symbol, not a string literal. Change "DMA_BUF" to DMA_BUF in all vendor .c and _main.c files (mvgal_nvidia, mvgal_amd, mvgal_intel, mvgal_mtt). On modern kernels both forms are accepted; on RHEL 9's 5.14 kernel only the unquoted form compiles. * Thu Jun 11 2026 AxoGM - 0.5.2-3 - Fix RHEL 9 modpost namespace check: add MODULE_IMPORT_NS("DMA_BUF") back into vendor impl .c files (mvgal_nvidia.c, mvgal_amd.c, mvgal_intel.c). RHEL 9's 5.14 kernel modpost checks per-object-file namespace imports; a single MODULE_IMPORT_NS in *_main.c does not satisfy the check for symbols used in other .o files of the same module. Both the .c and _main.c files now contain MODULE_IMPORT_NS("DMA_BUF"), which is harmless on modern kernels (duplicates are merged) and required on RHEL 9. * Thu Jun 11 2026 AxoGM - 0.5.2-2 - Fix %%prep failure: add -n mvgal-v%%{version} to %%setup so it matches GitHub's archive directory naming (mvgal-v0.5.2 not mvgal-0.5.2) - Fix tarball creation: use --prefix=mvgal-v0.5.2/ in git archive to match GitHub's archive structure * Thu Jun 11 2026 AxoGM - 0.5.2-1 - Fix .ko install ordering: move find %{_builddir} -name '*.ko' -delete to AFTER the install loop (was running before, so kernel module .ko files were deleted from the source tree before the spec could install them, resulting in RPMs with no .ko files and broken kernel module packages) * Thu Jun 11 2026 AxoGM - 0.5.1-1 - Fix MODULE_IMPORT_NS("DMA_BUF") placement: move from vendor impl .c files to vendor *_main.c entry points (mvgal_nvidia_main.c, mvgal_amd_main.c, mvgal_intel_main.c) where MODULE_LICENSE lives — kernel modpost requires namespace import in the same compilation unit as the module declaration * Thu Jun 11 2026 AxoGM - 0.5.0-1 - Multi-module refactoring: split kernel into per-vendor modules (mvgal.ko core, mvgal_ntsync.ko, vendor modules) - Fix 9 kernel build warnings (unused functions/variables) - Update MODULE_AUTHOR to 'AxoGM' across all kernel modules - Fix cmake .ko filenames to match Kbuild output (mvgal.ko not mvgal_core.ko) - Install all kernel modules via generated file list * Thu Jun 11 2026 AxoGM - 0.4.0-7 - Fix: add missing 'void *bo' field to struct mvgal_nvidia_alloc (struct was defined in header without the bo member, causing 'no member named bo' error on all chroots) * Thu Jun 11 2026 AxoGM - 0.4.0-8 - Fix COPR build failure: add %%{_bindir}/mvgal-hw-validate to %%files (built by tools/CMakeLists.txt but missing from packaging manifest) * Thu Jun 11 2026 AxoGM - 0.4.0-7 - Fix kernel module struct mvgal_nvidia_alloc missing 'void *bo' member * Thu Jun 11 2026 AxoGM - 0.4.0-6 - Fix: previous 0.4.0-5 changes were uncommitted - git archive shipped stale tarball without the dma-buf-map.h removal * Thu Jun 11 2026 AxoGM - 0.4.0-5 - Fix kernel module build on kernel >= 5.19: remove dead include from all 4 vendor files (mvgal_amd.c, mvgal_intel.c, mvgal_nvidia.c, mvgal_mtt.c); renamed to upstream and MVGAL never used any symbol from that header * Tue Jun 09 2026 AxoGM - 0.4.0-4 - Fix Mageia Cauldron build: use %%files -f with generated file list (Mageia's RPM errors on unmatched %%files globs when kernel-devel absent; previous glob-based approach failed with "File not found: ...*.ko") - Fallback file list uses %%dir %%{_prefix}/lib/mvgal anchor so the -f file is never empty (Mageia also rejects empty %%files -f files) * Sun Jun 07 2026 AxoGM - 0.4.0-2 - Fix almalinux-kitten-10 build: set COPR per-chroot --without dkms (dkms not available in those repos; EPEL chroot variant has it) * Sun May 31 2026 AxoGM - 0.2.19-1 - Kernel full stack fix: pass MVGAL_BUILD_FULL_STACK=1 to make in CMake - Fix modpost undefined symbols (mvgal_set_power_state, mvgal_logical_device) - Bump Version to 0.2.19 * Sun May 31 2026 AxoGM - 0.2.9-1 - Update Version to 0.2.9 - Fix unclosed %if in changelog * Sat May 30 2026 AxoGM - 0.2.7-2 - Add DKMS support with --with-dkms build option - Update DKMS configuration for full stack build * Sat May 30 2026 AxoGM - 0.2.7-1 - Fix GCC 15+ preprocessor rejecting RHEL_RELEASE_VERSION(9,0) even with defined() guard. Use #ifndef RHEL_RELEASE_VERSION fallback define instead. - Version bump to 0.2.7 - Fix class_create on EL9: kernel 5.14 backports the 1-arg class_create API from kernel 6.4. Guard with defined(RHEL_RELEASE_CODE) check alongside LINUX_VERSION_CODE in both mvgal_main.c and mvgal_core.c. - Fix kernel module build on EL8: add BuildRequires: elfutils-libelf-devel for ORC unwinder support. - Fix unpackaged mvgal-load/mvgal-unload on openSUSE Tumbleweed: add fallback install in spec %%install section when cmake skips them (kernel/CMakeLists.txt returns early when KERNEL_HEADERS not found). * Sat May 30 2026 AxoGM - 0.2.17-1 - Lower MODULE_IMPORT_NS threshold to 6.12.0 for RHEL 10 compatibility * Sat May 30 2026 AxoGM - 0.2.16-1 - Fix MODULE_IMPORT_NS syntax for older kernels (DMA_BUF as symbol) * Sat May 30 2026 AxoGM - 0.2.15-1 - Include linux/pci-p2pdma.h for compatibility with older kernels (RHEL 9) * Sat May 30 2026 AxoGM - 0.2.14-1 - Fix kernel module redefinition of mvgal_detect_all_p2p in mvgal_device.c - Fix kernel module warnings (unused variables, unused label, double unlock) - Package missing libmvgal_wow64.so library * Sat May 30 2026 AxoGM - 0.2.13-1 - Fix duplicated code in mvgal_device.c - remove orphaned code block - Remove mistakenly duplicated code outside any function * Sat May 30 2026 AxoGM - 0.2.12-1 - Fix missing linux/version.h include in mvgal_device.c - LINUX_VERSION_CODE and KERNEL_VERSION macros require this header * Sat May 30 2026 AxoGM - 0.2.11-1 - Fix kernel module build: enable MVGAL_BUILD_FULL_STACK=1 for full kernel module - Build full kernel module stack including power management and core symbols * Sat May 30 2026 AxoGM - 0.2.10-1 - Fix kernel module build: add mvgal_power.c to MODULE_SOURCES (was missing, caused undefined symbol errors) - Add mvgal_power.h to MODULE_HEADERS * Sat May 30 2026 AxoGM - 0.2.9-1 - Fix kernel module build: add mvgal_power.c to MODULE_SOURCES (was missing, caused undefined symbol errors) - Add mvgal_power.h to MODULE_HEADERS * Sat May 30 2026 AxoGM - 0.2.8-1 - Fix kernel module build on Mageia 9: add /usr/src/linux-* to kernel header search paths - Fix empty kernel-module.list error by adding comment line instead of empty file - Mageia uses /usr/src/linux- instead of /usr/src/kernels/ for kernel headers * Sat May 30 2026 AxoGM - 0.2.7-1 - Fix GCC 15+ preprocessor rejecting RHEL_RELEASE_VERSION(9,0) even with defined() guard. Use #ifndef RHEL_RELEASE_VERSION fallback define instead. - Version bump to 0.2.7 * Sat May 30 2026 AxoGM - 0.2.6-1 - Fix RHEL_RELEASE_VERSION undefined on non-RHEL (Fedora 42/43/44, Amazon Linux 2023) GCC 15+ preprocessor rejects RHEL_RELEASE_VERSION(9,0) as syntax error when RHEL_RELEASE_VERSION is not defined. Add defined(RHEL_RELEASE_VERSION) guard. - Version bump to 0.2.6 * Sat May 30 2026 AxoGM - 0.2.5-1 - Version bump to 0.2.5 - Fix class_create on EL9: kernel 5.14 backports the 1-arg class_create API from kernel 6.4. Guard with defined(RHEL_RELEASE_CODE) check alongside LINUX_VERSION_CODE in both mvgal_main.c and mvgal_core.c. - Fix kernel module build on EL8: add BuildRequires: elfutils-libelf-devel for ORC unwinder support. - Fix unpackaged mvgal-load/mvgal-unload on openSUSE Tumbleweed: add fallback install in spec %%install section when cmake skips them (kernel/CMakeLists.txt returns early when KERNEL_HEADERS not found). * Sun May 24 2026 AxoGM - 0.2.3-12 - Fix kernel module not built in COPR mock: kernel-devel alone puts headers under /usr/src/kernels/, NOT /lib/modules//build (the build symlink only exists when the full kernel meta-package is installed). Add /usr/src/kernels/* to search paths for KERNEL_BUILD_DIR (%%build) and KERNEL_RELEASE (%%install). Switch from ls to portable for/glob loop to avoid empty-directory colon noise. * Sun May 24 2026 AxoGM - 0.2.3-10 - Fix unpackaged files: remove cmake-installed mvgal.ko (wrong path under BUILDROOT) via find -delete in %%install; add %%{_bindir}/mvgal-load and %%{_bindir}/mvgal-unload to %%files. Bump Release to 10. * Sun May 24 2026 AxoGM - 0.2.3-9 - Fix kernel module install: manually install mvgal.ko in %%install section with dynamic file list (%%files -f) instead of relying on cmake's install(CODE COMPONENT kernel) which didn't place .ko into BUILDROOT. Empty file list created when .ko not built, so rpmbuild doesn't error. Bump Release to 9. * Sun May 24 2026 AxoGM - 0.2.3-8 - Enable kernel module (MVGAL_BUILD_KERNEL=ON) for all chroots. Add BuildRequires: kernel-devel and pass KERNEL_HEADERS from the spec so the find_path in kernel/CMakeLists.txt resolves to the mock/COPR chroot's kernel-devel instead of the build host's uname -r. Fix kernel module install path from %{_libdir}/modules/ (lib64) to lib/modules/ (correct). Add depmod -a to %%post/%%postun for modprobe mvgal support. * Sun May 24 2026 AxoGM - 0.2.3-7 - Fix RHEL 8 linker error: mvgald missing libmvgal_core.a on in-source cmake builds (cmake 3.26 EPEL). Use add_dependencies(mvgald mvgal_core) for build ordering and $ generator expression for absolute library path, which works in both in-source and out-of-source builds. * Thu May 21 2026 AxoGM - 0.2.3-6 - Enable MVGAL_BUILD_GAMING=ON on Fedora and all non-RHEL targets (%%else branch in %%build section) so Gaming integration shows as ON in COPR builds for Fedora, openSUSE, CentOS Stream, Amazon Linux, etc. This was previously only set in the %%if rhel == 8 branch. * Thu May 21 2026 AxoGM - 0.2.3-5 - GCC 8 LTO: guard -flto with version check (GCC < 9) in root CMakeLists.txt so the LTO option is never emitted for RHEL 8 / GCC 8 builds. Removes the need for spec-level sed stripping of -flto from generated build files. - Enable MVGAL_BUILD_GAMING=ON on RHEL 8 for Steam/Proton gaming integration. - mvgal_ai.c excluded from mvgal_core unless MVGAL_BUILD_GAMING=ON; gaming API functions only compiled when gaming integration is active. * Tue May 19 2026 AxoGM - 0.2.3-4 - Fix RHEL 8 linker error: add mvgal_ai.c to mvgal_core static library in src/userspace/CMakeLists.txt, link mvgal_core into mvgald. cmake refuses to compile source files listed via absolute or ../ paths from a different source tree (previous attempt). Reorder root CMakeLists.txt so src/userspace is processed before runtime, ensuring mvgal_core target exists for linking. * Tue May 19 2026 AxoGM - 0.2.3-2 - Fix RHEL 8 %%cmake macro breakage: cmake-rpm-macros 3.26 from EPEL emits "does in-source builds." as literal cmake arguments. Bypass %%cmake on RHEL 8 and invoke cmake directly with equivalent flags. - Keep %%cmake for all other chroots (Fedora, RHEL 9+, openSUSE, etc.) - Retain RHEL 8 LTO workaround (sed strip -flto from cmake build files) * Tue May 19 2026 AxoGM - 0.2.3-1 - Updated to version 0.2.3 - Fix SYCL backend: use correct mvgal_gpu_descriptor_t/mvgal_gpu_get_descriptor API - Fix Source0 to use GitHub archive URL - Enable Rust safety crates (BuildRequires rust cargo) * Mon May 18 2026 AxoGM - 0.2.2-21 - Fix RHEL 8 LTO: strip -flto from cmake-generated build files (flags.make, build.make, link.txt, .rsp) via sed after %%cmake configures but before %%cmake_build runs. Fresh mock chroot — no side effects. This bypasses the cmake-rpm-macros Lua %%cmake which injects -flto immune to all other override approaches (env CFLAGS, %%_lto_cflags, rm redhat-lto.cmake, -D cache variable overrides, -fno-lto compile/link options) * Mon May 18 2026 AxoGM - 0.2.2-20 - Fix RHEL 8 LTO: bypass %%cmake Lua macro entirely — invoke cmake directly with CFLAGS="%%{optflags}" only (no %%{_lto_cflags}). The %%cmake macro on RHEL 8 cmake 3.26 EPEL injects -flto in a way immune to all overrides (env, cache vars, system file patching). Direct cmake invocation with optflags on RHEL 8 does NOT include -flto (it comes from _lto_cflags which we bypass). On Fedora 44+, optflags include -flto=auto which modern GCC handles fine. * Mon May 18 2026 AxoGM - 0.2.2-19 - Fix RHEL 8 LTO: bypass %%cmake Lua macro entirely (cmake-rpm-macros on RHEL 8 cmake 3.26 from EPEL injects -flto immune to all normal overrides); invoke cmake directly with clean CFLAGS (optflags only, no _lto_cflags) - Extract common cmake args into %%mvgal_cmake_args macro shared by both RHEL 8 and non-RHEL build paths * Mon May 18 2026 AxoGM - 0.2.2-18 - Fix RHEL 8 LTO: build libmvgal_core.a with -fno-lto via GCC version check (GCC < 9) in src/userspace/CMakeLists.txt so static archive contains no LTO bytecode — GCC 8's LTO plugin cannot misinterpret regular bytecode. Remove all spec-level LTO workarounds (rhel_cmake_no_lto, CFLAGS stripping, redhat-lto.cmake removal) that fought the %%cmake macro in vain. * Mon May 18 2026 AxoGM - 0.2.2-17 - Fix RHEL 8 LTO: override CMAKE_C_FLAGS/CXX_FLAGS/C_FLAGS_RELEASE/ CXX_FLAGS_RELEASE via cmake -D cache vars instead of env CFLAGS sed (%%cmake macro assigns CFLAGS directly overriding env overrides) - Remove redhat-lto.cmake rm and CFLAGS env stripping (both ineffective) * Mon May 18 2026 AxoGM - 0.2.2-16 - Fix RHEL 8 LTO: strip -flto from CFLAGS/CXXFLAGS in %%build section via sed before %%cmake, and use set_target_properties(LINK_FLAGS "-fno-lto") unconditionally (removes cmake version conditional) — the RPM optflags persist -flto in CMAKE_C_FLAGS regardless of redhat-lto.cmake removal, and target_link_options on cmake 3.26 places -fno-lto before -flto in the link command so GCC picks -flto (last flag wins) * Mon May 18 2026 AxoGM - 0.2.2-15 - Fix RHEL 8 LTO: use LINK_FLAGS property (cmake <3.13) and target_link_options (cmake >=3.13) to add -fno-lto at link time in add_mvgal_tool(); remove redhat-lto.cmake in %%prep (sed didn't match file content); add_mvgal_tool handles compile + link separately so LTO is fully disabled for mvgal-config and mvgal-bin targets * Mon May 18 2026 AxoGM - 0.2.2-14 - Fix RHEL 8 LTO: patch redhat-lto.cmake in %%prep to set CMAKE_INTERPROCEDURAL_OPTIMIZATION=FALSE (system cmake module overrides both per-target properties and cache variables; GCC 8 LTO plugin drops static archive symbols regardless of workarounds) * Mon May 18 2026 AxoGM - 0.2.2-13 - Fix RHEL 8 LTO: disable globally via -DCMAKE_INTERPROCEDURAL_OPTIMIZATION:BOOL=OFF instead of per-target properties; redhat-lto.cmake on cmake 3.26 overrides per-target IPO settings and GCC 8 LTO plugin drops static archive symbols regardless of --whole-archive/-fno-lto tricks * Mon May 18 2026 AxoGM - 0.2.2-12 - Fix RHEL 8 LTO: use INTERPROCEDURAL_OPTIMIZATION per-target property (cmake 3.9+) in tools/CMakeLists.txt instead of CMAKE_C_FLAGS_RELEASE override; target_link_options requires cmake 3.13+ (RHEL 8 ships 3.11) * Mon May 18 2026 AxoGM - 0.2.2-11 - Fix RHEL 8 LTO: use single-line %%define to avoid shell expansion bug - Override CMAKE_C_FLAGS_RELEASE to strip -flto on RHEL 8 only * Mon May 18 2026 AxoGM - 0.2.2-10 - RHEL 8: override CMAKE_C_FLAGS_RELEASE to strip -flto (RPM _lto_cflags macro unreliable on COPR mock); GCC 8 LTO plugin drops static archive symbols * Mon May 18 2026 AxoGM - 0.2.2-9 - Fix RHEL 8 LTO: disable LTO entirely via %%_lto_cflags on RHEL 8 - GCC 8 / older binutils LTO plugin drops symbols from static archives even with --whole-archive or per-target -fno-lto; the RPM-level %%_lto_cflags macro is the only reliable way to suppress -flto * Mon May 18 2026 AxoGM - 0.2.2-8 - Fix RHEL 8 LTO linker: add -fno-lto to both compile and link for mvgal tools - RHEL 8 / GCC 8 LTO plugin drops static archive symbols even with --whole-archive; per-target -fno-lto at compile + link suppresses the LTO plugin entirely * Mon May 18 2026 AxoGM - 0.2.2-7 - Fix RHEL 8 LTO: disable per-target -flto for mvgal-config and mvgal-bin with -fno-lto override; GCC 8 LTO plugin drops unresolved symbols from static archives even with --whole-archive wrapper * Mon May 18 2026 AxoGM - 0.2.2-6 - Fix RHEL 8 LTO linker: use -Wl,--push-state,--whole-archive flags directly in target_link_libraries (not target_link_options) so --whole-archive is placed right before libmvgal_core.a in the library link order - Also apply to mvgal-config and mvgal-bin tools * Mon May 18 2026 AxoGM - 0.2.2-5 - Fix source tarball: use --prefix=mvgal-0.2.2/ so %%setup finds source dir - Enable CLI tools (MVGAL_BUILD_TOOLS=ON) with all binaries in %%files - Fix RHEL 8 LTO: wrap libmvgal_core with --whole-archive in link step - Add mvgal-probe, mvgal_amd_external_mem, libmvgal.so*, cmake config to %%files - Update shell-completion %%files to include bash/zsh completions * Mon May 18 2026 AxoGM - 0.2.2-4 - Fix RHEL 8 LTO linker error: wrap mvgal_core with --whole-archive in tools/CMakeLists.txt so older GCC 8.x resolves mvgal_* symbols from the static archive during LTO link phase * Mon May 18 2026 AxoGM - 0.2.2-3 - Fix unpackaged files from MVGAL_BUILD_TOOLS=ON: add mvgal-probe, mvgal_amd_external_mem, libmvgal.so*, and CMake config files to %%files * Mon May 18 2026 AxoGM - 0.2.2-2 - Enable MVGAL_BUILD_TOOLS=ON to build and package CLI tools (mvgal, mvgal-info, mvgal-status, mvgal-bench, mvgal-compat, mvgal-config, mvgal-steam-setup) * Sat May 16 2026 AxoGM - 0.2.2-1 - Version bump to 0.2.2 - Add libmvgal_prometheus.a and libmvgal_sycl_backend.a to %%files (fix unpackaged files error on COPR) - Fix Release numbering for 0.2.2 * Wed May 13 2026 AxoGM - 0.2.1-13 - Fix COPR source script: use packaging/rpm/mvgal.spec instead of pkg/rpm/mvgal.spec (broken path preventing SRPM builds) * Sun May 10 2026 AxoGM - 0.2.1-12 - Fix openSUSE documentation directory: use %%{_docdir}/mvgal/ instead of %%{_datadir}/doc/mvgal/ (%%{_datadir}/doc/ != %%{_docdir}/ on openSUSE) - Fix GCC 7.5 (openSUSE Leap 15.6) cmake configure: remove redundant target_compile_features(mvgald PRIVATE cxx_std_20) from runtime/CMakeLists.txt (CMAKE_CXX_STANDARD 20 already set at project level) - Fix C17 cmake configure error on older CMake (Mageia 8, CMake 3.20): conditionally use C17 only for CMake >= 3.21, fall back to C11 * Sun May 10 2026 AxoGM - 0.2.1-11 - Fix distro-specific package names: use pkgconfig(vulkan) instead of vulkan-loader for cross-distro portability (Fedora, RHEL, Mageia, openSUSE) - Use distro conditionals: ninja-build (Fedora/Mageia) vs ninja (openSUSE); vulkan-loader (Fedora/RHEL) vs lib64vulkan-loader1 (Mageia) vs libvulkan1 (openSUSE) for runtime dependency * Sun May 10 2026 AxoGM - 0.2.1-10 - Fix unpackaged files error: add pkexec helper, DKMS installer scripts, udev rules, and PolicyKit policy to %%files section * Sun May 10 2026 AxoGM - 0.2.1-9 - Add missing forward declaration for mvgal_get_queue_family_properties in device_group.c fixes implicit-declaration error * Sun May 10 2026 AxoGM - 0.2.1-8 - Fix implicit declaration error in device_group.c: rename mvgal_gpu_get_queue_family_properties to mvgal_get_queue_family_properties (function never existed, was a code artifact) * Sun May 10 2026 AxoGM - 0.2.1-7 - Fix fatal error: mvgal/mvgal.h: No such file or directory when building vk_layer.c on Fedora 44+: add missing ${MVGAL_INCLUDE_DIRS} to the vulkan layer CMake target include paths * Sun May 10 2026 AxoGM - 0.2.1-6 - Fix implicit declaration error on GCC 15+ (Fedora Rawhide): remove dead call to mvgal_rewrite_update_gpu_utilization from load_balancer.c * Sun May 10 2026 AxoGM - 0.2.1-5 - Add CMake compatibility aliases for subdirectory CMakeLists that reference old-style find_package patterns (DRM_IMPORTED_TARGET, PCI_IMPORTED_TARGET, UDEV_IMPORTED_TARGET) - Fix unconditional opengl and vulkan_icd subdirectory builds to be discoverable from parent CMakeLists.txt * Thu May 07 2026 AxoGM - 0.2.1-4 - Fix unpackaged files error: add headers (%%{_includedir}/mvgal/) and documentation (%%{_datadir}/doc/mvgal/) to %%files section - Add proper %%bcond_without opencl for conditional OpenCL library inclusion - Add ocl-icd-devel to BuildRequires (was missing for OpenCL support) - Remove duplicate BuildRequires: opencl-headers - Add %%dir %%{_localstatedir}/log/mvgal to %%files and %%install sections - Fix %%files section to properly conditionally include libmvgal_opencl.so * Wed May 06 2026 AxoGM - 0.2.1-2 - Fix CMake install paths to use CMAKE_INSTALL_LIBDIR instead of hardcoded "lib" This ensures libraries install to lib64 on 64-bit systems automatically - Remove complex versioned symlink logic from spec %%install (now handled by CMake) - Add missing API interception libraries to %%files section: libmvgal_opencl.so, libmvgal_d3d.so, libmvgal_metal.so, libmvgal_webgpu.so - Simplify spec file by relying on CMake GNUInstallDirs for proper paths * Mon May 04 2026 AxoGM - 0.2.1-1 - Fix ldconfig "not a symbolic link" warnings for libmvgal shared libs by installing versioned .so.MAJOR.MINOR.PATCH files with proper symlinks - Switch from manual /sbin/ldconfig call to %%ldconfig_scriptlets macro to avoid surfacing unrelated MTT driver packaging issues - Fix config file path: packaging/rpm/mvgal.conf (was rpm/mvgal.conf) - Fix service file path: packaging/rpm/mvgal-daemon.service - Switch %%build/%%install to %%cmake/%%cmake_build/%%cmake_install macros - Add pciutils-devel and pciaccess to BuildRequires - Add /etc/ld.so.conf.d/mvgal.conf fragment for reliable library discovery - Add %%preun service disable on uninstall * Tue Apr 21 2026 AxoGM - 0.2.0-1 - Updated to version 0.2.0 "Health Monitor" - GPU health monitoring with temperature, utilization tracking - Comprehensive scheduler with 7 strategies - DMA-BUF based cross-GPU memory management - OpenCL interception layer * Sun Apr 19 2026 AxoGM - 0.1.0-1 - Initial release - GPU detection, scheduler, memory manager - Vulkan layer, CUDA wrapper - Daemon for background GPU management