42 lines
1.7 KiB
Bash
Executable File
42 lines
1.7 KiB
Bash
Executable File
#!/bin/bash
|
|
# Waits for a just-started guest's network to actually come up, then turns
|
|
# kvm_amd cpuid_passthrough on.
|
|
#
|
|
# The readiness signal is the guest's own tap RX counter: it is fresh every boot,
|
|
# it needs nothing enabled inside the guest (no SSH, no RDP, no agent), and it only
|
|
# moves once the guest's NIC driver has really loaded - which is well past the CPU
|
|
# enumeration that the switch must not change under. A DHCP lease left over from a
|
|
# previous boot cannot trip it early.
|
|
#
|
|
# Launched as a transient systemd unit by the cpuid-passthrough hook, so it is free
|
|
# to call virsh (the hook itself must not - that deadlocks libvirtd).
|
|
|
|
DOMAIN=$1
|
|
BRAND=$2
|
|
PARAM=/sys/module/kvm_amd/parameters
|
|
V="virsh -c qemu:///system"
|
|
|
|
running() { [ "$($V domstate "$DOMAIN" 2>/dev/null)" = running ]; }
|
|
|
|
tap=""
|
|
i=0
|
|
for _ in $(seq 1 65); do # ~195 s cap, then flip anyway if still up
|
|
i=$((i + 1))
|
|
running || { sleep 3; continue; } # not "running" yet at prepare time - wait
|
|
[ -z "$tap" ] && tap=$($V domiflist "$DOMAIN" 2>/dev/null |
|
|
awk '$1 ~ /^(vnet|tap|macvtap)/ {print $1; exit}')
|
|
rx="/sys/class/net/$tap/statistics/rx_packets"
|
|
# the iteration floor keeps a stray pre-OS packet (a UEFI netboot attempt) from
|
|
# tripping the flip before the guest is even past its interrupt and timer setup
|
|
if [ "$i" -ge 4 ] && [ -n "$tap" ] && [ -r "$rx" ] &&
|
|
[ "$(cat "$rx" 2>/dev/null || echo 0)" -ge 4 ]; then
|
|
break
|
|
fi
|
|
sleep 3
|
|
done
|
|
|
|
running || exit 0 # guest went away before it came up
|
|
printf '%s' "$BRAND" > "$PARAM/brand_string"
|
|
echo Y > "$PARAM/cpuid_passthrough"
|
|
logger -t vfio-cpuid "$DOMAIN network up: cpuid_passthrough=Y"
|