#!/bin/sh
# ============================================================
# kvm_check.sh -- Detect KVM / hardware virtualization support
# Output:  "KVM_OK" on success
#          "KVM_FAIL:<reason>" on failure
# Exit:    0 on success, 1 on failure
# ============================================================

# ── Helper: attempt to load a kernel module ──────────────────
_try_modprobe() {
    if command -v modprobe >/dev/null 2>&1; then
        modprobe "$1" 2>/dev/null
        return $?
    fi
    if command -v insmod >/dev/null 2>&1; then
        # Fallback: try insmod with common module paths
        for _modpath in \
            "/lib/modules/$(uname -r 2>/dev/null)/kernel/arch/x86/kvm/$1.ko" \
            "/lib/modules/$(uname -r 2>/dev/null)/$1.ko" \
            "/$1.ko"; do
            if [ -f "$_modpath" ]; then
                insmod "$_modpath" 2>/dev/null && return 0
            fi
        done
    fi
    return 1
}

# ── Check 1: /dev/kvm already exists ─────────────────────────
if [ -c /dev/kvm ]; then
    printf 'KVM_OK\n'
    exit 0
fi

# ── Check 2: CPU supports virtualization ─────────────────────
#   vmx = Intel VT-x, svm = AMD-V
if ! grep -q -E '(vmx|svm)' /proc/cpuinfo 2>/dev/null; then
    printf 'KVM_FAIL:no_hw_virt (CPU lacks vmx/svm flags -- check BIOS/UEFI settings)\n'
    exit 1
fi

# ── Determine CPU vendor for correct KVM module ──────────────
_cpu_vendor=""
if [ -f /proc/cpuinfo ]; then
    _cpu_vendor=$(grep -m1 '^vendor_id' /proc/cpuinfo 2>/dev/null \
                  | cut -d: -f2 | tr -d ' ')
fi

# ── Check 3: Load KVM kernel modules ─────────────────────────
_try_modprobe kvm

case "$_cpu_vendor" in
    GenuineIntel)
        _try_modprobe kvm-intel
        ;;
    AuthenticAMD)
        _try_modprobe kvm-amd
        ;;
    *)
        # Unknown vendor -- try both
        _try_modprobe kvm-intel 2>/dev/null || _try_modprobe kvm-amd 2>/dev/null
        ;;
esac

# Give devtmpfs/udev a moment to create the device node
sleep 1

# ── Check 4: Verify /dev/kvm now exists ──────────────────────
if [ ! -e /dev/kvm ]; then
    printf 'KVM_FAIL:no_dev_kvm (modules may not have loaded -- dmesg for details)\n'
    exit 1
fi

# ── Check 5: Verify /dev/kvm is a char device ────────────────
if [ ! -c /dev/kvm ]; then
    printf 'KVM_FAIL:dev_kvm_not_char_device\n'
    exit 1
fi

# ── Success ──────────────────────────────────────────────────
printf 'KVM_OK\n'
exit 0
