From patchwork Fri Apr 8 13:15:37 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Prasad Joshi X-Patchwork-Id: 694561 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p38DFk1W005980 for ; Fri, 8 Apr 2011 13:15:46 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756627Ab1DHNPl (ORCPT ); Fri, 8 Apr 2011 09:15:41 -0400 Received: from mail-ww0-f44.google.com ([74.125.82.44]:32883 "EHLO mail-ww0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756550Ab1DHNPh (ORCPT ); Fri, 8 Apr 2011 09:15:37 -0400 Received: by wwa36 with SMTP id 36so4231291wwa.1 for ; Fri, 08 Apr 2011 06:15:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references; bh=hO6uc81ov6RJZQ1/qr4WrJhLIHt85Ios84igDfHn9+0=; b=VPOo2Qfk4M2vaO42mKyKSeK7Qx1ArCFNLKZbHmL/EWFvEACXwPjb3310h60U+0sfeE msJJGfpyZ84MRJcg/Qow7FttonPL63q5hT9qQtDF7c/+wbzT27p2o327BSPzoIgI+D76 TBSltCH7/yb9L5+NTE/xRWLe5SyXiwzK14qEo= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=KC4KK+OnhhBN2IBD8Waj98iSHbwwfjEvRmVWnv8YQoBRlfH/a+1qa7uG9LEQbDi6IE PLHGcuauGGMofJ9z3lhOJXCsgAAsRRuyMm3QPmieZV6asc2/8PicNSzbNgXGWD/671Uz n31Ve562O5c5rsOBGnLOfnkhSXYWwNCAdoCAc= Received: by 10.216.48.197 with SMTP id v47mr1889449web.82.1302268535454; Fri, 08 Apr 2011 06:15:35 -0700 (PDT) Received: from prasad-kvm.localdomain (pineapple.rdg.ac.uk [134.225.206.123]) by mx.google.com with ESMTPS id o23sm1704497wbc.10.2011.04.08.06.15.32 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 08 Apr 2011 06:15:33 -0700 (PDT) Received: by prasad-kvm.localdomain (Postfix, from userid 1000) id 9733726E0072; Fri, 8 Apr 2011 14:15:38 +0100 (BST) From: Prasad Joshi To: prasadjoshi12@gmail.com Cc: Prasad Joshi , mingo@elte.hu, kvm@vger.kernel.org, penberg@kernel.org, asias.hejun@gmail.com, gorcunov@gmail.com, oswaldo.cadenas@gmail.com Subject: [PATCH v2 kvm tool: 4/4] Using the Gitish freamwork to run the virtual machine Date: Fri, 8 Apr 2011 14:15:37 +0100 Message-Id: <1302268537-10067-4-git-send-email-prasadjoshi124@gmail.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1302268537-10067-1-git-send-email-prasadjoshi124@gmail.com> References: <1302268537-10067-1-git-send-email-prasadjoshi124@gmail.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Fri, 08 Apr 2011 13:15:47 +0000 (UTC) - kvm-run.[ch] Adds a new kvm command called 'run'. The most of the code is copied from main.c. - main.c is modified to use the functionality provided by framework. The old code from main.c is moved to kvm-run.c. Signed-off-by: Prasad Joshi --- tools/kvm/Makefile | 19 +++- tools/kvm/include/kvm/kvm-run.h | 6 + tools/kvm/kvm-run.c | 222 ++++++++++++++++++++++++++++++++++++++ tools/kvm/main.c | 223 ++------------------------------------ 4 files changed, 258 insertions(+), 212 deletions(-) create mode 100644 tools/kvm/include/kvm/kvm-run.h create mode 100644 tools/kvm/kvm-run.c diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile index 55f342d..9a2819d 100644 --- a/tools/kvm/Makefile +++ b/tools/kvm/Makefile @@ -26,6 +26,11 @@ OBJS += mmio.o OBJS += pci.o OBJS += util.o OBJS += term.o +OBJS += util/parse-options.o +OBJS += util/strbuf.o +OBJS += kvm-help.o +OBJS += kvm-cmd.o +OBJS += kvm-run.o DEPS := $(patsubst %.o,%.d,$(OBJS)) @@ -55,7 +60,8 @@ endif DEFINES += -D_FILE_OFFSET_BITS=64 DEFINES += -D_GNU_SOURCE -CFLAGS += $(CPPFLAGS) $(DEFINES) -Iinclude -I../../include -I../../arch/$(ARCH)/include/ -Os -g +KVM_INCLUDE := include +CFLAGS += $(CPPFLAGS) $(DEFINES) -I$(KVM_INCLUDE) -I../../include -I../../arch/$(ARCH)/include/ -Os -g WARNINGS += -Werror WARNINGS += -Wall @@ -87,12 +93,22 @@ $(DEPS): %.d: %.c $(Q) $(CC) -M -MT $(patsubst %.d,%.o,$@) $(CFLAGS) $< -o $@ +# The header file common-cmds.h is needed for compilation of kvm-help.c. +kvm-help.d: $(KVM_INCLUDE)/common-cmds.h + $(OBJS): %.o: %.c $(E) " CC " $@ $(Q) $(CC) -c $(CFLAGS) $< -o $@ + +$(KVM_INCLUDE)/common-cmds.h: util/generate-cmdlist.sh command-list.txt + +$(KVM_INCLUDE)/common-cmds.h: $(wildcard Documentation/kvm-*.txt) + $(E) " GEN " $@ + $(Q) util/generate-cmdlist.sh > $@+ && mv $@+ $@ + # # BIOS assembly weirdness # @@ -129,6 +145,7 @@ clean: $(Q) rm -f bios/bios-rom.h $(Q) rm -f $(DEPS) $(OBJS) $(PROGRAM) $(Q) rm -f cscope.* + $(Q) rm -f $(KVM_INCLUDE)/common-cmds.h .PHONY: clean KVM_DEV ?= /dev/kvm diff --git a/tools/kvm/include/kvm/kvm-run.h b/tools/kvm/include/kvm/kvm-run.h new file mode 100644 index 0000000..13104e2 --- /dev/null +++ b/tools/kvm/include/kvm/kvm-run.h @@ -0,0 +1,6 @@ +#ifndef __KVM_RUN_H__ +#define __KVM_RUN_H__ + +int kvm_cmd_run(int argc, const char **argv, const char *prefix); + +#endif diff --git a/tools/kvm/kvm-run.c b/tools/kvm/kvm-run.c new file mode 100644 index 0000000..1df0007 --- /dev/null +++ b/tools/kvm/kvm-run.c @@ -0,0 +1,222 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +/* user defined header files */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* header files for gitish interface */ +#include +#include + +#define DEFAULT_KVM_DEV "/dev/kvm" + +#define MB_SHIFT (20) +#define MIN_RAM_SIZE_MB (64UL) +#define MIN_RAM_SIZE_BYTE (MIN_RAM_SIZE_MB << MB_SHIFT) + +static struct kvm *kvm; + +static void handle_sigint(int sig) +{ + exit(1); +} + +static void handle_sigquit(int sig) +{ + kvm__show_registers(kvm); + kvm__show_code(kvm); + kvm__show_page_tables(kvm); + + kvm__delete(kvm); + + exit(1); +} + +static u64 ram_size; +static const char *kernel_cmdline; +static const char *kernel_filename; +static const char *initrd_filename; +static const char *image_filename; +static const char *kvm_dev; +static bool single_step = false; +static bool virtio_console = false; +extern bool ioport_debug; +extern int active_console; + +static const char * const run_usage[] = { + "kvm run []", + NULL +}; + +static const struct option options[] = { + OPT_U64('m', "mem", &ram_size, "Virtual machine memory size in MiB."), + OPT_STRING('p', "params", &kernel_cmdline, "params", + "Kernel command line arguments"), + OPT_STRING('i', "initrd", &initrd_filename, "initrd", + "Initial RAM disk image"), + OPT_STRING('k', "kernel", &kernel_filename, "kernel", + "Kernel to boot in virtual machine"), + OPT_STRING('d', "image", &image_filename, "image", "Disk image"), + OPT_STRING('k', "kvm-dev", &kvm_dev, "kvm-dev", "KVM device file"), + OPT_BOOLEAN('s', "single-step", &single_step, "Enable single stepping"), + OPT_BOOLEAN('g', "ioport-debug", &ioport_debug, + "Enable ioport debugging"), + OPT_BOOLEAN('c', "enable-virtio-console", &virtio_console, + "Enable the virtual IO console"), + OPT_END() +}; + +int kvm_cmd_run(int argc, const char **argv, const char *prefix) +{ + static char real_cmdline[2048]; + + signal(SIGQUIT, handle_sigquit); + signal(SIGINT, handle_sigint); + + argc = parse_options(argc, argv, options, run_usage, + PARSE_OPT_STOP_AT_NON_OPTION); + if (!argc && (!kernel_filename || !image_filename)) { + /* no argument specified or manadatory argument not specified + display the usage message + */ + usage_with_options(run_usage, options); + } + + if (ram_size < MIN_RAM_SIZE_MB) { + die("Not enough memory specified: %luMB (min %luMB)", ram_size, + MIN_RAM_SIZE_MB); + } + ram_size <<= MB_SHIFT; + + if (!kvm_dev) + kvm_dev = DEFAULT_KVM_DEV; + + if (virtio_console == true) + active_console = CONSOLE_VIRTIO; + + term_init(); + + kvm = kvm__init(kvm_dev, ram_size); + + if (image_filename) { + kvm->disk_image = disk_image__open(image_filename); + if (!kvm->disk_image) + die("unable to load disk image %s", image_filename); + } + + kvm__setup_cpuid(kvm); + + strcpy(real_cmdline, "notsc nolapic noacpi pci=conf1 console=ttyS0 "); + if (!kernel_cmdline || !strstr(kernel_cmdline, "root=")) { + strlcat(real_cmdline, "root=/dev/vda rw ", + sizeof(real_cmdline)); + } + + if (kernel_cmdline) { + strlcat(real_cmdline, kernel_cmdline, sizeof(real_cmdline)); + real_cmdline[sizeof(real_cmdline)-1] = '\0'; + } + + if (!kvm__load_kernel(kvm, kernel_filename, initrd_filename, + real_cmdline)) + die("unable to load kernel %s", kernel_filename); + + kvm__reset_vcpu(kvm); + + kvm__setup_bios(kvm); + + if (single_step) + kvm__enable_singlestep(kvm); + + serial8250__init(kvm); + + pci__init(); + + blk_virtio__init(kvm); + + virtio_console__init(kvm); + + kvm__start_timer(kvm); + + for (;;) { + kvm__run(kvm); + + switch (kvm->kvm_run->exit_reason) { + case KVM_EXIT_DEBUG: + kvm__show_registers(kvm); + kvm__show_code(kvm); + break; + case KVM_EXIT_IO: { + bool ret; + + ret = kvm__emulate_io(kvm, + kvm->kvm_run->io.port, + (uint8_t *)kvm->kvm_run + + kvm->kvm_run->io.data_offset, + kvm->kvm_run->io.direction, + kvm->kvm_run->io.size, + kvm->kvm_run->io.count); + + if (!ret) + goto panic_kvm; + break; + } + case KVM_EXIT_MMIO: { + bool ret; + + ret = kvm__emulate_mmio(kvm, + kvm->kvm_run->mmio.phys_addr, + kvm->kvm_run->mmio.data, + kvm->kvm_run->mmio.len, + kvm->kvm_run->mmio.is_write); + + if (!ret) + goto panic_kvm; + break; + } + case KVM_EXIT_INTR: { + serial8250__inject_interrupt(kvm); + virtio_console__inject_interrupt(kvm); + break; + } + case KVM_EXIT_SHUTDOWN: + goto exit_kvm; + default: + goto panic_kvm; + } + } +exit_kvm: + disk_image__close(kvm->disk_image); + kvm__delete(kvm); + + return 0; + +panic_kvm: + fprintf(stderr, "KVM exit reason: %" PRIu32 " (\"%s\")\n", + kvm->kvm_run->exit_reason, + kvm_exit_reasons[kvm->kvm_run->exit_reason]); + if (kvm->kvm_run->exit_reason == KVM_EXIT_UNKNOWN) + fprintf(stderr, "KVM exit code: 0x%" PRIu64 "\n", + kvm->kvm_run->hw.hardware_exit_reason); + disk_image__close(kvm->disk_image); + kvm__show_registers(kvm); + kvm__show_code(kvm); + kvm__show_page_tables(kvm); + kvm__delete(kvm); + + return 1; +} diff --git a/tools/kvm/main.c b/tools/kvm/main.c index 5bcefde..f33660b 100644 --- a/tools/kvm/main.c +++ b/tools/kvm/main.c @@ -1,221 +1,22 @@ -#include "kvm/kvm.h" - -#include "kvm/8250-serial.h" -#include "kvm/blk-virtio.h" -#include "kvm/console-virtio.h" -#include "kvm/disk-image.h" -#include "kvm/util.h" -#include "kvm/pci.h" -#include "kvm/term.h" - -#include -#include -#include -#include -#include -#include #include -extern bool ioport_debug; -extern int active_console; - -static void usage(char *argv[]) -{ - fprintf(stderr, " usage: %s " - "[--single-step] [--ioport-debug] [--enable-virtio-console] " - "[--kvm-dev=] [--mem=] [--params=] " - "[--initrd=] [--kernel=] [--image=]\n", - argv[0]); - exit(1); -} - -static struct kvm *kvm; +/* user defined header files */ +#include +#include +#include -static void handle_sigint(int sig) +static int handle_kvm_command(int argc, char **argv) { - exit(1); -} - -static void handle_sigquit(int sig) -{ - kvm__show_registers(kvm); - kvm__show_code(kvm); - kvm__show_page_tables(kvm); - kvm__delete(kvm); - - exit(1); -} - -static char real_cmdline[2048]; +struct cmd_struct command[] = { + { "help", kvm_cmd_help, 0 }, + { "run", kvm_cmd_run, 0 }, + { NULL, NULL, 0 }, +}; -static bool option_matches(char *arg, const char *option) -{ - return !strncmp(arg, option, strlen(option)); + return handle_command(command, argc, (const char **) &argv[0]); } int main(int argc, char *argv[]) { - const char *kernel_filename = NULL; - const char *initrd_filename = NULL; - const char *image_filename = NULL; - const char *kernel_cmdline = NULL; - const char *kvm_dev = "/dev/kvm"; - unsigned long ram_size = 64UL << 20; - bool single_step = false; - int i; - - signal(SIGQUIT, handle_sigquit); - signal(SIGINT, handle_sigint); - - for (i = 1; i < argc; i++) { - if (option_matches(argv[i], "--kernel=")) { - kernel_filename = &argv[i][9]; - continue; - } else if (option_matches(argv[i], "--image=")) { - image_filename = &argv[i][8]; - continue; - } else if (option_matches(argv[i], "--initrd=")) { - initrd_filename = &argv[i][9]; - continue; - } else if (option_matches(argv[i], "--params=")) { - kernel_cmdline = &argv[i][9]; - continue; - } else if (option_matches(argv[i], "--kvm-dev=")) { - kvm_dev = &argv[i][10]; - continue; - } else if (option_matches(argv[i], "--single-step")) { - single_step = true; - continue; - } else if (option_matches(argv[i], "--enable-virtio-console")) { - active_console = CONSOLE_VIRTIO; - continue; - } else if (option_matches(argv[i], "--mem=")) { - unsigned long val = atol(&argv[i][6]) << 20; - if (val < ram_size) - die("Not enough memory specified: %sMB (min %luMB)", - argv[i], ram_size >> 20); - ram_size = val; - continue; - } else if (option_matches(argv[i], "--ioport-debug")) { - ioport_debug = true; - continue; - } else { - /* any unspecified arg is kernel image */ - if (argv[i][0] != '-') - kernel_filename = argv[i]; - else - warning("Unknown option: %s", argv[i]); - } - } - - /* at least we should have kernel image passed */ - if (!kernel_filename) - usage(argv); - - term_init(); - - kvm = kvm__init(kvm_dev, ram_size); - - if (image_filename) { - kvm->disk_image = disk_image__open(image_filename); - if (!kvm->disk_image) - die("unable to load disk image %s", image_filename); - } - - kvm__setup_cpuid(kvm); - - strcpy(real_cmdline, "notsc nolapic noacpi pci=conf1 console=ttyS0 "); - if (!kernel_cmdline || !strstr(kernel_cmdline, "root=")) - strlcat(real_cmdline, "root=/dev/vda rw ", sizeof(real_cmdline)); - - if (kernel_cmdline) { - strlcat(real_cmdline, kernel_cmdline, sizeof(real_cmdline)); - real_cmdline[sizeof(real_cmdline)-1] = '\0'; - } - - if (!kvm__load_kernel(kvm, kernel_filename, initrd_filename, real_cmdline)) - die("unable to load kernel %s", kernel_filename); - - kvm__reset_vcpu(kvm); - - kvm__setup_bios(kvm); - - if (single_step) - kvm__enable_singlestep(kvm); - - serial8250__init(kvm); - - pci__init(); - - blk_virtio__init(kvm); - - virtio_console__init(kvm); - - kvm__start_timer(kvm); - - for (;;) { - kvm__run(kvm); - - switch (kvm->kvm_run->exit_reason) { - case KVM_EXIT_DEBUG: - kvm__show_registers(kvm); - kvm__show_code(kvm); - break; - case KVM_EXIT_IO: { - bool ret; - - ret = kvm__emulate_io(kvm, - kvm->kvm_run->io.port, - (uint8_t *)kvm->kvm_run + kvm->kvm_run->io.data_offset, - kvm->kvm_run->io.direction, - kvm->kvm_run->io.size, - kvm->kvm_run->io.count); - - if (!ret) - goto panic_kvm; - break; - } - case KVM_EXIT_MMIO: { - bool ret; - - ret = kvm__emulate_mmio(kvm, - kvm->kvm_run->mmio.phys_addr, - kvm->kvm_run->mmio.data, - kvm->kvm_run->mmio.len, - kvm->kvm_run->mmio.is_write); - - if (!ret) - goto panic_kvm; - break; - } - case KVM_EXIT_INTR: { - serial8250__inject_interrupt(kvm); - virtio_console__inject_interrupt(kvm); - break; - } - case KVM_EXIT_SHUTDOWN: - goto exit_kvm; - default: - goto panic_kvm; - } - } -exit_kvm: - disk_image__close(kvm->disk_image); - kvm__delete(kvm); - - return 0; - -panic_kvm: - fprintf(stderr, "KVM exit reason: %" PRIu32 " (\"%s\")\n", - kvm->kvm_run->exit_reason, kvm_exit_reasons[kvm->kvm_run->exit_reason]); - if (kvm->kvm_run->exit_reason == KVM_EXIT_UNKNOWN) - fprintf(stderr, "KVM exit code: 0x%" PRIu64 "\n", - kvm->kvm_run->hw.hardware_exit_reason); - disk_image__close(kvm->disk_image); - kvm__show_registers(kvm); - kvm__show_code(kvm); - kvm__show_page_tables(kvm); - kvm__delete(kvm); - - return 1; + return handle_kvm_command(argc - 1, &argv[1]); }