Re: [Qemu-devel] [PATCH] KVM: Add wrapper script around QEMU to test kernels

From: Blue Swirl
Date: Thu Aug 25 2011 - 14:02:26 EST


On Wed, Aug 24, 2011 at 9:38 PM, Alexander Graf <agraf@xxxxxxx> wrote:
> On LinuxCon I had a nice chat with Linus on what he thinks kvm-tool
> would be doing and what he expects from it. Basically he wants a
> small and simple tool he and other developers can run to try out and
> see if the kernel they just built actually works.
>
> Fortunately, QEMU can do that today already! The only piece that was
> missing was the "simple" piece of the equation, so here is a script
> that wraps around QEMU and executes a kernel you just built.
>
> If you do have KVM around and are not cross-compiling, it will use
> KVM. But if you don't, you can still fall back to emulation mode and
> at least check if your kernel still does what you expect. I only
> implemented support for s390x and ppc there, but it's easily extensible
> to more platforms, as QEMU can emulate (and virtualize) pretty much
> any platform out there.
>
> If you don't have qemu installed, please do so before using this script. Your
> distro should provide a package for it (might even call it "kvm"). If not,
> just compile it from source - it's not hard!
>
> To quickly get going, just execute the following as user:
>
> Â Â$ ./Documentation/run-qemu.sh -r / -a init=/bin/bash
>
> This will drop you into a shell on your rootfs.
>
> Happy hacking!
>
> Signed-off-by: Alexander Graf <agraf@xxxxxxx>
>
> ---
>
> v1 -> v2:
>
> Â- fix naming of QEMU
> Â- use grep -q for has_config
> Â- support multiple -a args
> Â- spawn gdb on execution
> Â- pass through qemu options
> Â- dont use qemu-system-x86_64 on i386
> Â- add funny sentence to startup text
> Â- more helpful error messages
> ---
> Âscripts/run-qemu.sh | Â334 +++++++++++++++++++++++++++++++++++++++++++++++++++
> Â1 files changed, 334 insertions(+), 0 deletions(-)
> Âcreate mode 100755 scripts/run-qemu.sh
>
> diff --git a/scripts/run-qemu.sh b/scripts/run-qemu.sh
> new file mode 100755
> index 0000000..5d4e185
> --- /dev/null
> +++ b/scripts/run-qemu.sh
> @@ -0,0 +1,334 @@
> +#!/bin/bash
> +#
> +# QEMU Launcher
> +#
> +# This script enables simple use of the KVM and QEMU tool stack for
> +# easy kernel testing. It allows to pass either a host directory to
> +# the guest or a disk image. Example usage:
> +#
> +# Run the host root fs inside a VM:
> +#
> +# $ ./scripts/run-qemu.sh -r /
> +#
> +# Run the same with SDL:
> +#
> +# $ ./scripts/run-qemu.sh -r / --sdl
> +#
> +# Or with a PPC build:
> +#
> +# $ ARCH=ppc ./scripts/run-qemu.sh -r /
> +#
> +# PPC with a mac99 model by passing options to QEMU:
> +#
> +# $ ARCH=ppc ./scripts/run-qemu.sh -r / -- -M mac99
> +#
> +
> +USE_SDL=
> +USE_VNC=
> +USE_GDB=1
> +KERNEL_BIN=arch/x86/boot/bzImage
> +MON_STDIO=
> +KERNEL_APPEND2=
> +SERIAL=ttyS0
> +SERIAL_KCONFIG=SERIAL_8250
> +BASENAME=$(basename "$0")
> +
> +function usage() {
> + Â Â Â echo "
> +$BASENAME allows you to execute a virtual machine with the Linux kernel
> +that you just built. To only execute a simple VM, you can just run it
> +on your root fs with \"-r / -a init=/bin/bash\"
> +
> + Â Â Â -a, --append parameters
> + Â Â Â Â Â Â Â Append the given parameters to the kernel command line.
> +
> + Â Â Â -d, --disk image
> + Â Â Â Â Â Â Â Add the image file as disk into the VM.
> +
> + Â Â Â -D, --no-gdb
> + Â Â Â Â Â Â Â Don't run an xterm with gdb attached to the guest.
> +
> + Â Â Â -r, --root directory
> + Â Â Â Â Â Â Â Use the specified directory as root directory inside the guest.
> +
> + Â Â Â -s, --sdl
> + Â Â Â Â Â Â Â Enable SDL graphical output.
> +
> + Â Â Â -S, --smp cpus
> + Â Â Â Â Â Â Â Set number of virtual CPUs.
> +
> + Â Â Â -v, --vnc
> + Â Â Â Â Â Â Â Enable VNC graphical output.
> +
> +Examples:
> +
> + Â Â Â Run the host root fs inside a VM:
> + Â Â Â $ ./scripts/run-qemu.sh -r /
> +
> + Â Â Â Run the same with SDL:
> + Â Â Â $ ./scripts/run-qemu.sh -r / --sdl
> +
> + Â Â Â Or with a PPC build:
> + Â Â Â $ ARCH=ppc ./scripts/run-qemu.sh -r /
> +
> + Â Â Â PPC with a mac99 model by passing options to QEMU:
> + Â Â Â $ ARCH=ppc ./scripts/run-qemu.sh -r / -- -M mac99
> +"
> +}
> +
> +function require_config() {
> + Â Â Â if [ "$(grep CONFIG_$1=y .config)" ]; then
> + Â Â Â Â Â Â Â return
> + Â Â Â fi
> +
> + Â Â Â echo "You need to enable CONFIG_$1 for run-qemu to work properly"
> + Â Â Â exit 1
> +}
> +
> +function has_config() {
> + Â Â Â grep -q "CONFIG_$1=y" .config
> +}
> +
> +function drive_if() {
> + Â Â Â if has_config VIRTIO_BLK; then
> + Â Â Â Â Â Â Â echo virtio
> + Â Â Â elif has_config ATA_PIIX; then
> + Â Â Â Â Â Â Â echo ide
> + Â Â Â else
> + Â Â Â Â Â Â Â echo "\
> +Your kernel must have either VIRTIO_BLK or ATA_PIIX
> +enabled for block device assignment" >&2
> + Â Â Â Â Â Â Â exit 1
> + Â Â Â fi
> +}
> +
> +GETOPT=`getopt -o a:d:Dhr:sS:v --long append,disk:,no-gdb,help,root:,sdl,smp:,vnc \
> + Â Â Â -n "$(basename \"$0\")" -- "$@"`
> +
> +if [ $? != 0 ]; then
> + Â Â Â echo "Terminating..." >&2
> + Â Â Â exit 1
> +fi
> +
> +eval set -- "$GETOPT"
> +
> +while true; do
> + Â Â Â case "$1" in
> + Â Â Â -a|--append)
> + Â Â Â Â Â Â Â KERNEL_APPEND2="$KERNEL_APPEND2 $KERNEL_APPEND2"
> + Â Â Â Â Â Â Â shift
> + Â Â Â Â Â Â Â ;;
> + Â Â Â -d|--disk)
> + Â Â Â Â Â Â Â QEMU_OPTIONS="$QEMU_OPTIONS -drive \
> + Â Â Â Â Â Â Â Â Â Â Â file=$2,if=$(drive_if),cache=unsafe"
> + Â Â Â Â Â Â Â USE_DISK=1
> + Â Â Â Â Â Â Â shift
> + Â Â Â Â Â Â Â ;;
> + Â Â Â -D|--no-gdb)
> + Â Â Â Â Â Â Â USE_GDB=
> + Â Â Â Â Â Â Â ;;
> + Â Â Â -h|--help)
> + Â Â Â Â Â Â Â usage
> + Â Â Â Â Â Â Â exit 0
> + Â Â Â Â Â Â Â ;;
> + Â Â Â -r|--root)
> + Â Â Â Â Â Â Â ROOTFS="$2"
> + Â Â Â Â Â Â Â shift
> + Â Â Â Â Â Â Â ;;
> + Â Â Â -s|--sdl)
> + Â Â Â Â Â Â Â USE_SDL=1
> + Â Â Â Â Â Â Â ;;
> + Â Â Â -S|--smp)
> + Â Â Â Â Â Â Â SMP="$2"
> + Â Â Â Â Â Â Â shift
> + Â Â Â Â Â Â Â ;;
> + Â Â Â -v|--vnc)
> + Â Â Â Â Â Â Â USE_VNC=1
> + Â Â Â Â Â Â Â ;;
> + Â Â Â --)
> + Â Â Â Â Â Â Â shift
> + Â Â Â Â Â Â Â break
> + Â Â Â Â Â Â Â ;;
> + Â Â Â *)
> + Â Â Â Â Â Â Â echo "Could not parse option: $1" >&2
> + Â Â Â Â Â Â Â exit 1
> + Â Â Â Â Â Â Â ;;
> + Â Â Â esac
> + Â Â Â shift
> +done
> +
> +if [ ! "$ROOTFS" -a ! "$USE_DISK" ]; then
> + Â Â Â echo "\
> +Error: Please specify at least -r or -d with a target \
> +FS to run off of" >&2
> + Â Â Â exit 1
> +fi
> +
> +# Try to find the KVM accelerated QEMU binary
> +
> +[ "$ARCH" ] || ARCH=$(uname -m)
> +case $ARCH in
> +x86_64)
> + Â Â Â KERNEL_BIN=arch/x86/boot/bzImage
> + Â Â Â # SUSE and Red Hat call the binary qemu-kvm
> + Â Â Â [ "$QEMU_BIN" ] || QEMU_BIN=$(which qemu-kvm 2>/dev/null)
> +
> + Â Â Â # Debian and Gentoo call it kvm
> + Â Â Â [ "$QEMU_BIN" ] || QEMU_BIN=$(which kvm 2>/dev/null)
> +
> + Â Â Â # QEMU's own build system calls it qemu-system-x86_64
> + Â Â Â [ "$QEMU_BIN" ] || QEMU_BIN=$(which qemu-system-x86_64 2>/dev/null)
> + Â Â Â ;;
> +i*86)
> + Â Â Â KERNEL_BIN=arch/x86/boot/bzImage
> + Â Â Â # SUSE and Red Hat call the binary qemu-kvm
> + Â Â Â [ "$QEMU_BIN" ] || QEMU_BIN=$(which qemu-kvm 2>/dev/null)
> +
> + Â Â Â # Debian and Gentoo call it kvm
> + Â Â Â [ "$QEMU_BIN" ] || QEMU_BIN=$(which kvm 2>/dev/null)
> +
> + Â Â Â KERNEL_BIN=arch/x86/boot/bzImage
> + Â Â Â # i386 version of QEMU
> + Â Â Â [ "$QEMU_BIN" ] || QEMU_BIN=$(which qemu 2>/dev/null)
> + Â Â Â ;;
> +s390*)
> + Â Â Â KERNEL_BIN=arch/s390/boot/image
> + Â Â Â [ "$QEMU_BIN" ] || QEMU_BIN=$(which qemu-system-s390x 2>/dev/null)
> + Â Â Â ;;
> +ppc*)
> + Â Â Â KERNEL_BIN=vmlinux
> +
> + Â Â Â IS_64BIT=
> + Â Â Â has_config PPC64 && IS_64BIT=64
> + Â Â Â if has_config PPC_85xx; then
> + Â Â Â Â Â Â Â QEMU_OPTIONS="$QEMU_OPTIONS -M mpc8544ds"
> + Â Â Â elif has_config PPC_PSERIES; then
> + Â Â Â Â Â Â Â QEMU_OPTIONS="$QEMU_OPTIONS -M pseries"
> + Â Â Â Â Â Â Â SERIAL=hvc0
> + Â Â Â Â Â Â Â SERIAL_KCONFIG=HVC_CONSOLE
> + Â Â Â elif has_config PPC_PMAC; then
> + Â Â Â Â Â Â Â has_config SERIAL_PMACZILOG_TTYS || SERIAL=ttyPZ0
> + Â Â Â Â Â Â Â SERIAL_KCONFIG=SERIAL_PMACZILOG
> + Â Â Â else
> + Â Â Â Â Â Â Â echo "Unknown PPC board" >&2
> + Â Â Â Â Â Â Â exit 1
> + Â Â Â fi
> +
> + Â Â Â [ "$QEMU_BIN" ] || QEMU_BIN=$(which qemu-system-ppc${IS_64BIT} 2>/dev/null)
> + Â Â Â ;;
> +esac
> +
> +if [ ! -e "$QEMU_BIN" ]; then
> + Â Â Â echo "\
> +Could not find a usable QEMU binary. Please install one from \
> +your distro or from source code using:
> +
> + Â$ git clone git://git.qemu.org/qemu.git
> + Â$ cd qemu
> + Â$ ./configure
> + Â$ make -j
> + Â$ sudo make install
> +" >&2
> + Â Â Â exit 1
> +fi
> +
> +# The binaries without kvm in their name can be too old to support KVM, so
> +# check for that before the user gets confused
> +if [ ! "$(echo $QEMU_BIN | grep kvm)" -a \
> + Â Â ! "$($QEMU_BIN --help | egrep '^-machine')" ]; then
> + Â Â Â echo "Your QEMU binary is too old, please update to at least 0.15." >&2
> + Â Â Â exit 1
> +fi
> +QEMU_OPTIONS="$QEMU_OPTIONS -machine accel=kvm:tcg"
> +
> +# We need to check some .config variables to make sure we actually work
> +# on the respective kernel.
> +if [ ! -e .config ]; then
> + Â Â Â echo "\
> +Please run this script on a fully compiled and configured
> +Linux kernel build directory" >&2
> + Â Â Â exit 1
> +fi
> +
> +if [ ! -e "$KERNEL_BIN" ]; then
> + Â Â Â echo "Could not find kernel binary: $KERNEL_BIN" >&2
> + Â Â Â exit 1
> +fi
> +
> +QEMU_OPTIONS="$QEMU_OPTIONS -kernel $KERNEL_BIN"
> +
> +if [ "$USE_SDL" ]; then
> + Â Â Â # SDL is the default, so nothing to do
> + Â Â Â :
> +elif [ "$USE_VNC" ]; then
> + Â Â Â QEMU_OPTIONS="$QEMU_OPTIONS -vnc :5"
> +else
> + Â Â Â # When emulating a serial console, tell the kernel to use it as well
> + Â Â Â QEMU_OPTIONS="$QEMU_OPTIONS -nographic"
> + Â Â Â KERNEL_APPEND="$KERNEL_APPEND console=$SERIAL earlyprintk=serial"
> + Â Â Â MON_STDIO=1
> + Â Â Â require_config "$SERIAL_KCONFIG"
> +fi
> +
> +if [ "$ROOTFS" ]; then
> + Â Â Â # Using rootfs with 9p
> + Â Â Â require_config "NET_9P_VIRTIO"
> + Â Â Â KERNEL_APPEND="$KERNEL_APPEND \
> +root=/dev/root rootflags=rw,trans=virtio,version=9p2000.L rootfstype=9p"
> +
> +#Usage: -virtfs fstype,path=/share_path/,security_model=[mapped|passthrough|none],mount_tag=tag.
> +
> +
> + Â Â Â QEMU_OPTIONS="$QEMU_OPTIONS \
> +-virtfs local,id=root,path=$ROOTFS,mount_tag=root,security_model=passthrough \
> +-device virtio-9p-pci,fsdev=root,mount_tag=/dev/root"
> +fi
> +
> +[ "$SMP" ] || SMP=1
> +
> +# User append args come last
> +KERNEL_APPEND="$KERNEL_APPEND $KERNEL_APPEND2"
> +
> +############### Execution #################
> +
> +QEMU_OPTIONS="$QEMU_OPTIONS -smp $SMP"
> +
> +echo "
> + Â Â Â ################# Linux QEMU launcher #################
> +
> +This script executes your currently built Linux kernel using QEMU. If KVM is
> +available, it will also use KVM for fast virtualization of your guest.
> +
> +The intent is to make it very easy to run your kernel. If you need to do more
> +advanced things, such as passing through real devices, please use QEMU command
> +line options and add them to the $BASENAME command line using --.
> +
> +This tool is for simplicity, not world dominating functionality coverage.
> +(just a hobby, won't be big and professional like libvirt)
> +
> +"
> +
> +if [ "$MON_STDIO" ]; then
> + Â Â Â echo "\
> +### Your guest is bound to the current foreground shell. To quit the guest, ###
> +### please use Ctrl-A x                           ###
> +"
> +fi
> +
> +echo " ÂExecuting: $QEMU_BIN $QEMU_OPTIONS -append \"$KERNEL_APPEND\""

This line does not match [1] below.

> +echo
> +
> +GDB_PID=
> +if [ "$USE_GDB" -a "$DISPLAY" -a -x "$(which xterm)" -a -e "$(which gdb)" ]; then
> + Â Â Â # Run a gdb console in parallel to the kernel
> +
> + Â Â Â # XXX find out if port is in use
> + Â Â Â PORT=$$

$$ could be <1024.

> + Â Â Â xterm -T "$BASENAME" -e "sleep 2; gdb vmlinux -ex 'target remote localhost:$PORT' -ex c" &

But the gnomes might not have xterms but instead gterms and so on.
Then there are wrappers like x-terminal-emulator on some distros.

> + Â Â Â GDB_PID=$!
> + Â Â Â QEMU_OPTIONS="$QEMU_OPTIONS -gdb tcp::$PORT"
> +fi
> +
> +$QEMU_BIN $QEMU_OPTIONS -append "$KERNEL_APPEND" "$@"

[1]

> +wait $GDB_PID &>/dev/null
> +
> --
> 1.6.0.2
>
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/