mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-09-14 10:47:36 +00:00
refine post-install and hardware GPU docs, Monitor UX and CLI styling
- rewrite the 15 post-install pages and the 3 hardware GPU pages so they reflect the current scripts (reversibility, tracked-tool counts, kernel parameters, per-tool commands, Alpine LXC propagation flow) - migrate the legacy step-badge helper on post-install/optional and create-vm/synology to the canonical pill component, with the stepLabel key added in each locale - fix rich-text i18n calls missing helpers across network, automated, optional, security, customization and the post-install landing pages, and escape the `<iface>` placeholder in automated so intl no longer parses it as a tag - remove the mouse-follow blue overlay from the docs landing layout - reposition the App-tab Edit button and stack the Search and Register controls vertically on mobile - move the Bulk update Configure/Edit control into the section header so it behaves the same on desktop and mobile - show a spinner during the final autoremove/autoclean pass of update-pve-safe so the cleanup step reads as active instead of silent - restyle the shell spinner and msg_info in a distinctive purple and drop the unused msg_lang duplicate - add a web-docs i18n build script and its CI workflow, plus tests for the pushover notification channel
This commit is contained in:
+50
-110
@@ -5,8 +5,8 @@
|
||||
# Author : MacRimi
|
||||
# Copyright : (c) 2024 MacRimi
|
||||
# License : GPL-3.0
|
||||
# Version : 1.0
|
||||
# Last Updated: 03/04/2026
|
||||
# Version : 1.1
|
||||
# Last Updated: 26/08/2026
|
||||
# ==========================================================
|
||||
# Description:
|
||||
# Automates full GPU passthrough (VFIO) from Proxmox host to a VM.
|
||||
@@ -323,25 +323,40 @@ evaluate_host_reboot_requirement() {
|
||||
_file_has_exact_line "$mod" "$modules_file" || needs_change=true
|
||||
done
|
||||
|
||||
# vfio-pci ids
|
||||
# VFIO ownership. NVIDIA uses exact BDFs so another GPU with the same
|
||||
# vendor:device ID can remain native; AMD/Intel keep the legacy IDs list.
|
||||
local vfio_conf="/etc/modprobe.d/vfio.conf"
|
||||
local ids_line ids_part
|
||||
ids_line=$(grep "^options vfio-pci ids=" "$vfio_conf" 2>/dev/null | head -1)
|
||||
if [[ -z "$ids_line" ]]; then
|
||||
needs_change=true
|
||||
else
|
||||
[[ "$ids_line" == *"disable_vga=1"* ]] || needs_change=true
|
||||
ids_part=$(echo "$ids_line" | grep -oE 'ids=[^[:space:]]+' | sed 's/ids=//')
|
||||
local existing_ids=()
|
||||
IFS=',' read -ra existing_ids <<< "$ids_part"
|
||||
local required found existing
|
||||
for required in "${IOMMU_VFIO_IDS[@]}"; do
|
||||
found=false
|
||||
for existing in "${existing_ids[@]}"; do
|
||||
[[ "$existing" == "$required" ]] && found=true && break
|
||||
done
|
||||
$found || needs_change=true
|
||||
if [[ "$SELECTED_GPU" == "nvidia" ]]; then
|
||||
local required_bdf
|
||||
for required_bdf in "${IOMMU_DEVICES[@]}"; do
|
||||
if ! declare -F _proxmenux_vfio_bind_has_bdf >/dev/null 2>&1 \
|
||||
|| ! _proxmenux_vfio_bind_has_bdf "$required_bdf"; then
|
||||
needs_change=true
|
||||
fi
|
||||
done
|
||||
_file_has_exact_line "softdep nvidia pre: vfio-pci" "$vfio_conf" || needs_change=true
|
||||
_file_has_exact_line "softdep nvidia_drm pre: vfio-pci" "$vfio_conf" || needs_change=true
|
||||
_file_has_exact_line "softdep nvidia_modeset pre: vfio-pci" "$vfio_conf" || needs_change=true
|
||||
_file_has_exact_line "softdep nvidia_uvm pre: vfio-pci" "$vfio_conf" || needs_change=true
|
||||
else
|
||||
ids_line=$(grep "^options vfio-pci ids=" "$vfio_conf" 2>/dev/null | head -1)
|
||||
if [[ -z "$ids_line" ]]; then
|
||||
needs_change=true
|
||||
else
|
||||
[[ "$ids_line" == *"disable_vga=1"* ]] || needs_change=true
|
||||
ids_part=$(echo "$ids_line" | grep -oE 'ids=[^[:space:]]+' | sed 's/ids=//')
|
||||
local existing_ids=()
|
||||
IFS=',' read -ra existing_ids <<< "$ids_part"
|
||||
local required found existing
|
||||
for required in "${IOMMU_VFIO_IDS[@]}"; do
|
||||
found=false
|
||||
for existing in "${existing_ids[@]}"; do
|
||||
[[ "$existing" == "$required" ]] && found=true && break
|
||||
done
|
||||
$found || needs_change=true
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
# modprobe options files
|
||||
@@ -362,21 +377,16 @@ evaluate_host_reboot_requirement() {
|
||||
case "$SELECTED_GPU" in
|
||||
nvidia)
|
||||
_file_has_exact_line "blacklist nouveau" "$blacklist_file" || needs_change=true
|
||||
_file_has_exact_line "blacklist nvidia" "$blacklist_file" || needs_change=true
|
||||
_file_has_exact_line "blacklist nvidia_drm" "$blacklist_file" || needs_change=true
|
||||
_file_has_exact_line "blacklist nvidia_modeset" "$blacklist_file" || needs_change=true
|
||||
_file_has_exact_line "blacklist nvidia_uvm" "$blacklist_file" || needs_change=true
|
||||
_file_has_exact_line "blacklist nvidiafb" "$blacklist_file" || needs_change=true
|
||||
_file_has_exact_line "blacklist lbm-nouveau" "$blacklist_file" || needs_change=true
|
||||
_file_has_exact_line "options nouveau modeset=0" "$blacklist_file" || needs_change=true
|
||||
[[ -f /etc/modules-load.d/nvidia-vfio.conf ]] && needs_change=true
|
||||
grep -qE '^(nvidia|nvidia_uvm|nvidia_drm|nvidia_modeset)$' /etc/modules 2>/dev/null && needs_change=true
|
||||
local svc
|
||||
for svc in nvidia-persistenced.service nvidia-persistenced nvidia-powerd.service nvidia-fabricmanager.service; do
|
||||
if systemctl is-active --quiet "$svc" 2>/dev/null || systemctl is-enabled --quiet "$svc" 2>/dev/null; then
|
||||
needs_change=true
|
||||
fi
|
||||
done
|
||||
# The managed global NVIDIA blacklist is required only when
|
||||
# every NVIDIA GPU is in VFIO. On a mixed host it must be absent.
|
||||
if declare -F _proxmenux_all_nvidia_in_vfio >/dev/null 2>&1 \
|
||||
&& _proxmenux_all_nvidia_in_vfio; then
|
||||
[[ -f /etc/modprobe.d/proxmenux-nvidia-vfio-blacklist.conf ]] || needs_change=true
|
||||
else
|
||||
[[ -f /etc/modprobe.d/proxmenux-nvidia-vfio-blacklist.conf ]] && needs_change=true
|
||||
fi
|
||||
;;
|
||||
amd)
|
||||
_file_has_exact_line "blacklist radeon" "$blacklist_file" || needs_change=true
|
||||
@@ -1611,8 +1621,8 @@ configure_vfio_pci_ids() {
|
||||
# NVIDIA: per-BDF binding (multi-GPU safe). The `options vfio-pci
|
||||
# ids=VENDOR:DEVICE` approach captures EVERY GPU with the same
|
||||
# vendor:device ID — fatal when two NVIDIA GPUs share a model.
|
||||
# Instead, we list the exact BDF(s) of the target GPU in the
|
||||
# initramfs hook, and add `softdep nvidia pre: vfio-pci` so vfio
|
||||
# Instead, we list the exact BDF(s) of the target GPU in an early
|
||||
# udev driver_override rule, and add `softdep nvidia pre: vfio-pci` so vfio
|
||||
# has a chance to claim the BDF before nvidia loads.
|
||||
# ────────────────────────────────────────────────────────────────
|
||||
if [[ "$SELECTED_GPU" == "nvidia" ]]; then
|
||||
@@ -1649,7 +1659,7 @@ configure_vfio_pci_ids() {
|
||||
_add_line_if_missing "softdep nvidia_modeset pre: vfio-pci" "$vfio_conf"
|
||||
_add_line_if_missing "softdep nvidia_uvm pre: vfio-pci" "$vfio_conf"
|
||||
|
||||
# Per-BDF binder hook. IOMMU_DEVICES has the BDFs for the GPU
|
||||
# Per-BDF binder rule. IOMMU_DEVICES has the BDFs for the GPU
|
||||
# we're passing (and any same-group functions like the audio
|
||||
# function). Add all of them so the whole IOMMU group goes to
|
||||
# vfio-pci as Proxmox expects.
|
||||
@@ -1755,85 +1765,15 @@ blacklist_gpu_drivers() {
|
||||
}
|
||||
|
||||
sanitize_nvidia_host_stack_for_vfio() {
|
||||
# In the new per-BDF model we only stop systemd services that could
|
||||
# actively probe / lock GPUs at boot (persistenced) — but we DO NOT:
|
||||
# - blacklist the nvidia kernel module
|
||||
# - remove nvidia entries from /etc/modules
|
||||
# - rename /etc/modules-load.d/nvidia-vfio.conf
|
||||
# - rename /etc/udev/rules.d/70-nvidia.rules
|
||||
# - create /etc/modprobe.d/nvidia-blacklist.conf with install /bin/false
|
||||
# All of those were global and broke multi-GPU NVIDIA scenarios where
|
||||
# one GPU goes to a VM (vfio-pci) and another stays on the host
|
||||
# (nvidia driver). VFIO binding is now per-BDF via driver_override in
|
||||
# an initramfs hook — the nvidia module stays usable for any GPU not
|
||||
# explicitly targeted.
|
||||
# Host-wide NVIDIA services and module blacklisting are derived from
|
||||
# the complete per-BDF state. With two NVIDIA GPUs, assigning only one
|
||||
# to a VM keeps the native driver and services available for the other.
|
||||
msg_info "$(translate 'Sanitizing NVIDIA host services for VFIO mode...')"
|
||||
local changed=false
|
||||
local state_dir="/var/lib/proxmenux"
|
||||
local state_file="${state_dir}/nvidia-host-services.state"
|
||||
local svc
|
||||
local -a services=(
|
||||
"nvidia-persistenced.service"
|
||||
"nvidia-powerd.service"
|
||||
"nvidia-fabricmanager.service"
|
||||
)
|
||||
|
||||
mkdir -p "$state_dir" >/dev/null 2>&1 || true
|
||||
: > "$state_file"
|
||||
|
||||
for svc in "${services[@]}"; do
|
||||
local was_enabled=0 was_active=0
|
||||
if systemctl is-enabled --quiet "$svc" 2>/dev/null; then
|
||||
was_enabled=1
|
||||
fi
|
||||
if systemctl is-active --quiet "$svc" 2>/dev/null; then
|
||||
was_active=1
|
||||
fi
|
||||
if (( was_enabled == 1 || was_active == 1 )); then
|
||||
echo "${svc} enabled=${was_enabled} active=${was_active}" >>"$state_file"
|
||||
fi
|
||||
|
||||
if systemctl is-active --quiet "$svc" 2>/dev/null; then
|
||||
systemctl stop "$svc" >>"$LOG_FILE" 2>&1 || true
|
||||
changed=true
|
||||
fi
|
||||
if systemctl is-enabled --quiet "$svc" 2>/dev/null; then
|
||||
systemctl disable "$svc" >>"$LOG_FILE" 2>&1 || true
|
||||
changed=true
|
||||
fi
|
||||
done
|
||||
|
||||
[[ -s "$state_file" ]] || rm -f "$state_file"
|
||||
|
||||
if $changed; then
|
||||
HOST_CONFIG_CHANGED=true
|
||||
_proxmenux_nvidia_vfio_policy_sync || true
|
||||
if _proxmenux_all_nvidia_in_vfio; then
|
||||
msg_ok "$(translate 'NVIDIA host services disabled for VFIO mode')" | tee -a "$screen_capture"
|
||||
else
|
||||
msg_ok "$(translate 'NVIDIA host services already aligned for VFIO mode')" | tee -a "$screen_capture"
|
||||
fi
|
||||
|
||||
# Sync components_status.json — the host driver stays on disk but is
|
||||
# not in use for this GPU because it now belongs to a VM. Per-BDF
|
||||
# model: on multi-GPU hosts where another NVIDIA card still uses the
|
||||
# nvidia driver, keep the status as "installed" — the driver is
|
||||
# genuinely in use elsewhere. Only flip to "vfio_passthrough" when no
|
||||
# NVIDIA GPU is bound to the host driver anymore.
|
||||
if declare -F update_component_status >/dev/null 2>&1; then
|
||||
local _nvd_ver _nvd_new_status
|
||||
_nvd_ver=$(jq -r '.nvidia_driver.version // ""' \
|
||||
/usr/local/share/proxmenux/components_status.json 2>/dev/null)
|
||||
_nvd_new_status="vfio_passthrough"
|
||||
# Any NVIDIA PCI device still using the nvidia driver on the host?
|
||||
if lspci -nnk 2>/dev/null | awk '
|
||||
/NVIDIA/{gpu=1; next}
|
||||
gpu && /Kernel driver in use: nvidia$/ {found=1; exit}
|
||||
/^[^\t]/{gpu=0}
|
||||
END{exit !found}
|
||||
'; then
|
||||
_nvd_new_status="installed"
|
||||
fi
|
||||
update_component_status "nvidia_driver" "$_nvd_new_status" \
|
||||
"${_nvd_ver:-}" "gpu" '{"patched":false}' >>"$LOG_FILE" 2>&1 || true
|
||||
msg_ok "$(translate 'NVIDIA host services/autoload already aligned for native mode')" | tee -a "$screen_capture"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -5,18 +5,18 @@
|
||||
# Author : MacRimi
|
||||
# Copyright : (c) 2024 MacRimi
|
||||
# License : GPL-3.0
|
||||
# Version : 1.2
|
||||
# Last Updated: 26/03/2026
|
||||
# Version : 1.3
|
||||
# Last Updated: 26/08/2026
|
||||
# ==========================================================
|
||||
# Description:
|
||||
# Installs and manages the NVIDIA proprietary driver on a
|
||||
# Proxmox VE host. Detects hardware, picks a kernel-compatible
|
||||
# driver version and handles the full lifecycle
|
||||
# Proxmox VE host. Detects hardware, filters NVIDIA branches by
|
||||
# the installed GPU PCI IDs and handles the full lifecycle
|
||||
# (install / update / remove).
|
||||
#
|
||||
# Features:
|
||||
# - GPU detection + VFIO passthrough safety check
|
||||
# - Kernel-aware driver version filter (5.15 → 6.17+)
|
||||
# - GPU PCI-ID-aware branch filtering from NVIDIA supportedchips
|
||||
# - Nouveau blacklist + module unload
|
||||
# - DKMS-backed install (survives kernel upgrades)
|
||||
# - udev rules + nvidia-persistenced service
|
||||
@@ -36,6 +36,10 @@ screen_capture="/tmp/proxmenux_nvidia_screen_capture_$$.txt"
|
||||
|
||||
NVIDIA_BASE_URL="https://download.nvidia.com/XFree86/Linux-x86_64"
|
||||
NVIDIA_WORKDIR="/opt/nvidia"
|
||||
NVIDIA_NOUVEAU_BLACKLIST="/etc/modprobe.d/proxmenux-nouveau-blacklist.conf"
|
||||
NVIDIA_NOUVEAU_STATE="${BASE_DIR}/nvidia-nouveau-blacklist.state"
|
||||
NVIDIA_NOUVEAU_LEGACY_BLACKLIST="/etc/modprobe.d/nouveau-blacklist.conf"
|
||||
NVIDIA_GLOBAL_BLACKLIST="/etc/modprobe.d/blacklist.conf"
|
||||
|
||||
# LXC post-install update constants (used only when NVIDIA LXC passthrough
|
||||
# containers are detected and the user confirms updating them after the host
|
||||
@@ -541,16 +545,65 @@ ensure_repos_and_headers() {
|
||||
msg_ok "$(translate 'Kernel headers and build tools verified.')" | tee -a "$screen_capture"
|
||||
}
|
||||
|
||||
_nouveau_legacy_file_is_proxmenux_shape() {
|
||||
[[ -f "$NVIDIA_NOUVEAU_LEGACY_BLACKLIST" ]] || return 1
|
||||
local content
|
||||
content=$(sed '/^[[:space:]]*$/d' "$NVIDIA_NOUVEAU_LEGACY_BLACKLIST" 2>/dev/null)
|
||||
[[ "$content" == $'blacklist nouveau\noptions nouveau modeset=0' ]]
|
||||
}
|
||||
|
||||
_nouveau_state_set() {
|
||||
local key="$1"
|
||||
mkdir -p "$(dirname "$NVIDIA_NOUVEAU_STATE")"
|
||||
touch "$NVIDIA_NOUVEAU_STATE"
|
||||
grep -qFx "${key}=1" "$NVIDIA_NOUVEAU_STATE" 2>/dev/null \
|
||||
|| echo "${key}=1" >> "$NVIDIA_NOUVEAU_STATE"
|
||||
}
|
||||
|
||||
restore_nouveau_after_uninstall() {
|
||||
local remove_global_line=false
|
||||
|
||||
if [[ -f "$NVIDIA_NOUVEAU_STATE" ]] \
|
||||
&& grep -qFx 'blacklist_conf_line_added=1' "$NVIDIA_NOUVEAU_STATE" 2>/dev/null; then
|
||||
remove_global_line=true
|
||||
fi
|
||||
|
||||
# Migration for installations made by older ProxMenux versions. That
|
||||
# version overwrote this exact two-line file and added the matching line
|
||||
# to blacklist.conf, but had no ownership state yet.
|
||||
if _nouveau_legacy_file_is_proxmenux_shape; then
|
||||
rm -f "$NVIDIA_NOUVEAU_LEGACY_BLACKLIST"
|
||||
remove_global_line=true
|
||||
fi
|
||||
|
||||
rm -f "$NVIDIA_NOUVEAU_BLACKLIST"
|
||||
if $remove_global_line && [[ -f "$NVIDIA_GLOBAL_BLACKLIST" ]]; then
|
||||
sed -i '/^blacklist nouveau$/d' "$NVIDIA_GLOBAL_BLACKLIST"
|
||||
fi
|
||||
rm -f "$NVIDIA_NOUVEAU_STATE"
|
||||
}
|
||||
|
||||
blacklist_nouveau() {
|
||||
msg_info "$(translate 'Blacklisting nouveau driver...')"
|
||||
|
||||
# Write blacklist config files
|
||||
if ! grep -q '^blacklist nouveau' /etc/modprobe.d/blacklist.conf 2>/dev/null; then
|
||||
echo "blacklist nouveau" >> /etc/modprobe.d/blacklist.conf
|
||||
local legacy_owned=false
|
||||
if _nouveau_legacy_file_is_proxmenux_shape; then
|
||||
rm -f "$NVIDIA_NOUVEAU_LEGACY_BLACKLIST"
|
||||
legacy_owned=true
|
||||
_nouveau_state_set "legacy_migrated"
|
||||
fi
|
||||
|
||||
# Also write explicit options file to ensure it's fully disabled
|
||||
cat > /etc/modprobe.d/nouveau-blacklist.conf <<'EOF'
|
||||
if ! grep -q '^blacklist nouveau$' "$NVIDIA_GLOBAL_BLACKLIST" 2>/dev/null; then
|
||||
echo "blacklist nouveau" >> "$NVIDIA_GLOBAL_BLACKLIST"
|
||||
_nouveau_state_set "blacklist_conf_line_added"
|
||||
elif $legacy_owned; then
|
||||
# The legacy ProxMenux file proves ownership of the companion line.
|
||||
_nouveau_state_set "blacklist_conf_line_added"
|
||||
fi
|
||||
|
||||
# ProxMenux-owned file: uninstall can now remove only what we created.
|
||||
cat > "$NVIDIA_NOUVEAU_BLACKLIST" <<'EOF'
|
||||
# Managed by ProxMenux NVIDIA installer.
|
||||
blacklist nouveau
|
||||
options nouveau modeset=0
|
||||
EOF
|
||||
@@ -678,6 +731,7 @@ complete_nvidia_uninstall() {
|
||||
rm -f /etc/udev/rules.d/70-nvidia.rules
|
||||
rm -rf /usr/lib/modprobe.d/nvidia*.conf
|
||||
rm -rf /etc/modprobe.d/nvidia*.conf
|
||||
restore_nouveau_after_uninstall
|
||||
|
||||
if [[ -d "$NVIDIA_WORKDIR" ]]; then
|
||||
find "$NVIDIA_WORKDIR" -type d -name "nvidia-persistenced" -exec rm -rf {} + 2>/dev/null || true
|
||||
@@ -709,28 +763,14 @@ ensure_workdir() {
|
||||
}
|
||||
|
||||
# ==========================================================
|
||||
# Kernel + system detection
|
||||
# System detection
|
||||
# ==========================================================
|
||||
get_kernel_compatibility_info() {
|
||||
local kernel_version
|
||||
kernel_version=$(uname -r)
|
||||
|
||||
get_system_info() {
|
||||
if [[ -f /etc/pve/.version ]]; then
|
||||
PVE_VERSION=$(cat /etc/pve/.version)
|
||||
else
|
||||
PVE_VERSION="unknown"
|
||||
fi
|
||||
|
||||
KERNEL_MAJOR=$(echo "$kernel_version" | cut -d. -f1)
|
||||
KERNEL_MINOR=$(echo "$kernel_version" | cut -d. -f2)
|
||||
|
||||
MIN_DRIVER_VERSION=""
|
||||
RECOMMENDED_BRANCH=""
|
||||
COMPATIBILITY_NOTE=""
|
||||
}
|
||||
|
||||
is_version_compatible() {
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
@@ -1546,7 +1586,7 @@ show_version_menu() {
|
||||
|
||||
show_proxmenux_logo
|
||||
msg_title "$(translate 'NVIDIA GPU Driver Installation')"
|
||||
msg_info "$(translate 'Fetching compatible driver versions for your kernel and GPU...')"
|
||||
msg_info "$(translate 'Fetching NVIDIA driver versions supported by your GPU...')"
|
||||
|
||||
latest=$(download_latest_version 2>/dev/null)
|
||||
versions_list=$(list_available_versions 2>/dev/null)
|
||||
@@ -1573,18 +1613,6 @@ show_version_menu() {
|
||||
latest=$(echo "$latest" | tr -d '[:space:]')
|
||||
|
||||
local current_list="$versions_list"
|
||||
|
||||
# Apply kernel compatibility filter if needed
|
||||
if [[ -n "$MIN_DRIVER_VERSION" ]]; then
|
||||
local filtered_list=""
|
||||
while IFS= read -r ver; do
|
||||
[[ -z "$ver" ]] && continue
|
||||
if is_version_compatible "$ver"; then
|
||||
filtered_list+="$ver"$'\n'
|
||||
fi
|
||||
done <<< "$current_list"
|
||||
current_list="$filtered_list"
|
||||
fi
|
||||
|
||||
if [[ -n "$current_list" ]]; then
|
||||
current_list=$(filter_option_c_branch "$current_list" "$CURRENT_DRIVER_VERSION" "")
|
||||
@@ -1636,7 +1664,7 @@ show_version_menu() {
|
||||
# 2. Fresh install (no current driver) → Production Branch head
|
||||
# from NVIDIA's Unix drivers page, when present in the list.
|
||||
# 3. Fallback → highest numeric in the list (Production may have
|
||||
# been filtered out by kernel-compat / GPU-compat / patch
|
||||
# been filtered out by maintained-branch / GPU PCI-ID / patch
|
||||
# awareness).
|
||||
latest=""
|
||||
if [[ -n "$CURRENT_DRIVER_VERSION" && -n "$current_list" ]]; then
|
||||
@@ -1665,7 +1693,7 @@ show_version_menu() {
|
||||
fi
|
||||
|
||||
local menu_text="$(translate 'Select the NVIDIA driver version to install:')\n\n"
|
||||
menu_text+="$(translate 'Versions shown are compatible with your kernel and your GPU. The recommended version keeps you on your current driver branch, or defaults to the NVIDIA Production Branch head on a fresh install.')"
|
||||
menu_text+="$(translate 'Versions shown belong to maintained NVIDIA branches that list your GPU PCI ID. DKMS compilation is the final validation against the running kernel. The recommended version keeps the current branch, or uses the NVIDIA Production Branch on a fresh install.')"
|
||||
if $patch_filtered; then
|
||||
menu_text+="\n\n$(translate 'NVENC patch detected — list narrowed to versions supported by keylase/nvidia-patch.')"
|
||||
elif [[ -n "$patch_filter_note" ]]; then
|
||||
@@ -1689,7 +1717,7 @@ show_version_menu() {
|
||||
choices+=("$ver" "$ver")
|
||||
done <<< "$current_list"
|
||||
else
|
||||
choices+=("" "$(translate 'No compatible versions found for your kernel')")
|
||||
choices+=("" "$(translate 'No supported NVIDIA versions found for this GPU')")
|
||||
fi
|
||||
|
||||
stop_spinner
|
||||
@@ -1741,7 +1769,7 @@ main() {
|
||||
exit 0
|
||||
fi
|
||||
|
||||
get_kernel_compatibility_info
|
||||
get_system_info
|
||||
|
||||
show_version_menu
|
||||
if [[ "$DRIVER_VERSION" == "cancel" || -z "$DRIVER_VERSION" ]]; then
|
||||
@@ -2008,4 +2036,4 @@ if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
|
||||
exit $?
|
||||
fi
|
||||
main
|
||||
fi
|
||||
fi
|
||||
|
||||
+100
-208
@@ -5,8 +5,8 @@
|
||||
# Author : MacRimi
|
||||
# Copyright : (c) 2024 MacRimi
|
||||
# License : GPL-3.0
|
||||
# Version : 1.0
|
||||
# Last Updated: 05/04/2026
|
||||
# Version : 1.1
|
||||
# Last Updated: 26/08/2026
|
||||
# ==========================================================
|
||||
# Description:
|
||||
# Moves an already-assigned GPU between the two modes it can
|
||||
@@ -67,7 +67,8 @@ if [[ -f "$LOCAL_SCRIPTS_LOCAL/global/pci_passthrough_helpers.sh" ]]; then
|
||||
elif [[ -f "$LOCAL_SCRIPTS_DEFAULT/global/pci_passthrough_helpers.sh" ]]; then
|
||||
source "$LOCAL_SCRIPTS_DEFAULT/global/pci_passthrough_helpers.sh"
|
||||
else
|
||||
msg_warn "$(translate 'pci_passthrough_helpers.sh missing — SR-IOV / orphan-audio guards will be skipped')"
|
||||
echo "ProxMenux: pci_passthrough_helpers.sh is required; refusing to change GPU ownership." >&2
|
||||
exit 1
|
||||
fi
|
||||
load_language
|
||||
initialize_cache
|
||||
@@ -81,6 +82,8 @@ declare -a SELECTED_GPU_IDX=()
|
||||
|
||||
declare -a SELECTED_IOMMU_IDS=()
|
||||
declare -a SELECTED_PCI_SLOTS=()
|
||||
declare -a SELECTED_NVIDIA_BDFS=()
|
||||
declare -a SELECTED_LEGACY_IOMMU_IDS=()
|
||||
|
||||
declare -a LXC_AFFECTED_CTIDS=()
|
||||
declare -a LXC_AFFECTED_NAMES=()
|
||||
@@ -167,12 +170,30 @@ _get_iommu_group_ids() {
|
||||
done
|
||||
}
|
||||
|
||||
_get_iommu_group_bdfs() {
|
||||
local pci_full="$1"
|
||||
local group_link="/sys/bus/pci/devices/${pci_full}/iommu_group"
|
||||
[[ -L "$group_link" ]] || return 0
|
||||
|
||||
local group_dir dev_path dev_class
|
||||
group_dir="/sys/kernel/iommu_groups/$(basename "$(readlink "$group_link")")/devices"
|
||||
for dev_path in "${group_dir}/"*; do
|
||||
[[ -e "$dev_path" ]] || continue
|
||||
dev_class=$(cat "$dev_path/class" 2>/dev/null)
|
||||
# Bridges belong to the isolation boundary, but vfio-pci does not
|
||||
# support PCI bridges. Proxmox passes the endpoint devices only.
|
||||
[[ "$dev_class" == 0x0604* || "$dev_class" == 0x0600* ]] && continue
|
||||
basename "$dev_path"
|
||||
done
|
||||
}
|
||||
|
||||
_read_vfio_ids() {
|
||||
local vfio_conf="/etc/modprobe.d/vfio.conf"
|
||||
local ids_line ids_part
|
||||
ids_line=$(grep "^options vfio-pci ids=" "$vfio_conf" 2>/dev/null | head -1)
|
||||
[[ -z "$ids_line" ]] && return
|
||||
ids_part=$(echo "$ids_line" | grep -oE 'ids=[^[:space:]]+' | sed 's/ids=//')
|
||||
ids_part=$(echo "$ids_line" | grep -oE 'ids=[^[:space:]]+' | sed 's/ids=//' \
|
||||
| tr '[:upper:]' '[:lower:]')
|
||||
[[ -z "$ids_part" ]] && return
|
||||
tr ',' '\n' <<< "$ids_part" | sed '/^$/d'
|
||||
}
|
||||
@@ -213,15 +234,10 @@ _remove_gpu_blacklist() {
|
||||
local changed=false
|
||||
case "$gpu_type" in
|
||||
nvidia)
|
||||
grep -qE '^blacklist (nouveau|nvidia|nvidiafb|nvidia_drm|nvidia_modeset|nvidia_uvm|lbm-nouveau)$|^options nouveau modeset=0$' "$blacklist_file" 2>/dev/null && changed=true
|
||||
sed -i '/^blacklist nouveau$/d' "$blacklist_file"
|
||||
sed -i '/^blacklist nvidia$/d' "$blacklist_file"
|
||||
sed -i '/^blacklist nvidiafb$/d' "$blacklist_file"
|
||||
sed -i '/^blacklist nvidia_drm$/d' "$blacklist_file"
|
||||
sed -i '/^blacklist nvidia_modeset$/d' "$blacklist_file"
|
||||
sed -i '/^blacklist nvidia_uvm$/d' "$blacklist_file"
|
||||
sed -i '/^blacklist lbm-nouveau$/d' "$blacklist_file"
|
||||
sed -i '/^options nouveau modeset=0$/d' "$blacklist_file"
|
||||
# NVIDIA ownership is per BDF. Never alter the global blacklist here:
|
||||
# it may belong to the host-driver installer and another NVIDIA GPU may
|
||||
# still need the native driver.
|
||||
return 1
|
||||
;;
|
||||
amd)
|
||||
grep -qE '^blacklist (radeon|amdgpu)$' "$blacklist_file" 2>/dev/null && changed=true
|
||||
@@ -243,14 +259,8 @@ _add_gpu_blacklist() {
|
||||
touch "$blacklist_file"
|
||||
case "$gpu_type" in
|
||||
nvidia)
|
||||
_add_line_if_missing "blacklist nouveau" "$blacklist_file"
|
||||
_add_line_if_missing "blacklist nvidia" "$blacklist_file"
|
||||
_add_line_if_missing "blacklist nvidiafb" "$blacklist_file"
|
||||
_add_line_if_missing "blacklist nvidia_drm" "$blacklist_file"
|
||||
_add_line_if_missing "blacklist nvidia_modeset" "$blacklist_file"
|
||||
_add_line_if_missing "blacklist nvidia_uvm" "$blacklist_file"
|
||||
_add_line_if_missing "blacklist lbm-nouveau" "$blacklist_file"
|
||||
_add_line_if_missing "options nouveau modeset=0" "$blacklist_file"
|
||||
# NVIDIA is handled exclusively by the shared per-BDF policy.
|
||||
return 0
|
||||
;;
|
||||
amd)
|
||||
_add_line_if_missing "blacklist radeon" "$blacklist_file"
|
||||
@@ -263,174 +273,18 @@ _add_gpu_blacklist() {
|
||||
}
|
||||
|
||||
_sanitize_nvidia_host_stack_for_vfio() {
|
||||
local changed=false
|
||||
local state_dir="/var/lib/proxmenux"
|
||||
local state_file="${state_dir}/nvidia-host-services.state"
|
||||
local svc
|
||||
local -a services=(
|
||||
"nvidia-persistenced.service"
|
||||
"nvidia-powerd.service"
|
||||
"nvidia-fabricmanager.service"
|
||||
)
|
||||
|
||||
mkdir -p "$state_dir" >/dev/null 2>&1 || true
|
||||
: > "$state_file"
|
||||
|
||||
for svc in "${services[@]}"; do
|
||||
local was_enabled=0 was_active=0
|
||||
if systemctl is-enabled --quiet "$svc" 2>/dev/null; then
|
||||
was_enabled=1
|
||||
fi
|
||||
if systemctl is-active --quiet "$svc" 2>/dev/null; then
|
||||
was_active=1
|
||||
fi
|
||||
if (( was_enabled == 1 || was_active == 1 )); then
|
||||
echo "${svc} enabled=${was_enabled} active=${was_active}" >>"$state_file"
|
||||
fi
|
||||
|
||||
if systemctl is-active --quiet "$svc" 2>/dev/null; then
|
||||
systemctl stop "$svc" >>"$LOG_FILE" 2>&1 || true
|
||||
changed=true
|
||||
fi
|
||||
if systemctl is-enabled --quiet "$svc" 2>/dev/null; then
|
||||
systemctl disable "$svc" >>"$LOG_FILE" 2>&1 || true
|
||||
changed=true
|
||||
fi
|
||||
done
|
||||
|
||||
[[ -s "$state_file" ]] || rm -f "$state_file"
|
||||
|
||||
if [[ -f /etc/modules-load.d/nvidia-vfio.conf ]]; then
|
||||
mv /etc/modules-load.d/nvidia-vfio.conf /etc/modules-load.d/nvidia-vfio.conf.proxmenux-disabled-vfio >>"$LOG_FILE" 2>&1 || true
|
||||
changed=true
|
||||
fi
|
||||
|
||||
if grep -qE '^(nvidia|nvidia_uvm|nvidia_drm|nvidia_modeset)$' /etc/modules 2>/dev/null; then
|
||||
sed -i '/^nvidia$/d;/^nvidia_uvm$/d;/^nvidia_drm$/d;/^nvidia_modeset$/d' /etc/modules
|
||||
changed=true
|
||||
fi
|
||||
|
||||
# Disable NVIDIA udev rules that trigger nvidia-smi (causes conflict with vfio-pci)
|
||||
local udev_rules="/etc/udev/rules.d/70-nvidia.rules"
|
||||
if [[ -f "$udev_rules" ]]; then
|
||||
mv "$udev_rules" "${udev_rules}.proxmenux-disabled" >>"$LOG_FILE" 2>&1 || true
|
||||
udevadm control --reload-rules >>"$LOG_FILE" 2>&1 || true
|
||||
changed=true
|
||||
fi
|
||||
|
||||
# Create hard blacklist to prevent ANY nvidia module loading (even via modprobe/nvidia-smi)
|
||||
local nvidia_blacklist="/etc/modprobe.d/nvidia-blacklist.conf"
|
||||
if [[ ! -f "$nvidia_blacklist" ]]; then
|
||||
cat > "$nvidia_blacklist" <<'EOF'
|
||||
# ProxMenux: Hard blacklist to prevent ANY nvidia module loading in VFIO mode
|
||||
# This prevents nvidia-smi and other tools from triggering module load attempts
|
||||
install nvidia /bin/false
|
||||
install nvidia_uvm /bin/false
|
||||
install nvidia_drm /bin/false
|
||||
install nvidia_modeset /bin/false
|
||||
EOF
|
||||
changed=true
|
||||
fi
|
||||
|
||||
if $changed; then
|
||||
HOST_CONFIG_CHANGED=true
|
||||
msg_ok "$(translate 'NVIDIA host services/autoload disabled for VFIO mode')" | tee -a "$screen_capture"
|
||||
else
|
||||
msg_ok "$(translate 'NVIDIA host services/autoload already aligned for VFIO mode')" | tee -a "$screen_capture"
|
||||
fi
|
||||
|
||||
# Sync components_status.json — the host driver stays on disk but is
|
||||
# not in use because the GPU now belongs to a VM. Prevents the update
|
||||
# notification path (and any future logic gated on nvidia_driver.status)
|
||||
# from acting on a state that no longer matches reality.
|
||||
if declare -F update_component_status >/dev/null 2>&1; then
|
||||
local _nvd_ver
|
||||
_nvd_ver=$(jq -r '.nvidia_driver.version // ""' \
|
||||
/usr/local/share/proxmenux/components_status.json 2>/dev/null)
|
||||
update_component_status "nvidia_driver" "vfio_passthrough" \
|
||||
"${_nvd_ver:-}" "gpu" '{"patched":false}' >>"$LOG_FILE" 2>&1 || true
|
||||
fi
|
||||
_proxmenux_nvidia_vfio_policy_sync || true
|
||||
}
|
||||
|
||||
_restore_nvidia_host_stack_for_lxc() {
|
||||
local changed=false
|
||||
local state_file="/var/lib/proxmenux/nvidia-host-services.state"
|
||||
local disabled_file="/etc/modules-load.d/nvidia-vfio.conf.proxmenux-disabled-vfio"
|
||||
local active_file="/etc/modules-load.d/nvidia-vfio.conf"
|
||||
|
||||
# New per-BDF model: drop every NVIDIA BDF from the initramfs binder so
|
||||
# the nvidia module reclaims the GPU after the next reboot. Idempotent:
|
||||
# no-op if no NVIDIA BDFs are tracked. Vendor 10de = NVIDIA.
|
||||
if declare -F _proxmenux_vfio_bind_purge_vendor >/dev/null 2>&1; then
|
||||
_proxmenux_vfio_bind_purge_vendor "10de" && changed=true
|
||||
fi
|
||||
|
||||
# Remove hard blacklist that was preventing nvidia module loading
|
||||
local nvidia_blacklist="/etc/modprobe.d/nvidia-blacklist.conf"
|
||||
if [[ -f "$nvidia_blacklist" ]]; then
|
||||
rm -f "$nvidia_blacklist" >>"$LOG_FILE" 2>&1 || true
|
||||
changed=true
|
||||
fi
|
||||
|
||||
# Restore NVIDIA udev rules if they were disabled
|
||||
local udev_disabled="/etc/udev/rules.d/70-nvidia.rules.proxmenux-disabled"
|
||||
local udev_rules="/etc/udev/rules.d/70-nvidia.rules"
|
||||
if [[ -f "$udev_disabled" ]]; then
|
||||
mv "$udev_disabled" "$udev_rules" >>"$LOG_FILE" 2>&1 || true
|
||||
udevadm control --reload-rules >>"$LOG_FILE" 2>&1 || true
|
||||
changed=true
|
||||
fi
|
||||
|
||||
# Restore previous modules-load policy if ProxMenux disabled it in VM mode.
|
||||
if [[ -f "$disabled_file" ]]; then
|
||||
mv "$disabled_file" "$active_file" >>"$LOG_FILE" 2>&1 || true
|
||||
changed=true
|
||||
fi
|
||||
|
||||
# Best effort: load NVIDIA kernel modules now that we are back in native mode.
|
||||
# If not installed, these calls simply fail silently.
|
||||
modprobe nvidia >/dev/null 2>&1 || true
|
||||
modprobe nvidia_uvm >/dev/null 2>&1 || true
|
||||
modprobe nvidia_modeset >/dev/null 2>&1 || true
|
||||
modprobe nvidia_drm >/dev/null 2>&1 || true
|
||||
|
||||
if [[ -f "$state_file" ]]; then
|
||||
while IFS= read -r line; do
|
||||
[[ -z "$line" ]] && continue
|
||||
local svc enabled active
|
||||
svc=$(echo "$line" | awk '{print $1}')
|
||||
enabled=$(echo "$line" | awk -F'enabled=' '{print $2}' | awk '{print $1}')
|
||||
active=$(echo "$line" | awk -F'active=' '{print $2}' | awk '{print $1}')
|
||||
[[ "$enabled" == "1" ]] && systemctl enable "$svc" >>"$LOG_FILE" 2>&1 || true
|
||||
[[ "$active" == "1" ]] && systemctl start "$svc" >>"$LOG_FILE" 2>&1 || true
|
||||
done <"$state_file"
|
||||
rm -f "$state_file"
|
||||
changed=true
|
||||
fi
|
||||
|
||||
if $changed; then
|
||||
HOST_CONFIG_CHANGED=true
|
||||
msg_ok "$(translate 'NVIDIA host services/autoload restored for native mode')" | tee -a "$screen_capture"
|
||||
else
|
||||
msg_ok "$(translate 'NVIDIA host services/autoload already aligned for native mode')" | tee -a "$screen_capture"
|
||||
fi
|
||||
|
||||
# Sync components_status.json back to installed — the host has reclaimed
|
||||
# the GPU and the nvidia stack is being reloaded. Restores the state to
|
||||
# what it was before the VFIO switch so the update notification path and
|
||||
# the auto-reinstall gate see the driver as active on the host again.
|
||||
if declare -F update_component_status >/dev/null 2>&1; then
|
||||
local _nvd_ver
|
||||
_nvd_ver=$(nvidia-smi --query-gpu=driver_version --format=csv,noheader 2>/dev/null | head -1)
|
||||
if [[ -z "$_nvd_ver" ]]; then
|
||||
_nvd_ver=$(jq -r '.nvidia_driver.version // ""' \
|
||||
/usr/local/share/proxmenux/components_status.json 2>/dev/null)
|
||||
fi
|
||||
update_component_status "nvidia_driver" "installed" \
|
||||
"${_nvd_ver:-}" "gpu" '{"patched":false}' >>"$LOG_FILE" 2>&1 || true
|
||||
_proxmenux_nvidia_vfio_policy_sync || true
|
||||
if ! _proxmenux_all_nvidia_in_vfio; then
|
||||
modprobe nvidia >/dev/null 2>&1 || true
|
||||
modprobe nvidia_uvm >/dev/null 2>&1 || true
|
||||
modprobe nvidia_modeset >/dev/null 2>&1 || true
|
||||
modprobe nvidia_drm >/dev/null 2>&1 || true
|
||||
fi
|
||||
}
|
||||
|
||||
_add_amd_softdep() {
|
||||
local vfio_conf="/etc/modprobe.d/vfio.conf"
|
||||
_add_line_if_missing "softdep radeon pre: vfio-pci" "$vfio_conf"
|
||||
@@ -468,6 +322,10 @@ _remove_vfio_modules_if_unused() {
|
||||
local vfio_count
|
||||
vfio_count=$(_read_vfio_ids | wc -l | tr -d '[:space:]')
|
||||
[[ "$vfio_count" != "0" ]] && return 1
|
||||
if declare -F _proxmenux_vfio_bind_has_entries >/dev/null 2>&1 \
|
||||
&& _proxmenux_vfio_bind_has_entries; then
|
||||
return 1
|
||||
fi
|
||||
local modules_file="/etc/modules"
|
||||
[[ ! -f "$modules_file" ]] && return 1
|
||||
local had_any=false
|
||||
@@ -811,25 +669,37 @@ check_sriov_and_block_if_needed() {
|
||||
collect_selected_iommu_ids() {
|
||||
SELECTED_IOMMU_IDS=()
|
||||
SELECTED_PCI_SLOTS=()
|
||||
SELECTED_NVIDIA_BDFS=()
|
||||
SELECTED_LEGACY_IOMMU_IDS=()
|
||||
|
||||
local idx pci viddid slot
|
||||
local idx pci viddid slot selected_type bdf vid did gid
|
||||
for idx in "${SELECTED_GPU_IDX[@]}"; do
|
||||
pci="${ALL_GPU_PCIS[$idx]}"
|
||||
viddid="${ALL_GPU_VIDDID[$idx]}"
|
||||
selected_type="${ALL_GPU_TYPES[$idx]}"
|
||||
slot="${pci#0000:}"
|
||||
slot="${slot%.*}"
|
||||
SELECTED_PCI_SLOTS+=("$slot")
|
||||
|
||||
local -a group_ids=()
|
||||
mapfile -t group_ids < <(_get_iommu_group_ids "$pci")
|
||||
if [[ ${#group_ids[@]} -gt 0 ]]; then
|
||||
local gid
|
||||
for gid in "${group_ids[@]}"; do
|
||||
local -a group_bdfs=()
|
||||
mapfile -t group_bdfs < <(_get_iommu_group_bdfs "$pci")
|
||||
[[ ${#group_bdfs[@]} -gt 0 ]] || group_bdfs=("$pci")
|
||||
|
||||
for bdf in "${group_bdfs[@]}"; do
|
||||
[[ "$bdf" == 0000:* ]] || bdf="0000:${bdf}"
|
||||
vid=$(cat "/sys/bus/pci/devices/${bdf}/vendor" 2>/dev/null | sed 's/^0x//')
|
||||
did=$(cat "/sys/bus/pci/devices/${bdf}/device" 2>/dev/null | sed 's/^0x//')
|
||||
gid="${vid}:${did}"
|
||||
if [[ -n "$vid" && -n "$did" ]]; then
|
||||
_contains_in_array "$gid" "${SELECTED_IOMMU_IDS[@]}" || SELECTED_IOMMU_IDS+=("$gid")
|
||||
done
|
||||
elif [[ -n "$viddid" ]]; then
|
||||
_contains_in_array "$viddid" "${SELECTED_IOMMU_IDS[@]}" || SELECTED_IOMMU_IDS+=("$viddid")
|
||||
fi
|
||||
if [[ "$selected_type" != "nvidia" ]]; then
|
||||
_contains_in_array "$gid" "${SELECTED_LEGACY_IOMMU_IDS[@]}" || SELECTED_LEGACY_IOMMU_IDS+=("$gid")
|
||||
fi
|
||||
fi
|
||||
if [[ "$selected_type" == "nvidia" ]]; then
|
||||
_contains_in_array "$bdf" "${SELECTED_NVIDIA_BDFS[@]}" || SELECTED_NVIDIA_BDFS+=("$bdf")
|
||||
fi
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
@@ -1167,6 +1037,9 @@ apply_vm_action_for_lxc_mode() {
|
||||
if ! _contains_in_array "$_vd_id" "${SELECTED_IOMMU_IDS[@]}"; then
|
||||
SELECTED_IOMMU_IDS+=("$_vd_id")
|
||||
fi
|
||||
if ! _contains_in_array "$_vd_id" "${SELECTED_LEGACY_IOMMU_IDS[@]}"; then
|
||||
SELECTED_LEGACY_IOMMU_IDS+=("$_vd_id")
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
@@ -1234,6 +1107,12 @@ switch_to_vm_mode() {
|
||||
|
||||
msg_info "$(translate 'Configuring host for GPU -> VM mode...')"
|
||||
|
||||
local -a selected_types=()
|
||||
mapfile -t selected_types < <(_selected_types_unique)
|
||||
if _contains_in_array "nvidia" "${selected_types[@]}"; then
|
||||
_proxmenux_nvidia_migrate_legacy_blacklist
|
||||
fi
|
||||
|
||||
if declare -F _pci_is_iommu_active >/dev/null 2>&1 && _pci_is_iommu_active; then
|
||||
_register_iommu_tool
|
||||
msg_ok "$(translate 'IOMMU is already active on this system')" | tee -a "$screen_capture"
|
||||
@@ -1269,24 +1148,30 @@ switch_to_vm_mode() {
|
||||
local -a current_ids=()
|
||||
mapfile -t current_ids < <(_read_vfio_ids)
|
||||
local id
|
||||
for id in "${SELECTED_IOMMU_IDS[@]}"; do
|
||||
for id in "${SELECTED_LEGACY_IOMMU_IDS[@]}"; do
|
||||
_contains_in_array "$id" "${current_ids[@]}" || current_ids+=("$id")
|
||||
done
|
||||
_write_vfio_ids "${current_ids[@]}"
|
||||
if [[ ${#SELECTED_IOMMU_IDS[@]} -gt 0 ]]; then
|
||||
if [[ ${#SELECTED_LEGACY_IOMMU_IDS[@]} -gt 0 ]]; then
|
||||
local ids_label
|
||||
ids_label=$(IFS=','; echo "${SELECTED_IOMMU_IDS[*]}")
|
||||
ids_label=$(IFS=','; echo "${SELECTED_LEGACY_IOMMU_IDS[*]}")
|
||||
msg_ok "$(translate 'vfio-pci IDs configured') (${ids_label})" | tee -a "$screen_capture"
|
||||
fi
|
||||
|
||||
local -a selected_types=()
|
||||
mapfile -t selected_types < <(_selected_types_unique)
|
||||
local t
|
||||
if [[ ${#SELECTED_NVIDIA_BDFS[@]} -gt 0 ]]; then
|
||||
_proxmenux_vfio_bind_add_bdfs "${SELECTED_NVIDIA_BDFS[@]}"
|
||||
msg_ok "$(translate 'NVIDIA per-BDF VFIO binding configured') (${SELECTED_NVIDIA_BDFS[*]})" | tee -a "$screen_capture"
|
||||
fi
|
||||
|
||||
local t legacy_blacklist_configured=false
|
||||
for t in "${selected_types[@]}"; do
|
||||
[[ "$t" == "nvidia" ]] && continue
|
||||
_add_gpu_blacklist "$t"
|
||||
legacy_blacklist_configured=true
|
||||
done
|
||||
msg_ok "$(translate 'GPU host driver blacklisted in /etc/modprobe.d/blacklist.conf')" | tee -a "$screen_capture"
|
||||
_contains_in_array "nvidia" "${selected_types[@]}" && _sanitize_nvidia_host_stack_for_vfio
|
||||
$legacy_blacklist_configured \
|
||||
&& msg_ok "$(translate 'GPU host driver blacklisted in /etc/modprobe.d/blacklist.conf')" | tee -a "$screen_capture"
|
||||
_contains_in_array "nvidia" "${selected_types[@]}" && _proxmenux_nvidia_vfio_policy_sync || true
|
||||
_contains_in_array "amd" "${selected_types[@]}" && _add_amd_softdep
|
||||
|
||||
if [[ "$HOST_CONFIG_CHANGED" == "true" ]]; then
|
||||
@@ -1320,12 +1205,20 @@ switch_to_lxc_mode() {
|
||||
|
||||
msg_info "$(translate 'Removing VFIO ownership for selected GPU(s)...')"
|
||||
|
||||
local -a selected_types=()
|
||||
mapfile -t selected_types < <(_selected_types_unique)
|
||||
if _contains_in_array "nvidia" "${selected_types[@]}"; then
|
||||
_proxmenux_nvidia_migrate_legacy_blacklist
|
||||
[[ ${#SELECTED_NVIDIA_BDFS[@]} -gt 0 ]] \
|
||||
&& _proxmenux_vfio_bind_remove_bdfs "${SELECTED_NVIDIA_BDFS[@]}"
|
||||
fi
|
||||
|
||||
local -a current_ids=() remaining_ids=() removed_ids=()
|
||||
mapfile -t current_ids < <(_read_vfio_ids)
|
||||
local id remove
|
||||
for id in "${current_ids[@]}"; do
|
||||
remove=false
|
||||
_contains_in_array "$id" "${SELECTED_IOMMU_IDS[@]}" && remove=true
|
||||
_contains_in_array "$id" "${SELECTED_LEGACY_IOMMU_IDS[@]}" && remove=true
|
||||
if $remove; then
|
||||
removed_ids+=("$id")
|
||||
else
|
||||
@@ -1339,17 +1232,16 @@ switch_to_lxc_mode() {
|
||||
msg_ok "$(translate 'VFIO device IDs removed from /etc/modprobe.d/vfio.conf') (${ids_label})" | tee -a "$screen_capture"
|
||||
fi
|
||||
|
||||
local -a selected_types=()
|
||||
mapfile -t selected_types < <(_selected_types_unique)
|
||||
local t
|
||||
for t in "${selected_types[@]}"; do
|
||||
if [[ "$t" == "nvidia" ]]; then
|
||||
_proxmenux_nvidia_vfio_policy_sync || true
|
||||
continue
|
||||
fi
|
||||
if ! _type_has_remaining_vfio_ids "$t" "${remaining_ids[@]}"; then
|
||||
if _remove_gpu_blacklist "$t"; then
|
||||
msg_ok "$(translate 'Driver blacklist removed for') ${t}" | tee -a "$screen_capture"
|
||||
fi
|
||||
if [[ "$t" == "nvidia" ]]; then
|
||||
_restore_nvidia_host_stack_for_lxc
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# Author : MacRimi
|
||||
# Copyright : (c) 2024 MacRimi
|
||||
# License : GPL-3.0
|
||||
# Version : 1.0
|
||||
# Last Updated: 09/04/2026
|
||||
# Version : 1.1
|
||||
# Last Updated: 26/08/2026
|
||||
# ==========================================================
|
||||
# This script is a hybrid version for ProxMenux Monitor.
|
||||
# It accepts parameters to skip GPU selection and uses
|
||||
@@ -36,6 +36,9 @@ if [[ -f "$LOCAL_SCRIPTS_LOCAL/global/pci_passthrough_helpers.sh" ]]; then
|
||||
source "$LOCAL_SCRIPTS_LOCAL/global/pci_passthrough_helpers.sh"
|
||||
elif [[ -f "$LOCAL_SCRIPTS_DEFAULT/global/pci_passthrough_helpers.sh" ]]; then
|
||||
source "$LOCAL_SCRIPTS_DEFAULT/global/pci_passthrough_helpers.sh"
|
||||
else
|
||||
echo "ProxMenux: pci_passthrough_helpers.sh is required; refusing to change GPU ownership." >&2
|
||||
exit 1
|
||||
fi
|
||||
load_language
|
||||
initialize_cache
|
||||
@@ -52,6 +55,8 @@ declare -a SELECTED_GPU_IDX=()
|
||||
|
||||
declare -a SELECTED_IOMMU_IDS=()
|
||||
declare -a SELECTED_PCI_SLOTS=()
|
||||
declare -a SELECTED_NVIDIA_BDFS=()
|
||||
declare -a SELECTED_LEGACY_IOMMU_IDS=()
|
||||
|
||||
declare -a LXC_AFFECTED_CTIDS=()
|
||||
declare -a LXC_AFFECTED_NAMES=()
|
||||
@@ -145,12 +150,28 @@ _get_iommu_group_ids() {
|
||||
done
|
||||
}
|
||||
|
||||
_get_iommu_group_bdfs() {
|
||||
local pci_full="$1"
|
||||
local group_link="/sys/bus/pci/devices/${pci_full}/iommu_group"
|
||||
[[ -L "$group_link" ]] || return 0
|
||||
|
||||
local group_dir dev_path dev_class
|
||||
group_dir="/sys/kernel/iommu_groups/$(basename "$(readlink "$group_link")")/devices"
|
||||
for dev_path in "${group_dir}/"*; do
|
||||
[[ -e "$dev_path" ]] || continue
|
||||
dev_class=$(cat "$dev_path/class" 2>/dev/null)
|
||||
[[ "$dev_class" == 0x0604* || "$dev_class" == 0x0600* ]] && continue
|
||||
basename "$dev_path"
|
||||
done
|
||||
}
|
||||
|
||||
_read_vfio_ids() {
|
||||
local vfio_conf="/etc/modprobe.d/vfio.conf"
|
||||
local ids_line ids_part
|
||||
ids_line=$(grep "^options vfio-pci ids=" "$vfio_conf" 2>/dev/null | head -1)
|
||||
[[ -z "$ids_line" ]] && return
|
||||
ids_part=$(echo "$ids_line" | grep -oE 'ids=[^[:space:]]+' | sed 's/ids=//')
|
||||
ids_part=$(echo "$ids_line" | grep -oE 'ids=[^[:space:]]+' | sed 's/ids=//' \
|
||||
| tr '[:upper:]' '[:lower:]')
|
||||
[[ -z "$ids_part" ]] && return
|
||||
tr ',' '\n' <<< "$ids_part" | sed '/^$/d'
|
||||
}
|
||||
@@ -191,15 +212,10 @@ _remove_gpu_blacklist() {
|
||||
local changed=false
|
||||
case "$gpu_type" in
|
||||
nvidia)
|
||||
grep -qE '^blacklist (nouveau|nvidia|nvidiafb|nvidia_drm|nvidia_modeset|nvidia_uvm|lbm-nouveau)$|^options nouveau modeset=0$' "$blacklist_file" 2>/dev/null && changed=true
|
||||
sed -i '/^blacklist nouveau$/d' "$blacklist_file"
|
||||
sed -i '/^blacklist nvidia$/d' "$blacklist_file"
|
||||
sed -i '/^blacklist nvidiafb$/d' "$blacklist_file"
|
||||
sed -i '/^blacklist nvidia_drm$/d' "$blacklist_file"
|
||||
sed -i '/^blacklist nvidia_modeset$/d' "$blacklist_file"
|
||||
sed -i '/^blacklist nvidia_uvm$/d' "$blacklist_file"
|
||||
sed -i '/^blacklist lbm-nouveau$/d' "$blacklist_file"
|
||||
sed -i '/^options nouveau modeset=0$/d' "$blacklist_file"
|
||||
# NVIDIA ownership is per BDF. Never alter the global blacklist here:
|
||||
# it may belong to the host-driver installer and another NVIDIA GPU may
|
||||
# still need the native driver.
|
||||
return 1
|
||||
;;
|
||||
amd)
|
||||
grep -qE '^blacklist (radeon|amdgpu)$' "$blacklist_file" 2>/dev/null && changed=true
|
||||
@@ -221,14 +237,8 @@ _add_gpu_blacklist() {
|
||||
touch "$blacklist_file"
|
||||
case "$gpu_type" in
|
||||
nvidia)
|
||||
_add_line_if_missing "blacklist nouveau" "$blacklist_file"
|
||||
_add_line_if_missing "blacklist nvidia" "$blacklist_file"
|
||||
_add_line_if_missing "blacklist nvidiafb" "$blacklist_file"
|
||||
_add_line_if_missing "blacklist nvidia_drm" "$blacklist_file"
|
||||
_add_line_if_missing "blacklist nvidia_modeset" "$blacklist_file"
|
||||
_add_line_if_missing "blacklist nvidia_uvm" "$blacklist_file"
|
||||
_add_line_if_missing "blacklist lbm-nouveau" "$blacklist_file"
|
||||
_add_line_if_missing "options nouveau modeset=0" "$blacklist_file"
|
||||
# NVIDIA is handled exclusively by the shared per-BDF policy.
|
||||
return 0
|
||||
;;
|
||||
amd)
|
||||
_add_line_if_missing "blacklist radeon" "$blacklist_file"
|
||||
@@ -241,170 +251,18 @@ _add_gpu_blacklist() {
|
||||
}
|
||||
|
||||
_sanitize_nvidia_host_stack_for_vfio() {
|
||||
local changed=false
|
||||
local state_dir="/var/lib/proxmenux"
|
||||
local state_file="${state_dir}/nvidia-host-services.state"
|
||||
local svc
|
||||
local -a services=(
|
||||
"nvidia-persistenced.service"
|
||||
"nvidia-powerd.service"
|
||||
"nvidia-fabricmanager.service"
|
||||
)
|
||||
|
||||
mkdir -p "$state_dir" >/dev/null 2>&1 || true
|
||||
: > "$state_file"
|
||||
|
||||
for svc in "${services[@]}"; do
|
||||
local was_enabled=0 was_active=0
|
||||
if systemctl is-enabled --quiet "$svc" 2>/dev/null; then
|
||||
was_enabled=1
|
||||
fi
|
||||
if systemctl is-active --quiet "$svc" 2>/dev/null; then
|
||||
was_active=1
|
||||
fi
|
||||
if (( was_enabled == 1 || was_active == 1 )); then
|
||||
echo "${svc} enabled=${was_enabled} active=${was_active}" >>"$state_file"
|
||||
fi
|
||||
|
||||
if systemctl is-active --quiet "$svc" 2>/dev/null; then
|
||||
systemctl stop "$svc" >>"$LOG_FILE" 2>&1 || true
|
||||
changed=true
|
||||
fi
|
||||
if systemctl is-enabled --quiet "$svc" 2>/dev/null; then
|
||||
systemctl disable "$svc" >>"$LOG_FILE" 2>&1 || true
|
||||
changed=true
|
||||
fi
|
||||
done
|
||||
|
||||
[[ -s "$state_file" ]] || rm -f "$state_file"
|
||||
|
||||
if [[ -f /etc/modules-load.d/nvidia-vfio.conf ]]; then
|
||||
mv /etc/modules-load.d/nvidia-vfio.conf /etc/modules-load.d/nvidia-vfio.conf.proxmenux-disabled-vfio >>"$LOG_FILE" 2>&1 || true
|
||||
changed=true
|
||||
fi
|
||||
|
||||
if grep -qE '^(nvidia|nvidia_uvm|nvidia_drm|nvidia_modeset)$' /etc/modules 2>/dev/null; then
|
||||
sed -i '/^nvidia$/d;/^nvidia_uvm$/d;/^nvidia_drm$/d;/^nvidia_modeset$/d' /etc/modules
|
||||
changed=true
|
||||
fi
|
||||
|
||||
# Disable NVIDIA udev rules that trigger nvidia-smi (causes conflict with vfio-pci)
|
||||
local udev_rules="/etc/udev/rules.d/70-nvidia.rules"
|
||||
if [[ -f "$udev_rules" ]]; then
|
||||
mv "$udev_rules" "${udev_rules}.proxmenux-disabled" >>"$LOG_FILE" 2>&1 || true
|
||||
udevadm control --reload-rules >>"$LOG_FILE" 2>&1 || true
|
||||
changed=true
|
||||
fi
|
||||
|
||||
# Create hard blacklist to prevent ANY nvidia module loading (even via modprobe/nvidia-smi)
|
||||
local nvidia_blacklist="/etc/modprobe.d/nvidia-blacklist.conf"
|
||||
if [[ ! -f "$nvidia_blacklist" ]]; then
|
||||
cat > "$nvidia_blacklist" <<'EOF'
|
||||
# ProxMenux: Hard blacklist to prevent ANY nvidia module loading in VFIO mode
|
||||
# This prevents nvidia-smi and other tools from triggering module load attempts
|
||||
install nvidia /bin/false
|
||||
install nvidia_uvm /bin/false
|
||||
install nvidia_drm /bin/false
|
||||
install nvidia_modeset /bin/false
|
||||
EOF
|
||||
changed=true
|
||||
fi
|
||||
|
||||
if $changed; then
|
||||
HOST_CONFIG_CHANGED=true
|
||||
msg_ok "$(translate 'NVIDIA host services/autoload disabled for VFIO mode')" | tee -a "$screen_capture"
|
||||
else
|
||||
msg_ok "$(translate 'NVIDIA host services/autoload already aligned for VFIO mode')" | tee -a "$screen_capture"
|
||||
fi
|
||||
|
||||
# Sync components_status.json — the host driver stays on disk but is
|
||||
# not in use because the GPU now belongs to a VM. Prevents the update
|
||||
# notification path (and any future logic gated on nvidia_driver.status)
|
||||
# from acting on a state that no longer matches reality.
|
||||
if declare -F update_component_status >/dev/null 2>&1; then
|
||||
local _nvd_ver
|
||||
_nvd_ver=$(jq -r '.nvidia_driver.version // ""' \
|
||||
/usr/local/share/proxmenux/components_status.json 2>/dev/null)
|
||||
update_component_status "nvidia_driver" "vfio_passthrough" \
|
||||
"${_nvd_ver:-}" "gpu" '{"patched":false}' >>"$LOG_FILE" 2>&1 || true
|
||||
fi
|
||||
_proxmenux_nvidia_vfio_policy_sync || true
|
||||
}
|
||||
|
||||
_restore_nvidia_host_stack_for_lxc() {
|
||||
local changed=false
|
||||
local state_file="/var/lib/proxmenux/nvidia-host-services.state"
|
||||
local disabled_file="/etc/modules-load.d/nvidia-vfio.conf.proxmenux-disabled-vfio"
|
||||
local active_file="/etc/modules-load.d/nvidia-vfio.conf"
|
||||
|
||||
# New per-BDF model: drop every NVIDIA BDF from the initramfs binder so
|
||||
# the nvidia module reclaims the GPU after the next reboot. Idempotent.
|
||||
if declare -F _proxmenux_vfio_bind_purge_vendor >/dev/null 2>&1; then
|
||||
_proxmenux_vfio_bind_purge_vendor "10de" && changed=true
|
||||
fi
|
||||
|
||||
# Remove hard blacklist that was preventing nvidia module loading
|
||||
local nvidia_blacklist="/etc/modprobe.d/nvidia-blacklist.conf"
|
||||
if [[ -f "$nvidia_blacklist" ]]; then
|
||||
rm -f "$nvidia_blacklist" >>"$LOG_FILE" 2>&1 || true
|
||||
changed=true
|
||||
fi
|
||||
|
||||
# Restore NVIDIA udev rules if they were disabled
|
||||
local udev_disabled="/etc/udev/rules.d/70-nvidia.rules.proxmenux-disabled"
|
||||
local udev_rules="/etc/udev/rules.d/70-nvidia.rules"
|
||||
if [[ -f "$udev_disabled" ]]; then
|
||||
mv "$udev_disabled" "$udev_rules" >>"$LOG_FILE" 2>&1 || true
|
||||
udevadm control --reload-rules >>"$LOG_FILE" 2>&1 || true
|
||||
changed=true
|
||||
fi
|
||||
|
||||
if [[ -f "$disabled_file" ]]; then
|
||||
mv "$disabled_file" "$active_file" >>"$LOG_FILE" 2>&1 || true
|
||||
changed=true
|
||||
fi
|
||||
|
||||
modprobe nvidia >/dev/null 2>&1 || true
|
||||
modprobe nvidia_uvm >/dev/null 2>&1 || true
|
||||
modprobe nvidia_modeset >/dev/null 2>&1 || true
|
||||
modprobe nvidia_drm >/dev/null 2>&1 || true
|
||||
|
||||
if [[ -f "$state_file" ]]; then
|
||||
while IFS= read -r line; do
|
||||
[[ -z "$line" ]] && continue
|
||||
local svc enabled active
|
||||
svc=$(echo "$line" | awk '{print $1}')
|
||||
enabled=$(echo "$line" | awk -F'enabled=' '{print $2}' | awk '{print $1}')
|
||||
active=$(echo "$line" | awk -F'active=' '{print $2}' | awk '{print $1}')
|
||||
[[ "$enabled" == "1" ]] && systemctl enable "$svc" >>"$LOG_FILE" 2>&1 || true
|
||||
[[ "$active" == "1" ]] && systemctl start "$svc" >>"$LOG_FILE" 2>&1 || true
|
||||
done <"$state_file"
|
||||
rm -f "$state_file"
|
||||
changed=true
|
||||
fi
|
||||
|
||||
if $changed; then
|
||||
HOST_CONFIG_CHANGED=true
|
||||
msg_ok "$(translate 'NVIDIA host services/autoload restored for native mode')" | tee -a "$screen_capture"
|
||||
else
|
||||
msg_ok "$(translate 'NVIDIA host services/autoload already aligned for native mode')" | tee -a "$screen_capture"
|
||||
fi
|
||||
|
||||
# Sync components_status.json back to installed — the host has reclaimed
|
||||
# the GPU and the nvidia stack is being reloaded. Restores the state to
|
||||
# what it was before the VFIO switch so the update notification path and
|
||||
# the auto-reinstall gate see the driver as active on the host again.
|
||||
if declare -F update_component_status >/dev/null 2>&1; then
|
||||
local _nvd_ver
|
||||
_nvd_ver=$(nvidia-smi --query-gpu=driver_version --format=csv,noheader 2>/dev/null | head -1)
|
||||
if [[ -z "$_nvd_ver" ]]; then
|
||||
_nvd_ver=$(jq -r '.nvidia_driver.version // ""' \
|
||||
/usr/local/share/proxmenux/components_status.json 2>/dev/null)
|
||||
fi
|
||||
update_component_status "nvidia_driver" "installed" \
|
||||
"${_nvd_ver:-}" "gpu" '{"patched":false}' >>"$LOG_FILE" 2>&1 || true
|
||||
_proxmenux_nvidia_vfio_policy_sync || true
|
||||
if ! _proxmenux_all_nvidia_in_vfio; then
|
||||
modprobe nvidia >/dev/null 2>&1 || true
|
||||
modprobe nvidia_uvm >/dev/null 2>&1 || true
|
||||
modprobe nvidia_modeset >/dev/null 2>&1 || true
|
||||
modprobe nvidia_drm >/dev/null 2>&1 || true
|
||||
fi
|
||||
}
|
||||
|
||||
_add_amd_softdep() {
|
||||
local vfio_conf="/etc/modprobe.d/vfio.conf"
|
||||
_add_line_if_missing "softdep radeon pre: vfio-pci" "$vfio_conf"
|
||||
@@ -442,6 +300,10 @@ _remove_vfio_modules_if_unused() {
|
||||
local vfio_count
|
||||
vfio_count=$(_read_vfio_ids | wc -l | tr -d '[:space:]')
|
||||
[[ "$vfio_count" != "0" ]] && return 1
|
||||
if declare -F _proxmenux_vfio_bind_has_entries >/dev/null 2>&1 \
|
||||
&& _proxmenux_vfio_bind_has_entries; then
|
||||
return 1
|
||||
fi
|
||||
local modules_file="/etc/modules"
|
||||
[[ ! -f "$modules_file" ]] && return 1
|
||||
local had_any=false
|
||||
@@ -632,25 +494,37 @@ validate_vm_mode_blocked_ids() {
|
||||
collect_selected_iommu_ids() {
|
||||
SELECTED_IOMMU_IDS=()
|
||||
SELECTED_PCI_SLOTS=()
|
||||
SELECTED_NVIDIA_BDFS=()
|
||||
SELECTED_LEGACY_IOMMU_IDS=()
|
||||
|
||||
local idx pci viddid slot
|
||||
local idx pci viddid slot selected_type bdf vid did gid
|
||||
for idx in "${SELECTED_GPU_IDX[@]}"; do
|
||||
pci="${ALL_GPU_PCIS[$idx]}"
|
||||
viddid="${ALL_GPU_VIDDID[$idx]}"
|
||||
selected_type="${ALL_GPU_TYPES[$idx]}"
|
||||
slot="${pci#0000:}"
|
||||
slot="${slot%.*}"
|
||||
SELECTED_PCI_SLOTS+=("$slot")
|
||||
|
||||
local -a group_ids=()
|
||||
mapfile -t group_ids < <(_get_iommu_group_ids "$pci")
|
||||
if [[ ${#group_ids[@]} -gt 0 ]]; then
|
||||
local gid
|
||||
for gid in "${group_ids[@]}"; do
|
||||
local -a group_bdfs=()
|
||||
mapfile -t group_bdfs < <(_get_iommu_group_bdfs "$pci")
|
||||
[[ ${#group_bdfs[@]} -gt 0 ]] || group_bdfs=("$pci")
|
||||
|
||||
for bdf in "${group_bdfs[@]}"; do
|
||||
[[ "$bdf" == 0000:* ]] || bdf="0000:${bdf}"
|
||||
vid=$(cat "/sys/bus/pci/devices/${bdf}/vendor" 2>/dev/null | sed 's/^0x//')
|
||||
did=$(cat "/sys/bus/pci/devices/${bdf}/device" 2>/dev/null | sed 's/^0x//')
|
||||
gid="${vid}:${did}"
|
||||
if [[ -n "$vid" && -n "$did" ]]; then
|
||||
_contains_in_array "$gid" "${SELECTED_IOMMU_IDS[@]}" || SELECTED_IOMMU_IDS+=("$gid")
|
||||
done
|
||||
elif [[ -n "$viddid" ]]; then
|
||||
_contains_in_array "$viddid" "${SELECTED_IOMMU_IDS[@]}" || SELECTED_IOMMU_IDS+=("$viddid")
|
||||
fi
|
||||
if [[ "$selected_type" != "nvidia" ]]; then
|
||||
_contains_in_array "$gid" "${SELECTED_LEGACY_IOMMU_IDS[@]}" || SELECTED_LEGACY_IOMMU_IDS+=("$gid")
|
||||
fi
|
||||
fi
|
||||
if [[ "$selected_type" == "nvidia" ]]; then
|
||||
_contains_in_array "$bdf" "${SELECTED_NVIDIA_BDFS[@]}" || SELECTED_NVIDIA_BDFS+=("$bdf")
|
||||
fi
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
@@ -948,6 +822,9 @@ apply_vm_action_for_lxc_mode() {
|
||||
if ! _contains_in_array "$_vd_id" "${SELECTED_IOMMU_IDS[@]}"; then
|
||||
SELECTED_IOMMU_IDS+=("$_vd_id")
|
||||
fi
|
||||
if ! _contains_in_array "$_vd_id" "${SELECTED_LEGACY_IOMMU_IDS[@]}"; then
|
||||
SELECTED_LEGACY_IOMMU_IDS+=("$_vd_id")
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
@@ -1018,6 +895,12 @@ switch_to_vm_mode() {
|
||||
|
||||
msg_info "$(translate 'Configuring host for GPU -> VM mode...')"
|
||||
|
||||
local -a selected_types=()
|
||||
mapfile -t selected_types < <(_selected_types_unique)
|
||||
if _contains_in_array "nvidia" "${selected_types[@]}"; then
|
||||
_proxmenux_nvidia_migrate_legacy_blacklist
|
||||
fi
|
||||
|
||||
if declare -F _pci_is_iommu_active >/dev/null 2>&1 && _pci_is_iommu_active; then
|
||||
_register_iommu_tool
|
||||
msg_ok "$(translate 'IOMMU is already active on this system')" | tee -a "$screen_capture"
|
||||
@@ -1044,24 +927,30 @@ switch_to_vm_mode() {
|
||||
local -a current_ids=()
|
||||
mapfile -t current_ids < <(_read_vfio_ids)
|
||||
local id
|
||||
for id in "${SELECTED_IOMMU_IDS[@]}"; do
|
||||
for id in "${SELECTED_LEGACY_IOMMU_IDS[@]}"; do
|
||||
_contains_in_array "$id" "${current_ids[@]}" || current_ids+=("$id")
|
||||
done
|
||||
_write_vfio_ids "${current_ids[@]}"
|
||||
if [[ ${#SELECTED_IOMMU_IDS[@]} -gt 0 ]]; then
|
||||
if [[ ${#SELECTED_LEGACY_IOMMU_IDS[@]} -gt 0 ]]; then
|
||||
local ids_label
|
||||
ids_label=$(IFS=','; echo "${SELECTED_IOMMU_IDS[*]}")
|
||||
ids_label=$(IFS=','; echo "${SELECTED_LEGACY_IOMMU_IDS[*]}")
|
||||
msg_ok "$(translate 'vfio-pci IDs configured') (${ids_label})" | tee -a "$screen_capture"
|
||||
fi
|
||||
|
||||
local -a selected_types=()
|
||||
mapfile -t selected_types < <(_selected_types_unique)
|
||||
local t
|
||||
if [[ ${#SELECTED_NVIDIA_BDFS[@]} -gt 0 ]]; then
|
||||
_proxmenux_vfio_bind_add_bdfs "${SELECTED_NVIDIA_BDFS[@]}"
|
||||
msg_ok "$(translate 'NVIDIA per-BDF VFIO binding configured') (${SELECTED_NVIDIA_BDFS[*]})" | tee -a "$screen_capture"
|
||||
fi
|
||||
|
||||
local t legacy_blacklist_configured=false
|
||||
for t in "${selected_types[@]}"; do
|
||||
[[ "$t" == "nvidia" ]] && continue
|
||||
_add_gpu_blacklist "$t"
|
||||
legacy_blacklist_configured=true
|
||||
done
|
||||
msg_ok "$(translate 'GPU host driver blacklisted in /etc/modprobe.d/blacklist.conf')" | tee -a "$screen_capture"
|
||||
_contains_in_array "nvidia" "${selected_types[@]}" && _sanitize_nvidia_host_stack_for_vfio
|
||||
$legacy_blacklist_configured \
|
||||
&& msg_ok "$(translate 'GPU host driver blacklisted in /etc/modprobe.d/blacklist.conf')" | tee -a "$screen_capture"
|
||||
_contains_in_array "nvidia" "${selected_types[@]}" && _proxmenux_nvidia_vfio_policy_sync || true
|
||||
_contains_in_array "amd" "${selected_types[@]}" && _add_amd_softdep
|
||||
|
||||
if [[ "$HOST_CONFIG_CHANGED" == "true" ]]; then
|
||||
@@ -1095,12 +984,20 @@ switch_to_lxc_mode() {
|
||||
|
||||
msg_info "$(translate 'Removing VFIO ownership for selected GPU(s)...')"
|
||||
|
||||
local -a selected_types=()
|
||||
mapfile -t selected_types < <(_selected_types_unique)
|
||||
if _contains_in_array "nvidia" "${selected_types[@]}"; then
|
||||
_proxmenux_nvidia_migrate_legacy_blacklist
|
||||
[[ ${#SELECTED_NVIDIA_BDFS[@]} -gt 0 ]] \
|
||||
&& _proxmenux_vfio_bind_remove_bdfs "${SELECTED_NVIDIA_BDFS[@]}"
|
||||
fi
|
||||
|
||||
local -a current_ids=() remaining_ids=() removed_ids=()
|
||||
mapfile -t current_ids < <(_read_vfio_ids)
|
||||
local id remove
|
||||
for id in "${current_ids[@]}"; do
|
||||
remove=false
|
||||
_contains_in_array "$id" "${SELECTED_IOMMU_IDS[@]}" && remove=true
|
||||
_contains_in_array "$id" "${SELECTED_LEGACY_IOMMU_IDS[@]}" && remove=true
|
||||
if $remove; then
|
||||
removed_ids+=("$id")
|
||||
else
|
||||
@@ -1114,17 +1011,16 @@ switch_to_lxc_mode() {
|
||||
msg_ok "$(translate 'VFIO device IDs removed from /etc/modprobe.d/vfio.conf') (${ids_label})" | tee -a "$screen_capture"
|
||||
fi
|
||||
|
||||
local -a selected_types=()
|
||||
mapfile -t selected_types < <(_selected_types_unique)
|
||||
local t
|
||||
for t in "${selected_types[@]}"; do
|
||||
if [[ "$t" == "nvidia" ]]; then
|
||||
_proxmenux_nvidia_vfio_policy_sync || true
|
||||
continue
|
||||
fi
|
||||
if ! _type_has_remaining_vfio_ids "$t" "${remaining_ids[@]}"; then
|
||||
if _remove_gpu_blacklist "$t"; then
|
||||
msg_ok "$(translate 'Driver blacklist removed for') ${t}" | tee -a "$screen_capture"
|
||||
fi
|
||||
if [[ "$t" == "nvidia" ]]; then
|
||||
_restore_nvidia_host_stack_for_lxc
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
Reference in New Issue
Block a user