- 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 <prasadjoshi124@xxxxxxxxx> --- tools/kvm/Makefile | 19 +++- tools/kvm/include/kvm/kvm-run.h | 6 + tools/kvm/kvm-run.c | 231 +++++++++++++++++++++++++++++++++++++ tools/kvm/main.c | 243 ++------------------------------------- 4 files changed, 267 insertions(+), 232 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 747aa51..3224cee 100644 --- a/tools/kvm/Makefile +++ b/tools/kvm/Makefile @@ -24,6 +24,11 @@ OBJS += main.o OBJS += mmio.o OBJS += pci.o OBJS += util.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)) @@ -53,7 +58,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 @@ -85,12 +91,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 # @@ -127,6 +143,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..832e811 --- /dev/null +++ b/tools/kvm/kvm-run.c @@ -0,0 +1,231 @@ +#include <stdio.h> +#include <string.h> +#include <signal.h> +#include <stdint.h> +#include <unistd.h> +#include <inttypes.h> +#include <stdlib.h> +#include <termios.h> + +/* user defined header files */ +#include <linux/types.h> +#include <kvm/kvm.h> +#include <kvm/8250-serial.h> +#include <kvm/blk-virtio.h> +#include <kvm/disk-image.h> +#include <kvm/util.h> +#include <kvm/pci.h> + +/* header files for gitish interface */ +#include <kvm/kvm-run.h> +#include <kvm/parse-options.h> + +#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 struct termios orig_term; + +static void setup_console(void) +{ + struct termios term; + + if (tcgetattr(STDIN_FILENO, &orig_term) < 0) + die("unable to save initial standard input settings"); + + term = orig_term; + + term.c_lflag &= ~(ICANON|ECHO); + + tcsetattr(STDIN_FILENO, TCSANOW, &term); +} + +static void cleanup_console(void) +{ + tcsetattr(STDIN_FILENO, TCSANOW, &orig_term); +} + +static void shutdown(void) +{ + cleanup_console(); +} + +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 bool single_step = false; +extern bool ioport_debug; + +static const char * const run_usage[] = { + "kvm run [<options>]", + 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_BOOLEAN('s', "single-step", &single_step, "Enable single stepping"), + OPT_BOOLEAN('g', "ioport-debug", &ioport_debug, + "Enable ioport debugging"), + OPT_END() +}; + +int kvm_cmd_run(int argc, const char **argv, const char *prefix) +{ + const char *kvm_dev = "/dev/kvm"; + static char real_cmdline[2048]; + + 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; + + signal(SIGQUIT, handle_sigquit); + signal(SIGINT, handle_sigint); + + setup_console(); + + atexit(shutdown); + + + 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); + + 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__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 7beb6a6..4fbb268 100644 --- a/tools/kvm/main.c +++ b/tools/kvm/main.c @@ -1,241 +1,22 @@ -#include "kvm/kvm.h" - -#include "kvm/8250-serial.h" -#include "kvm/blk-virtio.h" -#include "kvm/disk-image.h" -#include "kvm/util.h" -#include "kvm/pci.h" - -#include <inttypes.h> -#include <termios.h> -#include <signal.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> #include <stdio.h> -extern bool ioport_debug; - -static void usage(char *argv[]) -{ - fprintf(stderr, " usage: %s " - "[--single-step] [--ioport-debug] " - "[--kvm-dev=<device>] [--mem=<size-in-MiB>] [--params=<kernel-params>] " - "[--initrd=<initrd>] [--kernel=]<kernel-image> [--image=]<disk-image>\n", - argv[0]); - exit(1); -} - -static struct kvm *kvm; - -static struct termios orig_term; - -static void setup_console(void) -{ - struct termios term; - - if (tcgetattr(STDIN_FILENO, &orig_term) < 0) - die("unable to save initial standard input settings"); - - term = orig_term; - - term.c_lflag &= ~(ICANON|ECHO); - - tcsetattr(STDIN_FILENO, TCSANOW, &term); -} +/* user defined header files */ +#include <kvm/kvm-cmd.h> +#include <kvm/kvm-help.h> +#include <kvm/kvm-run.h> -static void cleanup_console(void) +static int handle_kvm_command(int argc, char **argv) { - tcsetattr(STDIN_FILENO, TCSANOW, &orig_term); -} - -static void shutdown(void) -{ - cleanup_console(); -} - -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 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); - - setup_console(); - - atexit(shutdown); - - 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], "--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); - - 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); - - 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__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]); } -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html