diff mbox

KVM: Add wrapper script around Qemu to test kernels

Message ID 1314137806-5747-1-git-send-email-agraf@suse.de
State New
Headers show

Commit Message

Alexander Graf Aug. 23, 2011, 10:16 p.m. UTC
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@suse.de>
---
 Documentation/run-qemu.sh |  284 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 284 insertions(+), 0 deletions(-)
 create mode 100755 Documentation/run-qemu.sh

Comments

Pekka Enberg Aug. 24, 2011, 5:19 a.m. UTC | #1
On Wed, Aug 24, 2011 at 1:16 AM, Alexander Graf <agraf@suse.de> 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!

It's nice to see such an honest attempt at improving QEMU usability, Alexander!

One comment: in my experience, having shell scripts under
Documentation reduces the likelihood that people actually discover
them so you might want to consider putting it under scripts or tools.

                        Pekka
Cong Wang Aug. 24, 2011, 5:31 a.m. UTC | #2
On Wed, Aug 24, 2011 at 1:19 PM, Pekka Enberg <penberg@kernel.org> wrote:
>
> It's nice to see such an honest attempt at improving QEMU usability, Alexander!
>
> One comment: in my experience, having shell scripts under
> Documentation reduces the likelihood that people actually discover
> them so you might want to consider putting it under scripts or tools.
>

I was going to give the same suggestion, +1 for tools/ directory.

Thanks!
Avi Kivity Aug. 24, 2011, 8:25 a.m. UTC | #3
On 08/24/2011 01:16 AM, Alexander Graf 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!
>
> +
> +function has_config() {
> +	grep "CONFIG_$1=y" .config
> +}

grep -q ?

> +	case "$1" in
> +	-a|--append)
> +		KERNEL_APPEND2="$2"

Might want to append to KERNEL_APPEND2, so you could have multiple -a args.

> +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 take the command
> +line shown below and modify it to your needs. This tool is for simplicity, not
> +world dominating functionality coverage.

Device assignment could be useful for driver developers, yes.

> +"
> +echo "\
> +Your guest is bound to the current foreground shell. To quit the guest,
> +please use Ctrl-A x"
> +echo "  Executing: $QEMU_BIN $QEMU_OPTIONS -append \"$KERNEL_APPEND\" -smp $SMP"
> +echo
> +
> +exec $QEMU_BIN $QEMU_OPTIONS -append "$KERNEL_APPEND -smp $SMP"

Would be nice to support launching gdb in a separate terminal with 
vmlinux already loaded, and already attached to qemu.
Jan Kiszka Aug. 24, 2011, 9:16 a.m. UTC | #4
On 2011-08-24 10:25, Avi Kivity wrote:
> On 08/24/2011 01:16 AM, Alexander Graf wrote:
>> +"
>> +echo "\
>> +Your guest is bound to the current foreground shell. To quit the guest,
>> +please use Ctrl-A x"
>> +echo "  Executing: $QEMU_BIN $QEMU_OPTIONS -append \"$KERNEL_APPEND\"
>> -smp $SMP"
>> +echo
>> +
>> +exec $QEMU_BIN $QEMU_OPTIONS -append "$KERNEL_APPEND -smp $SMP"
> 
> Would be nice to support launching gdb in a separate terminal with
> vmlinux already loaded, and already attached to qemu.

+ loading a python script into gdb to pull in module symbols. There are
a few implementations floating around (including my own one).

It would also be nice if one could append QEMU (note the capitalization
BTW) options to the script, maybe everything after a '--' separator.

Jan
Blue Swirl Aug. 24, 2011, 5:40 p.m. UTC | #5
On Tue, Aug 23, 2011 at 10:16 PM, Alexander Graf <agraf@suse.de> 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@suse.de>
> ---
>  Documentation/run-qemu.sh |  284 +++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 284 insertions(+), 0 deletions(-)
>  create mode 100755 Documentation/run-qemu.sh
>
> diff --git a/Documentation/run-qemu.sh b/Documentation/run-qemu.sh
> new file mode 100755
> index 0000000..0bac924
> --- /dev/null
> +++ b/Documentation/run-qemu.sh
> @@ -0,0 +1,284 @@
> +#!/bin/bash
> +#
> +# QEMU Launcher
> +#
> +# This script enables simple use of the KVM and Qemu tool stack for

QEMU

> +# 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:
> +#
> +# $ ./Documentation/run-qemu.sh -r /
> +#
> +# Run the same with SDL:
> +#
> +# $ ./Documentation/run-qemu.sh -r / --sdl
> +#
> +# Or with a PPC build:
> +#
> +# $ ARCH=ppc ./Documentation/run-qemu.sh -r /
> +#
> +#
> +
> +USE_SDL=
> +USE_VNC=
> +KERNEL_BIN=arch/x86/boot/bzImage
> +MON_STDIO=
> +KERNEL_APPEND2=
> +SERIAL=ttyS0
> +SERIAL_KCONFIG=SERIAL_8250
> +
> +function usage() {
> +       echo "
> +Run-Qemu allows you to execute a virtual machine with the Linux kernel

run-qemu.sh or $0

> +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
> +
> +       -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:
> +       $ ./Documentation/run-qemu.sh -r /
> +
> +       Run the same with SDL:
> +       $ ./Documentation/run-qemu.sh -r / --sdl
> +
> +       Or with a PPC build:
> +       $ ARCH=ppc ./Documentation/run-qemu.sh -r /
> +"
> +}
> +
> +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 "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:hr:sS:v --long append,disk:,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="$2"
> +               shift 2
> +               ;;
> +       -d|--disk)
> +               QEMU_OPTIONS="$QEMU_OPTIONS -drive \
> +                       file=$2,if=$(drive_if),cache=unsafe"
> +               USE_DISK=1
> +               shift 2
> +               ;;
> +       -h|--help)
> +               usage
> +               exit 0
> +               ;;
> +       -r|--root)
> +               ROOTFS="$2"
> +               shift 2
> +               ;;
> +       -s|--sdl)
> +               USE_SDL=1
> +               shift
> +               ;;
> +       -S|--smp)
> +               SMP="$2"
> +               shift 2
> +               ;;
> +       -v|--vnc)
> +               USE_VNC=1
> +               shift
> +               ;;
> +       --)
> +               shift
> +               break
> +               ;;
> +       *)
> +               echo "Could not parse option: $1" >&2
> +               exit 1
> +               ;;
> +       esac
> +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
> +i*86|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)

If you run qemu-system-x86_64 on an i386 host, will it use kvm at all?
If testing kvm  is not needed, then why don't you just grab the target
CPU from .config and use qemu-system-$CPU?

> +
> +       # i386 version of Qemu
> +       if [ ! "$(has_config X86_64)" ]; then
> +               [ "$QEMU_BIN" ] || QEMU_BIN=$(which qemu 2>/dev/null)

I'd just make a separate case for i386, even if the first two checks
are duplicated.

> +       fi
> +       ;;
> +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 [ ! "$QEMU_BIN" ]; then
> +       echo "\
> +Could not find a usable Qemu binary. Please install one from \
> +your distro or from source code." >&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 #################
> +
> +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 take the command
> +line shown below and modify it to your needs. This tool is for simplicity, not
> +world dominating functionality coverage.

Please add this:
(just a hobby, won't be big and professional like libvirt)

Though usually Unix tools should be terse unless the user specifies -v.

> +"
> +echo "\
> +Your guest is bound to the current foreground shell. To quit the guest,
> +please use Ctrl-A x"
> +echo "  Executing: $QEMU_BIN $QEMU_OPTIONS -append \"$KERNEL_APPEND\" -smp $SMP"
> +echo
> +
> +exec $QEMU_BIN $QEMU_OPTIONS -append "$KERNEL_APPEND -smp $SMP"

How about something like this (modulo quoting to allow compiling the
kernel in C:\Documents and Settings\agraf\):
CMD="$QEMU_BIN $QEMU_OPTIONS -append $KERNEL_APPEND -smp $SMP"
echo "  Executing: $CMD"
exec $CMD
Avi Kivity Aug. 24, 2011, 7:17 p.m. UTC | #6
On 08/24/2011 08:40 PM, Blue Swirl wrote:
> >  +
> >  +       # Qemu's own build system calls it qemu-system-x86_64
> >  +       [ "$QEMU_BIN" ] || QEMU_BIN=$(which qemu-system-x86_64 2>/dev/null)
>
> If you run qemu-system-x86_64 on an i386 host, will it use kvm at all?

I think it will, and that's actually a bug, since kvm doesn't support 
virtualizing long mode on a 32-bit host.
Alexander Graf Aug. 24, 2011, 8:35 p.m. UTC | #7
On 24.08.2011, at 00:31, Américo Wang wrote:

> On Wed, Aug 24, 2011 at 1:19 PM, Pekka Enberg <penberg@kernel.org> wrote:
>> 
>> It's nice to see such an honest attempt at improving QEMU usability, Alexander!
>> 
>> One comment: in my experience, having shell scripts under
>> Documentation reduces the likelihood that people actually discover
>> them so you might want to consider putting it under scripts or tools.
>> 
> 
> I was going to give the same suggestion, +1 for tools/ directory.

Well, scripts/ is a flat directory where I can just throw in the script. Tools however is split by tool and creating a full new directory for only a single script sounds a bit like overkill to me. I'll move it to scripts/ for now :)


Alex
Alexander Graf Aug. 24, 2011, 9:06 p.m. UTC | #8
On 24.08.2011, at 04:16, Jan Kiszka wrote:

> On 2011-08-24 10:25, Avi Kivity wrote:
>> On 08/24/2011 01:16 AM, Alexander Graf wrote:
>>> +"
>>> +echo "\
>>> +Your guest is bound to the current foreground shell. To quit the guest,
>>> +please use Ctrl-A x"
>>> +echo "  Executing: $QEMU_BIN $QEMU_OPTIONS -append \"$KERNEL_APPEND\"
>>> -smp $SMP"
>>> +echo
>>> +
>>> +exec $QEMU_BIN $QEMU_OPTIONS -append "$KERNEL_APPEND -smp $SMP"
>> 
>> Would be nice to support launching gdb in a separate terminal with
>> vmlinux already loaded, and already attached to qemu.
> 
> + loading a python script into gdb to pull in module symbols. There are
> a few implementations floating around (including my own one).

I'll leave that part to you then :). I haven't figured out a nice way how to get modules into the VM for now anyways.

> It would also be nice if one could append QEMU (note the capitalization
> BTW) options to the script, maybe everything after a '--' separator.

Good point :)


Alex
Alexander Graf Aug. 24, 2011, 9:17 p.m. UTC | #9
On 24.08.2011, at 12:40, Blue Swirl wrote:

> On Tue, Aug 23, 2011 at 10:16 PM, Alexander Graf <agraf@suse.de> 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@suse.de>
>> ---
>>  Documentation/run-qemu.sh |  284 +++++++++++++++++++++++++++++++++++++++++++++
>>  1 files changed, 284 insertions(+), 0 deletions(-)
>>  create mode 100755 Documentation/run-qemu.sh
>> 
>> diff --git a/Documentation/run-qemu.sh b/Documentation/run-qemu.sh
>> new file mode 100755
>> index 0000000..0bac924
>> --- /dev/null
>> +++ b/Documentation/run-qemu.sh
>> @@ -0,0 +1,284 @@
>> +#!/bin/bash
>> +#
>> +# QEMU Launcher
>> +#
>> +# This script enables simple use of the KVM and Qemu tool stack for
> 
> QEMU
> 
>> +# 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:
>> +#
>> +# $ ./Documentation/run-qemu.sh -r /
>> +#
>> +# Run the same with SDL:
>> +#
>> +# $ ./Documentation/run-qemu.sh -r / --sdl
>> +#
>> +# Or with a PPC build:
>> +#
>> +# $ ARCH=ppc ./Documentation/run-qemu.sh -r /
>> +#
>> +#
>> +
>> +USE_SDL=
>> +USE_VNC=
>> +KERNEL_BIN=arch/x86/boot/bzImage
>> +MON_STDIO=
>> +KERNEL_APPEND2=
>> +SERIAL=ttyS0
>> +SERIAL_KCONFIG=SERIAL_8250
>> +
>> +function usage() {
>> +       echo "
>> +Run-Qemu allows you to execute a virtual machine with the Linux kernel
> 
> run-qemu.sh or $0
> 
>> +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
>> +
>> +       -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:
>> +       $ ./Documentation/run-qemu.sh -r /
>> +
>> +       Run the same with SDL:
>> +       $ ./Documentation/run-qemu.sh -r / --sdl
>> +
>> +       Or with a PPC build:
>> +       $ ARCH=ppc ./Documentation/run-qemu.sh -r /
>> +"
>> +}
>> +
>> +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 "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:hr:sS:v --long append,disk:,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="$2"
>> +               shift 2
>> +               ;;
>> +       -d|--disk)
>> +               QEMU_OPTIONS="$QEMU_OPTIONS -drive \
>> +                       file=$2,if=$(drive_if),cache=unsafe"
>> +               USE_DISK=1
>> +               shift 2
>> +               ;;
>> +       -h|--help)
>> +               usage
>> +               exit 0
>> +               ;;
>> +       -r|--root)
>> +               ROOTFS="$2"
>> +               shift 2
>> +               ;;
>> +       -s|--sdl)
>> +               USE_SDL=1
>> +               shift
>> +               ;;
>> +       -S|--smp)
>> +               SMP="$2"
>> +               shift 2
>> +               ;;
>> +       -v|--vnc)
>> +               USE_VNC=1
>> +               shift
>> +               ;;
>> +       --)
>> +               shift
>> +               break
>> +               ;;
>> +       *)
>> +               echo "Could not parse option: $1" >&2
>> +               exit 1
>> +               ;;
>> +       esac
>> +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
>> +i*86|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)
> 
> If you run qemu-system-x86_64 on an i386 host, will it use kvm at all?
> If testing kvm  is not needed, then why don't you just grab the target
> CPU from .config and use qemu-system-$CPU?

Well, how do you find out if it's needed? The goal is to use as few command line parameters as possible to get a kernel test going. And most people will want to use KVM if it's available, right? Plus, on x86_64, there are very few machines that don't support KVM these days.

Also, how would you fetch $CPU from .config? I haven't found anything in .config that is explicitly telling me the ARCH for the respective build.

> 
>> +
>> +       # i386 version of Qemu
>> +       if [ ! "$(has_config X86_64)" ]; then
>> +               [ "$QEMU_BIN" ] || QEMU_BIN=$(which qemu 2>/dev/null)
> 
> I'd just make a separate case for i386, even if the first two checks
> are duplicated.

Hrm. On i386 we can just always fall back to the qemu binary I'd say. You're pretty unlikely to get KVM there and if you do, -machine accel= should sort that one out for you.

> 
>> +       fi
>> +       ;;
>> +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 [ ! "$QEMU_BIN" ]; then
>> +       echo "\
>> +Could not find a usable Qemu binary. Please install one from \
>> +your distro or from source code." >&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 #################
>> +
>> +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 take the command
>> +line shown below and modify it to your needs. This tool is for simplicity, not
>> +world dominating functionality coverage.
> 
> Please add this:
> (just a hobby, won't be big and professional like libvirt)
> 
> Though usually Unix tools should be terse unless the user specifies -v.
> 
>> +"
>> +echo "\
>> +Your guest is bound to the current foreground shell. To quit the guest,
>> +please use Ctrl-A x"
>> +echo "  Executing: $QEMU_BIN $QEMU_OPTIONS -append \"$KERNEL_APPEND\" -smp $SMP"
>> +echo
>> +
>> +exec $QEMU_BIN $QEMU_OPTIONS -append "$KERNEL_APPEND -smp $SMP"
> 
> How about something like this (modulo quoting to allow compiling the
> kernel in C:\Documents and Settings\agraf\):
> CMD="$QEMU_BIN $QEMU_OPTIONS -append $KERNEL_APPEND -smp $SMP"
> echo "  Executing: $CMD"
> exec $CMD

Yeah, I tried that, but my bash foo is not good enough :(. The quoting isn't quite as simple. I think I'd have to make this be an array - and before I do that I'd rather have the code be slightly more verbose.


Alex
Cong Wang Aug. 25, 2011, 3:44 a.m. UTC | #10
On Thu, Aug 25, 2011 at 4:35 AM, Alexander Graf <agraf@suse.de> wrote:
>
> On 24.08.2011, at 00:31, Américo Wang wrote:
>
>> On Wed, Aug 24, 2011 at 1:19 PM, Pekka Enberg <penberg@kernel.org> wrote:
>>>
>>> It's nice to see such an honest attempt at improving QEMU usability, Alexander!
>>>
>>> One comment: in my experience, having shell scripts under
>>> Documentation reduces the likelihood that people actually discover
>>> them so you might want to consider putting it under scripts or tools.
>>>
>>
>> I was going to give the same suggestion, +1 for tools/ directory.
>
> Well, scripts/ is a flat directory where I can just throw in the script. Tools however is split by tool and creating a full new directory for only a single script sounds a bit like overkill to me. I'll move it to scripts/ for now :)

How about the directory tools/testing/ ?

scripts/ is mainly for the tools/utilities we use to build kernel or
do kernel dev,
it is not so suitable for your script IMHO.

Thanks.
Alexander Graf Nov. 5, 2011, 11:47 p.m. UTC | #11
On 24.08.2011, at 20:44, Américo Wang wrote:

> On Thu, Aug 25, 2011 at 4:35 AM, Alexander Graf <agraf@suse.de> wrote:
>> 
>> On 24.08.2011, at 00:31, Américo Wang wrote:
>> 
>>> On Wed, Aug 24, 2011 at 1:19 PM, Pekka Enberg <penberg@kernel.org> wrote:
>>>> 
>>>> It's nice to see such an honest attempt at improving QEMU usability, Alexander!
>>>> 
>>>> One comment: in my experience, having shell scripts under
>>>> Documentation reduces the likelihood that people actually discover
>>>> them so you might want to consider putting it under scripts or tools.
>>>> 
>>> 
>>> I was going to give the same suggestion, +1 for tools/ directory.
>> 
>> Well, scripts/ is a flat directory where I can just throw in the script. Tools however is split by tool and creating a full new directory for only a single script sounds a bit like overkill to me. I'll move it to scripts/ for now :)
> 
> How about the directory tools/testing/ ?
> 
> scripts/ is mainly for the tools/utilities we use to build kernel or
> do kernel dev,
> it is not so suitable for your script IMHO.

Good idea! I talked to Steven about it as well and completely forgot your email pointing me to the same directory. I guess that one does fit it pretty well.


Alex
diff mbox

Patch

diff --git a/Documentation/run-qemu.sh b/Documentation/run-qemu.sh
new file mode 100755
index 0000000..0bac924
--- /dev/null
+++ b/Documentation/run-qemu.sh
@@ -0,0 +1,284 @@ 
+#!/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:
+#
+# $ ./Documentation/run-qemu.sh -r /
+#
+# Run the same with SDL:
+#
+# $ ./Documentation/run-qemu.sh -r / --sdl
+# 
+# Or with a PPC build:
+#
+# $ ARCH=ppc ./Documentation/run-qemu.sh -r /
+# 
+#
+
+USE_SDL=
+USE_VNC=
+KERNEL_BIN=arch/x86/boot/bzImage
+MON_STDIO=
+KERNEL_APPEND2=
+SERIAL=ttyS0
+SERIAL_KCONFIG=SERIAL_8250
+
+function usage() {
+	echo "
+Run-Qemu 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
+
+	-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:
+	$ ./Documentation/run-qemu.sh -r /
+
+	Run the same with SDL:
+	$ ./Documentation/run-qemu.sh -r / --sdl
+	
+	Or with a PPC build:
+	$ ARCH=ppc ./Documentation/run-qemu.sh -r /
+"
+}
+
+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 "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:hr:sS:v --long append,disk:,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="$2"
+		shift 2
+		;;
+	-d|--disk)
+		QEMU_OPTIONS="$QEMU_OPTIONS -drive \
+			file=$2,if=$(drive_if),cache=unsafe"
+		USE_DISK=1
+		shift 2
+		;;
+	-h|--help)
+		usage
+		exit 0
+		;;
+	-r|--root)
+		ROOTFS="$2"
+		shift 2
+		;;
+	-s|--sdl)
+		USE_SDL=1
+		shift
+		;;
+	-S|--smp)
+		SMP="$2"
+		shift 2
+		;;
+	-v|--vnc)
+		USE_VNC=1
+		shift
+		;;
+	--)
+		shift
+		break
+		;;
+	*)
+		echo "Could not parse option: $1" >&2
+		exit 1
+		;;
+	esac
+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
+i*86|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)
+
+	# i386 version of Qemu
+	if [ ! "$(has_config X86_64)" ]; then
+		[ "$QEMU_BIN" ] || QEMU_BIN=$(which qemu 2>/dev/null)
+	fi
+	;;
+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 [ ! "$QEMU_BIN" ]; then
+	echo "\
+Could not find a usable Qemu binary. Please install one from \
+your distro or from source code." >&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 #################
+
+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 take the command
+line shown below and modify it to your needs. This tool is for simplicity, not
+world dominating functionality coverage.
+"
+echo "\
+Your guest is bound to the current foreground shell. To quit the guest,
+please use Ctrl-A x"
+echo "  Executing: $QEMU_BIN $QEMU_OPTIONS -append \"$KERNEL_APPEND\" -smp $SMP"
+echo
+
+exec $QEMU_BIN $QEMU_OPTIONS -append "$KERNEL_APPEND -smp $SMP"