#!/bin/bash

min_kernel_version=24
max_kernel_version=34
force_build=
kernelsourcedir=
kerneldir=/lib/modules/$(uname -r)/build
cc=gcc
ld=ld
objcopy=objcopy
ar=ar
want_module=1
cross_prefix=
arch=`uname -m`
if [ -z "TMPDIR" ] ; then
    TMPDIR=.
fi

usage() {
    cat <<-EOF
	Usage: $0 [options]

	Options include:
	    --arch=ARCH            architecture to compile for ($arch)
	    --cross-prefix=PREFIX  prefix for cross compile
	    --kerneldir=DIR        kernel build directory ($kerneldir)
	    --force                continue even if kernel is not supported
	    --help                 this helpful text
EOF
    exit 1
}

while [[ "$1" = -* ]]; do
    opt="$1"; shift
    arg=
    hasarg=
    if [[ "$opt" = *=* ]]; then
	arg="${opt#*=}"
	opt="${opt%%=*}"
	hasarg=1
    fi
    case "$opt" in
	--kerneldir)
	    kerneldir="$arg"
	    ;;
        --force)
            force_build=1
            ;;
	--with-patched-kernel)
	    want_module=
	    ;;
	--arch)
	    arch="$arg"
	    ;;
	--cross-prefix)
	    cross_prefix="$arg"
            ;;
	--help)
	    usage
	    ;;
	*)
	    usage
	    ;;
    esac
done

karch="$arch"

case $arch in
    i?86*|x86_64*)
        arch=${arch/#i?86/i386}
	karch="x86"
        ;;
esac

kvm_version() {
    local fname="$(dirname "$0")/KVM_VERSION"

    if test -f "$fname"; then
        cat "$fname"
    else
        echo "kvm-devel"
    fi
}

processor=${arch#*-}
arch=${arch%%-*}

# see if we have split build and source directories
if [ -d "$kerneldir/include2" -o -L "$kerneldir/source" ]; then
    kernelsourcedir=$kerneldir/source
    if [ ! -L "$kernelsourcedir" ]; then
        kernelsourcedir=${kerneldir%/build*}/source
    fi
fi

kernel_version=
if [ -e "$kerneldir/.kernelrelease" ]; then
	kernel_version=`cat "$kerneldir/.kernelrelease"`
elif [ -e "$kerneldir/include/config/kernel.release" ]; then
	kernel_version=`cat "$kerneldir/include/config/kernel.release"`
elif [ -e "$kerneldir/.config" ]; then
	kernel_version=$(awk '/Linux kernel version:/ { print $NF }' \
		"$kerneldir/.config")
fi
if [ ! -n "$kernel_version" ]; then
	echo
	echo "Error: kernel version not found."
	echo "Please make sure your kernel is configured."
	echo
	exit 1
fi

kernel_subversion=`echo $kernel_version | sed 's/[0-9]*\.[0-9]*\.\([0-9]*\)*.*/\1/'`
if [ ! -n "$force_build" ]; then
	if [ $kernel_subversion -lt $min_kernel_version ]; then
		echo
		echo "Error: kernel is too old for this kvm-kmod release."
		echo
		exit 1
	elif [ $kernel_subversion -gt $max_kernel_version ]; then
		echo
		echo "Error: kernel is more recent than KVM modules delivered with this release."
		echo "You probably want to use the KVM support that is already part of your kernel."
		echo
		exit 1
	fi
fi

kernel_extraversion=`echo $kernel_version | sed 's/[0-9]*\.[0-9]*\.[0-9]*\.\([0-9]*\)*.*/\1/'`
if [ ! -n $kernel_extraversion -o $kernel_extraversion = $kernel_version ]; then
	kernel_extraversion=0
fi

. "$kerneldir/.config"
if [ "$CONFIG_PREEMPT_NOTIFIERS" = "" ]; then
	if [ $kernel_subversion -ge 33 ]; then
		echo
		echo "Error: kernel lacks KVM support, keeping preemption notifiers disabled."
		echo "Since kernel 2.6.33, kvm-kmod is no longer able to provide a workaround"
		echo "implementation for this feature. You have to enable KVM as module(!) in your"
		echo "kernel first, rebuild and install it."
		echo
		exit 1
	fi
	echo "WARNING: kvm-kmod will emulate missing preemption notifiers."
	echo "Do not benchmark this system!"
fi

if [ -n "$no_uname" -a "$want_module" ]; then
	depmod_version=$kernel_version
fi

rm -f include/asm include-compat/asm
mkdir -p include
ln -sf asm-"$karch" include/asm
ln -sf asm-"$karch" include-compat/asm

cat <<EOF > config.mak
ARCH=$arch
PROCESSOR=$processor
PREFIX=$prefix
KERNELDIR=$kerneldir
KERNELSOURCEDIR=$kernelsourcedir
KERNELVERSION=$kernel_version
CROSS_COMPILE=$cross_prefix
CC=$cross_prefix$cc
LD=$cross_prefix$ld
OBJCOPY=$cross_prefix$objcopy
AR=$cross_prefix$ar
KVM_VERSION=$(kvm_version)
EOF

cat <<EOF > kvm-kmod-config.h
#define KERNEL_EXTRAVERSION $kernel_extraversion
EOF
