#!/bin/bash
set -euo pipefail
configuration=$1
machine=$(jq -er .machine "$configuration")
accelerator=$(jq -er .accelerator "$configuration")
cpu=$(jq -er .cpu "$configuration")
cpus=$(jq -er .cpus "$configuration")
memory=$(jq -er .memory_mb "$configuration")
kernel=$(jq -er .kernel "$configuration")
initramfs=$(jq -er .initramfs "$configuration")
arguments=$(jq -er .kernel_arguments "$configuration")
socket_path=$(jq -er .socket "$configuration")
serial_log=$(jq -er .serial_log "$configuration")
stderr_log=$(jq -er .stderr_log "$configuration")
no_posted_writes=$(jq -c '.no_posted_writes | if type == "boolean" then . else error("no_posted_writes must be boolean") end' "$configuration")
maximum_seconds=$(jq -er '.maximum_seconds | select(type == "number" and . > 0)' "$configuration")
shutdown_grace=$(jq -er '.shutdown_grace_seconds | select(type == "number" and . > 0)' "$configuration")
root_port=$(jq -ec .root_port "$configuration")
device_bus=$(jq -er .device_bus "$configuration")
device_address=$(jq -er .device_address "$configuration")
device=$(jq -cn --arg path "$socket_path" --arg bus "$device_bus" --arg addr "$device_address" \
    --argjson acknowledged "$no_posted_writes" \
    '{driver:"vfio-user-pci",socket:{type:"unix",path:$path},bus:$bus,addr:$addr,rombar:0,"x-no-posted-writes":$acknowledged}')
exec 2> >(tee "$stderr_log" >&2)
printf 'VM_TRANSPORT no_posted_writes=%s serial_log=%s\n' "$no_posted_writes" "$serial_log" >&2
exec timeout --signal=TERM --kill-after="$shutdown_grace" "$maximum_seconds" \
    qemu-system-x86_64 -machine "$machine,memory-backend=guest-memory" \
    -accel "$accelerator" -cpu "$cpu" -smp "$cpus" -m "$memory" \
    -object "memory-backend-memfd,id=guest-memory,size=${memory}M,share=on" \
    -kernel "$kernel" -initrd "$initramfs" -append "$arguments" \
    -device "$root_port" -device "$device" -nodefaults -no-reboot -display none -monitor none \
    -chardev "stdio,id=console,logfile=$serial_log,logappend=off,signal=off" \
    -serial chardev:console
