#!/bin/sh
# DF-5655 run driver — boots the vkernel and fires the in-vkernel trigger.
# usage: vk_run.sh <mode:baseline|fixed> [which]
#
# baseline: unpatched vkernel + unpatched host  -> HOST kernel panic
#           (Fatal trap 9 in set_user_TLS wrmsr on the go_user return path)
# fixed:    vkernel carries the DF-5655 fix     -> -1/EINVAL, all alive
MODE=${1:-baseline}
WHICH=${2:-1}
VK=/usr/obj/usr/src/sys/VKERNEL64/kernel.debug
LOG=/tmp/vk5655.log

cd /usr/obj/usr/src/sys/VKERNEL64

pkill -9 -f kernel.debug 2>/dev/null; sleep 1
rm -f /tmp/vkin
mkfifo /tmp/vkin
(sleep 600 > /tmp/vkin 2>/dev/null) </dev/null &
HOLDER=$!

( exec 3> /tmp/vkin; echo "ufs:vkd0" >&3 ) &

# vkernel console goes to the GUEST serial console (/dev/console) so the
# trigger marker and the host panic land in one transcript (boot.log);
# a private copy is kept via tee for the alive phases.
./kernel.debug -m 512m -r /vkroot.img -n 2 \
      -e init_path=/bin/vkinit \
      -s < /tmp/vkin 2>&1 | tee $LOG > /dev/console &
sleep 2
VKPID=$(pgrep -f "kernel.debug -m 512m")
echo "MODE=$MODE vkernel pid=$VKPID"

# wait for the in-vkernel shell (root mounted + init ran)
i=0
while [ $i -lt 120 ]; do
  grep -q "Mounting root from ufs:vkd0" $LOG 2>/dev/null && grep -q "^# " $LOG 2>/dev/null && break
  pgrep -f "kernel.debug -m 512m" >/dev/null 2>&1 || break
  sleep 1
  i=$((i+1))
done
sleep 3
echo "=== vkernel booted (i=$i) ==="

# fire the trigger as unprivileged in-vkernel user
( exec 4> /tmp/vkin; echo "/bin/as_nobody /bin/vk_tls_noncanon $WHICH" >&4; sleep 2; echo "echo MARKER_AFTER_TRIGGER" >&4 ) &

# watch outcome
sleep 12
if pgrep -f "kernel.debug -m 512m" >/dev/null 2>&1; then ALIVE=yes; else ALIVE=no; fi
echo "VKERNEL_ALIVE=$ALIVE"
grep -an "DF5655\|MARKER_AFTER\|panic\|Fatal trap" $LOG | head -20
echo "=== vkernel console tail ==="
tail -12 $LOG

kill $HOLDER 2>/dev/null
pkill -9 -f kernel.debug 2>/dev/null
echo "DRIVER_DONE"
