198 lines
5.6 KiB
Bash
198 lines
5.6 KiB
Bash
#!/usr/bin/env bash
|
|
# Hardware and configuration detection for Strix Halo
|
|
|
|
# Find the amdgpu DRM card path
|
|
find_gpu_card() {
|
|
local card
|
|
for card in /sys/class/drm/card*/device/vendor; do
|
|
if [[ -f "$card" ]] && [[ "$(cat "$card")" == "0x1002" ]]; then
|
|
echo "$(dirname "$card")"
|
|
return 0
|
|
fi
|
|
done
|
|
# Fallback: try any card with mem_info_vram_total (i.e., an amdgpu device)
|
|
for card in /sys/class/drm/card*/device/mem_info_vram_total; do
|
|
if [[ -f "$card" ]]; then
|
|
echo "$(dirname "$card")"
|
|
return 0
|
|
fi
|
|
done
|
|
echo "/sys/class/drm/card1/device" # last resort
|
|
}
|
|
|
|
GPU_SYSFS="$(find_gpu_card)"
|
|
|
|
# --- CPU ---
|
|
detect_cpu_model() { grep -m1 'model name' /proc/cpuinfo | cut -d: -f2 | xargs; }
|
|
detect_cpu_cores() { grep -c '^processor' /proc/cpuinfo; }
|
|
detect_cpu_physical() { grep 'cpu cores' /proc/cpuinfo | head -1 | cut -d: -f2 | xargs; }
|
|
|
|
# --- GPU ---
|
|
detect_gpu_name() {
|
|
lspci | grep -i 'Display\|VGA' | grep -i 'AMD' | head -1 | sed 's/.*: //'
|
|
}
|
|
|
|
detect_gpu_device_id() {
|
|
cat "$GPU_SYSFS/device" 2>/dev/null | sed 's/^0x//'
|
|
}
|
|
|
|
# --- Memory (bytes) ---
|
|
detect_vram_total() { cat "$GPU_SYSFS/mem_info_vram_total" 2>/dev/null || echo 0; }
|
|
detect_vram_used() { cat "$GPU_SYSFS/mem_info_vram_used" 2>/dev/null || echo 0; }
|
|
detect_gtt_total() { cat "$GPU_SYSFS/mem_info_gtt_total" 2>/dev/null || echo 0; }
|
|
detect_gtt_used() { cat "$GPU_SYSFS/mem_info_gtt_used" 2>/dev/null || echo 0; }
|
|
|
|
detect_system_ram_kb() {
|
|
local kb
|
|
kb="$(grep MemTotal /proc/meminfo 2>/dev/null | awk '{print $2}')"
|
|
echo "${kb:-0}"
|
|
}
|
|
detect_system_ram_bytes() { echo $(( $(detect_system_ram_kb) * 1024 )); }
|
|
|
|
# --- Kernel ---
|
|
detect_kernel_version() { uname -r; }
|
|
|
|
detect_kernel_param() {
|
|
# Returns the value of a kernel param, or empty if not present
|
|
local param="$1"
|
|
local cmdline
|
|
cmdline="$(cat /proc/cmdline)"
|
|
# Escape dots for regex and anchor with word boundary (space or start-of-string)
|
|
local pattern="${param//./\\.}"
|
|
if [[ "$cmdline" =~ (^|[[:space:]])${pattern}=([^ ]+) ]]; then
|
|
echo "${BASH_REMATCH[2]}"
|
|
elif [[ "$cmdline" =~ (^|[[:space:]])${pattern}([[:space:]]|$) ]]; then
|
|
echo "present"
|
|
fi
|
|
}
|
|
|
|
detect_has_iommu_pt() {
|
|
local val
|
|
val="$(detect_kernel_param 'iommu')"
|
|
[[ "$val" == "pt" ]]
|
|
}
|
|
|
|
detect_gttsize_param() { detect_kernel_param 'amdgpu.gttsize'; }
|
|
detect_pages_limit_param() { detect_kernel_param 'ttm.pages_limit'; }
|
|
|
|
# --- Tuned ---
|
|
detect_tuned_profile() {
|
|
if is_cmd tuned-adm; then
|
|
tuned-adm active 2>/dev/null | sed 's/Current active profile: //'
|
|
else
|
|
echo "tuned not installed"
|
|
fi
|
|
}
|
|
|
|
# --- Firmware ---
|
|
detect_firmware_version() {
|
|
rpm -q linux-firmware 2>/dev/null | sed 's/linux-firmware-//' | sed 's/\.fc.*//' || echo "unknown"
|
|
}
|
|
|
|
detect_firmware_bad() {
|
|
# Returns 0 (true) if firmware is the known-bad version
|
|
local fw
|
|
fw="$(detect_firmware_version)"
|
|
[[ "$fw" == *"20251125"* ]]
|
|
}
|
|
|
|
# --- ROCm ---
|
|
detect_rocm_version() {
|
|
if [[ -f /opt/rocm/.info/version ]]; then
|
|
cat /opt/rocm/.info/version
|
|
else
|
|
rpm -qa 2>/dev/null | grep '^rocm-core-' | head -1 | sed 's/rocm-core-//' | sed 's/-.*//' || echo "not installed"
|
|
fi
|
|
}
|
|
|
|
detect_rocm_packages() {
|
|
rpm -qa 2>/dev/null | grep -i rocm | sort
|
|
}
|
|
|
|
# --- Vulkan ---
|
|
detect_vulkan_driver() {
|
|
if is_cmd vulkaninfo; then
|
|
vulkaninfo --summary 2>/dev/null | grep 'driverName' | head -1 | awk '{print $NF}'
|
|
else
|
|
echo "vulkaninfo not available"
|
|
fi
|
|
}
|
|
|
|
detect_vulkan_version() {
|
|
if is_cmd vulkaninfo; then
|
|
vulkaninfo --summary 2>/dev/null | grep 'apiVersion' | head -1 | awk '{print $NF}'
|
|
fi
|
|
}
|
|
|
|
# --- Toolbox containers ---
|
|
detect_toolboxes() {
|
|
if is_cmd toolbox; then
|
|
toolbox list --containers 2>/dev/null | tail -n +2
|
|
fi
|
|
}
|
|
|
|
detect_toolbox_names() {
|
|
detect_toolboxes | awk '{print $2}' 2>/dev/null
|
|
}
|
|
|
|
# --- LLM stacks ---
|
|
detect_stack_ollama() { is_cmd ollama && echo "installed" || echo "missing"; }
|
|
detect_stack_lmstudio() { is_cmd lms && echo "installed" || echo "missing"; }
|
|
detect_stack_llamacpp() { (is_cmd llama-cli || is_cmd llama-bench) && echo "installed" || echo "missing"; }
|
|
detect_stack_opencode() { is_cmd opencode && echo "installed" || echo "missing"; }
|
|
|
|
# --- Sensors ---
|
|
detect_gpu_temp() {
|
|
# Returns temperature in millidegrees C
|
|
local hwmon
|
|
for hwmon in "$GPU_SYSFS"/hwmon/hwmon*/temp1_input; do
|
|
if [[ -f "$hwmon" ]]; then
|
|
cat "$hwmon"
|
|
return
|
|
fi
|
|
done
|
|
echo 0
|
|
}
|
|
|
|
detect_gpu_power() {
|
|
# Returns power in microwatts
|
|
local hwmon
|
|
for hwmon in "$GPU_SYSFS"/hwmon/hwmon*/power1_average; do
|
|
if [[ -f "$hwmon" ]]; then
|
|
cat "$hwmon"
|
|
return
|
|
fi
|
|
done
|
|
echo 0
|
|
}
|
|
|
|
detect_gpu_busy() {
|
|
cat "$GPU_SYSFS/gpu_busy_percent" 2>/dev/null || echo 0
|
|
}
|
|
|
|
# --- Total physical memory (visible + VRAM dedicated) ---
|
|
detect_total_physical_ram_kb() {
|
|
local visible_kb vram_bytes vram_kb
|
|
visible_kb="$(detect_system_ram_kb)"
|
|
vram_bytes="$(detect_vram_total)"
|
|
vram_kb=$(( vram_bytes / 1024 ))
|
|
echo $(( visible_kb + vram_kb ))
|
|
}
|
|
|
|
# --- Recommended values for this system ---
|
|
recommended_gttsize_mib() {
|
|
# Total physical RAM (including VRAM allocation) minus 4 GiB reserve, in MiB
|
|
local total_kb
|
|
total_kb="$(detect_total_physical_ram_kb)"
|
|
local total_gib=$(( total_kb / 1024 / 1024 ))
|
|
local gtt_gib=$(( total_gib - 4 ))
|
|
echo $(( gtt_gib * 1024 ))
|
|
}
|
|
|
|
recommended_pages_limit() {
|
|
# GTT GiB * 1024 MiB/GiB * 256 pages/MiB
|
|
local gtt_mib
|
|
gtt_mib="$(recommended_gttsize_mib)"
|
|
echo $(( gtt_mib * 256 ))
|
|
}
|