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 1493b55dcdeSSasha Levin #define BUILD_OPTIONS(name, cfg, kvm) \ 150b816364aSSasha Levin struct option name[] = { \ 151b816364aSSasha Levin OPT_GROUP("Basic options:"), \ 152b816364aSSasha Levin OPT_STRING('\0', "name", &(cfg)->guest_name, "guest name", \ 153b816364aSSasha Levin "A name for the guest"), \ 15400ebbe96SSasha Levin OPT_INTEGER('c', "cpus", &(cfg)->nrcpus, "Number of CPUs"), \ 155b816364aSSasha Levin OPT_U64('m', "mem", &(cfg)->ram_size, "Virtual machine memory size\ 156b816364aSSasha Levin in MiB."), \ 157b816364aSSasha Levin OPT_CALLBACK('\0', "shmem", NULL, \ 158b816364aSSasha Levin "[pci:]<addr>:<size>[:handle=<handle>][:create]", \ 159b816364aSSasha Levin "Share host shmem with guest via pci device", \ 1601dc24dccSSasha Levin shmem_parser, NULL), \ 1611dc24dccSSasha Levin OPT_CALLBACK('d', "disk", kvm, "image or rootfs_dir", "Disk \ 1621dc24dccSSasha Levin image or rootfs directory", img_name_parser, \ 1633b55dcdeSSasha Levin kvm), \ 164b816364aSSasha Levin OPT_BOOLEAN('\0', "balloon", &(cfg)->balloon, "Enable virtio \ 165b816364aSSasha Levin balloon"), \ 166b816364aSSasha Levin OPT_BOOLEAN('\0', "vnc", &(cfg)->vnc, "Enable VNC framebuffer"),\ 167b816364aSSasha Levin OPT_BOOLEAN('\0', "sdl", &(cfg)->sdl, "Enable SDL framebuffer"),\ 168b816364aSSasha Levin OPT_BOOLEAN('\0', "rng", &(cfg)->virtio_rng, "Enable virtio Random\ 169b816364aSSasha Levin Number Generator"), \ 170b816364aSSasha Levin OPT_CALLBACK('\0', "9p", NULL, "dir_to_share,tag_name", \ 171b816364aSSasha Levin "Enable virtio 9p to share files between host and \ 1721dc24dccSSasha Levin guest", virtio_9p_rootdir_parser, NULL), \ 173b816364aSSasha Levin OPT_STRING('\0', "console", &(cfg)->console, "serial, virtio or \ 174b816364aSSasha Levin hv", "Console to use"), \ 175b816364aSSasha Levin OPT_STRING('\0', "dev", &(cfg)->dev, "device_file", \ 176b816364aSSasha Levin "KVM device file"), \ 177b816364aSSasha Levin OPT_CALLBACK('\0', "tty", NULL, "tty id", \ 178b816364aSSasha Levin "Remap guest TTY into a pty on the host", \ 1791dc24dccSSasha Levin tty_parser, NULL), \ 180b816364aSSasha Levin OPT_STRING('\0', "sandbox", &(cfg)->sandbox, "script", \ 181b816364aSSasha Levin "Run this script when booting into custom \ 182b816364aSSasha Levin rootfs"), \ 183b816364aSSasha Levin OPT_STRING('\0', "hugetlbfs", &(cfg)->hugetlbfs_path, "path", \ 184b816364aSSasha Levin "Hugetlbfs path"), \ 185b816364aSSasha Levin \ 186b816364aSSasha Levin OPT_GROUP("Kernel options:"), \ 187b816364aSSasha Levin OPT_STRING('k', "kernel", &(cfg)->kernel_filename, "kernel", \ 188b816364aSSasha Levin "Kernel to boot in virtual machine"), \ 189b816364aSSasha Levin OPT_STRING('i', "initrd", &(cfg)->initrd_filename, "initrd", \ 190b816364aSSasha Levin "Initial RAM disk image"), \ 191b816364aSSasha Levin OPT_STRING('p', "params", &(cfg)->kernel_cmdline, "params", \ 192b816364aSSasha Levin "Kernel command line arguments"), \ 193b816364aSSasha Levin OPT_STRING('f', "firmware", &(cfg)->firmware_filename, "firmware",\ 194b816364aSSasha Levin "Firmware image to boot in virtual machine"), \ 195b816364aSSasha Levin \ 196b816364aSSasha Levin OPT_GROUP("Networking options:"), \ 197b816364aSSasha Levin OPT_CALLBACK_DEFAULT('n', "network", NULL, "network params", \ 198b816364aSSasha Levin "Create a new guest NIC", \ 1995f225124SSasha Levin netdev_parser, NULL, kvm), \ 200b816364aSSasha Levin OPT_BOOLEAN('\0', "no-dhcp", &(cfg)->no_dhcp, "Disable kernel DHCP\ 201b816364aSSasha Levin in rootfs mode"), \ 202b816364aSSasha Levin \ 203b816364aSSasha Levin OPT_GROUP("BIOS options:"), \ 204b816364aSSasha Levin OPT_INTEGER('\0', "vidmode", &vidmode, \ 205b816364aSSasha Levin "Video mode"), \ 206b816364aSSasha Levin \ 207b816364aSSasha Levin OPT_GROUP("Debug options:"), \ 208b816364aSSasha Levin OPT_BOOLEAN('\0', "debug", &do_debug_print, \ 209b816364aSSasha Levin "Enable debug messages"), \ 210b816364aSSasha Levin OPT_BOOLEAN('\0', "debug-single-step", &(cfg)->single_step, \ 211b816364aSSasha Levin "Enable single stepping"), \ 2125765977dSSasha Levin OPT_BOOLEAN('\0', "debug-ioport", &(cfg)->ioport_debug, \ 213b816364aSSasha Levin "Enable ioport debugging"), \ 214e830cce7SSasha Levin OPT_BOOLEAN('\0', "debug-mmio", &(cfg)->mmio_debug, \ 215b816364aSSasha Levin "Enable MMIO debugging"), \ 2163b55dcdeSSasha Levin OPT_INTEGER('\0', "debug-iodelay", &(cfg)->debug_iodelay, \ 217b816364aSSasha Levin "Delay IO by millisecond"), \ 218b816364aSSasha Levin OPT_END() \ 219f967c427SPrasad Joshi }; 220f967c427SPrasad Joshi 2219e854d1aSPekka Enberg static void handle_sigalrm(int sig) 2229e854d1aSPekka Enberg { 2230b69bdefSMatt Evans kvm__arch_periodic_poll(kvm); 2249e854d1aSPekka Enberg } 2259e854d1aSPekka Enberg 2265ee154d1SPekka Enberg static void *kvm_cpu_thread(void *arg) 2275ee154d1SPekka Enberg { 228d77a9efaSCyrill Gorcunov current_kvm_cpu = arg; 2295ee154d1SPekka Enberg 230d77a9efaSCyrill Gorcunov if (kvm_cpu__start(current_kvm_cpu)) 2315ee154d1SPekka Enberg goto panic_kvm; 2325ee154d1SPekka Enberg 2335ee154d1SPekka Enberg return (void *) (intptr_t) 0; 2345ee154d1SPekka Enberg 2355ee154d1SPekka Enberg panic_kvm: 2363fdf659dSSasha Levin fprintf(stderr, "KVM exit reason: %u (\"%s\")\n", 237d77a9efaSCyrill Gorcunov current_kvm_cpu->kvm_run->exit_reason, 238d77a9efaSCyrill Gorcunov kvm_exit_reasons[current_kvm_cpu->kvm_run->exit_reason]); 239d77a9efaSCyrill Gorcunov if (current_kvm_cpu->kvm_run->exit_reason == KVM_EXIT_UNKNOWN) 2405ee154d1SPekka Enberg fprintf(stderr, "KVM exit code: 0x%Lu\n", 241d77a9efaSCyrill Gorcunov current_kvm_cpu->kvm_run->hw.hardware_exit_reason); 2428e5accedSPekka Enberg 243b7d2f013SSasha Levin kvm_cpu__set_debug_fd(STDOUT_FILENO); 244d77a9efaSCyrill Gorcunov kvm_cpu__show_registers(current_kvm_cpu); 245d77a9efaSCyrill Gorcunov kvm_cpu__show_code(current_kvm_cpu); 246d77a9efaSCyrill Gorcunov kvm_cpu__show_page_tables(current_kvm_cpu); 2475ee154d1SPekka Enberg 2485ee154d1SPekka Enberg return (void *) (intptr_t) 1; 2495ee154d1SPekka Enberg } 2505ee154d1SPekka Enberg 251e08c0896SPrasad Joshi static char kernel[PATH_MAX]; 252b0b42ba0SPekka Enberg 253b0b42ba0SPekka Enberg static const char *host_kernels[] = { 254e08c0896SPrasad Joshi "/boot/vmlinuz", 255e08c0896SPrasad Joshi "/boot/bzImage", 256e08c0896SPrasad Joshi NULL 257e08c0896SPrasad Joshi }; 258b0b42ba0SPekka Enberg 259b0b42ba0SPekka Enberg static const char *default_kernels[] = { 260e08c0896SPrasad Joshi "./bzImage", 261b03af790SKonstantin Khlebnikov "arch/" BUILD_ARCH "/boot/bzImage", 262af7b0868SMatt Evans "../../arch/" BUILD_ARCH "/boot/bzImage", 263e08c0896SPrasad Joshi NULL 264e08c0896SPrasad Joshi }; 2658329f30bSPekka Enberg 266b0b42ba0SPekka Enberg static const char *default_vmlinux[] = { 267b03af790SKonstantin Khlebnikov "vmlinux", 268b0b42ba0SPekka Enberg "../../../vmlinux", 269b0b42ba0SPekka Enberg "../../vmlinux", 270b0b42ba0SPekka Enberg NULL 271b0b42ba0SPekka Enberg }; 272b0b42ba0SPekka Enberg 273e08c0896SPrasad Joshi static void kernel_usage_with_options(void) 2748329f30bSPekka Enberg { 275e08c0896SPrasad Joshi const char **k; 2768329f30bSPekka Enberg struct utsname uts; 277e08c0896SPrasad Joshi 278e08c0896SPrasad Joshi fprintf(stderr, "Fatal: could not find default kernel image in:\n"); 27965182f37SPrasad Joshi k = &default_kernels[0]; 280e08c0896SPrasad Joshi while (*k) { 281e08c0896SPrasad Joshi fprintf(stderr, "\t%s\n", *k); 282e08c0896SPrasad Joshi k++; 283e08c0896SPrasad Joshi } 284e08c0896SPrasad Joshi 285e08c0896SPrasad Joshi if (uname(&uts) < 0) 286e08c0896SPrasad Joshi return; 287e08c0896SPrasad Joshi 288e08c0896SPrasad Joshi k = &host_kernels[0]; 289e08c0896SPrasad Joshi while (*k) { 290e08c0896SPrasad Joshi if (snprintf(kernel, PATH_MAX, "%s-%s", *k, uts.release) < 0) 291e08c0896SPrasad Joshi return; 292e08c0896SPrasad Joshi fprintf(stderr, "\t%s\n", kernel); 293e08c0896SPrasad Joshi k++; 294e08c0896SPrasad Joshi } 295ee8b1456SWanlong Gao fprintf(stderr, "\nPlease see '%s run --help' for more options.\n\n", 296ee8b1456SWanlong Gao KVM_BINARY_NAME); 297e08c0896SPrasad Joshi } 298e08c0896SPrasad Joshi 29960ded003SPekka Enberg static u64 host_ram_size(void) 30060ded003SPekka Enberg { 30160ded003SPekka Enberg long page_size; 30260ded003SPekka Enberg long nr_pages; 30360ded003SPekka Enberg 30460ded003SPekka Enberg nr_pages = sysconf(_SC_PHYS_PAGES); 305d63c5ce6SPekka Enberg if (nr_pages < 0) { 3064542f276SCyrill Gorcunov pr_warning("sysconf(_SC_PHYS_PAGES) failed"); 307d63c5ce6SPekka Enberg return 0; 308d63c5ce6SPekka Enberg } 30960ded003SPekka Enberg 31060ded003SPekka Enberg page_size = sysconf(_SC_PAGE_SIZE); 311d63c5ce6SPekka Enberg if (page_size < 0) { 3124542f276SCyrill Gorcunov pr_warning("sysconf(_SC_PAGE_SIZE) failed"); 313d63c5ce6SPekka Enberg return 0; 314d63c5ce6SPekka Enberg } 31560ded003SPekka Enberg 31660ded003SPekka Enberg return (nr_pages * page_size) >> MB_SHIFT; 31760ded003SPekka Enberg } 31860ded003SPekka Enberg 31918bd8c3bSPekka Enberg /* 32018bd8c3bSPekka Enberg * If user didn't specify how much memory it wants to allocate for the guest, 32118bd8c3bSPekka Enberg * avoid filling the whole host RAM. 32218bd8c3bSPekka Enberg */ 32318bd8c3bSPekka Enberg #define RAM_SIZE_RATIO 0.8 32418bd8c3bSPekka Enberg 325fd834defSPekka Enberg static u64 get_ram_size(int nr_cpus) 326fd834defSPekka Enberg { 32706761c76SPekka Enberg u64 available; 32806761c76SPekka Enberg u64 ram_size; 329fd834defSPekka Enberg 330fd834defSPekka Enberg ram_size = 64 * (nr_cpus + 3); 331fd834defSPekka Enberg 33260ded003SPekka Enberg available = host_ram_size() * RAM_SIZE_RATIO; 333d63c5ce6SPekka Enberg if (!available) 334d63c5ce6SPekka Enberg available = MIN_RAM_SIZE_MB; 335fd834defSPekka Enberg 336fd834defSPekka Enberg if (ram_size > available) 337fd834defSPekka Enberg ram_size = available; 338fd834defSPekka Enberg 339fd834defSPekka Enberg return ram_size; 340fd834defSPekka Enberg } 341fd834defSPekka Enberg 342e08c0896SPrasad Joshi static const char *find_kernel(void) 343e08c0896SPrasad Joshi { 344e08c0896SPrasad Joshi const char **k; 3458329f30bSPekka Enberg struct stat st; 346e08c0896SPrasad Joshi struct utsname uts; 347e08c0896SPrasad Joshi 34865182f37SPrasad Joshi k = &default_kernels[0]; 349e08c0896SPrasad Joshi while (*k) { 350e08c0896SPrasad Joshi if (stat(*k, &st) < 0 || !S_ISREG(st.st_mode)) { 351e08c0896SPrasad Joshi k++; 352e08c0896SPrasad Joshi continue; 353e08c0896SPrasad Joshi } 354e08c0896SPrasad Joshi strncpy(kernel, *k, PATH_MAX); 355e08c0896SPrasad Joshi return kernel; 356e08c0896SPrasad Joshi } 3578329f30bSPekka Enberg 3588329f30bSPekka Enberg if (uname(&uts) < 0) 3598329f30bSPekka Enberg return NULL; 3608329f30bSPekka Enberg 361e08c0896SPrasad Joshi k = &host_kernels[0]; 362e08c0896SPrasad Joshi while (*k) { 363e08c0896SPrasad Joshi if (snprintf(kernel, PATH_MAX, "%s-%s", *k, uts.release) < 0) 3648329f30bSPekka Enberg return NULL; 3658329f30bSPekka Enberg 366e08c0896SPrasad Joshi if (stat(kernel, &st) < 0 || !S_ISREG(st.st_mode)) { 367e08c0896SPrasad Joshi k++; 368e08c0896SPrasad Joshi continue; 369e08c0896SPrasad Joshi } 370e08c0896SPrasad Joshi return kernel; 3718329f30bSPekka Enberg 372e08c0896SPrasad Joshi } 3738329f30bSPekka Enberg return NULL; 3748329f30bSPekka Enberg } 3758329f30bSPekka Enberg 376b0b42ba0SPekka Enberg static const char *find_vmlinux(void) 377b0b42ba0SPekka Enberg { 378b0b42ba0SPekka Enberg const char **vmlinux; 379b0b42ba0SPekka Enberg 380b0b42ba0SPekka Enberg vmlinux = &default_vmlinux[0]; 381b0b42ba0SPekka Enberg while (*vmlinux) { 382b0b42ba0SPekka Enberg struct stat st; 383b0b42ba0SPekka Enberg 384b0b42ba0SPekka Enberg if (stat(*vmlinux, &st) < 0 || !S_ISREG(st.st_mode)) { 385b0b42ba0SPekka Enberg vmlinux++; 386b0b42ba0SPekka Enberg continue; 387b0b42ba0SPekka Enberg } 388b0b42ba0SPekka Enberg return *vmlinux; 389b0b42ba0SPekka Enberg } 390b0b42ba0SPekka Enberg return NULL; 391b0b42ba0SPekka Enberg } 392b0b42ba0SPekka Enberg 393f6677a1dSAmerigo Wang void kvm_run_help(void) 394f6677a1dSAmerigo Wang { 3953b55dcdeSSasha Levin BUILD_OPTIONS(options, &kvm->cfg, kvm); 396f6677a1dSAmerigo Wang usage_with_options(run_usage, options); 397f6677a1dSAmerigo Wang } 398f6677a1dSAmerigo Wang 399afc2c7c0SAsias He static int kvm_setup_guest_init(void) 4009cec19c8SSasha Levin { 40147621338SSasha Levin const char *rootfs = kvm->cfg.custom_rootfs_name; 402afc2c7c0SAsias He char tmp[PATH_MAX]; 403afc2c7c0SAsias He size_t size; 404afc2c7c0SAsias He int fd, ret; 405afc2c7c0SAsias He char *data; 4069cec19c8SSasha Levin 407afc2c7c0SAsias He /* Setup /virt/init */ 408afc2c7c0SAsias He size = (size_t)&_binary_guest_init_size; 409afc2c7c0SAsias He data = (char *)&_binary_guest_init_start; 410afc2c7c0SAsias He snprintf(tmp, PATH_MAX, "%s%s/virt/init", kvm__get_dir(), rootfs); 411afc2c7c0SAsias He remove(tmp); 412afc2c7c0SAsias He fd = open(tmp, O_CREAT | O_WRONLY, 0755); 413afc2c7c0SAsias He if (fd < 0) 414afc2c7c0SAsias He die("Fail to setup %s", tmp); 415afc2c7c0SAsias He ret = xwrite(fd, data, size); 416afc2c7c0SAsias He if (ret < 0) 417afc2c7c0SAsias He die("Fail to setup %s", tmp); 418afc2c7c0SAsias He close(fd); 4199cec19c8SSasha Levin 420afc2c7c0SAsias He return 0; 4219cec19c8SSasha Levin } 4229cec19c8SSasha Levin 423d50fe489SSasha Levin static int kvm_run_set_sandbox(void) 424d50fe489SSasha Levin { 42547621338SSasha Levin const char *guestfs_name = kvm->cfg.custom_rootfs_name; 426d50fe489SSasha Levin char path[PATH_MAX], script[PATH_MAX], *tmp; 427d50fe489SSasha Levin 428d50fe489SSasha Levin snprintf(path, PATH_MAX, "%s%s/virt/sandbox.sh", kvm__get_dir(), guestfs_name); 429d50fe489SSasha Levin 430d50fe489SSasha Levin remove(path); 431d50fe489SSasha Levin 43247621338SSasha Levin if (kvm->cfg.sandbox == NULL) 433d50fe489SSasha Levin return 0; 434d50fe489SSasha Levin 43547621338SSasha Levin tmp = realpath(kvm->cfg.sandbox, NULL); 436d50fe489SSasha Levin if (tmp == NULL) 437d50fe489SSasha Levin return -ENOMEM; 438d50fe489SSasha Levin 439d50fe489SSasha Levin snprintf(script, PATH_MAX, "/host/%s", tmp); 440d50fe489SSasha Levin free(tmp); 441d50fe489SSasha Levin 442d50fe489SSasha Levin return symlink(script, path); 443d50fe489SSasha Levin } 444d50fe489SSasha Levin 4455173b4afSLai Jiangshan static void kvm_write_sandbox_cmd_exactly(int fd, const char *arg) 4465173b4afSLai Jiangshan { 4475173b4afSLai Jiangshan const char *single_quote; 4485173b4afSLai Jiangshan 4495173b4afSLai Jiangshan if (!*arg) { /* zero length string */ 4505173b4afSLai Jiangshan if (write(fd, "''", 2) <= 0) 4515173b4afSLai Jiangshan die("Failed writing sandbox script"); 4525173b4afSLai Jiangshan return; 4535173b4afSLai Jiangshan } 4545173b4afSLai Jiangshan 4555173b4afSLai Jiangshan while (*arg) { 4565173b4afSLai Jiangshan single_quote = strchrnul(arg, '\''); 4575173b4afSLai Jiangshan 4585173b4afSLai Jiangshan /* write non-single-quote string as #('string') */ 4595173b4afSLai Jiangshan if (arg != single_quote) { 4605173b4afSLai Jiangshan if (write(fd, "'", 1) <= 0 || 4615173b4afSLai Jiangshan write(fd, arg, single_quote - arg) <= 0 || 4625173b4afSLai Jiangshan write(fd, "'", 1) <= 0) 4635173b4afSLai Jiangshan die("Failed writing sandbox script"); 4645173b4afSLai Jiangshan } 4655173b4afSLai Jiangshan 4665173b4afSLai Jiangshan /* write single quote as #("'") */ 4675173b4afSLai Jiangshan if (*single_quote) { 4685173b4afSLai Jiangshan if (write(fd, "\"'\"", 3) <= 0) 4695173b4afSLai Jiangshan die("Failed writing sandbox script"); 4705173b4afSLai Jiangshan } else 4715173b4afSLai Jiangshan break; 4725173b4afSLai Jiangshan 4735173b4afSLai Jiangshan arg = single_quote + 1; 4745173b4afSLai Jiangshan } 4755173b4afSLai Jiangshan } 4765173b4afSLai Jiangshan 4775cd19aa0SPekka Enberg static void resolve_program(const char *src, char *dst, size_t len) 4785cd19aa0SPekka Enberg { 4795cd19aa0SPekka Enberg struct stat st; 480c2c742d9SPekka Enberg int err; 4815cd19aa0SPekka Enberg 482c2c742d9SPekka Enberg err = stat(src, &st); 4835cd19aa0SPekka Enberg 484c2c742d9SPekka Enberg if (!err && S_ISREG(st.st_mode)) { 4855cd19aa0SPekka Enberg char resolved_path[PATH_MAX]; 4865cd19aa0SPekka Enberg 487de3f75c9SPekka Enberg if (!realpath(src, resolved_path)) 488de3f75c9SPekka Enberg die("Unable to resolve program %s: %s\n", src, strerror(errno)); 4895cd19aa0SPekka Enberg 4905cd19aa0SPekka Enberg snprintf(dst, len, "/host%s", resolved_path); 4915cd19aa0SPekka Enberg } else 4925cd19aa0SPekka Enberg strncpy(dst, src, len); 4935cd19aa0SPekka Enberg } 4945cd19aa0SPekka Enberg 4953c29e2aaSSasha Levin static void kvm_run_write_sandbox_cmd(const char **argv, int argc) 4963c29e2aaSSasha Levin { 4973c29e2aaSSasha Levin const char script_hdr[] = "#! /bin/bash\n\n"; 4985cd19aa0SPekka Enberg char program[PATH_MAX]; 4993c29e2aaSSasha Levin int fd; 5003c29e2aaSSasha Levin 50147621338SSasha Levin remove(kvm->cfg.sandbox); 5023c29e2aaSSasha Levin 50347621338SSasha Levin fd = open(kvm->cfg.sandbox, O_RDWR | O_CREAT, 0777); 5043c29e2aaSSasha Levin if (fd < 0) 5053c29e2aaSSasha Levin die("Failed creating sandbox script"); 5063c29e2aaSSasha Levin 5073c29e2aaSSasha Levin if (write(fd, script_hdr, sizeof(script_hdr) - 1) <= 0) 5083c29e2aaSSasha Levin die("Failed writing sandbox script"); 5093c29e2aaSSasha Levin 5105cd19aa0SPekka Enberg resolve_program(argv[0], program, PATH_MAX); 5115cd19aa0SPekka Enberg kvm_write_sandbox_cmd_exactly(fd, program); 5125cd19aa0SPekka Enberg 5135cd19aa0SPekka Enberg argv++; 5145cd19aa0SPekka Enberg argc--; 5155cd19aa0SPekka Enberg 5163c29e2aaSSasha Levin while (argc) { 5173c29e2aaSSasha Levin if (write(fd, " ", 1) <= 0) 5183c29e2aaSSasha Levin die("Failed writing sandbox script"); 5195cd19aa0SPekka Enberg 5205cd19aa0SPekka Enberg kvm_write_sandbox_cmd_exactly(fd, argv[0]); 5213c29e2aaSSasha Levin argv++; 5223c29e2aaSSasha Levin argc--; 5233c29e2aaSSasha Levin } 5243c29e2aaSSasha Levin if (write(fd, "\n", 1) <= 0) 5253c29e2aaSSasha Levin die("Failed writing sandbox script"); 5263c29e2aaSSasha Levin 5273c29e2aaSSasha Levin close(fd); 5283c29e2aaSSasha Levin } 5293c29e2aaSSasha Levin 530e1e46fe6SSasha Levin static int kvm_cmd_run_init(int argc, const char **argv) 531f967c427SPrasad Joshi { 5322d96f6b6SSasha Levin static char real_cmdline[2048], default_name[20]; 533aba1efa5SPekka Enberg struct framebuffer *fb = NULL; 534384922b3SPekka Enberg unsigned int nr_online_cpus; 5355f225124SSasha Levin int r; 53647621338SSasha Levin 53747621338SSasha Levin kvm = kvm__new(); 53847621338SSasha Levin if (IS_ERR(kvm)) 53947621338SSasha Levin return PTR_ERR(kvm); 540f967c427SPrasad Joshi 5415ee154d1SPekka Enberg signal(SIGALRM, handle_sigalrm); 542f967c427SPrasad Joshi 543cfd63bbbSSasha Levin nr_online_cpus = sysconf(_SC_NPROCESSORS_ONLN); 54447621338SSasha Levin kvm->cfg.custom_rootfs_name = "default"; 545cfd63bbbSSasha Levin 546f967c427SPrasad Joshi while (argc != 0) { 5473b55dcdeSSasha Levin BUILD_OPTIONS(options, &kvm->cfg, kvm); 548f967c427SPrasad Joshi argc = parse_options(argc, argv, options, run_usage, 5491a007c82SSasha Levin PARSE_OPT_STOP_AT_NON_OPTION | 5501a007c82SSasha Levin PARSE_OPT_KEEP_DASHDASH); 551f967c427SPrasad Joshi if (argc != 0) { 5521a007c82SSasha Levin /* Cusrom options, should have been handled elsewhere */ 5533c29e2aaSSasha Levin if (strcmp(argv[0], "--") == 0) { 5543c29e2aaSSasha Levin if (kvm_run_wrapper == KVM_RUN_SANDBOX) { 55547621338SSasha Levin kvm->cfg.sandbox = DEFAULT_SANDBOX_FILENAME; 5563c29e2aaSSasha Levin kvm_run_write_sandbox_cmd(argv+1, argc-1); 5571a007c82SSasha Levin break; 5583c29e2aaSSasha Levin } 5593c29e2aaSSasha Levin } 5601a007c82SSasha Levin 56147621338SSasha Levin if ((kvm_run_wrapper == KVM_RUN_DEFAULT && kvm->cfg.kernel_filename) || 56247621338SSasha Levin (kvm_run_wrapper == KVM_RUN_SANDBOX && kvm->cfg.sandbox)) { 563f967c427SPrasad Joshi fprintf(stderr, "Cannot handle parameter: " 564f967c427SPrasad Joshi "%s\n", argv[0]); 565f967c427SPrasad Joshi usage_with_options(run_usage, options); 56647621338SSasha Levin free(kvm); 567e120b624SPaul Neumann return -EINVAL; 568f967c427SPrasad Joshi } 569e0747665SSasha Levin if (kvm_run_wrapper == KVM_RUN_SANDBOX) { 570e0747665SSasha Levin /* 571e0747665SSasha Levin * first unhandled parameter is treated as 572e0747665SSasha Levin * sandbox command 573e0747665SSasha Levin */ 57447621338SSasha Levin kvm->cfg.sandbox = DEFAULT_SANDBOX_FILENAME; 575e0747665SSasha Levin kvm_run_write_sandbox_cmd(argv, argc); 576e0747665SSasha Levin } else { 577e0747665SSasha Levin /* 578e0747665SSasha Levin * first unhandled parameter is treated as a kernel 579e0747665SSasha Levin * image 580f967c427SPrasad Joshi */ 58147621338SSasha Levin kvm->cfg.kernel_filename = argv[0]; 582e0747665SSasha Levin } 583f967c427SPrasad Joshi argv++; 584f967c427SPrasad Joshi argc--; 585f967c427SPrasad Joshi } 586f967c427SPrasad Joshi 587f967c427SPrasad Joshi } 588f967c427SPrasad Joshi 5893b55dcdeSSasha Levin kvm->nr_disks = kvm->cfg.image_count; 5903b55dcdeSSasha Levin 59147621338SSasha Levin if (!kvm->cfg.kernel_filename) 59247621338SSasha Levin kvm->cfg.kernel_filename = find_kernel(); 5938329f30bSPekka Enberg 59447621338SSasha Levin if (!kvm->cfg.kernel_filename) { 595e08c0896SPrasad Joshi kernel_usage_with_options(); 596e120b624SPaul Neumann return -EINVAL; 5978329f30bSPekka Enberg } 5988329f30bSPekka Enberg 59947621338SSasha Levin kvm->cfg.vmlinux_filename = find_vmlinux(); 600b0b42ba0SPekka Enberg 60100ebbe96SSasha Levin if (kvm->cfg.nrcpus == 0) 60200ebbe96SSasha Levin kvm->cfg.nrcpus = nr_online_cpus; 603d77a9efaSCyrill Gorcunov 60447621338SSasha Levin if (!kvm->cfg.ram_size) 60500ebbe96SSasha Levin kvm->cfg.ram_size = get_ram_size(kvm->cfg.nrcpus); 606fd834defSPekka Enberg 60747621338SSasha Levin if (kvm->cfg.ram_size < MIN_RAM_SIZE_MB) 60847621338SSasha Levin die("Not enough memory specified: %lluMB (min %lluMB)", kvm->cfg.ram_size, MIN_RAM_SIZE_MB); 609a2a002f9SIngo Molnar 61047621338SSasha Levin if (kvm->cfg.ram_size > host_ram_size()) 61147621338SSasha Levin pr_warning("Guest memory size %lluMB exceeds host physical RAM size %lluMB", kvm->cfg.ram_size, host_ram_size()); 61260ded003SPekka Enberg 61347621338SSasha Levin kvm->cfg.ram_size <<= MB_SHIFT; 614f967c427SPrasad Joshi 61547621338SSasha Levin if (!kvm->cfg.dev) 61647621338SSasha Levin kvm->cfg.dev = DEFAULT_KVM_DEV; 617f967c427SPrasad Joshi 61847621338SSasha Levin if (!kvm->cfg.console) 61947621338SSasha Levin kvm->cfg.console = DEFAULT_CONSOLE; 6209aa4a0ebSAsias He 62147621338SSasha Levin if (!strncmp(kvm->cfg.console, "virtio", 6)) 6222651ea58SSasha Levin kvm->cfg.active_console = CONSOLE_VIRTIO; 62347621338SSasha Levin else if (!strncmp(kvm->cfg.console, "serial", 6)) 6242651ea58SSasha Levin kvm->cfg.active_console = CONSOLE_8250; 62547621338SSasha Levin else if (!strncmp(kvm->cfg.console, "hv", 2)) 6262651ea58SSasha Levin kvm->cfg.active_console = CONSOLE_HV; 6273bbc49b6SMatt Evans else 6283bbc49b6SMatt Evans pr_warning("No console!"); 629f967c427SPrasad Joshi 63047621338SSasha Levin if (!kvm->cfg.host_ip) 63147621338SSasha Levin kvm->cfg.host_ip = DEFAULT_HOST_ADDR; 6324d67c820SSasha Levin 63347621338SSasha Levin if (!kvm->cfg.guest_ip) 63447621338SSasha Levin kvm->cfg.guest_ip = DEFAULT_GUEST_ADDR; 635bb8ffd2fSAsias He 63647621338SSasha Levin if (!kvm->cfg.guest_mac) 63747621338SSasha Levin kvm->cfg.guest_mac = DEFAULT_GUEST_MAC; 638a4e724ddSSasha Levin 63947621338SSasha Levin if (!kvm->cfg.host_mac) 64047621338SSasha Levin kvm->cfg.host_mac = DEFAULT_HOST_MAC; 641d7098b9bSAsias He 64247621338SSasha Levin if (!kvm->cfg.script) 64347621338SSasha Levin kvm->cfg.script = DEFAULT_SCRIPT; 64473b7d038SAmos Kong 645dca745e4SSasha Levin r = term_init(kvm); 646dca745e4SSasha Levin if (r < 0) { 647dca745e4SSasha Levin pr_err("term_init() failed with error %d\n", r); 648dca745e4SSasha Levin goto fail; 649dca745e4SSasha Levin } 650f967c427SPrasad Joshi 65147621338SSasha Levin if (!kvm->cfg.guest_name) { 65247621338SSasha Levin if (kvm->cfg.custom_rootfs) { 65347621338SSasha Levin kvm->cfg.guest_name = kvm->cfg.custom_rootfs_name; 654587a4d17SLai Jiangshan } else { 6552d96f6b6SSasha Levin sprintf(default_name, "guest-%u", getpid()); 65647621338SSasha Levin kvm->cfg.guest_name = default_name; 6572d96f6b6SSasha Levin } 658587a4d17SLai Jiangshan } 6592d96f6b6SSasha Levin 66047621338SSasha Levin r = kvm__init(kvm); 66147621338SSasha Levin if (r) 662d648dbf5SCyrill Gorcunov goto fail; 663f967c427SPrasad Joshi 664ea6eeb1cSSasha Levin r = ioeventfd__init(kvm); 665ea6eeb1cSSasha Levin if (r < 0) { 666ea6eeb1cSSasha Levin pr_err("ioeventfd__init() failed with error %d\n", r); 667ea6eeb1cSSasha Levin goto fail; 668ea6eeb1cSSasha Levin } 66937f3d50eSSasha Levin 670df4239fbSSasha Levin r = kvm_cpu__init(kvm); 671df4239fbSSasha Levin if (r < 0) { 672df4239fbSSasha Levin pr_err("kvm_cpu__init() failed with error %d\n", r); 673df4239fbSSasha Levin goto fail; 674384922b3SPekka Enberg } 675384922b3SPekka Enberg 676e3c4f8aaSSasha Levin r = irq__init(kvm); 677e3c4f8aaSSasha Levin if (r < 0) { 678e3c4f8aaSSasha Levin pr_err("irq__init() failed with error %d\n", r); 679e3c4f8aaSSasha Levin goto fail; 680e3c4f8aaSSasha Levin } 68119e6c8b8SMatt Evans 6826d987703SSasha Levin r = pci__init(kvm); 6836d987703SSasha Levin if (r < 0) { 6846d987703SSasha Levin pr_err("pci__init() failed with error %d\n", r); 6856d987703SSasha Levin goto fail; 6866d987703SSasha Levin } 687b91be965SMatt Evans 6887af40b91SSasha Levin r = ioport__init(kvm); 6897af40b91SSasha Levin if (r < 0) { 6907af40b91SSasha Levin pr_err("ioport__init() failed with error %d\n", r); 6917af40b91SSasha Levin goto fail; 6927af40b91SSasha Levin } 6937af40b91SSasha Levin 694890364f8SCyrill Gorcunov /* 695890364f8SCyrill Gorcunov * vidmode should be either specified 696890364f8SCyrill Gorcunov * either set by default 697890364f8SCyrill Gorcunov */ 69847621338SSasha Levin if (kvm->cfg.vnc || kvm->cfg.sdl) { 699890364f8SCyrill Gorcunov if (vidmode == -1) 700890364f8SCyrill Gorcunov vidmode = 0x312; 70148d9e01aSSasha Levin } else { 702890364f8SCyrill Gorcunov vidmode = 0; 70348d9e01aSSasha Levin } 704890364f8SCyrill Gorcunov 70526c853e4SPrasad Joshi memset(real_cmdline, 0, sizeof(real_cmdline)); 70647621338SSasha Levin kvm__arch_set_cmdline(real_cmdline, kvm->cfg.vnc || kvm->cfg.sdl); 7078e704a7aSMatt Evans 7088e704a7aSMatt Evans if (strlen(real_cmdline) > 0) 709d74181ccSSasha Levin strcat(real_cmdline, " "); 7108e704a7aSMatt Evans 71147621338SSasha Levin if (kvm->cfg.kernel_cmdline) 71247621338SSasha Levin strlcat(real_cmdline, kvm->cfg.kernel_cmdline, sizeof(real_cmdline)); 71326c853e4SPrasad Joshi 71447621338SSasha Levin if (!kvm->cfg.using_rootfs && !kvm->cfg.disk_image[0].filename && !kvm->cfg.initrd_filename) { 715c8675741SSasha Levin char tmp[PATH_MAX]; 7166df1471eSPekka Enberg 71747621338SSasha Levin kvm_setup_create_new(kvm->cfg.custom_rootfs_name); 71847621338SSasha Levin kvm_setup_resolv(kvm->cfg.custom_rootfs_name); 719c8675741SSasha Levin 7209667701cSPekka Enberg snprintf(tmp, PATH_MAX, "%s%s", kvm__get_dir(), "default"); 721c8675741SSasha Levin if (virtio_9p__register(kvm, tmp, "/dev/root") < 0) 722c8675741SSasha Levin die("Unable to initialize virtio 9p"); 723c8675741SSasha Levin if (virtio_9p__register(kvm, "/", "hostfs") < 0) 724c8675741SSasha Levin die("Unable to initialize virtio 9p"); 72547621338SSasha Levin kvm->cfg.using_rootfs = kvm->cfg.custom_rootfs = 1; 72626c853e4SPrasad Joshi } 72726c853e4SPrasad Joshi 72847621338SSasha Levin if (kvm->cfg.using_rootfs) { 729ff42603fSSasha Levin strcat(real_cmdline, " root=/dev/root rw rootflags=rw,trans=virtio,version=9p2000.L rootfstype=9p"); 73047621338SSasha Levin if (kvm->cfg.custom_rootfs) { 731d50fe489SSasha Levin kvm_run_set_sandbox(); 732d50fe489SSasha Levin 733a8e6b4b9SSasha Levin strcat(real_cmdline, " init=/virt/init"); 734d50fe489SSasha Levin 73547621338SSasha Levin if (!kvm->cfg.no_dhcp) 736a8e6b4b9SSasha Levin strcat(real_cmdline, " ip=dhcp"); 737afc2c7c0SAsias He if (kvm_setup_guest_init()) 738afc2c7c0SAsias He die("Failed to setup init for guest."); 739a8e6b4b9SSasha Levin } 74082d65b5eSSasha Levin } else if (!strstr(real_cmdline, "root=")) { 741ff42603fSSasha Levin strlcat(real_cmdline, " root=/dev/vda rw ", sizeof(real_cmdline)); 74282d65b5eSSasha Levin } 74359aa2d30SSasha Levin 7443b55dcdeSSasha Levin r = disk_image__init(kvm); 7453b55dcdeSSasha Levin if (r < 0) { 7463b55dcdeSSasha Levin pr_err("disk_image__init() failed with error %d\n", r); 7479f9207c5SSasha Levin goto fail; 7489f9207c5SSasha Levin } 749c1ed214eSPrasad Joshi 750ee8b1456SWanlong Gao printf(" # %s run -k %s -m %Lu -c %d --name %s\n", KVM_BINARY_NAME, 75100ebbe96SSasha Levin kvm->cfg.kernel_filename, kvm->cfg.ram_size / 1024 / 1024, kvm->cfg.nrcpus, kvm->cfg.guest_name); 752471c6facSPekka Enberg 75347621338SSasha Levin if (!kvm->cfg.firmware_filename) { 75447621338SSasha Levin if (!kvm__load_kernel(kvm, kvm->cfg.kernel_filename, 75547621338SSasha Levin kvm->cfg.initrd_filename, real_cmdline, vidmode)) 75647621338SSasha Levin die("unable to load kernel %s", kvm->cfg.kernel_filename); 757f967c427SPrasad Joshi 75847621338SSasha Levin kvm->vmlinux = kvm->cfg.vmlinux_filename; 759807b77b9SCyrill Gorcunov r = symbol_init(kvm); 760b56f1728SCyrill Gorcunov if (r < 0) 761c4b716ecSPekka Enberg pr_debug("symbol_init() failed with error %d\n", r); 7625ad8db5eSPekka Enberg } 763b0b42ba0SPekka Enberg 764af7b0868SMatt Evans ioport__setup_arch(); 765ac38f433SPekka Enberg 76620c39545SSasha Levin r = rtc__init(kvm); 76720c39545SSasha Levin if (r < 0) { 76820c39545SSasha Levin pr_err("rtc__init() failed with error %d\n", r); 76920c39545SSasha Levin goto fail; 77020c39545SSasha Levin } 77164136c1cSPekka Enberg 77220715a22SSasha Levin r = serial8250__init(kvm); 77320715a22SSasha Levin if (r < 0) { 77420715a22SSasha Levin pr_err("serial__init() failed with error %d\n", r); 77520715a22SSasha Levin goto fail; 77620715a22SSasha Levin } 777f967c427SPrasad Joshi 7789f9207c5SSasha Levin r = virtio_blk__init(kvm); 7799f9207c5SSasha Levin if (r < 0) { 7809f9207c5SSasha Levin pr_err("virtio_blk__init() failed with error %d\n", r); 7819f9207c5SSasha Levin goto fail; 7829f9207c5SSasha Levin } 7839f9207c5SSasha Levin 784a67da3beSAsias He r = virtio_scsi_init(kvm); 785a67da3beSAsias He if (r < 0) { 786a67da3beSAsias He pr_err("virtio_scsi_init() failed with error %d\n", r); 787a67da3beSAsias He goto fail; 788a67da3beSAsias He } 789a67da3beSAsias He 790a3fa3f86SSasha Levin r = virtio_console__init(kvm); 791a3fa3f86SSasha Levin if (r < 0) { 792a3fa3f86SSasha Levin pr_err("virtio_console__init() failed with error %d\n", r); 793a3fa3f86SSasha Levin goto fail; 794a3fa3f86SSasha Levin } 795f967c427SPrasad Joshi 796f16653adSSasha Levin r = virtio_rng__init(kvm); 797f16653adSSasha Levin if (r < 0) { 798f16653adSSasha Levin pr_err("virtio_rng__init() failed with error %d\n", r); 799f16653adSSasha Levin goto fail; 800f16653adSSasha Levin } 80153eca082SSasha Levin 802d06db2fdSSasha Levin r = virtio_bln__init(kvm); 803d06db2fdSSasha Levin if (r < 0) { 804d06db2fdSSasha Levin pr_err("virtio_rng__init() failed with error %d\n", r); 805d06db2fdSSasha Levin goto fail; 806d06db2fdSSasha Levin } 80782d2f21eSSasha Levin 80847621338SSasha Levin if (!kvm->cfg.network) 80947621338SSasha Levin kvm->cfg.network = DEFAULT_NETWORK; 8104f56d42cSAsias He 811c7838fbdSSasha Levin virtio_9p__init(kvm); 812c7838fbdSSasha Levin 8135f225124SSasha Levin r = virtio_net__init(kvm); 8145f225124SSasha Levin if (r < 0) { 8155f225124SSasha Levin pr_err("virtio_net__init() failed with error %d\n", r); 8165f225124SSasha Levin goto fail; 817bdfcfca6SSasha Levin } 8184f56d42cSAsias He 819839051d9SSasha Levin kvm__init_ram(kvm); 820839051d9SSasha Levin 821*be1eb89bSSasha Levin r = kbd__init(kvm); 822*be1eb89bSSasha Levin if (r < 0) { 823*be1eb89bSSasha Levin pr_err("kbd__init() failed with error %d\n", r); 824*be1eb89bSSasha Levin goto fail; 825*be1eb89bSSasha Levin } 826714e5b7fSSasha Levin 8278cec93dbSSasha Levin r = pci_shmem__init(kvm); 8288cec93dbSSasha Levin if (r < 0) { 8298cec93dbSSasha Levin pr_err("pci_shmem__init() failed with error %d\n", r); 8308cec93dbSSasha Levin goto fail; 8318cec93dbSSasha Levin } 83295d13a52SSasha Levin 83347621338SSasha Levin if (kvm->cfg.vnc || kvm->cfg.sdl) { 8343f838fecSPekka Enberg fb = vesa__init(kvm); 83548d9e01aSSasha Levin if (IS_ERR(fb)) { 83648d9e01aSSasha Levin pr_err("vesa__init() failed with error %ld\n", PTR_ERR(fb)); 83748d9e01aSSasha Levin goto fail; 83848d9e01aSSasha Levin } 8393f838fecSPekka Enberg } 8403f838fecSPekka Enberg 84147621338SSasha Levin if (kvm->cfg.vnc && fb) { 84248d9e01aSSasha Levin r = vnc__init(fb); 84348d9e01aSSasha Levin if (r < 0) { 84448d9e01aSSasha Levin pr_err("vnc__init() failed with error %d\n", r); 84548d9e01aSSasha Levin goto fail; 84648d9e01aSSasha Levin } 84748d9e01aSSasha Levin } 84848d9e01aSSasha Levin 84947621338SSasha Levin if (kvm->cfg.sdl && fb) { 8503f838fecSPekka Enberg sdl__init(fb); 85148d9e01aSSasha Levin if (r < 0) { 85248d9e01aSSasha Levin pr_err("sdl__init() failed with error %d\n", r); 85348d9e01aSSasha Levin goto fail; 85448d9e01aSSasha Levin } 8553f838fecSPekka Enberg } 856aba1efa5SPekka Enberg 857ba46fe53SSasha Levin r = fb__init(kvm); 85848d9e01aSSasha Levin if (r < 0) { 85948d9e01aSSasha Levin pr_err("fb__init() failed with error %d\n", r); 86048d9e01aSSasha Levin goto fail; 86148d9e01aSSasha Levin } 862aba1efa5SPekka Enberg 863df4239fbSSasha Levin /* 864df4239fbSSasha Levin * Device init all done; firmware init must 86525af47eeSMatt Evans * come after this (it may set up device trees etc.) 86625af47eeSMatt Evans */ 86725af47eeSMatt Evans 868b4532ca9SSasha Levin r = kvm_timer__init(kvm); 869b4532ca9SSasha Levin if (r < 0) { 870b4532ca9SSasha Levin pr_err("kvm_timer__init() failed with error %d\n", r); 871b4532ca9SSasha Levin goto fail; 872b4532ca9SSasha Levin } 87325af47eeSMatt Evans 87447621338SSasha Levin if (kvm->cfg.firmware_filename) { 87547621338SSasha Levin if (!kvm__load_firmware(kvm, kvm->cfg.firmware_filename)) 87647621338SSasha Levin die("unable to load firmware image %s: %s", kvm->cfg.firmware_filename, strerror(errno)); 8775ad8db5eSPekka Enberg } else { 878e1e46fe6SSasha Levin kvm__arch_setup_firmware(kvm); 8791add9f73SSasha Levin if (r < 0) { 8801add9f73SSasha Levin pr_err("kvm__arch_setup_firmware() failed with error %d\n", r); 8811add9f73SSasha Levin goto fail; 8821add9f73SSasha Levin } 8835ad8db5eSPekka Enberg } 88425af47eeSMatt Evans 885f6a3c571SSasha Levin r = thread_pool__init(kvm); 886f6a3c571SSasha Levin if (r < 0) { 887f6a3c571SSasha Levin pr_err("thread_pool__init() failed with error %d\n", r); 888f6a3c571SSasha Levin goto fail; 889f6a3c571SSasha Levin } 890f6a3c571SSasha Levin 8914932d174SSasha Levin fail: 8924932d174SSasha Levin return r; 893e1e46fe6SSasha Levin } 894e1e46fe6SSasha Levin 895e1e46fe6SSasha Levin static int kvm_cmd_run_work(void) 896e1e46fe6SSasha Levin { 897df4239fbSSasha Levin int i; 898e1e46fe6SSasha Levin void *ret = NULL; 899e1e46fe6SSasha Levin 90000ebbe96SSasha Levin for (i = 0; i < kvm->nrcpus; i++) { 901df4239fbSSasha Levin if (pthread_create(&kvm->cpus[i]->thread, NULL, kvm_cpu_thread, kvm->cpus[i]) != 0) 9025ee154d1SPekka Enberg die("unable to create KVM VCPU thread"); 9035ee154d1SPekka Enberg } 9045ee154d1SPekka Enberg 90549e5227dSSasha Levin /* Only VCPU #0 is going to exit by itself when shutting down */ 906df4239fbSSasha Levin return pthread_join(kvm->cpus[0]->thread, &ret); 907e1e46fe6SSasha Levin } 908e1e46fe6SSasha Levin 9094932d174SSasha Levin static void kvm_cmd_run_exit(int guest_ret) 910e1e46fe6SSasha Levin { 9114932d174SSasha Levin int r = 0; 9124932d174SSasha Levin 913e6694207SSasha Levin compat__print_all_messages(); 914e6694207SSasha Levin 915df4239fbSSasha Levin r = kvm_cpu__exit(kvm); 916df4239fbSSasha Levin if (r < 0) 917df4239fbSSasha Levin pr_warning("kvm_cpu__exit() failed with error %d\n", r); 918df4239fbSSasha Levin 919807b77b9SCyrill Gorcunov r = symbol_exit(kvm); 9204932d174SSasha Levin if (r < 0) 921807b77b9SCyrill Gorcunov pr_warning("symbol_exit() failed with error %d\n", r); 9224932d174SSasha Levin 923e3c4f8aaSSasha Levin r = irq__exit(kvm); 924e3c4f8aaSSasha Levin if (r < 0) 925e3c4f8aaSSasha Levin pr_warning("irq__exit() failed with error %d\n", r); 926e3c4f8aaSSasha Levin 927b4532ca9SSasha Levin r = kvm_timer__exit(kvm); 928b4532ca9SSasha Levin if (r < 0) 929b4532ca9SSasha Levin pr_warning("kvm_timer__exit() failed with error %d\n", r); 930b4532ca9SSasha Levin 931ba46fe53SSasha Levin r = fb__exit(kvm); 932ba46fe53SSasha Levin if (r < 0) 933b4532ca9SSasha Levin pr_warning("kvm_timer__exit() failed with error %d\n", r); 934aba1efa5SPekka Enberg 9355f225124SSasha Levin r = virtio_net__exit(kvm); 9365f225124SSasha Levin if (r < 0) 9375f225124SSasha Levin pr_warning("virtio_net__exit() failed with error %d\n", r); 9385f225124SSasha Levin 939a67da3beSAsias He r = virtio_scsi_exit(kvm); 940a67da3beSAsias He if (r < 0) 941a67da3beSAsias He pr_warning("virtio_scsi_exit() failed with error %d\n", r); 942a67da3beSAsias He 9439f9207c5SSasha Levin r = virtio_blk__exit(kvm); 9449f9207c5SSasha Levin if (r < 0) 9459f9207c5SSasha Levin pr_warning("virtio_blk__exit() failed with error %d\n", r); 9469f9207c5SSasha Levin 947495fbd4eSSasha Levin r = virtio_rng__exit(kvm); 948495fbd4eSSasha Levin if (r < 0) 949495fbd4eSSasha Levin pr_warning("virtio_rng__exit() failed with error %d\n", r); 950a0a1e3c2SPrasad Joshi 951d06db2fdSSasha Levin r = virtio_bln__exit(kvm); 952d06db2fdSSasha Levin if (r < 0) 953d06db2fdSSasha Levin pr_warning("virtio_bln__exit() failed with error %d\n", r); 954d06db2fdSSasha Levin 955a3fa3f86SSasha Levin r = virtio_console__exit(kvm); 956a3fa3f86SSasha Levin if (r < 0) 957a3fa3f86SSasha Levin pr_warning("virtio_console__exit() failed with error %d\n", r); 958a3fa3f86SSasha Levin 9598cec93dbSSasha Levin r = pci_shmem__exit(kvm); 9608cec93dbSSasha Levin if (r < 0) 9618cec93dbSSasha Levin pr_warning("pci_shmem__exit() failed with error %d\n", r); 9628cec93dbSSasha Levin 9633b55dcdeSSasha Levin r = disk_image__exit(kvm); 9649f9207c5SSasha Levin if (r < 0) 9653b55dcdeSSasha Levin pr_warning("disk_image__exit() failed with error %d\n", r); 9667af40b91SSasha Levin 96720715a22SSasha Levin r = serial8250__exit(kvm); 96820715a22SSasha Levin if (r < 0) 96920715a22SSasha Levin pr_warning("serial8250__exit() failed with error %d\n", r); 97020715a22SSasha Levin 97120c39545SSasha Levin r = rtc__exit(kvm); 97220c39545SSasha Levin if (r < 0) 97320c39545SSasha Levin pr_warning("rtc__exit() failed with error %d\n", r); 97420c39545SSasha Levin 9751add9f73SSasha Levin r = kvm__arch_free_firmware(kvm); 9761add9f73SSasha Levin if (r < 0) 9771add9f73SSasha Levin pr_warning("kvm__arch_free_firmware() failed with error %d\n", r); 9781add9f73SSasha Levin 9797af40b91SSasha Levin r = ioport__exit(kvm); 9807af40b91SSasha Levin if (r < 0) 9817af40b91SSasha Levin pr_warning("ioport__exit() failed with error %d\n", r); 9827af40b91SSasha Levin 983ea6eeb1cSSasha Levin r = ioeventfd__exit(kvm); 984ea6eeb1cSSasha Levin if (r < 0) 985ea6eeb1cSSasha Levin pr_warning("ioeventfd__exit() failed with error %d\n", r); 986ea6eeb1cSSasha Levin 9876d987703SSasha Levin r = pci__exit(kvm); 9886d987703SSasha Levin if (r < 0) 9896d987703SSasha Levin pr_warning("pci__exit() failed with error %d\n", r); 9906d987703SSasha Levin 991dca745e4SSasha Levin r = term_exit(kvm); 992dca745e4SSasha Levin if (r < 0) 993dca745e4SSasha Levin pr_warning("pci__exit() failed with error %d\n", r); 994dca745e4SSasha Levin 995f6a3c571SSasha Levin r = thread_pool__exit(kvm); 996f6a3c571SSasha Levin if (r < 0) 997f6a3c571SSasha Levin pr_warning("thread_pool__exit() failed with error %d\n", r); 998f6a3c571SSasha Levin 999495fbd4eSSasha Levin r = kvm__exit(kvm); 1000495fbd4eSSasha Levin if (r < 0) 1001495fbd4eSSasha Levin pr_warning("pci__exit() failed with error %d\n", r); 1002f967c427SPrasad Joshi 1003e1e46fe6SSasha Levin if (guest_ret == 0) 1004f967c427SPrasad Joshi printf("\n # KVM session ended normally.\n"); 1005e1e46fe6SSasha Levin } 1006e1e46fe6SSasha Levin 1007e1e46fe6SSasha Levin int kvm_cmd_run(int argc, const char **argv, const char *prefix) 1008e1e46fe6SSasha Levin { 10094932d174SSasha Levin int r, ret = -EFAULT; 1010e1e46fe6SSasha Levin 1011e1e46fe6SSasha Levin r = kvm_cmd_run_init(argc, argv); 1012e1e46fe6SSasha Levin if (r < 0) 1013e1e46fe6SSasha Levin return r; 1014e1e46fe6SSasha Levin 1015e1e46fe6SSasha Levin ret = kvm_cmd_run_work(); 1016e1e46fe6SSasha Levin kvm_cmd_run_exit(ret); 1017e1e46fe6SSasha Levin 1018e1e46fe6SSasha Levin return ret; 1019f967c427SPrasad Joshi } 1020