@@ -48,6 +48,10 @@ readonly C_RESET='\033[0m'
4848
4949MODE=" audit"
5050IFACES=" "
51+ APPLY_IOMMU=0
52+ APPLY_SMT=" "
53+ PERSIST_SMT=0
54+ AUTO_YES=0
5155
5256usage () {
5357 cat << 'EOF '
@@ -61,6 +65,10 @@ Options:
6165 --ifaces LIST Comma-separated interfaces to check/tune. Default: all up, non-loopback
6266 --target TYPE Host type: measurement (default) or dtn (data transfer node)
6367 --color Use color codes (green=ok, yellow=warning, red=critical)
68+ --apply-iommu (apply only) Edit GRUB to enable IOMMU (intel/amd flags + iommu=pt)
69+ --apply-smt STATE Apply runtime SMT change (on|off). Requires --mode apply
70+ --persist-smt (apply only) Also persist SMT choice via GRUB changes (adds/removes 'nosmt')
71+ --yes Skip interactive confirmations (use with caution)
6472 --verbose More detail in audit output
6573 -h, --help Show this help
6674EOF
@@ -606,6 +614,143 @@ check_iommu() {
606614 fi
607615}
608616
617+ apply_iommu () {
618+ # Apply GRUB edits to enable IOMMU (intel/amd + iommu=pt) if requested. Safe, interactive by default.
619+ if [[ " $MODE " != " apply" ]]; then
620+ log_warn " --apply-iommu ignored unless --mode apply"
621+ return
622+ fi
623+ require_root
624+ local cmdline
625+ cmdline=$( cat /proc/cmdline 2> /dev/null || true)
626+ local cpu_vendor iommu_cmd
627+ if grep -q ' ^vendor_id.*GenuineIntel' /proc/cpuinfo 2> /dev/null; then
628+ cpu_vendor=" Intel"
629+ iommu_cmd=" intel_iommu=on iommu=pt"
630+ elif grep -q ' ^vendor_id.*AuthenticAMD' /proc/cpuinfo 2> /dev/null; then
631+ cpu_vendor=" AMD"
632+ iommu_cmd=" amd_iommu=on iommu=pt"
633+ else
634+ cpu_vendor=" unknown"
635+ iommu_cmd=" iommu=pt"
636+ fi
637+ if echo " $cmdline " | grep -q -E ' iommu=pt|intel_iommu=on|amd_iommu=on' ; then
638+ log_info " IOMMU appears to be enabled: $cmdline "
639+ return
640+ fi
641+ log_warn " IOMMU not in kernel cmdline (CPU: $cpu_vendor ). Will add: $iommu_cmd "
642+ if [[ $AUTO_YES -ne 1 ]]; then
643+ read -r -p " Update /etc/default/grub and regenerate GRUB to add '$iommu_cmd '? [y/N] " resp
644+ if [[ ! " $resp " =~ ^[Yy]$ ]]; then
645+ log_info " Skipping GRUB edit for IOMMU"
646+ return
647+ fi
648+ fi
649+ # Backup grub config
650+ local backup=" /etc/default/grub.bak.$( date +%Y%m%d%H%M%S) "
651+ cp -a /etc/default/grub " $backup "
652+ log_info " Backed up /etc/default/grub to $backup "
653+ # Read existing value and ensure we append without duplicates
654+ local existing
655+ existing=$( awk -F= ' /^GRUB_CMDLINE_LINUX=/ { match($0,/=(\"|\")(.*)\1/,m); print m[2]; exit }' /etc/default/grub || true)
656+ if [[ -z " $existing " ]]; then
657+ echo " GRUB_CMDLINE_LINUX=\" $iommu_cmd \" " >> /etc/default/grub
658+ else
659+ if echo " $existing " | grep -qF " $iommu_cmd " ; then
660+ log_info " GRUB already contains required IOMMU flags"
661+ else
662+ # Append flags
663+ local newval=" $existing $iommu_cmd "
664+ # Replace the line
665+ sed -i " s|^GRUB_CMDLINE_LINUX=.*|GRUB_CMDLINE_LINUX=\" $newval \" |" /etc/default/grub
666+ fi
667+ fi
668+ # Regenerate grub
669+ if command -v grub2-mkconfig > /dev/null 2>&1 ; then
670+ grub2-mkconfig -o /boot/grub2/grub.cfg
671+ elif command -v update-grub > /dev/null 2>&1 ; then
672+ update-grub || true
673+ else
674+ log_warn " No grub2-mkconfig or update-grub found; edit /etc/default/grub manually"
675+ return
676+ fi
677+ log_info " GRUB config updated; please reboot to apply IOMMU settings"
678+ }
679+
680+ apply_smt () {
681+ # Apply SMT changes at runtime and optionally persist via GRUB (adds/removes 'nosmt')
682+ if [[ " $MODE " != " apply" ]]; then
683+ log_warn " --apply-smt ignored unless --mode apply"
684+ return
685+ fi
686+ require_root
687+ if [[ ! -r /sys/devices/system/cpu/smt/control ]]; then
688+ log_warn " SMT control not available on this system"
689+ return
690+ fi
691+ local cur=$( cat /sys/devices/system/cpu/smt/control)
692+ if [[ " $APPLY_SMT " != " on" && " $APPLY_SMT " != " off" ]]; then
693+ log_warn " Invalid or missing --apply-smt STATE (expected 'on' or 'off')"
694+ return
695+ fi
696+ if [[ " $cur " == " $APPLY_SMT " ]]; then
697+ log_info " SMT already set to $cur "
698+ else
699+ log_warn " Changing SMT from $cur to $APPLY_SMT "
700+ if [[ $AUTO_YES -ne 1 ]]; then
701+ read -r -p " Apply SMT change now (writes to /sys/devices/system/cpu/smt/control)? [y/N] " resp
702+ if [[ ! " $resp " =~ ^[Yy]$ ]]; then
703+ log_info " SMT change cancelled"
704+ return
705+ fi
706+ fi
707+ echo " $APPLY_SMT " | tee /sys/devices/system/cpu/smt/control > /dev/null
708+ log_info " SMT set to $APPLY_SMT "
709+ fi
710+ # If persist requested, update grub kernel cmdline
711+ if [[ $PERSIST_SMT -eq 1 ]]; then
712+ local grubnosmt
713+ if [[ " $APPLY_SMT " == " off" ]]; then
714+ grubnosmt=" nosmt"
715+ else
716+ grubnosmt=" "
717+ fi
718+ # Edit GRUB similar to apply_iommu (backup/append/remove nosmt)
719+ local backup=" /etc/default/grub.bak.$( date +%Y%m%d%H%M%S) "
720+ cp -a /etc/default/grub " $backup "
721+ log_info " Backed up /etc/default/grub to $backup "
722+ local existing
723+ existing=$( awk -F= ' /^GRUB_CMDLINE_LINUX=/ { match($0,/=(\"|\")(.*)\1/,m); print m[2]; exit }' /etc/default/grub || true)
724+ if [[ -z " $existing " ]]; then
725+ if [[ -n " $grubnosmt " ]]; then
726+ echo " GRUB_CMDLINE_LINUX=\" $grubnosmt \" " >> /etc/default/grub
727+ fi
728+ else
729+ if [[ -n " $grubnosmt " ]]; then
730+ if echo " $existing " | grep -qF " $grubnosmt " ; then
731+ log_info " GRUB already contains $grubnosmt "
732+ else
733+ local newval=" $existing $grubnosmt "
734+ sed -i " s|^GRUB_CMDLINE_LINUX=.*|GRUB_CMDLINE_LINUX=\" $newval \" |" /etc/default/grub
735+ fi
736+ else
737+ # Remove nosmt bit if present
738+ local newval=$( echo " $existing " | sed ' s/\bnosmt\b//g' | sed ' s/ */ /g' | sed ' s/^ *//;s/ *$//' )
739+ sed -i " s|^GRUB_CMDLINE_LINUX=.*|GRUB_CMDLINE_LINUX=\" $newval \" |" /etc/default/grub
740+ fi
741+ fi
742+ if command -v grub2-mkconfig > /dev/null 2>&1 ; then
743+ grub2-mkconfig -o /boot/grub2/grub.cfg
744+ elif command -v update-grub > /dev/null 2>&1 ; then
745+ update-grub || true
746+ else
747+ log_warn " No grub2-mkconfig or update-grub found; edit /etc/default/grub manually"
748+ return
749+ fi
750+ log_info " GRUB updated to persist SMT change; reboot to apply"
751+ fi
752+ }
753+
609754print_host_info () {
610755 local os_release kernel_ver mem_info_str fqdn smt_status cpu_info cpu_vendor
611756 os_release=$( awk -F' =' ' /^PRETTY_NAME/ {print $2}' /etc/os-release 2> /dev/null | tr -d ' "' )
@@ -815,6 +960,10 @@ main() {
815960 --ifaces) IFACES=" $2 " ; shift 2;;
816961 --target) TARGET_TYPE=" $2 " ; shift 2;;
817962 --color) USE_COLOR=1; shift ;;
963+ --apply-iommu) APPLY_IOMMU=1; shift ;;
964+ --apply-smt) APPLY_SMT=" $2 " ; shift 2;;
965+ --persist-smt) PERSIST_SMT=1; shift ;;
966+ --yes) AUTO_YES=1; shift ;;
818967 -h|--help) usage; exit 0;;
819968 * ) echo " Unknown arg: $1 " >&2 ; usage; exit 1;;
820969 esac
@@ -834,6 +983,18 @@ main() {
834983 fi
835984 [[ " $MODE " == " apply" ]] && require_root
836985
986+ # Validate apply flags
987+ if [[ -n " $APPLY_SMT " ]]; then
988+ if [[ " $APPLY_SMT " != " on" && " $APPLY_SMT " != " off" ]]; then
989+ echo " ERROR: --apply-smt requires 'on' or 'off'" >&2
990+ exit 1
991+ fi
992+ fi
993+ if [[ $PERSIST_SMT -eq 1 && -z " $APPLY_SMT " ]]; then
994+ echo " ERROR: --persist-smt requires --apply-smt to be set" >&2
995+ exit 1
996+ fi
997+
837998 if [[ " $MODE " == " audit" ]]; then
838999 print_host_info
8391000 print_sysctl_diff
@@ -867,6 +1028,13 @@ main() {
8671028
8681029 if [[ " $MODE " == " apply" ]]; then
8691030 create_ethtool_persist_service
1031+ # Apply optional additional host changes requested via flags
1032+ if [[ $APPLY_IOMMU -eq 1 ]]; then
1033+ apply_iommu
1034+ fi
1035+ if [[ -n " $APPLY_SMT " ]]; then
1036+ apply_smt
1037+ fi
8701038 log_info " Apply complete. Consider rebooting or rerunning audit to confirm settings."
8711039 else
8721040 log_info " Audit complete. Entries marked with '*' differ from recommended values."
0 commit comments