- Replace GNU \b with portable word-boundary sed patterns in kernel-params - Warn on unknown CLI arguments instead of silently swallowing - Add floor check on recommended_gttsize_mib to prevent negative values - Fix Python operator precedence in benchmark log parser - Add root checks to tuned-profile.sh and rollback.sh - Remove redundant sudo calls (scripts already require root at entry) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
150 lines
5.6 KiB
Bash
150 lines
5.6 KiB
Bash
#!/usr/bin/env bash
|
|
# Configure kernel boot parameters for unified memory optimization
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
source "$SCRIPT_DIR/../../lib/common.sh"
|
|
source "$SCRIPT_DIR/../../lib/detect.sh"
|
|
source "$SCRIPT_DIR/../../lib/format.sh"
|
|
|
|
GRUB_FILE="/etc/default/grub"
|
|
|
|
log_header "Kernel Boot Parameter Optimization"
|
|
|
|
# ── Check root early ────────────────────────────────────
|
|
if [[ $EUID -ne 0 ]]; then
|
|
log_error "This script requires root. Re-run with: sudo make optimize-kernel"
|
|
exit 1
|
|
fi
|
|
|
|
# ── Show current state ───────────────────────────────────
|
|
log_info "Current kernel command line:"
|
|
printf " ${DIM}%s${RESET}\n" "$(cat /proc/cmdline)"
|
|
echo ""
|
|
|
|
param_iommu="$(detect_kernel_param 'iommu')"
|
|
param_gttsize="$(detect_gttsize_param)"
|
|
param_pages="$(detect_pages_limit_param)"
|
|
|
|
rec_gttsize="$(recommended_gttsize_mib)"
|
|
rec_pages="$(recommended_pages_limit)"
|
|
|
|
# ── Check what's needed ──────────────────────────────────
|
|
needs_change=false
|
|
|
|
log_info "Parameter status:"
|
|
|
|
if [[ "$param_iommu" == "pt" ]]; then
|
|
print_status pass "iommu=pt" "already set"
|
|
else
|
|
print_status fail "iommu=pt" "$([ -n "$param_iommu" ] && echo "current: $param_iommu" || echo "missing")"
|
|
needs_change=true
|
|
fi
|
|
|
|
if [[ -n "$param_gttsize" ]] && (( param_gttsize >= rec_gttsize )); then
|
|
print_status pass "amdgpu.gttsize" "current: $param_gttsize MiB"
|
|
else
|
|
print_status fail "amdgpu.gttsize" "$([ -n "$param_gttsize" ] && echo "current: $param_gttsize MiB, " || echo "missing, ")recommended: $rec_gttsize MiB (~$(human_mib "$rec_gttsize"))"
|
|
needs_change=true
|
|
fi
|
|
|
|
if [[ -n "$param_pages" ]] && (( param_pages >= rec_pages )); then
|
|
print_status pass "ttm.pages_limit" "current: $param_pages"
|
|
else
|
|
print_status fail "ttm.pages_limit" "$([ -n "$param_pages" ] && echo "current: $param_pages, " || echo "missing, ")recommended: $rec_pages"
|
|
needs_change=true
|
|
fi
|
|
|
|
if ! $needs_change; then
|
|
echo ""
|
|
log_success "All kernel parameters are already optimal!"
|
|
exit 0
|
|
fi
|
|
|
|
# ── Explain what we're doing ─────────────────────────────
|
|
echo ""
|
|
log_info "These parameters enable unified memory for the integrated GPU:"
|
|
echo " iommu=pt IOMMU passthrough — reduces memory access latency"
|
|
echo " amdgpu.gttsize=$rec_gttsize GPU can dynamically access ~$(human_mib "$rec_gttsize") system RAM"
|
|
echo " ttm.pages_limit=$rec_pages Pin limit for GPU memory pages ($(human_mib "$rec_gttsize") in 4K pages)"
|
|
echo ""
|
|
|
|
# ── Apply changes ────────────────────────────────────────
|
|
if ! confirm "Apply these kernel parameters to GRUB?"; then
|
|
log_info "Skipped. You can apply manually by editing $GRUB_FILE"
|
|
exit 0
|
|
fi
|
|
|
|
# Backup
|
|
BACKUP_DIR="$(data_dir backups)"
|
|
backup_file="$BACKUP_DIR/grub-$(timestamp).bak"
|
|
cp "$GRUB_FILE" "$backup_file"
|
|
log_success "GRUB backup saved: $backup_file"
|
|
|
|
# Parse current GRUB_CMDLINE_LINUX using Python (data via env vars, not interpolation)
|
|
current_cmdline="$(GRUB_PATH="$GRUB_FILE" python3 -c '
|
|
import re, os
|
|
with open(os.environ["GRUB_PATH"]) as f:
|
|
for line in f:
|
|
m = re.match(r"^GRUB_CMDLINE_LINUX=\"(.*)\"", line)
|
|
if m:
|
|
print(m.group(1))
|
|
raise SystemExit(0)
|
|
print("")
|
|
')"
|
|
|
|
# Remove any existing values of these params (portable, no GNU \b)
|
|
new_cmdline="$current_cmdline"
|
|
new_cmdline="$(echo " $new_cmdline " | sed -E 's/ iommu=[^ ]*/ /g')"
|
|
new_cmdline="$(echo " $new_cmdline " | sed -E 's/ amd_iommu=[^ ]*/ /g')"
|
|
new_cmdline="$(echo " $new_cmdline " | sed -E 's/ amdgpu\.gttsize=[^ ]*/ /g')"
|
|
new_cmdline="$(echo " $new_cmdline " | sed -E 's/ ttm\.pages_limit=[^ ]*/ /g')"
|
|
# Clean up extra spaces
|
|
new_cmdline="$(echo "$new_cmdline" | xargs)"
|
|
|
|
# Add new params
|
|
new_cmdline="$new_cmdline iommu=pt amdgpu.gttsize=$rec_gttsize ttm.pages_limit=$rec_pages"
|
|
|
|
log_info "GRUB_CMDLINE_LINUX change:"
|
|
printf " ${RED}Before:${RESET} %s\n" "$current_cmdline"
|
|
printf " ${GREEN}After:${RESET} %s\n" "$new_cmdline"
|
|
echo ""
|
|
|
|
if ! confirm "Write this change?"; then
|
|
log_info "Aborted. Backup remains at: $backup_file"
|
|
exit 0
|
|
fi
|
|
|
|
# Apply using Python (all data via env vars — no shell interpolation into Python code)
|
|
GRUB_PATH="$GRUB_FILE" NEW_CMDLINE="$new_cmdline" python3 -c '
|
|
import re, os
|
|
grub_path = os.environ["GRUB_PATH"]
|
|
new_line = "GRUB_CMDLINE_LINUX=\"" + os.environ["NEW_CMDLINE"] + "\""
|
|
with open(grub_path) as f:
|
|
content = f.read()
|
|
content = re.sub(r"^GRUB_CMDLINE_LINUX=.*", new_line, content, count=1, flags=re.MULTILINE)
|
|
with open(grub_path, "w") as f:
|
|
f.write(content)
|
|
'
|
|
log_success "GRUB config updated"
|
|
|
|
# Regenerate GRUB — prefer grubby on modern Fedora (BLS), fall back to grub2-mkconfig
|
|
log_info "Regenerating boot configuration..."
|
|
if is_cmd grubby; then
|
|
grubby --update-kernel=ALL --args="iommu=pt amdgpu.gttsize=$rec_gttsize ttm.pages_limit=$rec_pages"
|
|
log_success "Boot entries updated via grubby"
|
|
elif [[ -d /boot/grub2 ]]; then
|
|
grub2-mkconfig -o /boot/grub2/grub.cfg
|
|
log_success "GRUB regenerated via grub2-mkconfig"
|
|
elif [[ -d /boot/grub ]]; then
|
|
grub-mkconfig -o /boot/grub/grub.cfg
|
|
log_success "GRUB regenerated via grub-mkconfig"
|
|
else
|
|
log_error "Could not find grubby or grub config directory. Regenerate manually."
|
|
exit 1
|
|
fi
|
|
|
|
echo ""
|
|
log_warn "REBOOT REQUIRED for kernel parameters to take effect."
|
|
log_info "After reboot, verify with: make audit"
|