1ece09f8fSPekka Enberg #include "kvm/builtin-run.h" 2ece09f8fSPekka Enberg 3c8675741SSasha Levin #include "kvm/builtin-setup.h" 4ece09f8fSPekka Enberg #include "kvm/virtio-balloon.h" 5ece09f8fSPekka Enberg #include "kvm/virtio-console.h" 6ece09f8fSPekka Enberg #include "kvm/parse-options.h" 7ece09f8fSPekka Enberg #include "kvm/8250-serial.h" 8ece09f8fSPekka Enberg #include "kvm/framebuffer.h" 9ece09f8fSPekka Enberg #include "kvm/disk-image.h" 10ece09f8fSPekka Enberg #include "kvm/threadpool.h" 11a67da3beSAsias He #include "kvm/virtio-scsi.h" 12ece09f8fSPekka Enberg #include "kvm/virtio-blk.h" 13ece09f8fSPekka Enberg #include "kvm/virtio-net.h" 14ece09f8fSPekka Enberg #include "kvm/virtio-rng.h" 15ece09f8fSPekka Enberg #include "kvm/ioeventfd.h" 16ece09f8fSPekka Enberg #include "kvm/virtio-9p.h" 17ece09f8fSPekka Enberg #include "kvm/barrier.h" 18ece09f8fSPekka Enberg #include "kvm/kvm-cpu.h" 19ece09f8fSPekka Enberg #include "kvm/ioport.h" 20ece09f8fSPekka Enberg #include "kvm/symbol.h" 21ece09f8fSPekka Enberg #include "kvm/i8042.h" 22ece09f8fSPekka Enberg #include "kvm/mutex.h" 23ece09f8fSPekka Enberg #include "kvm/term.h" 24ece09f8fSPekka Enberg #include "kvm/util.h" 25ec52d504SLai Jiangshan #include "kvm/strbuf.h" 26ece09f8fSPekka Enberg #include "kvm/vesa.h" 27ece09f8fSPekka Enberg #include "kvm/irq.h" 28ece09f8fSPekka Enberg #include "kvm/kvm.h" 29ece09f8fSPekka Enberg #include "kvm/pci.h" 30ece09f8fSPekka Enberg #include "kvm/rtc.h" 31ece09f8fSPekka Enberg #include "kvm/sdl.h" 32ece09f8fSPekka Enberg #include "kvm/vnc.h" 33e6694207SSasha Levin #include "kvm/guest_compat.h" 3495d13a52SSasha Levin #include "kvm/pci-shmem.h" 354b1addaeSSasha Levin #include "kvm/kvm-ipc.h" 364b1c6f6eSSasha Levin #include "kvm/builtin-debug.h" 37ece09f8fSPekka Enberg 38ece09f8fSPekka Enberg #include <linux/types.h> 3948d9e01aSSasha Levin #include <linux/err.h> 40ece09f8fSPekka Enberg 418329f30bSPekka Enberg #include <sys/utsname.h> 428329f30bSPekka Enberg #include <sys/types.h> 438329f30bSPekka Enberg #include <sys/stat.h> 44ece09f8fSPekka Enberg #include <termios.h> 45ece09f8fSPekka Enberg #include <signal.h> 46ece09f8fSPekka Enberg #include <stdlib.h> 47ece09f8fSPekka Enberg #include <string.h> 48ece09f8fSPekka Enberg #include <unistd.h> 4926c853e4SPrasad Joshi #include <ctype.h> 50ece09f8fSPekka Enberg #include <stdio.h> 51f967c427SPrasad Joshi 52f967c427SPrasad Joshi #define MB_SHIFT (20) 5395d13a52SSasha Levin #define KB_SHIFT (10) 5495d13a52SSasha Levin #define GB_SHIFT (30) 55f967c427SPrasad Joshi 564298ddadSSasha Levin struct kvm *kvm; 57656be1b8SSasha Levin __thread struct kvm_cpu *current_kvm_cpu; 58f967c427SPrasad Joshi 593c29e2aaSSasha Levin static int kvm_run_wrapper; 60f967c427SPrasad Joshi 61ed036f03SCyrill Gorcunov bool do_debug_print = false; 62ed036f03SCyrill Gorcunov 63890364f8SCyrill Gorcunov static int vidmode = -1; 64d77a9efaSCyrill Gorcunov 65afc2c7c0SAsias He extern char _binary_guest_init_start; 66afc2c7c0SAsias He extern char _binary_guest_init_size; 67afc2c7c0SAsias He 68f967c427SPrasad Joshi static const char * const run_usage[] = { 698d2ff5daSWanlong Gao "lkvm run [<options>] [<kernel image>]", 70f967c427SPrasad Joshi NULL 71f967c427SPrasad Joshi }; 72f967c427SPrasad Joshi 733c29e2aaSSasha Levin enum { 74e0747665SSasha Levin KVM_RUN_DEFAULT, 753c29e2aaSSasha Levin KVM_RUN_SANDBOX, 763c29e2aaSSasha Levin }; 773c29e2aaSSasha Levin 78a33979d8SSasha Levin static int img_name_parser(const struct option *opt, const char *arg, int unset) 79a33979d8SSasha Levin { 8082d65b5eSSasha Levin char path[PATH_MAX]; 815236b505SAsias He struct stat st; 823b55dcdeSSasha Levin struct kvm *kvm = opt->ptr; 8359aa2d30SSasha Levin 8459aa2d30SSasha Levin if (stat(arg, &st) == 0 && 8559aa2d30SSasha Levin S_ISDIR(st.st_mode)) { 8659aa2d30SSasha Levin char tmp[PATH_MAX]; 8759aa2d30SSasha Levin 8847621338SSasha Levin if (kvm->cfg.using_rootfs) 892c908af9SLai Jiangshan die("Please use only one rootfs directory atmost"); 902c908af9SLai Jiangshan 9159aa2d30SSasha Levin if (realpath(arg, tmp) == 0 || 92c7838fbdSSasha Levin virtio_9p__register(kvm, tmp, "/dev/root") < 0) 9359aa2d30SSasha Levin die("Unable to initialize virtio 9p"); 9447621338SSasha Levin kvm->cfg.using_rootfs = 1; 9559aa2d30SSasha Levin return 0; 9659aa2d30SSasha Levin } 97a33979d8SSasha Levin 989667701cSPekka Enberg snprintf(path, PATH_MAX, "%s%s", kvm__get_dir(), arg); 9982d65b5eSSasha Levin 10082d65b5eSSasha Levin if (stat(path, &st) == 0 && 10182d65b5eSSasha Levin S_ISDIR(st.st_mode)) { 10282d65b5eSSasha Levin char tmp[PATH_MAX]; 10382d65b5eSSasha Levin 10447621338SSasha Levin if (kvm->cfg.using_rootfs) 1052c908af9SLai Jiangshan die("Please use only one rootfs directory atmost"); 1062c908af9SLai Jiangshan 10782d65b5eSSasha Levin if (realpath(path, tmp) == 0 || 10882d65b5eSSasha Levin virtio_9p__register(kvm, tmp, "/dev/root") < 0) 10982d65b5eSSasha Levin die("Unable to initialize virtio 9p"); 11082d65b5eSSasha Levin if (virtio_9p__register(kvm, "/", "hostfs") < 0) 11182d65b5eSSasha Levin die("Unable to initialize virtio 9p"); 11269c88b95SSasha Levin kvm_setup_resolv(arg); 11347621338SSasha Levin kvm->cfg.using_rootfs = kvm->cfg.custom_rootfs = 1; 11447621338SSasha Levin kvm->cfg.custom_rootfs_name = arg; 11582d65b5eSSasha Levin return 0; 11682d65b5eSSasha Levin } 11782d65b5eSSasha Levin 1183b55dcdeSSasha Levin return disk_img_name_parser(opt, arg, unset); 119a67da3beSAsias He } 120a67da3beSAsias He 1213b55dcdeSSasha Levin void kvm_run_set_wrapper_sandbox(void) 1223b55dcdeSSasha Levin { 1233b55dcdeSSasha Levin kvm_run_wrapper = KVM_RUN_SANDBOX; 124a33979d8SSasha Levin } 125a33979d8SSasha Levin 126b4422bf3SAneesh Kumar K.V static int virtio_9p_rootdir_parser(const struct option *opt, const char *arg, int unset) 127b4422bf3SAneesh Kumar K.V { 128b4422bf3SAneesh Kumar K.V char *tag_name; 129b4422bf3SAneesh Kumar K.V char tmp[PATH_MAX]; 130b4422bf3SAneesh Kumar K.V 131b4422bf3SAneesh Kumar K.V /* 132b4422bf3SAneesh Kumar K.V * 9p dir can be of the form dirname,tag_name or 133b4422bf3SAneesh Kumar K.V * just dirname. In the later case we use the 134b4422bf3SAneesh Kumar K.V * default tag name 135b4422bf3SAneesh Kumar K.V */ 136b4422bf3SAneesh Kumar K.V tag_name = strstr(arg, ","); 137b4422bf3SAneesh Kumar K.V if (tag_name) { 138b4422bf3SAneesh Kumar K.V *tag_name = '\0'; 139b4422bf3SAneesh Kumar K.V tag_name++; 140b4422bf3SAneesh Kumar K.V } 14154f6802dSPekka Enberg if (realpath(arg, tmp)) { 142c7838fbdSSasha Levin if (virtio_9p__register(kvm, tmp, tag_name) < 0) 14354f6802dSPekka Enberg die("Unable to initialize virtio 9p"); 14454f6802dSPekka Enberg } else 145b4422bf3SAneesh Kumar K.V die("Failed resolving 9p path"); 146b4422bf3SAneesh Kumar K.V return 0; 147b4422bf3SAneesh Kumar K.V } 148b4422bf3SAneesh Kumar K.V 1499a6d73f1SSasha Levin static inline void str_to_mac(const char *str, char *mac) 1509a6d73f1SSasha Levin { 1519a6d73f1SSasha Levin sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", 1529a6d73f1SSasha Levin mac, mac+1, mac+2, mac+3, mac+4, mac+5); 1539a6d73f1SSasha Levin } 1549a6d73f1SSasha Levin static int set_net_param(struct virtio_net_params *p, const char *param, 1559a6d73f1SSasha Levin const char *val) 1569a6d73f1SSasha Levin { 1579a6d73f1SSasha Levin if (strcmp(param, "guest_mac") == 0) { 1589a6d73f1SSasha Levin str_to_mac(val, p->guest_mac); 1599a6d73f1SSasha Levin } else if (strcmp(param, "mode") == 0) { 1609a6d73f1SSasha Levin if (!strncmp(val, "user", 4)) { 1619a6d73f1SSasha Levin int i; 1629a6d73f1SSasha Levin 16347621338SSasha Levin for (i = 0; i < kvm->cfg.num_net_devices; i++) 16447621338SSasha Levin if (kvm->cfg.net_params[i].mode == NET_MODE_USER) 1659a6d73f1SSasha Levin die("Only one usermode network device allowed at a time"); 1669a6d73f1SSasha Levin p->mode = NET_MODE_USER; 1679a6d73f1SSasha Levin } else if (!strncmp(val, "tap", 3)) { 1689a6d73f1SSasha Levin p->mode = NET_MODE_TAP; 1699a6d73f1SSasha Levin } else if (!strncmp(val, "none", 4)) { 17047621338SSasha Levin kvm->cfg.no_net = 1; 1719a6d73f1SSasha Levin return -1; 1729a6d73f1SSasha Levin } else 17347621338SSasha Levin die("Unknown network mode %s, please use user, tap or none", kvm->cfg.network); 1749a6d73f1SSasha Levin } else if (strcmp(param, "script") == 0) { 1759a6d73f1SSasha Levin p->script = strdup(val); 1769a6d73f1SSasha Levin } else if (strcmp(param, "guest_ip") == 0) { 1779a6d73f1SSasha Levin p->guest_ip = strdup(val); 1789a6d73f1SSasha Levin } else if (strcmp(param, "host_ip") == 0) { 1799a6d73f1SSasha Levin p->host_ip = strdup(val); 18069205aa1SAsias He } else if (strcmp(param, "trans") == 0) { 18169205aa1SAsias He p->trans = strdup(val); 1829ed67cdcSSasha Levin } else if (strcmp(param, "vhost") == 0) { 1839ed67cdcSSasha Levin p->vhost = atoi(val); 184f19edd1eSSasha Levin } else if (strcmp(param, "fd") == 0) { 185f19edd1eSSasha Levin p->fd = atoi(val); 18621aa628eSMichael Ellerman } else 18721aa628eSMichael Ellerman die("Unknown network parameter %s", param); 1889a6d73f1SSasha Levin 1899a6d73f1SSasha Levin return 0; 1909a6d73f1SSasha Levin } 1919a6d73f1SSasha Levin 1929a6d73f1SSasha Levin static int netdev_parser(const struct option *opt, const char *arg, int unset) 1939a6d73f1SSasha Levin { 1949a6d73f1SSasha Levin struct virtio_net_params p; 1959a6d73f1SSasha Levin char *buf = NULL, *cmd = NULL, *cur = NULL; 1969a6d73f1SSasha Levin bool on_cmd = true; 1979a6d73f1SSasha Levin 1989a6d73f1SSasha Levin if (arg) { 1999a6d73f1SSasha Levin buf = strdup(arg); 2009a6d73f1SSasha Levin if (buf == NULL) 2019a6d73f1SSasha Levin die("Failed allocating new net buffer"); 2029a6d73f1SSasha Levin cur = strtok(buf, ",="); 2039a6d73f1SSasha Levin } 2049a6d73f1SSasha Levin 2059a6d73f1SSasha Levin p = (struct virtio_net_params) { 2069a6d73f1SSasha Levin .guest_ip = DEFAULT_GUEST_ADDR, 2079a6d73f1SSasha Levin .host_ip = DEFAULT_HOST_ADDR, 2089a6d73f1SSasha Levin .script = DEFAULT_SCRIPT, 2099a6d73f1SSasha Levin .mode = NET_MODE_TAP, 2109a6d73f1SSasha Levin }; 2119a6d73f1SSasha Levin 2129a6d73f1SSasha Levin str_to_mac(DEFAULT_GUEST_MAC, p.guest_mac); 21347621338SSasha Levin p.guest_mac[5] += kvm->cfg.num_net_devices; 2149a6d73f1SSasha Levin 2159a6d73f1SSasha Levin while (cur) { 2169a6d73f1SSasha Levin if (on_cmd) { 2179a6d73f1SSasha Levin cmd = cur; 2189a6d73f1SSasha Levin } else { 2199a6d73f1SSasha Levin if (set_net_param(&p, cmd, cur) < 0) 2209a6d73f1SSasha Levin goto done; 2219a6d73f1SSasha Levin } 2229a6d73f1SSasha Levin on_cmd = !on_cmd; 2239a6d73f1SSasha Levin 2249a6d73f1SSasha Levin cur = strtok(NULL, ",="); 2259a6d73f1SSasha Levin }; 2269a6d73f1SSasha Levin 22747621338SSasha Levin kvm->cfg.num_net_devices++; 2289a6d73f1SSasha Levin 22947621338SSasha Levin kvm->cfg.net_params = realloc(kvm->cfg.net_params, kvm->cfg.num_net_devices * sizeof(*kvm->cfg.net_params)); 23047621338SSasha Levin if (kvm->cfg.net_params == NULL) 2319a6d73f1SSasha Levin die("Failed adding new network device"); 2329a6d73f1SSasha Levin 23347621338SSasha Levin kvm->cfg.net_params[kvm->cfg.num_net_devices - 1] = p; 2349a6d73f1SSasha Levin 2359a6d73f1SSasha Levin done: 2369a6d73f1SSasha Levin free(buf); 2379a6d73f1SSasha Levin return 0; 2389a6d73f1SSasha Levin } 2399a6d73f1SSasha Levin 2403b55dcdeSSasha Levin #define BUILD_OPTIONS(name, cfg, kvm) \ 241b816364aSSasha Levin struct option name[] = { \ 242b816364aSSasha Levin OPT_GROUP("Basic options:"), \ 243b816364aSSasha Levin OPT_STRING('\0', "name", &(cfg)->guest_name, "guest name", \ 244b816364aSSasha Levin "A name for the guest"), \ 24500ebbe96SSasha Levin OPT_INTEGER('c', "cpus", &(cfg)->nrcpus, "Number of CPUs"), \ 246b816364aSSasha Levin OPT_U64('m', "mem", &(cfg)->ram_size, "Virtual machine memory size\ 247b816364aSSasha Levin in MiB."), \ 248b816364aSSasha Levin OPT_CALLBACK('\0', "shmem", NULL, \ 249b816364aSSasha Levin "[pci:]<addr>:<size>[:handle=<handle>][:create]", \ 250b816364aSSasha Levin "Share host shmem with guest via pci device", \ 2511dc24dccSSasha Levin shmem_parser, NULL), \ 2521dc24dccSSasha Levin OPT_CALLBACK('d', "disk", kvm, "image or rootfs_dir", "Disk \ 2531dc24dccSSasha Levin image or rootfs directory", img_name_parser, \ 2543b55dcdeSSasha Levin kvm), \ 255b816364aSSasha Levin OPT_BOOLEAN('\0', "balloon", &(cfg)->balloon, "Enable virtio \ 256b816364aSSasha Levin balloon"), \ 257b816364aSSasha Levin OPT_BOOLEAN('\0', "vnc", &(cfg)->vnc, "Enable VNC framebuffer"),\ 258b816364aSSasha Levin OPT_BOOLEAN('\0', "sdl", &(cfg)->sdl, "Enable SDL framebuffer"),\ 259b816364aSSasha Levin OPT_BOOLEAN('\0', "rng", &(cfg)->virtio_rng, "Enable virtio Random\ 260b816364aSSasha Levin Number Generator"), \ 261b816364aSSasha Levin OPT_CALLBACK('\0', "9p", NULL, "dir_to_share,tag_name", \ 262b816364aSSasha Levin "Enable virtio 9p to share files between host and \ 2631dc24dccSSasha Levin guest", virtio_9p_rootdir_parser, NULL), \ 264b816364aSSasha Levin OPT_STRING('\0', "console", &(cfg)->console, "serial, virtio or \ 265b816364aSSasha Levin hv", "Console to use"), \ 266b816364aSSasha Levin OPT_STRING('\0', "dev", &(cfg)->dev, "device_file", \ 267b816364aSSasha Levin "KVM device file"), \ 268b816364aSSasha Levin OPT_CALLBACK('\0', "tty", NULL, "tty id", \ 269b816364aSSasha Levin "Remap guest TTY into a pty on the host", \ 2701dc24dccSSasha Levin tty_parser, NULL), \ 271b816364aSSasha Levin OPT_STRING('\0', "sandbox", &(cfg)->sandbox, "script", \ 272b816364aSSasha Levin "Run this script when booting into custom \ 273b816364aSSasha Levin rootfs"), \ 274b816364aSSasha Levin OPT_STRING('\0', "hugetlbfs", &(cfg)->hugetlbfs_path, "path", \ 275b816364aSSasha Levin "Hugetlbfs path"), \ 276b816364aSSasha Levin \ 277b816364aSSasha Levin OPT_GROUP("Kernel options:"), \ 278b816364aSSasha Levin OPT_STRING('k', "kernel", &(cfg)->kernel_filename, "kernel", \ 279b816364aSSasha Levin "Kernel to boot in virtual machine"), \ 280b816364aSSasha Levin OPT_STRING('i', "initrd", &(cfg)->initrd_filename, "initrd", \ 281b816364aSSasha Levin "Initial RAM disk image"), \ 282b816364aSSasha Levin OPT_STRING('p', "params", &(cfg)->kernel_cmdline, "params", \ 283b816364aSSasha Levin "Kernel command line arguments"), \ 284b816364aSSasha Levin OPT_STRING('f', "firmware", &(cfg)->firmware_filename, "firmware",\ 285b816364aSSasha Levin "Firmware image to boot in virtual machine"), \ 286b816364aSSasha Levin \ 287b816364aSSasha Levin OPT_GROUP("Networking options:"), \ 288b816364aSSasha Levin OPT_CALLBACK_DEFAULT('n', "network", NULL, "network params", \ 289b816364aSSasha Levin "Create a new guest NIC", \ 2901dc24dccSSasha Levin netdev_parser, NULL, NULL), \ 291b816364aSSasha Levin OPT_BOOLEAN('\0', "no-dhcp", &(cfg)->no_dhcp, "Disable kernel DHCP\ 292b816364aSSasha Levin in rootfs mode"), \ 293b816364aSSasha Levin \ 294b816364aSSasha Levin OPT_GROUP("BIOS options:"), \ 295b816364aSSasha Levin OPT_INTEGER('\0', "vidmode", &vidmode, \ 296b816364aSSasha Levin "Video mode"), \ 297b816364aSSasha Levin \ 298b816364aSSasha Levin OPT_GROUP("Debug options:"), \ 299b816364aSSasha Levin OPT_BOOLEAN('\0', "debug", &do_debug_print, \ 300b816364aSSasha Levin "Enable debug messages"), \ 301b816364aSSasha Levin OPT_BOOLEAN('\0', "debug-single-step", &(cfg)->single_step, \ 302b816364aSSasha Levin "Enable single stepping"), \ 3035765977dSSasha Levin OPT_BOOLEAN('\0', "debug-ioport", &(cfg)->ioport_debug, \ 304b816364aSSasha Levin "Enable ioport debugging"), \ 305e830cce7SSasha Levin OPT_BOOLEAN('\0', "debug-mmio", &(cfg)->mmio_debug, \ 306b816364aSSasha Levin "Enable MMIO debugging"), \ 3073b55dcdeSSasha Levin OPT_INTEGER('\0', "debug-iodelay", &(cfg)->debug_iodelay, \ 308b816364aSSasha Levin "Delay IO by millisecond"), \ 309b816364aSSasha Levin OPT_END() \ 310f967c427SPrasad Joshi }; 311f967c427SPrasad Joshi 312b5b501ccSIngo Molnar /* 313b5b501ccSIngo Molnar * Serialize debug printout so that the output of multiple vcpus does not 314b5b501ccSIngo Molnar * get mixed up: 315b5b501ccSIngo Molnar */ 316cffeab25SIngo Molnar static int printout_done; 317b5b501ccSIngo Molnar 31843119af7SPekka Enberg static void handle_sigusr1(int sig) 31943119af7SPekka Enberg { 32043119af7SPekka Enberg struct kvm_cpu *cpu = current_kvm_cpu; 321b7d2f013SSasha Levin int fd = kvm_cpu__get_debug_fd(); 32243119af7SPekka Enberg 3234b1c6f6eSSasha Levin if (!cpu || cpu->needs_nmi) 32443119af7SPekka Enberg return; 32543119af7SPekka Enberg 326b7d2f013SSasha Levin dprintf(fd, "\n #\n # vCPU #%ld's dump:\n #\n", cpu->cpu_id); 32743119af7SPekka Enberg kvm_cpu__show_registers(cpu); 32843119af7SPekka Enberg kvm_cpu__show_code(cpu); 32943119af7SPekka Enberg kvm_cpu__show_page_tables(cpu); 330b5b501ccSIngo Molnar fflush(stdout); 331cffeab25SIngo Molnar printout_done = 1; 332cffeab25SIngo Molnar mb(); 33343119af7SPekka Enberg } 33443119af7SPekka Enberg 335d94e22b9SSasha Levin /* Pause/resume the guest using SIGUSR2 */ 336d94e22b9SSasha Levin static int is_paused; 337d94e22b9SSasha Levin 3384b1addaeSSasha Levin static void handle_pause(int fd, u32 type, u32 len, u8 *msg) 339d94e22b9SSasha Levin { 3405aa502e4SLai Jiangshan if (WARN_ON(len)) 3415aa502e4SLai Jiangshan return; 3425aa502e4SLai Jiangshan 3437021c50bSAsias He if (type == KVM_IPC_RESUME && is_paused) { 3447021c50bSAsias He kvm->vm_state = KVM_VMSTATE_RUNNING; 345d94e22b9SSasha Levin kvm__continue(); 3467021c50bSAsias He } else if (type == KVM_IPC_PAUSE && !is_paused) { 3477021c50bSAsias He kvm->vm_state = KVM_VMSTATE_PAUSED; 348eb8dad9dSSasha Levin ioctl(kvm->vm_fd, KVM_KVMCLOCK_CTRL); 349d94e22b9SSasha Levin kvm__pause(); 3507021c50bSAsias He } else { 35102317b74SSasha Levin return; 3525aa502e4SLai Jiangshan } 353d94e22b9SSasha Levin 354d94e22b9SSasha Levin is_paused = !is_paused; 355d94e22b9SSasha Levin } 356d94e22b9SSasha Levin 3577021c50bSAsias He static void handle_vmstate(int fd, u32 type, u32 len, u8 *msg) 3587021c50bSAsias He { 3597021c50bSAsias He int r = 0; 3607021c50bSAsias He 3617021c50bSAsias He if (type == KVM_IPC_VMSTATE) 3627021c50bSAsias He r = write(fd, &kvm->vm_state, sizeof(kvm->vm_state)); 3637021c50bSAsias He 3647021c50bSAsias He if (r < 0) 3657021c50bSAsias He pr_warning("Failed sending VMSTATE"); 3667021c50bSAsias He } 3677021c50bSAsias He 3684b1addaeSSasha Levin static void handle_debug(int fd, u32 type, u32 len, u8 *msg) 3699e854d1aSPekka Enberg { 3709e854d1aSPekka Enberg int i; 371a59cdf44SLai Jiangshan struct debug_cmd_params *params; 372a59cdf44SLai Jiangshan u32 dbg_type; 373a59cdf44SLai Jiangshan u32 vcpu; 374a59cdf44SLai Jiangshan 375a59cdf44SLai Jiangshan if (WARN_ON(type != KVM_IPC_DEBUG || len != sizeof(*params))) 376a59cdf44SLai Jiangshan return; 377a59cdf44SLai Jiangshan 378a59cdf44SLai Jiangshan params = (void *)msg; 379a59cdf44SLai Jiangshan dbg_type = params->dbg_type; 380a59cdf44SLai Jiangshan vcpu = params->cpu; 3814b1c6f6eSSasha Levin 382226e727bSSasha Levin if (dbg_type & KVM_DEBUG_CMD_TYPE_SYSRQ) 383226e727bSSasha Levin serial8250__inject_sysrq(kvm, params->sysrq); 384226e727bSSasha Levin 3854b1c6f6eSSasha Levin if (dbg_type & KVM_DEBUG_CMD_TYPE_NMI) { 3867070414aSSasha Levin if ((int)vcpu >= kvm->nrcpus) 3874b1c6f6eSSasha Levin return; 3884b1c6f6eSSasha Levin 389df4239fbSSasha Levin kvm->cpus[vcpu]->needs_nmi = 1; 390df4239fbSSasha Levin pthread_kill(kvm->cpus[vcpu]->thread, SIGUSR1); 3914b1c6f6eSSasha Levin } 3924b1c6f6eSSasha Levin 3934b1c6f6eSSasha Levin if (!(dbg_type & KVM_DEBUG_CMD_TYPE_DUMP)) 3944b1c6f6eSSasha Levin return; 3959e854d1aSPekka Enberg 39600ebbe96SSasha Levin for (i = 0; i < kvm->nrcpus; i++) { 397df4239fbSSasha Levin struct kvm_cpu *cpu = kvm->cpus[i]; 3989e854d1aSPekka Enberg 39943119af7SPekka Enberg if (!cpu) 40043119af7SPekka Enberg continue; 40143119af7SPekka Enberg 402cffeab25SIngo Molnar printout_done = 0; 403b7d2f013SSasha Levin 404b7d2f013SSasha Levin kvm_cpu__set_debug_fd(fd); 40543119af7SPekka Enberg pthread_kill(cpu->thread, SIGUSR1); 406cffeab25SIngo Molnar /* 407cffeab25SIngo Molnar * Wait for the vCPU to dump state before signalling 408cffeab25SIngo Molnar * the next thread. Since this is debug code it does 409cffeab25SIngo Molnar * not matter that we are burning CPU time a bit: 410cffeab25SIngo Molnar */ 411cffeab25SIngo Molnar while (!printout_done) 412cffeab25SIngo Molnar mb(); 4139e854d1aSPekka Enberg } 4149e854d1aSPekka Enberg 415b7d2f013SSasha Levin close(fd); 416b7d2f013SSasha Levin 417226e727bSSasha Levin serial8250__inject_sysrq(kvm, 'p'); 4189e854d1aSPekka Enberg } 4199e854d1aSPekka Enberg 4209e854d1aSPekka Enberg static void handle_sigalrm(int sig) 4219e854d1aSPekka Enberg { 4220b69bdefSMatt Evans kvm__arch_periodic_poll(kvm); 4239e854d1aSPekka Enberg } 4249e854d1aSPekka Enberg 4254b1addaeSSasha Levin static void handle_stop(int fd, u32 type, u32 len, u8 *msg) 426daf4cb5aSSasha Levin { 427e333e41aSLai Jiangshan if (WARN_ON(type != KVM_IPC_STOP || len)) 428e333e41aSLai Jiangshan return; 429e333e41aSLai Jiangshan 430df4239fbSSasha Levin kvm_cpu__reboot(kvm); 431daf4cb5aSSasha Levin } 432daf4cb5aSSasha Levin 4335ee154d1SPekka Enberg static void *kvm_cpu_thread(void *arg) 4345ee154d1SPekka Enberg { 435d77a9efaSCyrill Gorcunov current_kvm_cpu = arg; 4365ee154d1SPekka Enberg 437d77a9efaSCyrill Gorcunov if (kvm_cpu__start(current_kvm_cpu)) 4385ee154d1SPekka Enberg goto panic_kvm; 4395ee154d1SPekka Enberg 4405ee154d1SPekka Enberg return (void *) (intptr_t) 0; 4415ee154d1SPekka Enberg 4425ee154d1SPekka Enberg panic_kvm: 4433fdf659dSSasha Levin fprintf(stderr, "KVM exit reason: %u (\"%s\")\n", 444d77a9efaSCyrill Gorcunov current_kvm_cpu->kvm_run->exit_reason, 445d77a9efaSCyrill Gorcunov kvm_exit_reasons[current_kvm_cpu->kvm_run->exit_reason]); 446d77a9efaSCyrill Gorcunov if (current_kvm_cpu->kvm_run->exit_reason == KVM_EXIT_UNKNOWN) 4475ee154d1SPekka Enberg fprintf(stderr, "KVM exit code: 0x%Lu\n", 448d77a9efaSCyrill Gorcunov current_kvm_cpu->kvm_run->hw.hardware_exit_reason); 4498e5accedSPekka Enberg 450b7d2f013SSasha Levin kvm_cpu__set_debug_fd(STDOUT_FILENO); 451d77a9efaSCyrill Gorcunov kvm_cpu__show_registers(current_kvm_cpu); 452d77a9efaSCyrill Gorcunov kvm_cpu__show_code(current_kvm_cpu); 453d77a9efaSCyrill Gorcunov kvm_cpu__show_page_tables(current_kvm_cpu); 4545ee154d1SPekka Enberg 4555ee154d1SPekka Enberg return (void *) (intptr_t) 1; 4565ee154d1SPekka Enberg } 4575ee154d1SPekka Enberg 458e08c0896SPrasad Joshi static char kernel[PATH_MAX]; 459b0b42ba0SPekka Enberg 460b0b42ba0SPekka Enberg static const char *host_kernels[] = { 461e08c0896SPrasad Joshi "/boot/vmlinuz", 462e08c0896SPrasad Joshi "/boot/bzImage", 463e08c0896SPrasad Joshi NULL 464e08c0896SPrasad Joshi }; 465b0b42ba0SPekka Enberg 466b0b42ba0SPekka Enberg static const char *default_kernels[] = { 467e08c0896SPrasad Joshi "./bzImage", 468b03af790SKonstantin Khlebnikov "arch/" BUILD_ARCH "/boot/bzImage", 469af7b0868SMatt Evans "../../arch/" BUILD_ARCH "/boot/bzImage", 470e08c0896SPrasad Joshi NULL 471e08c0896SPrasad Joshi }; 4728329f30bSPekka Enberg 473b0b42ba0SPekka Enberg static const char *default_vmlinux[] = { 474b03af790SKonstantin Khlebnikov "vmlinux", 475b0b42ba0SPekka Enberg "../../../vmlinux", 476b0b42ba0SPekka Enberg "../../vmlinux", 477b0b42ba0SPekka Enberg NULL 478b0b42ba0SPekka Enberg }; 479b0b42ba0SPekka Enberg 480e08c0896SPrasad Joshi static void kernel_usage_with_options(void) 4818329f30bSPekka Enberg { 482e08c0896SPrasad Joshi const char **k; 4838329f30bSPekka Enberg struct utsname uts; 484e08c0896SPrasad Joshi 485e08c0896SPrasad Joshi fprintf(stderr, "Fatal: could not find default kernel image in:\n"); 48665182f37SPrasad Joshi k = &default_kernels[0]; 487e08c0896SPrasad Joshi while (*k) { 488e08c0896SPrasad Joshi fprintf(stderr, "\t%s\n", *k); 489e08c0896SPrasad Joshi k++; 490e08c0896SPrasad Joshi } 491e08c0896SPrasad Joshi 492e08c0896SPrasad Joshi if (uname(&uts) < 0) 493e08c0896SPrasad Joshi return; 494e08c0896SPrasad Joshi 495e08c0896SPrasad Joshi k = &host_kernels[0]; 496e08c0896SPrasad Joshi while (*k) { 497e08c0896SPrasad Joshi if (snprintf(kernel, PATH_MAX, "%s-%s", *k, uts.release) < 0) 498e08c0896SPrasad Joshi return; 499e08c0896SPrasad Joshi fprintf(stderr, "\t%s\n", kernel); 500e08c0896SPrasad Joshi k++; 501e08c0896SPrasad Joshi } 502ee8b1456SWanlong Gao fprintf(stderr, "\nPlease see '%s run --help' for more options.\n\n", 503ee8b1456SWanlong Gao KVM_BINARY_NAME); 504e08c0896SPrasad Joshi } 505e08c0896SPrasad Joshi 50660ded003SPekka Enberg static u64 host_ram_size(void) 50760ded003SPekka Enberg { 50860ded003SPekka Enberg long page_size; 50960ded003SPekka Enberg long nr_pages; 51060ded003SPekka Enberg 51160ded003SPekka Enberg nr_pages = sysconf(_SC_PHYS_PAGES); 512d63c5ce6SPekka Enberg if (nr_pages < 0) { 5134542f276SCyrill Gorcunov pr_warning("sysconf(_SC_PHYS_PAGES) failed"); 514d63c5ce6SPekka Enberg return 0; 515d63c5ce6SPekka Enberg } 51660ded003SPekka Enberg 51760ded003SPekka Enberg page_size = sysconf(_SC_PAGE_SIZE); 518d63c5ce6SPekka Enberg if (page_size < 0) { 5194542f276SCyrill Gorcunov pr_warning("sysconf(_SC_PAGE_SIZE) failed"); 520d63c5ce6SPekka Enberg return 0; 521d63c5ce6SPekka Enberg } 52260ded003SPekka Enberg 52360ded003SPekka Enberg return (nr_pages * page_size) >> MB_SHIFT; 52460ded003SPekka Enberg } 52560ded003SPekka Enberg 52618bd8c3bSPekka Enberg /* 52718bd8c3bSPekka Enberg * If user didn't specify how much memory it wants to allocate for the guest, 52818bd8c3bSPekka Enberg * avoid filling the whole host RAM. 52918bd8c3bSPekka Enberg */ 53018bd8c3bSPekka Enberg #define RAM_SIZE_RATIO 0.8 53118bd8c3bSPekka Enberg 532fd834defSPekka Enberg static u64 get_ram_size(int nr_cpus) 533fd834defSPekka Enberg { 53406761c76SPekka Enberg u64 available; 53506761c76SPekka Enberg u64 ram_size; 536fd834defSPekka Enberg 537fd834defSPekka Enberg ram_size = 64 * (nr_cpus + 3); 538fd834defSPekka Enberg 53960ded003SPekka Enberg available = host_ram_size() * RAM_SIZE_RATIO; 540d63c5ce6SPekka Enberg if (!available) 541d63c5ce6SPekka Enberg available = MIN_RAM_SIZE_MB; 542fd834defSPekka Enberg 543fd834defSPekka Enberg if (ram_size > available) 544fd834defSPekka Enberg ram_size = available; 545fd834defSPekka Enberg 546fd834defSPekka Enberg return ram_size; 547fd834defSPekka Enberg } 548fd834defSPekka Enberg 549e08c0896SPrasad Joshi static const char *find_kernel(void) 550e08c0896SPrasad Joshi { 551e08c0896SPrasad Joshi const char **k; 5528329f30bSPekka Enberg struct stat st; 553e08c0896SPrasad Joshi struct utsname uts; 554e08c0896SPrasad Joshi 55565182f37SPrasad Joshi k = &default_kernels[0]; 556e08c0896SPrasad Joshi while (*k) { 557e08c0896SPrasad Joshi if (stat(*k, &st) < 0 || !S_ISREG(st.st_mode)) { 558e08c0896SPrasad Joshi k++; 559e08c0896SPrasad Joshi continue; 560e08c0896SPrasad Joshi } 561e08c0896SPrasad Joshi strncpy(kernel, *k, PATH_MAX); 562e08c0896SPrasad Joshi return kernel; 563e08c0896SPrasad Joshi } 5648329f30bSPekka Enberg 5658329f30bSPekka Enberg if (uname(&uts) < 0) 5668329f30bSPekka Enberg return NULL; 5678329f30bSPekka Enberg 568e08c0896SPrasad Joshi k = &host_kernels[0]; 569e08c0896SPrasad Joshi while (*k) { 570e08c0896SPrasad Joshi if (snprintf(kernel, PATH_MAX, "%s-%s", *k, uts.release) < 0) 5718329f30bSPekka Enberg return NULL; 5728329f30bSPekka Enberg 573e08c0896SPrasad Joshi if (stat(kernel, &st) < 0 || !S_ISREG(st.st_mode)) { 574e08c0896SPrasad Joshi k++; 575e08c0896SPrasad Joshi continue; 576e08c0896SPrasad Joshi } 577e08c0896SPrasad Joshi return kernel; 5788329f30bSPekka Enberg 579e08c0896SPrasad Joshi } 5808329f30bSPekka Enberg return NULL; 5818329f30bSPekka Enberg } 5828329f30bSPekka Enberg 583b0b42ba0SPekka Enberg static const char *find_vmlinux(void) 584b0b42ba0SPekka Enberg { 585b0b42ba0SPekka Enberg const char **vmlinux; 586b0b42ba0SPekka Enberg 587b0b42ba0SPekka Enberg vmlinux = &default_vmlinux[0]; 588b0b42ba0SPekka Enberg while (*vmlinux) { 589b0b42ba0SPekka Enberg struct stat st; 590b0b42ba0SPekka Enberg 591b0b42ba0SPekka Enberg if (stat(*vmlinux, &st) < 0 || !S_ISREG(st.st_mode)) { 592b0b42ba0SPekka Enberg vmlinux++; 593b0b42ba0SPekka Enberg continue; 594b0b42ba0SPekka Enberg } 595b0b42ba0SPekka Enberg return *vmlinux; 596b0b42ba0SPekka Enberg } 597b0b42ba0SPekka Enberg return NULL; 598b0b42ba0SPekka Enberg } 599b0b42ba0SPekka Enberg 600f6677a1dSAmerigo Wang void kvm_run_help(void) 601f6677a1dSAmerigo Wang { 6023b55dcdeSSasha Levin BUILD_OPTIONS(options, &kvm->cfg, kvm); 603f6677a1dSAmerigo Wang usage_with_options(run_usage, options); 604f6677a1dSAmerigo Wang } 605f6677a1dSAmerigo Wang 606afc2c7c0SAsias He static int kvm_setup_guest_init(void) 6079cec19c8SSasha Levin { 60847621338SSasha Levin const char *rootfs = kvm->cfg.custom_rootfs_name; 609afc2c7c0SAsias He char tmp[PATH_MAX]; 610afc2c7c0SAsias He size_t size; 611afc2c7c0SAsias He int fd, ret; 612afc2c7c0SAsias He char *data; 6139cec19c8SSasha Levin 614afc2c7c0SAsias He /* Setup /virt/init */ 615afc2c7c0SAsias He size = (size_t)&_binary_guest_init_size; 616afc2c7c0SAsias He data = (char *)&_binary_guest_init_start; 617afc2c7c0SAsias He snprintf(tmp, PATH_MAX, "%s%s/virt/init", kvm__get_dir(), rootfs); 618afc2c7c0SAsias He remove(tmp); 619afc2c7c0SAsias He fd = open(tmp, O_CREAT | O_WRONLY, 0755); 620afc2c7c0SAsias He if (fd < 0) 621afc2c7c0SAsias He die("Fail to setup %s", tmp); 622afc2c7c0SAsias He ret = xwrite(fd, data, size); 623afc2c7c0SAsias He if (ret < 0) 624afc2c7c0SAsias He die("Fail to setup %s", tmp); 625afc2c7c0SAsias He close(fd); 6269cec19c8SSasha Levin 627afc2c7c0SAsias He return 0; 6289cec19c8SSasha Levin } 6299cec19c8SSasha Levin 630d50fe489SSasha Levin static int kvm_run_set_sandbox(void) 631d50fe489SSasha Levin { 63247621338SSasha Levin const char *guestfs_name = kvm->cfg.custom_rootfs_name; 633d50fe489SSasha Levin char path[PATH_MAX], script[PATH_MAX], *tmp; 634d50fe489SSasha Levin 635d50fe489SSasha Levin snprintf(path, PATH_MAX, "%s%s/virt/sandbox.sh", kvm__get_dir(), guestfs_name); 636d50fe489SSasha Levin 637d50fe489SSasha Levin remove(path); 638d50fe489SSasha Levin 63947621338SSasha Levin if (kvm->cfg.sandbox == NULL) 640d50fe489SSasha Levin return 0; 641d50fe489SSasha Levin 64247621338SSasha Levin tmp = realpath(kvm->cfg.sandbox, NULL); 643d50fe489SSasha Levin if (tmp == NULL) 644d50fe489SSasha Levin return -ENOMEM; 645d50fe489SSasha Levin 646d50fe489SSasha Levin snprintf(script, PATH_MAX, "/host/%s", tmp); 647d50fe489SSasha Levin free(tmp); 648d50fe489SSasha Levin 649d50fe489SSasha Levin return symlink(script, path); 650d50fe489SSasha Levin } 651d50fe489SSasha Levin 6525173b4afSLai Jiangshan static void kvm_write_sandbox_cmd_exactly(int fd, const char *arg) 6535173b4afSLai Jiangshan { 6545173b4afSLai Jiangshan const char *single_quote; 6555173b4afSLai Jiangshan 6565173b4afSLai Jiangshan if (!*arg) { /* zero length string */ 6575173b4afSLai Jiangshan if (write(fd, "''", 2) <= 0) 6585173b4afSLai Jiangshan die("Failed writing sandbox script"); 6595173b4afSLai Jiangshan return; 6605173b4afSLai Jiangshan } 6615173b4afSLai Jiangshan 6625173b4afSLai Jiangshan while (*arg) { 6635173b4afSLai Jiangshan single_quote = strchrnul(arg, '\''); 6645173b4afSLai Jiangshan 6655173b4afSLai Jiangshan /* write non-single-quote string as #('string') */ 6665173b4afSLai Jiangshan if (arg != single_quote) { 6675173b4afSLai Jiangshan if (write(fd, "'", 1) <= 0 || 6685173b4afSLai Jiangshan write(fd, arg, single_quote - arg) <= 0 || 6695173b4afSLai Jiangshan write(fd, "'", 1) <= 0) 6705173b4afSLai Jiangshan die("Failed writing sandbox script"); 6715173b4afSLai Jiangshan } 6725173b4afSLai Jiangshan 6735173b4afSLai Jiangshan /* write single quote as #("'") */ 6745173b4afSLai Jiangshan if (*single_quote) { 6755173b4afSLai Jiangshan if (write(fd, "\"'\"", 3) <= 0) 6765173b4afSLai Jiangshan die("Failed writing sandbox script"); 6775173b4afSLai Jiangshan } else 6785173b4afSLai Jiangshan break; 6795173b4afSLai Jiangshan 6805173b4afSLai Jiangshan arg = single_quote + 1; 6815173b4afSLai Jiangshan } 6825173b4afSLai Jiangshan } 6835173b4afSLai Jiangshan 6845cd19aa0SPekka Enberg static void resolve_program(const char *src, char *dst, size_t len) 6855cd19aa0SPekka Enberg { 6865cd19aa0SPekka Enberg struct stat st; 687c2c742d9SPekka Enberg int err; 6885cd19aa0SPekka Enberg 689c2c742d9SPekka Enberg err = stat(src, &st); 6905cd19aa0SPekka Enberg 691c2c742d9SPekka Enberg if (!err && S_ISREG(st.st_mode)) { 6925cd19aa0SPekka Enberg char resolved_path[PATH_MAX]; 6935cd19aa0SPekka Enberg 694de3f75c9SPekka Enberg if (!realpath(src, resolved_path)) 695de3f75c9SPekka Enberg die("Unable to resolve program %s: %s\n", src, strerror(errno)); 6965cd19aa0SPekka Enberg 6975cd19aa0SPekka Enberg snprintf(dst, len, "/host%s", resolved_path); 6985cd19aa0SPekka Enberg } else 6995cd19aa0SPekka Enberg strncpy(dst, src, len); 7005cd19aa0SPekka Enberg } 7015cd19aa0SPekka Enberg 7023c29e2aaSSasha Levin static void kvm_run_write_sandbox_cmd(const char **argv, int argc) 7033c29e2aaSSasha Levin { 7043c29e2aaSSasha Levin const char script_hdr[] = "#! /bin/bash\n\n"; 7055cd19aa0SPekka Enberg char program[PATH_MAX]; 7063c29e2aaSSasha Levin int fd; 7073c29e2aaSSasha Levin 70847621338SSasha Levin remove(kvm->cfg.sandbox); 7093c29e2aaSSasha Levin 71047621338SSasha Levin fd = open(kvm->cfg.sandbox, O_RDWR | O_CREAT, 0777); 7113c29e2aaSSasha Levin if (fd < 0) 7123c29e2aaSSasha Levin die("Failed creating sandbox script"); 7133c29e2aaSSasha Levin 7143c29e2aaSSasha Levin if (write(fd, script_hdr, sizeof(script_hdr) - 1) <= 0) 7153c29e2aaSSasha Levin die("Failed writing sandbox script"); 7163c29e2aaSSasha Levin 7175cd19aa0SPekka Enberg resolve_program(argv[0], program, PATH_MAX); 7185cd19aa0SPekka Enberg kvm_write_sandbox_cmd_exactly(fd, program); 7195cd19aa0SPekka Enberg 7205cd19aa0SPekka Enberg argv++; 7215cd19aa0SPekka Enberg argc--; 7225cd19aa0SPekka Enberg 7233c29e2aaSSasha Levin while (argc) { 7243c29e2aaSSasha Levin if (write(fd, " ", 1) <= 0) 7253c29e2aaSSasha Levin die("Failed writing sandbox script"); 7265cd19aa0SPekka Enberg 7275cd19aa0SPekka Enberg kvm_write_sandbox_cmd_exactly(fd, argv[0]); 7283c29e2aaSSasha Levin argv++; 7293c29e2aaSSasha Levin argc--; 7303c29e2aaSSasha Levin } 7313c29e2aaSSasha Levin if (write(fd, "\n", 1) <= 0) 7323c29e2aaSSasha Levin die("Failed writing sandbox script"); 7333c29e2aaSSasha Levin 7343c29e2aaSSasha Levin close(fd); 7353c29e2aaSSasha Levin } 7363c29e2aaSSasha Levin 737e1e46fe6SSasha Levin static int kvm_cmd_run_init(int argc, const char **argv) 738f967c427SPrasad Joshi { 7392d96f6b6SSasha Levin static char real_cmdline[2048], default_name[20]; 740aba1efa5SPekka Enberg struct framebuffer *fb = NULL; 741384922b3SPekka Enberg unsigned int nr_online_cpus; 7424932d174SSasha Levin int i, r; 74347621338SSasha Levin 74447621338SSasha Levin kvm = kvm__new(); 74547621338SSasha Levin if (IS_ERR(kvm)) 74647621338SSasha Levin return PTR_ERR(kvm); 747f967c427SPrasad Joshi 7485ee154d1SPekka Enberg signal(SIGALRM, handle_sigalrm); 7494b1addaeSSasha Levin kvm_ipc__register_handler(KVM_IPC_DEBUG, handle_debug); 75043119af7SPekka Enberg signal(SIGUSR1, handle_sigusr1); 7514b1addaeSSasha Levin kvm_ipc__register_handler(KVM_IPC_PAUSE, handle_pause); 7524b1addaeSSasha Levin kvm_ipc__register_handler(KVM_IPC_RESUME, handle_pause); 7534b1addaeSSasha Levin kvm_ipc__register_handler(KVM_IPC_STOP, handle_stop); 7547021c50bSAsias He kvm_ipc__register_handler(KVM_IPC_VMSTATE, handle_vmstate); 755f967c427SPrasad Joshi 756cfd63bbbSSasha Levin nr_online_cpus = sysconf(_SC_NPROCESSORS_ONLN); 75747621338SSasha Levin kvm->cfg.custom_rootfs_name = "default"; 758cfd63bbbSSasha Levin 759f967c427SPrasad Joshi while (argc != 0) { 7603b55dcdeSSasha Levin BUILD_OPTIONS(options, &kvm->cfg, kvm); 761f967c427SPrasad Joshi argc = parse_options(argc, argv, options, run_usage, 7621a007c82SSasha Levin PARSE_OPT_STOP_AT_NON_OPTION | 7631a007c82SSasha Levin PARSE_OPT_KEEP_DASHDASH); 764f967c427SPrasad Joshi if (argc != 0) { 7651a007c82SSasha Levin /* Cusrom options, should have been handled elsewhere */ 7663c29e2aaSSasha Levin if (strcmp(argv[0], "--") == 0) { 7673c29e2aaSSasha Levin if (kvm_run_wrapper == KVM_RUN_SANDBOX) { 76847621338SSasha Levin kvm->cfg.sandbox = DEFAULT_SANDBOX_FILENAME; 7693c29e2aaSSasha Levin kvm_run_write_sandbox_cmd(argv+1, argc-1); 7701a007c82SSasha Levin break; 7713c29e2aaSSasha Levin } 7723c29e2aaSSasha Levin } 7731a007c82SSasha Levin 77447621338SSasha Levin if ((kvm_run_wrapper == KVM_RUN_DEFAULT && kvm->cfg.kernel_filename) || 77547621338SSasha Levin (kvm_run_wrapper == KVM_RUN_SANDBOX && kvm->cfg.sandbox)) { 776f967c427SPrasad Joshi fprintf(stderr, "Cannot handle parameter: " 777f967c427SPrasad Joshi "%s\n", argv[0]); 778f967c427SPrasad Joshi usage_with_options(run_usage, options); 77947621338SSasha Levin free(kvm); 780e120b624SPaul Neumann return -EINVAL; 781f967c427SPrasad Joshi } 782e0747665SSasha Levin if (kvm_run_wrapper == KVM_RUN_SANDBOX) { 783e0747665SSasha Levin /* 784e0747665SSasha Levin * first unhandled parameter is treated as 785e0747665SSasha Levin * sandbox command 786e0747665SSasha Levin */ 78747621338SSasha Levin kvm->cfg.sandbox = DEFAULT_SANDBOX_FILENAME; 788e0747665SSasha Levin kvm_run_write_sandbox_cmd(argv, argc); 789e0747665SSasha Levin } else { 790e0747665SSasha Levin /* 791e0747665SSasha Levin * first unhandled parameter is treated as a kernel 792e0747665SSasha Levin * image 793f967c427SPrasad Joshi */ 79447621338SSasha Levin kvm->cfg.kernel_filename = argv[0]; 795e0747665SSasha Levin } 796f967c427SPrasad Joshi argv++; 797f967c427SPrasad Joshi argc--; 798f967c427SPrasad Joshi } 799f967c427SPrasad Joshi 800f967c427SPrasad Joshi } 801f967c427SPrasad Joshi 8023b55dcdeSSasha Levin kvm->nr_disks = kvm->cfg.image_count; 8033b55dcdeSSasha Levin 80447621338SSasha Levin if (!kvm->cfg.kernel_filename) 80547621338SSasha Levin kvm->cfg.kernel_filename = find_kernel(); 8068329f30bSPekka Enberg 80747621338SSasha Levin if (!kvm->cfg.kernel_filename) { 808e08c0896SPrasad Joshi kernel_usage_with_options(); 809e120b624SPaul Neumann return -EINVAL; 8108329f30bSPekka Enberg } 8118329f30bSPekka Enberg 81247621338SSasha Levin kvm->cfg.vmlinux_filename = find_vmlinux(); 813b0b42ba0SPekka Enberg 81400ebbe96SSasha Levin if (kvm->cfg.nrcpus == 0) 81500ebbe96SSasha Levin kvm->cfg.nrcpus = nr_online_cpus; 816d77a9efaSCyrill Gorcunov 81747621338SSasha Levin if (!kvm->cfg.ram_size) 81800ebbe96SSasha Levin kvm->cfg.ram_size = get_ram_size(kvm->cfg.nrcpus); 819fd834defSPekka Enberg 82047621338SSasha Levin if (kvm->cfg.ram_size < MIN_RAM_SIZE_MB) 82147621338SSasha Levin die("Not enough memory specified: %lluMB (min %lluMB)", kvm->cfg.ram_size, MIN_RAM_SIZE_MB); 822a2a002f9SIngo Molnar 82347621338SSasha Levin if (kvm->cfg.ram_size > host_ram_size()) 82447621338SSasha Levin pr_warning("Guest memory size %lluMB exceeds host physical RAM size %lluMB", kvm->cfg.ram_size, host_ram_size()); 82560ded003SPekka Enberg 82647621338SSasha Levin kvm->cfg.ram_size <<= MB_SHIFT; 827f967c427SPrasad Joshi 82847621338SSasha Levin if (!kvm->cfg.dev) 82947621338SSasha Levin kvm->cfg.dev = DEFAULT_KVM_DEV; 830f967c427SPrasad Joshi 83147621338SSasha Levin if (!kvm->cfg.console) 83247621338SSasha Levin kvm->cfg.console = DEFAULT_CONSOLE; 8339aa4a0ebSAsias He 83447621338SSasha Levin if (!strncmp(kvm->cfg.console, "virtio", 6)) 8352651ea58SSasha Levin kvm->cfg.active_console = CONSOLE_VIRTIO; 83647621338SSasha Levin else if (!strncmp(kvm->cfg.console, "serial", 6)) 8372651ea58SSasha Levin kvm->cfg.active_console = CONSOLE_8250; 83847621338SSasha Levin else if (!strncmp(kvm->cfg.console, "hv", 2)) 8392651ea58SSasha Levin kvm->cfg.active_console = CONSOLE_HV; 8403bbc49b6SMatt Evans else 8413bbc49b6SMatt Evans pr_warning("No console!"); 842f967c427SPrasad Joshi 84347621338SSasha Levin if (!kvm->cfg.host_ip) 84447621338SSasha Levin kvm->cfg.host_ip = DEFAULT_HOST_ADDR; 8454d67c820SSasha Levin 84647621338SSasha Levin if (!kvm->cfg.guest_ip) 84747621338SSasha Levin kvm->cfg.guest_ip = DEFAULT_GUEST_ADDR; 848bb8ffd2fSAsias He 84947621338SSasha Levin if (!kvm->cfg.guest_mac) 85047621338SSasha Levin kvm->cfg.guest_mac = DEFAULT_GUEST_MAC; 851a4e724ddSSasha Levin 85247621338SSasha Levin if (!kvm->cfg.host_mac) 85347621338SSasha Levin kvm->cfg.host_mac = DEFAULT_HOST_MAC; 854d7098b9bSAsias He 85547621338SSasha Levin if (!kvm->cfg.script) 85647621338SSasha Levin kvm->cfg.script = DEFAULT_SCRIPT; 85773b7d038SAmos Kong 858dca745e4SSasha Levin r = term_init(kvm); 859dca745e4SSasha Levin if (r < 0) { 860dca745e4SSasha Levin pr_err("term_init() failed with error %d\n", r); 861dca745e4SSasha Levin goto fail; 862dca745e4SSasha Levin } 863f967c427SPrasad Joshi 86447621338SSasha Levin if (!kvm->cfg.guest_name) { 86547621338SSasha Levin if (kvm->cfg.custom_rootfs) { 86647621338SSasha Levin kvm->cfg.guest_name = kvm->cfg.custom_rootfs_name; 867587a4d17SLai Jiangshan } else { 8682d96f6b6SSasha Levin sprintf(default_name, "guest-%u", getpid()); 86947621338SSasha Levin kvm->cfg.guest_name = default_name; 8702d96f6b6SSasha Levin } 871587a4d17SLai Jiangshan } 8722d96f6b6SSasha Levin 87347621338SSasha Levin r = kvm__init(kvm); 87447621338SSasha Levin if (r) 875d648dbf5SCyrill Gorcunov goto fail; 876f967c427SPrasad Joshi 877ea6eeb1cSSasha Levin r = ioeventfd__init(kvm); 878ea6eeb1cSSasha Levin if (r < 0) { 879ea6eeb1cSSasha Levin pr_err("ioeventfd__init() failed with error %d\n", r); 880ea6eeb1cSSasha Levin goto fail; 881ea6eeb1cSSasha Levin } 88237f3d50eSSasha Levin 883df4239fbSSasha Levin r = kvm_cpu__init(kvm); 884df4239fbSSasha Levin if (r < 0) { 885df4239fbSSasha Levin pr_err("kvm_cpu__init() failed with error %d\n", r); 886df4239fbSSasha Levin goto fail; 887384922b3SPekka Enberg } 888384922b3SPekka Enberg 889e3c4f8aaSSasha Levin r = irq__init(kvm); 890e3c4f8aaSSasha Levin if (r < 0) { 891e3c4f8aaSSasha Levin pr_err("irq__init() failed with error %d\n", r); 892e3c4f8aaSSasha Levin goto fail; 893e3c4f8aaSSasha Levin } 89419e6c8b8SMatt Evans 8956d987703SSasha Levin r = pci__init(kvm); 8966d987703SSasha Levin if (r < 0) { 8976d987703SSasha Levin pr_err("pci__init() failed with error %d\n", r); 8986d987703SSasha Levin goto fail; 8996d987703SSasha Levin } 900b91be965SMatt Evans 9017af40b91SSasha Levin r = ioport__init(kvm); 9027af40b91SSasha Levin if (r < 0) { 9037af40b91SSasha Levin pr_err("ioport__init() failed with error %d\n", r); 9047af40b91SSasha Levin goto fail; 9057af40b91SSasha Levin } 9067af40b91SSasha Levin 907890364f8SCyrill Gorcunov /* 908890364f8SCyrill Gorcunov * vidmode should be either specified 909890364f8SCyrill Gorcunov * either set by default 910890364f8SCyrill Gorcunov */ 91147621338SSasha Levin if (kvm->cfg.vnc || kvm->cfg.sdl) { 912890364f8SCyrill Gorcunov if (vidmode == -1) 913890364f8SCyrill Gorcunov vidmode = 0x312; 91448d9e01aSSasha Levin } else { 915890364f8SCyrill Gorcunov vidmode = 0; 91648d9e01aSSasha Levin } 917890364f8SCyrill Gorcunov 91826c853e4SPrasad Joshi memset(real_cmdline, 0, sizeof(real_cmdline)); 91947621338SSasha Levin kvm__arch_set_cmdline(real_cmdline, kvm->cfg.vnc || kvm->cfg.sdl); 9208e704a7aSMatt Evans 9218e704a7aSMatt Evans if (strlen(real_cmdline) > 0) 922d74181ccSSasha Levin strcat(real_cmdline, " "); 9238e704a7aSMatt Evans 92447621338SSasha Levin if (kvm->cfg.kernel_cmdline) 92547621338SSasha Levin strlcat(real_cmdline, kvm->cfg.kernel_cmdline, sizeof(real_cmdline)); 92626c853e4SPrasad Joshi 92747621338SSasha Levin if (!kvm->cfg.using_rootfs && !kvm->cfg.disk_image[0].filename && !kvm->cfg.initrd_filename) { 928c8675741SSasha Levin char tmp[PATH_MAX]; 9296df1471eSPekka Enberg 93047621338SSasha Levin kvm_setup_create_new(kvm->cfg.custom_rootfs_name); 93147621338SSasha Levin kvm_setup_resolv(kvm->cfg.custom_rootfs_name); 932c8675741SSasha Levin 9339667701cSPekka Enberg snprintf(tmp, PATH_MAX, "%s%s", kvm__get_dir(), "default"); 934c8675741SSasha Levin if (virtio_9p__register(kvm, tmp, "/dev/root") < 0) 935c8675741SSasha Levin die("Unable to initialize virtio 9p"); 936c8675741SSasha Levin if (virtio_9p__register(kvm, "/", "hostfs") < 0) 937c8675741SSasha Levin die("Unable to initialize virtio 9p"); 93847621338SSasha Levin kvm->cfg.using_rootfs = kvm->cfg.custom_rootfs = 1; 93926c853e4SPrasad Joshi } 94026c853e4SPrasad Joshi 94147621338SSasha Levin if (kvm->cfg.using_rootfs) { 942ff42603fSSasha Levin strcat(real_cmdline, " root=/dev/root rw rootflags=rw,trans=virtio,version=9p2000.L rootfstype=9p"); 94347621338SSasha Levin if (kvm->cfg.custom_rootfs) { 944d50fe489SSasha Levin kvm_run_set_sandbox(); 945d50fe489SSasha Levin 946a8e6b4b9SSasha Levin strcat(real_cmdline, " init=/virt/init"); 947d50fe489SSasha Levin 94847621338SSasha Levin if (!kvm->cfg.no_dhcp) 949a8e6b4b9SSasha Levin strcat(real_cmdline, " ip=dhcp"); 950afc2c7c0SAsias He if (kvm_setup_guest_init()) 951afc2c7c0SAsias He die("Failed to setup init for guest."); 952a8e6b4b9SSasha Levin } 95382d65b5eSSasha Levin } else if (!strstr(real_cmdline, "root=")) { 954ff42603fSSasha Levin strlcat(real_cmdline, " root=/dev/vda rw ", sizeof(real_cmdline)); 95582d65b5eSSasha Levin } 95659aa2d30SSasha Levin 9573b55dcdeSSasha Levin r = disk_image__init(kvm); 9583b55dcdeSSasha Levin if (r < 0) { 9593b55dcdeSSasha Levin pr_err("disk_image__init() failed with error %d\n", r); 9609f9207c5SSasha Levin goto fail; 9619f9207c5SSasha Levin } 962c1ed214eSPrasad Joshi 963ee8b1456SWanlong Gao printf(" # %s run -k %s -m %Lu -c %d --name %s\n", KVM_BINARY_NAME, 96400ebbe96SSasha Levin kvm->cfg.kernel_filename, kvm->cfg.ram_size / 1024 / 1024, kvm->cfg.nrcpus, kvm->cfg.guest_name); 965471c6facSPekka Enberg 96647621338SSasha Levin if (!kvm->cfg.firmware_filename) { 96747621338SSasha Levin if (!kvm__load_kernel(kvm, kvm->cfg.kernel_filename, 96847621338SSasha Levin kvm->cfg.initrd_filename, real_cmdline, vidmode)) 96947621338SSasha Levin die("unable to load kernel %s", kvm->cfg.kernel_filename); 970f967c427SPrasad Joshi 97147621338SSasha Levin kvm->vmlinux = kvm->cfg.vmlinux_filename; 972807b77b9SCyrill Gorcunov r = symbol_init(kvm); 973b56f1728SCyrill Gorcunov if (r < 0) 974c4b716ecSPekka Enberg pr_debug("symbol_init() failed with error %d\n", r); 9755ad8db5eSPekka Enberg } 976b0b42ba0SPekka Enberg 977af7b0868SMatt Evans ioport__setup_arch(); 978ac38f433SPekka Enberg 97920c39545SSasha Levin r = rtc__init(kvm); 98020c39545SSasha Levin if (r < 0) { 98120c39545SSasha Levin pr_err("rtc__init() failed with error %d\n", r); 98220c39545SSasha Levin goto fail; 98320c39545SSasha Levin } 98464136c1cSPekka Enberg 98520715a22SSasha Levin r = serial8250__init(kvm); 98620715a22SSasha Levin if (r < 0) { 98720715a22SSasha Levin pr_err("serial__init() failed with error %d\n", r); 98820715a22SSasha Levin goto fail; 98920715a22SSasha Levin } 990f967c427SPrasad Joshi 9919f9207c5SSasha Levin r = virtio_blk__init(kvm); 9929f9207c5SSasha Levin if (r < 0) { 9939f9207c5SSasha Levin pr_err("virtio_blk__init() failed with error %d\n", r); 9949f9207c5SSasha Levin goto fail; 9959f9207c5SSasha Levin } 9969f9207c5SSasha Levin 997a67da3beSAsias He r = virtio_scsi_init(kvm); 998a67da3beSAsias He if (r < 0) { 999a67da3beSAsias He pr_err("virtio_scsi_init() failed with error %d\n", r); 1000a67da3beSAsias He goto fail; 1001a67da3beSAsias He } 1002a67da3beSAsias He 1003a3fa3f86SSasha Levin r = virtio_console__init(kvm); 1004a3fa3f86SSasha Levin if (r < 0) { 1005a3fa3f86SSasha Levin pr_err("virtio_console__init() failed with error %d\n", r); 1006a3fa3f86SSasha Levin goto fail; 1007a3fa3f86SSasha Levin } 1008f967c427SPrasad Joshi 1009f16653adSSasha Levin r = virtio_rng__init(kvm); 1010f16653adSSasha Levin if (r < 0) { 1011f16653adSSasha Levin pr_err("virtio_rng__init() failed with error %d\n", r); 1012f16653adSSasha Levin goto fail; 1013f16653adSSasha Levin } 101453eca082SSasha Levin 1015d06db2fdSSasha Levin r = virtio_bln__init(kvm); 1016d06db2fdSSasha Levin if (r < 0) { 1017d06db2fdSSasha Levin pr_err("virtio_rng__init() failed with error %d\n", r); 1018d06db2fdSSasha Levin goto fail; 1019d06db2fdSSasha Levin } 102082d2f21eSSasha Levin 102147621338SSasha Levin if (!kvm->cfg.network) 102247621338SSasha Levin kvm->cfg.network = DEFAULT_NETWORK; 10234f56d42cSAsias He 1024c7838fbdSSasha Levin virtio_9p__init(kvm); 1025c7838fbdSSasha Levin 102647621338SSasha Levin for (i = 0; i < kvm->cfg.num_net_devices; i++) { 102747621338SSasha Levin kvm->cfg.net_params[i].kvm = kvm; 102847621338SSasha Levin virtio_net__init(&kvm->cfg.net_params[i]); 10299a6d73f1SSasha Levin } 1030a4e724ddSSasha Levin 103147621338SSasha Levin if (kvm->cfg.num_net_devices == 0 && kvm->cfg.no_net == 0) { 10329a6d73f1SSasha Levin struct virtio_net_params net_params; 10339a6d73f1SSasha Levin 10349a6d73f1SSasha Levin net_params = (struct virtio_net_params) { 103547621338SSasha Levin .guest_ip = kvm->cfg.guest_ip, 103647621338SSasha Levin .host_ip = kvm->cfg.host_ip, 10379a6d73f1SSasha Levin .kvm = kvm, 103847621338SSasha Levin .script = kvm->cfg.script, 10399a6d73f1SSasha Levin .mode = NET_MODE_USER, 10409a6d73f1SSasha Levin }; 104147621338SSasha Levin str_to_mac(kvm->cfg.guest_mac, net_params.guest_mac); 104247621338SSasha Levin str_to_mac(kvm->cfg.host_mac, net_params.host_mac); 10439a6d73f1SSasha Levin 1044bdfcfca6SSasha Levin virtio_net__init(&net_params); 1045bdfcfca6SSasha Levin } 10464f56d42cSAsias He 1047839051d9SSasha Levin kvm__init_ram(kvm); 1048839051d9SSasha Levin 104957d7832bSMatt Evans #ifdef CONFIG_X86 1050714e5b7fSSasha Levin kbd__init(kvm); 105157d7832bSMatt Evans #endif 1052714e5b7fSSasha Levin 1053*8cec93dbSSasha Levin r = pci_shmem__init(kvm); 1054*8cec93dbSSasha Levin if (r < 0) { 1055*8cec93dbSSasha Levin pr_err("pci_shmem__init() failed with error %d\n", r); 1056*8cec93dbSSasha Levin goto fail; 1057*8cec93dbSSasha Levin } 105895d13a52SSasha Levin 105947621338SSasha Levin if (kvm->cfg.vnc || kvm->cfg.sdl) { 10603f838fecSPekka Enberg fb = vesa__init(kvm); 106148d9e01aSSasha Levin if (IS_ERR(fb)) { 106248d9e01aSSasha Levin pr_err("vesa__init() failed with error %ld\n", PTR_ERR(fb)); 106348d9e01aSSasha Levin goto fail; 106448d9e01aSSasha Levin } 10653f838fecSPekka Enberg } 10663f838fecSPekka Enberg 106747621338SSasha Levin if (kvm->cfg.vnc && fb) { 106848d9e01aSSasha Levin r = vnc__init(fb); 106948d9e01aSSasha Levin if (r < 0) { 107048d9e01aSSasha Levin pr_err("vnc__init() failed with error %d\n", r); 107148d9e01aSSasha Levin goto fail; 107248d9e01aSSasha Levin } 107348d9e01aSSasha Levin } 107448d9e01aSSasha Levin 107547621338SSasha Levin if (kvm->cfg.sdl && fb) { 10763f838fecSPekka Enberg sdl__init(fb); 107748d9e01aSSasha Levin if (r < 0) { 107848d9e01aSSasha Levin pr_err("sdl__init() failed with error %d\n", r); 107948d9e01aSSasha Levin goto fail; 108048d9e01aSSasha Levin } 10813f838fecSPekka Enberg } 1082aba1efa5SPekka Enberg 1083ba46fe53SSasha Levin r = fb__init(kvm); 108448d9e01aSSasha Levin if (r < 0) { 108548d9e01aSSasha Levin pr_err("fb__init() failed with error %d\n", r); 108648d9e01aSSasha Levin goto fail; 108748d9e01aSSasha Levin } 1088aba1efa5SPekka Enberg 1089df4239fbSSasha Levin /* 1090df4239fbSSasha Levin * Device init all done; firmware init must 109125af47eeSMatt Evans * come after this (it may set up device trees etc.) 109225af47eeSMatt Evans */ 109325af47eeSMatt Evans 1094b4532ca9SSasha Levin r = kvm_timer__init(kvm); 1095b4532ca9SSasha Levin if (r < 0) { 1096b4532ca9SSasha Levin pr_err("kvm_timer__init() failed with error %d\n", r); 1097b4532ca9SSasha Levin goto fail; 1098b4532ca9SSasha Levin } 109925af47eeSMatt Evans 110047621338SSasha Levin if (kvm->cfg.firmware_filename) { 110147621338SSasha Levin if (!kvm__load_firmware(kvm, kvm->cfg.firmware_filename)) 110247621338SSasha Levin die("unable to load firmware image %s: %s", kvm->cfg.firmware_filename, strerror(errno)); 11035ad8db5eSPekka Enberg } else { 1104e1e46fe6SSasha Levin kvm__arch_setup_firmware(kvm); 11051add9f73SSasha Levin if (r < 0) { 11061add9f73SSasha Levin pr_err("kvm__arch_setup_firmware() failed with error %d\n", r); 11071add9f73SSasha Levin goto fail; 11081add9f73SSasha Levin } 11095ad8db5eSPekka Enberg } 111025af47eeSMatt Evans 1111f6a3c571SSasha Levin r = thread_pool__init(kvm); 1112f6a3c571SSasha Levin if (r < 0) { 1113f6a3c571SSasha Levin pr_err("thread_pool__init() failed with error %d\n", r); 1114f6a3c571SSasha Levin goto fail; 1115f6a3c571SSasha Levin } 1116f6a3c571SSasha Levin 11174932d174SSasha Levin fail: 11184932d174SSasha Levin return r; 1119e1e46fe6SSasha Levin } 1120e1e46fe6SSasha Levin 1121e1e46fe6SSasha Levin static int kvm_cmd_run_work(void) 1122e1e46fe6SSasha Levin { 1123df4239fbSSasha Levin int i; 1124e1e46fe6SSasha Levin void *ret = NULL; 1125e1e46fe6SSasha Levin 112600ebbe96SSasha Levin for (i = 0; i < kvm->nrcpus; i++) { 1127df4239fbSSasha Levin if (pthread_create(&kvm->cpus[i]->thread, NULL, kvm_cpu_thread, kvm->cpus[i]) != 0) 11285ee154d1SPekka Enberg die("unable to create KVM VCPU thread"); 11295ee154d1SPekka Enberg } 11305ee154d1SPekka Enberg 113149e5227dSSasha Levin /* Only VCPU #0 is going to exit by itself when shutting down */ 1132df4239fbSSasha Levin return pthread_join(kvm->cpus[0]->thread, &ret); 1133e1e46fe6SSasha Levin } 1134e1e46fe6SSasha Levin 11354932d174SSasha Levin static void kvm_cmd_run_exit(int guest_ret) 1136e1e46fe6SSasha Levin { 11374932d174SSasha Levin int r = 0; 11384932d174SSasha Levin 1139e6694207SSasha Levin compat__print_all_messages(); 1140e6694207SSasha Levin 1141df4239fbSSasha Levin r = kvm_cpu__exit(kvm); 1142df4239fbSSasha Levin if (r < 0) 1143df4239fbSSasha Levin pr_warning("kvm_cpu__exit() failed with error %d\n", r); 1144df4239fbSSasha Levin 1145807b77b9SCyrill Gorcunov r = symbol_exit(kvm); 11464932d174SSasha Levin if (r < 0) 1147807b77b9SCyrill Gorcunov pr_warning("symbol_exit() failed with error %d\n", r); 11484932d174SSasha Levin 1149e3c4f8aaSSasha Levin r = irq__exit(kvm); 1150e3c4f8aaSSasha Levin if (r < 0) 1151e3c4f8aaSSasha Levin pr_warning("irq__exit() failed with error %d\n", r); 1152e3c4f8aaSSasha Levin 1153b4532ca9SSasha Levin r = kvm_timer__exit(kvm); 1154b4532ca9SSasha Levin if (r < 0) 1155b4532ca9SSasha Levin pr_warning("kvm_timer__exit() failed with error %d\n", r); 1156b4532ca9SSasha Levin 1157ba46fe53SSasha Levin r = fb__exit(kvm); 1158ba46fe53SSasha Levin if (r < 0) 1159b4532ca9SSasha Levin pr_warning("kvm_timer__exit() failed with error %d\n", r); 1160aba1efa5SPekka Enberg 1161a67da3beSAsias He r = virtio_scsi_exit(kvm); 1162a67da3beSAsias He if (r < 0) 1163a67da3beSAsias He pr_warning("virtio_scsi_exit() failed with error %d\n", r); 1164a67da3beSAsias He 11659f9207c5SSasha Levin r = virtio_blk__exit(kvm); 11669f9207c5SSasha Levin if (r < 0) 11679f9207c5SSasha Levin pr_warning("virtio_blk__exit() failed with error %d\n", r); 11689f9207c5SSasha Levin 1169495fbd4eSSasha Levin r = virtio_rng__exit(kvm); 1170495fbd4eSSasha Levin if (r < 0) 1171495fbd4eSSasha Levin pr_warning("virtio_rng__exit() failed with error %d\n", r); 1172a0a1e3c2SPrasad Joshi 1173d06db2fdSSasha Levin r = virtio_bln__exit(kvm); 1174d06db2fdSSasha Levin if (r < 0) 1175d06db2fdSSasha Levin pr_warning("virtio_bln__exit() failed with error %d\n", r); 1176d06db2fdSSasha Levin 1177a3fa3f86SSasha Levin r = virtio_console__exit(kvm); 1178a3fa3f86SSasha Levin if (r < 0) 1179a3fa3f86SSasha Levin pr_warning("virtio_console__exit() failed with error %d\n", r); 1180a3fa3f86SSasha Levin 1181*8cec93dbSSasha Levin r = pci_shmem__exit(kvm); 1182*8cec93dbSSasha Levin if (r < 0) 1183*8cec93dbSSasha Levin pr_warning("pci_shmem__exit() failed with error %d\n", r); 1184*8cec93dbSSasha Levin 11853b55dcdeSSasha Levin r = disk_image__exit(kvm); 11869f9207c5SSasha Levin if (r < 0) 11873b55dcdeSSasha Levin pr_warning("disk_image__exit() failed with error %d\n", r); 11887af40b91SSasha Levin 118920715a22SSasha Levin r = serial8250__exit(kvm); 119020715a22SSasha Levin if (r < 0) 119120715a22SSasha Levin pr_warning("serial8250__exit() failed with error %d\n", r); 119220715a22SSasha Levin 119320c39545SSasha Levin r = rtc__exit(kvm); 119420c39545SSasha Levin if (r < 0) 119520c39545SSasha Levin pr_warning("rtc__exit() failed with error %d\n", r); 119620c39545SSasha Levin 11971add9f73SSasha Levin r = kvm__arch_free_firmware(kvm); 11981add9f73SSasha Levin if (r < 0) 11991add9f73SSasha Levin pr_warning("kvm__arch_free_firmware() failed with error %d\n", r); 12001add9f73SSasha Levin 12017af40b91SSasha Levin r = ioport__exit(kvm); 12027af40b91SSasha Levin if (r < 0) 12037af40b91SSasha Levin pr_warning("ioport__exit() failed with error %d\n", r); 12047af40b91SSasha Levin 1205ea6eeb1cSSasha Levin r = ioeventfd__exit(kvm); 1206ea6eeb1cSSasha Levin if (r < 0) 1207ea6eeb1cSSasha Levin pr_warning("ioeventfd__exit() failed with error %d\n", r); 1208ea6eeb1cSSasha Levin 12096d987703SSasha Levin r = pci__exit(kvm); 12106d987703SSasha Levin if (r < 0) 12116d987703SSasha Levin pr_warning("pci__exit() failed with error %d\n", r); 12126d987703SSasha Levin 1213dca745e4SSasha Levin r = term_exit(kvm); 1214dca745e4SSasha Levin if (r < 0) 1215dca745e4SSasha Levin pr_warning("pci__exit() failed with error %d\n", r); 1216dca745e4SSasha Levin 1217f6a3c571SSasha Levin r = thread_pool__exit(kvm); 1218f6a3c571SSasha Levin if (r < 0) 1219f6a3c571SSasha Levin pr_warning("thread_pool__exit() failed with error %d\n", r); 1220f6a3c571SSasha Levin 1221495fbd4eSSasha Levin r = kvm__exit(kvm); 1222495fbd4eSSasha Levin if (r < 0) 1223495fbd4eSSasha Levin pr_warning("pci__exit() failed with error %d\n", r); 1224f967c427SPrasad Joshi 1225e1e46fe6SSasha Levin if (guest_ret == 0) 1226f967c427SPrasad Joshi printf("\n # KVM session ended normally.\n"); 1227e1e46fe6SSasha Levin } 1228e1e46fe6SSasha Levin 1229e1e46fe6SSasha Levin int kvm_cmd_run(int argc, const char **argv, const char *prefix) 1230e1e46fe6SSasha Levin { 12314932d174SSasha Levin int r, ret = -EFAULT; 1232e1e46fe6SSasha Levin 1233e1e46fe6SSasha Levin r = kvm_cmd_run_init(argc, argv); 1234e1e46fe6SSasha Levin if (r < 0) 1235e1e46fe6SSasha Levin return r; 1236e1e46fe6SSasha Levin 1237e1e46fe6SSasha Levin ret = kvm_cmd_run_work(); 1238e1e46fe6SSasha Levin kvm_cmd_run_exit(ret); 1239e1e46fe6SSasha Levin 1240e1e46fe6SSasha Levin return ret; 1241f967c427SPrasad Joshi } 1242