#!/usr/bin/env bash set -eo pipefail if [[ ! -t 1 ]]; then if [[ -z "$TERMINAL" ]]; then TERMINAL=i3-sensible-terminal fi "$TERMINAL" -e "$0" "$@" exit $? fi if [[ -n "$1" ]] && [[ -z "$VMNAME" ]]; then VMNAME="$1" fi if [[ -z "$VMNAME" ]]; then echo "VMNAME not specified, aborting" >&2 exit 1 fi if [[ -z "$DEBUG" ]]; then DEBUG= fi # Sudo prompt if [[ -n "$SUDO" ]]; then true elif [[ -t 1 ]]; then SUDO=sudo else export SUDO_ASKPASS=/usr/lib/ssh/ssh-askpass SUDO='sudo --askpass' fi if ! which "$SUDO" >/dev/null 2>&1; then SUDO=sudo fi set -u cd "$(dirname "$0")" $SUDO true NET_CONF_FILE="$($SUDO mktemp)" # create bridge NET_CONF_FILE="$NET_CONF_FILE" $SUDO --preserve-env=NET_CONF_FILE \ ./net create # rebind devices old_IFS="$IFS" IFS=$'\n' for device_override in $(< vfio_devices.txt); do device="$(echo "$device_override" | awk '{print $1}')" override="$(echo "$device_override" | awk '{print $2}')" $SUDO ./pci vfio_rebind_device "$device" "$override" done IFS="$old_IFS" # efi variables EFI_VARS="$(mktemp)" cp /usr/share/ovmf/x64/OVMF_VARS.fd "$EFI_VARS" EFI_FIRMWARE=/usr/share/ovmf/x64/OVMF_CODE.secboot.fd source config.conf base_path=base default_path=default hardware_path=hardware specific_path="$VMNAME" o_base_path="$(mktemp)" o_default_path="$(mktemp)" o_hardware_path="$(mktemp)" o_specific_path="$(mktemp)" if [[ -e "$base_path.conf.tmpl" ]]; then ( # shellcheck disable=SC1090 [[ -e "$base_path.sh" ]] && source "$base_path.sh" envsubst < "$base_path.conf.tmpl" > "$o_base_path" ) else cp "$base_path.conf" "$o_base_path" fi if [[ -e "$default_path.conf.tmpl" ]]; then ( # shellcheck disable=SC1090 [[ -e "$default_path.sh" ]] && source "$default_path.sh" envsubst < "$default_path.conf.tmpl" > "$o_default_path" ) else cp "$default_path.conf" "$o_default_path" fi if [[ -e "$hardware_path.conf.tmpl" ]]; then ( # shellcheck disable=SC1090 [[ -e "$hardware_path.sh" ]] && source "$hardware_path.sh" envsubst < "$hardware_path.conf.tmpl" > "$o_hardware_path" ) else cp "$hardware_path.conf" "$o_hardware_path" fi if [[ -e "$specific_path.conf.tmpl" ]]; then ( # shellcheck disable=SC1090 [[ -e "$specific_path.sh" ]] && source "$specific_path.sh" envsubst < "$specific_path.conf.tmpl" > "$o_specific_path" ) else cp "$specific_path.conf" "$o_specific_path" fi if [[ -e "pre-start.sh" ]]; then ./pre-start.sh fi if [[ -e "pre-start-$VMNAME.sh" ]]; then ./"pre-start-$VMNAME.sh" fi # run qemu base_arguments=() default_arguments=() hardware_arguments=() specific_arguments=() # mask EOF read -ra base_arguments -d '' < "$o_base_path" || true read -ra default_arguments -d '' < "$o_default_path" || true read -ra hardware_arguments -d '' < "$o_hardware_path" || true read -ra specific_arguments -d '' < "$o_specific_path" || true # preven host from using vm cpus set -x $SUDO qemu-system-x86_64 \ -name "$VMNAME,process=VMNAME,debug-threads=on" \ -daemonize -pidfile "$PIDFILE" \ -monitor unix:"$MONITOR",server,nowait \ -drive if=pflash,format=raw,readonly=on,file="$EFI_FIRMWARE" \ -drive if=pflash,format=raw,file="$EFI_VARS" \ "${base_arguments[@]}" \ "${default_arguments[@]}" \ "${hardware_arguments[@]}" \ "${specific_arguments[@]}" || true set +x $SUDO cat "$PIDFILE" $SUDO qemu-affinity \ -k $(./cpus decompress_seq "$(./cpus compute_vm $NUM_PROCESSORS)") \ -i *:$(./cpus compute_vm $NUM_PROCESSORS) \ -- $($SUDO cat "$PIDFILE") host_cpus="$(./cpus compute_host $NUM_PROCESSORS)" # $SUDO systemctl set-property --runtime -- user.slice AllowedCPUs="$host_cpus" # $SUDO systemctl set-property --runtime -- system.slice AllowedCPUs="$host_cpus" # $SUDO systemctl set-property --runtime -- init.slice AllowedCPUs="$host_cpus" # undo_file=/tmp/vfio-isolate.undo.bin # vfio-isolate \ # -u "$undo_file" \ # drop-caches \ # cpuset-modify --cpus C$host_cpus /system.slice \ # cpuset-modify --cpus C$host_cpus /user.slice while [ -f "$PIDFILE" ]; do sleep 1 done host_cpus="$(./cpus compute_all)" # vfio-isolate \ # restore "$undo_file" # $SUDO systemctl set-property --runtime -- user.slice AllowedCPUs="$host_cpus" # $SUDO systemctl set-property --runtime -- system.slice AllowedCPUs="$host_cpus" # $SUDO systemctl set-property --runtime -- init.slice AllowedCPUs="$host_cpus" # to power down the machine # echo system_powerdown | socat - UNIX-CONNECT:"$MONITOR" NET_CONF_FILE="$NET_CONF_FILE" $SUDO --preserve-env=NET_CONF_FILE \ ./net delete