Last active
August 28, 2019 20:18
-
-
Save PedroHLC/427d71bef2f2f6d45609edae3c0eb51e to your computer and use it in GitHub Desktop.
Script used in UFSCar for running guest computers using vfio passthrough
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env sh | |
# ====================================================================================== | |
# Maintaned by Pedro H Lara Campos <[email protected]> | |
# Contributors: | |
# Marcos Laerte | |
# Paulo Matias | |
# Version: 2019.08.28-6 | |
# -------------------------------------------------------------------------------------- | |
: ${PSEUDO_RUN:=0} | |
# Power off baremetal if this script ends (expected or not) | |
function exit_gracefully() { | |
[ '1' = "$PSEUDO_RUN" ] || poweroff | |
} | |
trap exit_gracefully EXIT HUP INT TERM | |
set -o errexit | |
# ====================================================================================== | |
# * Constants and Settings | |
# -------------------------------------------------------------------------------------- | |
# ** SIn Machines | |
# ====================================================================================== | |
# OptiPlex 7010 | |
readonly _O7010_ID='OptiPlex 7010' | |
# sequence: video, usb, usb, xhci, audio | |
readonly _O7010_BUS="\ | |
0000:00:02.0 \ | |
0000:00:1d.0 \ | |
0000:00:1a.0 \ | |
0000:00:14.0 \ | |
0000:00:1b.0" | |
readonly _O7010_DEV="\ | |
8086 0162 \ | |
8086 1e26 \ | |
8086 1e31 \ | |
8086 1e2d \ | |
8086 1e20" | |
# OptiPlex 7040 | |
readonly _O7040_ID='OptiPlex 7040' | |
# sequence: video, usb, usb, xhci, audio, isa, memctrl, smbus | |
readonly _O7040_BUS="\ | |
0000:00:02.0 \ | |
0000:00:14.0 \ | |
0000:00:14.2 \ | |
0000:00:1f.3 \ | |
0000:00:1f.0 \ | |
0000:00:1f.2 \ | |
0000:00:1f.4" | |
readonly _O7040_DEV="\ | |
8086 1912 \ | |
8086 a12f \ | |
8086 a131 \ | |
8086 a170 \ | |
8086 a146 \ | |
8086 a121 \ | |
8086 a123" | |
# OptiPlex 9020 | |
readonly _O9020_ID='OptiPlex 9020' | |
# sequence: video, usb, usb, xhci, audio | |
readonly _O9020_BUS="\ | |
0000:00:02.0 \ | |
0000:00:1d.0 \ | |
0000:00:1a.0 \ | |
0000:00:14.0 \ | |
0000:00:1b.0" | |
readonly _O9020_DEV="\ | |
'8086 0412' \ | |
'8086 8c26' \ | |
'8086 8c2d' \ | |
'8086 8c31' \ | |
'8086 8c20'" | |
# -------------------------------------------------------------------------------------- | |
# ** QEMU Parameters | |
# ====================================================================================== | |
readonly _QEMU_ARGS_BASE="\ | |
-accel kvm \ | |
-m 7G \ | |
-cpu host \ | |
-smp cores=`nproc` \ | |
-machine pc \ | |
-nodefaults \ | |
-device virtio-scsi-pci,id=scsi \ | |
-boot menu=off" | |
readonly _QEMU_WIN='-rtc base=localtime,clock=vm' | |
readonly _QEMU_NIX='-serial mon:stdio' | |
# ====================================================================================== | |
# * Failure Functions | |
# ====================================================================================== | |
wrong_args() { | |
echo 'Incorrect parameters usage, use: run_guest.sh [OSTYPE] [RAW_DRIVE]' 1>&2 | |
exit 11 | |
} | |
invalid_ostype() { | |
echo 'Invalid OSTYPE' 1>&2 | |
exit 12 | |
} | |
invalid_main_drive() { | |
echo 'Invalid RAW_DRIVE' 1>&2 | |
exit 13 | |
} | |
invalid_machine() { | |
echo 'Not running on a valid machine' 1>&2 | |
exit 14 | |
} | |
error_real_iface() { | |
echo 'Default network interface not found' 1>&2 | |
exit 15 | |
} | |
error_guest_mac() { | |
echo 'Impossible to guest/generate mac address' 1>&2 | |
exit 16 | |
} | |
# ====================================================================================== | |
# * Main Functions | |
# ====================================================================================== | |
parse_args() { | |
_OSTYPE="$1" | |
_MAIN_DRIVE="$2" | |
([ '' = "$_OSTYPE" ] || [ '' = "$_MAIN_DRIVE" ]) && wrong_args | |
[ -f "$_MAIN_DRIVE" ] || invalid_main_drive | |
} | |
detect_machine() { | |
case "`cctk --sysname | sed 's/^sysname=//'`" in | |
"$_O7010_ID") | |
_VFIO_BUS="${_O7010_BUS}"; | |
_VFIO_DEV="${_O7010_DEV}";; | |
"$_O7040_ID") | |
_VFIO_BUS="${_O7040_BUS}"; | |
_VFIO_DEV="${_O7040_DEV}";; | |
"$_O9020_ID") | |
_VFIO_BUS="${_O9020_BUS}"; | |
_VFIO_DEV="${_O9020_DEV}";; | |
*) | |
invalid_machine;; | |
esac | |
} | |
vfio_all() { | |
[ '1' = "$PSEUDO_RUN" ] && return | |
for _PCI in ${_VFIO_BUS}; do | |
continue echo "$_PCI" > /sys/bus/pci/devices/"$_PCI"/driver/unbind | |
while [ -d " /sys/bus/pci/devices/"$_PCI"/driver" ]; do | |
sleep 1 | |
echo "$_PCI" > /sys/bus/pci/devices/"$_PCI"/driver/unbind | |
done | |
done | |
for _PCI in ${_VFIO_DEV}; do | |
continue echo "$_PCI" > /sys/bus/pci/drivers/vfio-pci/new_id | |
while [ -d " /sys/bus/pci/devices/"$_PCI"/driver" ]; do | |
sleep 1 | |
echo "$_PCI" > /sys/bus/pci/drivers/vfio-pci/new_id | |
done | |
done | |
} | |
detect_guest() { | |
case "$_OSTYPE" in | |
'windows') | |
_QEMU_ARGS="${_QEMU_ARGS} ${_QEMU_WIN}";; | |
'linux') | |
_QEMU_ARGS="${_QEMU_ARGS} ${_QEMU_NIX}";; | |
*) | |
invalid_guest;; | |
esac | |
} | |
prepare_guest_mac() { | |
_REAL_IFACE=`ip route show default | awk '/default/ {print $5}'` | |
[ '' = "$_REAL_IFACE" ] && error_real_iface | |
_GUEST_MAC=`cat /sys/class/net/${_REAL_IFACE}/address |\ | |
sed 's/^..:..:../00:16:3E/'` | |
[ '' = "$_GUEST_MAC" ] && error_guest_mac | |
} | |
prepare_qemu_args() { | |
_QEMU_ARGS="${_QEMU_ARGS_BASE}" | |
for _PCI in ${_VFIO_BUS}; do | |
_PCI_SPLT="`echo "$_PCI" | sed 's/[:\.]/ /g'`" | |
set -- $_PCI_SPLT | |
_QEMU_ARGS="${_QEMU_ARGS} \ | |
-device vfio-pci-nohotplug,host=$1:$2.$3,bus=pci.$2,addr=0x$3" | |
done | |
_QEMU_ARGS="${_QEMU_ARGS} \ | |
-drive if=none,id=hd_sys,file=/dev/zvol/${_MAIN_DRIVE},format=raw \ | |
-device scsi-hd,drive=hd_sys \ | |
-netdev user,hostfwd=tcp:0.0.0.0:3389-:3389,id=net_sys,macaddr=$_GUEST_MAC \ | |
-device virtio-net-pci,netdev=net_sys" | |
detect_guest | |
} | |
run_qemu() { | |
if [ '1' = "$PSEUDO_RUN" ]; then | |
echo "$_QEMU_ARGS" | |
else | |
qemu-system-x86_64 $_QEMU_ARGS | |
fi | |
} | |
# ====================================================================================== | |
# * Main routine | |
# ====================================================================================== | |
parse_args $@ | |
detect_machine | |
vfio_all | |
prepare_qemu_args | |
run_qemu | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment