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" 344b1addaeSSasha Levin #include "kvm/kvm-ipc.h" 354b1c6f6eSSasha Levin #include "kvm/builtin-debug.h" 36ece09f8fSPekka Enberg 37ece09f8fSPekka Enberg #include <linux/types.h> 3848d9e01aSSasha Levin #include <linux/err.h> 39ece09f8fSPekka Enberg 408329f30bSPekka Enberg #include <sys/utsname.h> 418329f30bSPekka Enberg #include <sys/types.h> 428329f30bSPekka Enberg #include <sys/stat.h> 43ece09f8fSPekka Enberg #include <termios.h> 44ece09f8fSPekka Enberg #include <signal.h> 45ece09f8fSPekka Enberg #include <stdlib.h> 46ece09f8fSPekka Enberg #include <string.h> 47ece09f8fSPekka Enberg #include <unistd.h> 4826c853e4SPrasad Joshi #include <ctype.h> 49ece09f8fSPekka Enberg #include <stdio.h> 50f967c427SPrasad Joshi 51f967c427SPrasad Joshi #define MB_SHIFT (20) 5295d13a52SSasha Levin #define KB_SHIFT (10) 5395d13a52SSasha Levin #define GB_SHIFT (30) 54f967c427SPrasad Joshi 55656be1b8SSasha Levin __thread struct kvm_cpu *current_kvm_cpu; 56f967c427SPrasad Joshi 573c29e2aaSSasha Levin static int kvm_run_wrapper; 58f967c427SPrasad Joshi 59ed036f03SCyrill Gorcunov bool do_debug_print = false; 60ed036f03SCyrill Gorcunov 61f967c427SPrasad Joshi static const char * const run_usage[] = { 628d2ff5daSWanlong Gao "lkvm run [<options>] [<kernel image>]", 63f967c427SPrasad Joshi NULL 64f967c427SPrasad Joshi }; 65f967c427SPrasad Joshi 663c29e2aaSSasha Levin enum { 67e0747665SSasha Levin KVM_RUN_DEFAULT, 683c29e2aaSSasha Levin KVM_RUN_SANDBOX, 693c29e2aaSSasha Levin }; 703c29e2aaSSasha Levin 71a33979d8SSasha Levin static int img_name_parser(const struct option *opt, const char *arg, int unset) 72a33979d8SSasha Levin { 7382d65b5eSSasha Levin char path[PATH_MAX]; 745236b505SAsias He struct stat st; 75a33979d8SSasha Levin 769667701cSPekka Enberg snprintf(path, PATH_MAX, "%s%s", kvm__get_dir(), arg); 7782d65b5eSSasha Levin 78cac9e8fdSSasha Levin if ((stat(arg, &st) == 0 && S_ISDIR(st.st_mode)) || 79cac9e8fdSSasha Levin (stat(path, &st) == 0 && S_ISDIR(st.st_mode))) 80cac9e8fdSSasha Levin return virtio_9p_img_name_parser(opt, arg, unset); 813b55dcdeSSasha Levin return disk_img_name_parser(opt, arg, unset); 82a67da3beSAsias He } 83a67da3beSAsias He 843b55dcdeSSasha Levin void kvm_run_set_wrapper_sandbox(void) 853b55dcdeSSasha Levin { 863b55dcdeSSasha Levin kvm_run_wrapper = KVM_RUN_SANDBOX; 87a33979d8SSasha Levin } 88a33979d8SSasha Levin 89ff7ba6faSWill Deacon #ifndef OPT_ARCH_RUN 90ff7ba6faSWill Deacon #define OPT_ARCH_RUN(...) 91ff7ba6faSWill Deacon #endif 92ff7ba6faSWill Deacon 933b55dcdeSSasha Levin #define BUILD_OPTIONS(name, cfg, kvm) \ 94b816364aSSasha Levin struct option name[] = { \ 95b816364aSSasha Levin OPT_GROUP("Basic options:"), \ 96b816364aSSasha Levin OPT_STRING('\0', "name", &(cfg)->guest_name, "guest name", \ 97b816364aSSasha Levin "A name for the guest"), \ 9800ebbe96SSasha Levin OPT_INTEGER('c', "cpus", &(cfg)->nrcpus, "Number of CPUs"), \ 99b5e56fa3SWilliam Dauchy OPT_U64('m', "mem", &(cfg)->ram_size, "Virtual machine memory" \ 100b5e56fa3SWilliam Dauchy " size in MiB."), \ 101b5e56fa3SWilliam Dauchy OPT_CALLBACK('d', "disk", kvm, "image or rootfs_dir", "Disk " \ 102b5e56fa3SWilliam Dauchy " image or rootfs directory", img_name_parser, \ 1033b55dcdeSSasha Levin kvm), \ 104b5e56fa3SWilliam Dauchy OPT_BOOLEAN('\0', "balloon", &(cfg)->balloon, "Enable virtio" \ 105b5e56fa3SWilliam Dauchy " balloon"), \ 106b816364aSSasha Levin OPT_BOOLEAN('\0', "vnc", &(cfg)->vnc, "Enable VNC framebuffer"),\ 1077bcceb95SPekka Enberg OPT_BOOLEAN('\0', "gtk", &(cfg)->gtk, "Enable GTK framebuffer"),\ 108b816364aSSasha Levin OPT_BOOLEAN('\0', "sdl", &(cfg)->sdl, "Enable SDL framebuffer"),\ 109b5e56fa3SWilliam Dauchy OPT_BOOLEAN('\0', "rng", &(cfg)->virtio_rng, "Enable virtio" \ 110b5e56fa3SWilliam Dauchy " Random Number Generator"), \ 111*5613ae26SAlexandru Elisei OPT_BOOLEAN('\0', "nodefaults", &(cfg)->nodefaults, "Disable" \ 112*5613ae26SAlexandru Elisei " implicit configuration that cannot be" \ 113*5613ae26SAlexandru Elisei " disabled otherwise"), \ 114b816364aSSasha Levin OPT_CALLBACK('\0', "9p", NULL, "dir_to_share,tag_name", \ 115b5e56fa3SWilliam Dauchy "Enable virtio 9p to share files between host and" \ 116b5e56fa3SWilliam Dauchy " guest", virtio_9p_rootdir_parser, kvm), \ 117b5e56fa3SWilliam Dauchy OPT_STRING('\0', "console", &(cfg)->console, "serial, virtio or"\ 118b5e56fa3SWilliam Dauchy " hv", "Console to use"), \ 119117d6495STianjia Zhang OPT_U64('\0', "vsock", &(cfg)->vsock_cid, \ 120117d6495STianjia Zhang "Guest virtio socket CID"), \ 121b816364aSSasha Levin OPT_STRING('\0', "dev", &(cfg)->dev, "device_file", \ 122b816364aSSasha Levin "KVM device file"), \ 123b816364aSSasha Levin OPT_CALLBACK('\0', "tty", NULL, "tty id", \ 124b816364aSSasha Levin "Remap guest TTY into a pty on the host", \ 1251dc24dccSSasha Levin tty_parser, NULL), \ 126b816364aSSasha Levin OPT_STRING('\0', "sandbox", &(cfg)->sandbox, "script", \ 127b5e56fa3SWilliam Dauchy "Run this script when booting into custom" \ 128b5e56fa3SWilliam Dauchy " rootfs"), \ 129b816364aSSasha Levin OPT_STRING('\0', "hugetlbfs", &(cfg)->hugetlbfs_path, "path", \ 130b816364aSSasha Levin "Hugetlbfs path"), \ 131b816364aSSasha Levin \ 132b816364aSSasha Levin OPT_GROUP("Kernel options:"), \ 133b816364aSSasha Levin OPT_STRING('k', "kernel", &(cfg)->kernel_filename, "kernel", \ 134b816364aSSasha Levin "Kernel to boot in virtual machine"), \ 135b816364aSSasha Levin OPT_STRING('i', "initrd", &(cfg)->initrd_filename, "initrd", \ 136b816364aSSasha Levin "Initial RAM disk image"), \ 137b816364aSSasha Levin OPT_STRING('p', "params", &(cfg)->kernel_cmdline, "params", \ 138b816364aSSasha Levin "Kernel command line arguments"), \ 139b816364aSSasha Levin OPT_STRING('f', "firmware", &(cfg)->firmware_filename, "firmware",\ 140b816364aSSasha Levin "Firmware image to boot in virtual machine"), \ 14125cf3198SRaphael Gault OPT_STRING('F', "flash", &(cfg)->flash_filename, "flash",\ 14225cf3198SRaphael Gault "Flash image to present to virtual machine"), \ 143b816364aSSasha Levin \ 144b816364aSSasha Levin OPT_GROUP("Networking options:"), \ 145b816364aSSasha Levin OPT_CALLBACK_DEFAULT('n', "network", NULL, "network params", \ 146b816364aSSasha Levin "Create a new guest NIC", \ 1475f225124SSasha Levin netdev_parser, NULL, kvm), \ 148b5e56fa3SWilliam Dauchy OPT_BOOLEAN('\0', "no-dhcp", &(cfg)->no_dhcp, "Disable kernel" \ 149b5e56fa3SWilliam Dauchy " DHCP in rootfs mode"), \ 150b816364aSSasha Levin \ 1516078a454SJean-Philippe Brucker OPT_GROUP("VFIO options:"), \ 1526078a454SJean-Philippe Brucker OPT_CALLBACK('\0', "vfio-pci", NULL, "[domain:]bus:dev.fn", \ 1536078a454SJean-Philippe Brucker "Assign a PCI device to the virtual machine", \ 1546078a454SJean-Philippe Brucker vfio_device_parser, kvm), \ 1556078a454SJean-Philippe Brucker \ 156b816364aSSasha Levin OPT_GROUP("Debug options:"), \ 157b816364aSSasha Levin OPT_BOOLEAN('\0', "debug", &do_debug_print, \ 158b816364aSSasha Levin "Enable debug messages"), \ 159b816364aSSasha Levin OPT_BOOLEAN('\0', "debug-single-step", &(cfg)->single_step, \ 160b816364aSSasha Levin "Enable single stepping"), \ 1615765977dSSasha Levin OPT_BOOLEAN('\0', "debug-ioport", &(cfg)->ioport_debug, \ 162b816364aSSasha Levin "Enable ioport debugging"), \ 163e830cce7SSasha Levin OPT_BOOLEAN('\0', "debug-mmio", &(cfg)->mmio_debug, \ 164b816364aSSasha Levin "Enable MMIO debugging"), \ 1653b55dcdeSSasha Levin OPT_INTEGER('\0', "debug-iodelay", &(cfg)->debug_iodelay, \ 166b816364aSSasha Levin "Delay IO by millisecond"), \ 167ff7ba6faSWill Deacon \ 168ff7ba6faSWill Deacon OPT_ARCH(RUN, cfg) \ 169b816364aSSasha Levin OPT_END() \ 170f967c427SPrasad Joshi }; 171f967c427SPrasad Joshi 1725ee154d1SPekka Enberg static void *kvm_cpu_thread(void *arg) 1735ee154d1SPekka Enberg { 174a4d8c55eSSasha Levin char name[16]; 175a4d8c55eSSasha Levin 176d77a9efaSCyrill Gorcunov current_kvm_cpu = arg; 1775ee154d1SPekka Enberg 178a4d8c55eSSasha Levin sprintf(name, "kvm-vcpu-%lu", current_kvm_cpu->cpu_id); 179a4d8c55eSSasha Levin kvm__set_thread_name(name); 180a4d8c55eSSasha Levin 181d77a9efaSCyrill Gorcunov if (kvm_cpu__start(current_kvm_cpu)) 1825ee154d1SPekka Enberg goto panic_kvm; 1835ee154d1SPekka Enberg 1845ee154d1SPekka Enberg return (void *) (intptr_t) 0; 1855ee154d1SPekka Enberg 1865ee154d1SPekka Enberg panic_kvm: 1873fdf659dSSasha Levin fprintf(stderr, "KVM exit reason: %u (\"%s\")\n", 188d77a9efaSCyrill Gorcunov current_kvm_cpu->kvm_run->exit_reason, 189d77a9efaSCyrill Gorcunov kvm_exit_reasons[current_kvm_cpu->kvm_run->exit_reason]); 190d77a9efaSCyrill Gorcunov if (current_kvm_cpu->kvm_run->exit_reason == KVM_EXIT_UNKNOWN) 19169f50425SAndreas Herrmann fprintf(stderr, "KVM exit code: 0x%llu\n", 19269f50425SAndreas Herrmann (unsigned long long)current_kvm_cpu->kvm_run->hw.hardware_exit_reason); 1938e5accedSPekka Enberg 194b7d2f013SSasha Levin kvm_cpu__set_debug_fd(STDOUT_FILENO); 195d77a9efaSCyrill Gorcunov kvm_cpu__show_registers(current_kvm_cpu); 196d77a9efaSCyrill Gorcunov kvm_cpu__show_code(current_kvm_cpu); 197d77a9efaSCyrill Gorcunov kvm_cpu__show_page_tables(current_kvm_cpu); 1985ee154d1SPekka Enberg 1995ee154d1SPekka Enberg return (void *) (intptr_t) 1; 2005ee154d1SPekka Enberg } 2015ee154d1SPekka Enberg 202e08c0896SPrasad Joshi static char kernel[PATH_MAX]; 203b0b42ba0SPekka Enberg 204b0b42ba0SPekka Enberg static const char *host_kernels[] = { 205e08c0896SPrasad Joshi "/boot/vmlinuz", 206e08c0896SPrasad Joshi "/boot/bzImage", 207e08c0896SPrasad Joshi NULL 208e08c0896SPrasad Joshi }; 209b0b42ba0SPekka Enberg 210b0b42ba0SPekka Enberg static const char *default_kernels[] = { 211e08c0896SPrasad Joshi "./bzImage", 212b03af790SKonstantin Khlebnikov "arch/" BUILD_ARCH "/boot/bzImage", 213af7b0868SMatt Evans "../../arch/" BUILD_ARCH "/boot/bzImage", 214e08c0896SPrasad Joshi NULL 215e08c0896SPrasad Joshi }; 2168329f30bSPekka Enberg 217b0b42ba0SPekka Enberg static const char *default_vmlinux[] = { 218b03af790SKonstantin Khlebnikov "vmlinux", 219b0b42ba0SPekka Enberg "../../../vmlinux", 220b0b42ba0SPekka Enberg "../../vmlinux", 221b0b42ba0SPekka Enberg NULL 222b0b42ba0SPekka Enberg }; 223b0b42ba0SPekka Enberg 224e08c0896SPrasad Joshi static void kernel_usage_with_options(void) 2258329f30bSPekka Enberg { 226e08c0896SPrasad Joshi const char **k; 2278329f30bSPekka Enberg struct utsname uts; 228e08c0896SPrasad Joshi 229e08c0896SPrasad Joshi fprintf(stderr, "Fatal: could not find default kernel image in:\n"); 23065182f37SPrasad Joshi k = &default_kernels[0]; 231e08c0896SPrasad Joshi while (*k) { 232e08c0896SPrasad Joshi fprintf(stderr, "\t%s\n", *k); 233e08c0896SPrasad Joshi k++; 234e08c0896SPrasad Joshi } 235e08c0896SPrasad Joshi 236e08c0896SPrasad Joshi if (uname(&uts) < 0) 237e08c0896SPrasad Joshi return; 238e08c0896SPrasad Joshi 239e08c0896SPrasad Joshi k = &host_kernels[0]; 240e08c0896SPrasad Joshi while (*k) { 241e08c0896SPrasad Joshi if (snprintf(kernel, PATH_MAX, "%s-%s", *k, uts.release) < 0) 242e08c0896SPrasad Joshi return; 243e08c0896SPrasad Joshi fprintf(stderr, "\t%s\n", kernel); 244e08c0896SPrasad Joshi k++; 245e08c0896SPrasad Joshi } 246ee8b1456SWanlong Gao fprintf(stderr, "\nPlease see '%s run --help' for more options.\n\n", 247ee8b1456SWanlong Gao KVM_BINARY_NAME); 248e08c0896SPrasad Joshi } 249e08c0896SPrasad Joshi 25060ded003SPekka Enberg static u64 host_ram_size(void) 25160ded003SPekka Enberg { 25260ded003SPekka Enberg long page_size; 25360ded003SPekka Enberg long nr_pages; 25460ded003SPekka Enberg 25560ded003SPekka Enberg nr_pages = sysconf(_SC_PHYS_PAGES); 256d63c5ce6SPekka Enberg if (nr_pages < 0) { 2574542f276SCyrill Gorcunov pr_warning("sysconf(_SC_PHYS_PAGES) failed"); 258d63c5ce6SPekka Enberg return 0; 259d63c5ce6SPekka Enberg } 26060ded003SPekka Enberg 26160ded003SPekka Enberg page_size = sysconf(_SC_PAGE_SIZE); 262d63c5ce6SPekka Enberg if (page_size < 0) { 2634542f276SCyrill Gorcunov pr_warning("sysconf(_SC_PAGE_SIZE) failed"); 264d63c5ce6SPekka Enberg return 0; 265d63c5ce6SPekka Enberg } 26660ded003SPekka Enberg 26760ded003SPekka Enberg return (nr_pages * page_size) >> MB_SHIFT; 26860ded003SPekka Enberg } 26960ded003SPekka Enberg 27018bd8c3bSPekka Enberg /* 27118bd8c3bSPekka Enberg * If user didn't specify how much memory it wants to allocate for the guest, 27218bd8c3bSPekka Enberg * avoid filling the whole host RAM. 27318bd8c3bSPekka Enberg */ 27418bd8c3bSPekka Enberg #define RAM_SIZE_RATIO 0.8 27518bd8c3bSPekka Enberg 276fd834defSPekka Enberg static u64 get_ram_size(int nr_cpus) 277fd834defSPekka Enberg { 27806761c76SPekka Enberg u64 available; 27906761c76SPekka Enberg u64 ram_size; 280fd834defSPekka Enberg 281fd834defSPekka Enberg ram_size = 64 * (nr_cpus + 3); 282fd834defSPekka Enberg 28360ded003SPekka Enberg available = host_ram_size() * RAM_SIZE_RATIO; 284d63c5ce6SPekka Enberg if (!available) 285d63c5ce6SPekka Enberg available = MIN_RAM_SIZE_MB; 286fd834defSPekka Enberg 287fd834defSPekka Enberg if (ram_size > available) 288fd834defSPekka Enberg ram_size = available; 289fd834defSPekka Enberg 290fd834defSPekka Enberg return ram_size; 291fd834defSPekka Enberg } 292fd834defSPekka Enberg 293e08c0896SPrasad Joshi static const char *find_kernel(void) 294e08c0896SPrasad Joshi { 295e08c0896SPrasad Joshi const char **k; 2968329f30bSPekka Enberg struct stat st; 297e08c0896SPrasad Joshi struct utsname uts; 298e08c0896SPrasad Joshi 29965182f37SPrasad Joshi k = &default_kernels[0]; 300e08c0896SPrasad Joshi while (*k) { 301e08c0896SPrasad Joshi if (stat(*k, &st) < 0 || !S_ISREG(st.st_mode)) { 302e08c0896SPrasad Joshi k++; 303e08c0896SPrasad Joshi continue; 304e08c0896SPrasad Joshi } 305266a0ed4SAndre Przywara strlcpy(kernel, *k, PATH_MAX); 306e08c0896SPrasad Joshi return kernel; 307e08c0896SPrasad Joshi } 3088329f30bSPekka Enberg 3098329f30bSPekka Enberg if (uname(&uts) < 0) 3108329f30bSPekka Enberg return NULL; 3118329f30bSPekka Enberg 312e08c0896SPrasad Joshi k = &host_kernels[0]; 313e08c0896SPrasad Joshi while (*k) { 314e08c0896SPrasad Joshi if (snprintf(kernel, PATH_MAX, "%s-%s", *k, uts.release) < 0) 3158329f30bSPekka Enberg return NULL; 3168329f30bSPekka Enberg 317e08c0896SPrasad Joshi if (stat(kernel, &st) < 0 || !S_ISREG(st.st_mode)) { 318e08c0896SPrasad Joshi k++; 319e08c0896SPrasad Joshi continue; 320e08c0896SPrasad Joshi } 321e08c0896SPrasad Joshi return kernel; 3228329f30bSPekka Enberg 323e08c0896SPrasad Joshi } 3248329f30bSPekka Enberg return NULL; 3258329f30bSPekka Enberg } 3268329f30bSPekka Enberg 327b0b42ba0SPekka Enberg static const char *find_vmlinux(void) 328b0b42ba0SPekka Enberg { 329b0b42ba0SPekka Enberg const char **vmlinux; 330b0b42ba0SPekka Enberg 331b0b42ba0SPekka Enberg vmlinux = &default_vmlinux[0]; 332b0b42ba0SPekka Enberg while (*vmlinux) { 333b0b42ba0SPekka Enberg struct stat st; 334b0b42ba0SPekka Enberg 335b0b42ba0SPekka Enberg if (stat(*vmlinux, &st) < 0 || !S_ISREG(st.st_mode)) { 336b0b42ba0SPekka Enberg vmlinux++; 337b0b42ba0SPekka Enberg continue; 338b0b42ba0SPekka Enberg } 339b0b42ba0SPekka Enberg return *vmlinux; 340b0b42ba0SPekka Enberg } 341b0b42ba0SPekka Enberg return NULL; 342b0b42ba0SPekka Enberg } 343b0b42ba0SPekka Enberg 344f6677a1dSAmerigo Wang void kvm_run_help(void) 345f6677a1dSAmerigo Wang { 3464346fd8fSSasha Levin struct kvm *kvm = NULL; 3474346fd8fSSasha Levin 3483b55dcdeSSasha Levin BUILD_OPTIONS(options, &kvm->cfg, kvm); 349f6677a1dSAmerigo Wang usage_with_options(run_usage, options); 350f6677a1dSAmerigo Wang } 351f6677a1dSAmerigo Wang 3524346fd8fSSasha Levin static int kvm_run_set_sandbox(struct kvm *kvm) 353d50fe489SSasha Levin { 35447621338SSasha Levin const char *guestfs_name = kvm->cfg.custom_rootfs_name; 355d50fe489SSasha Levin char path[PATH_MAX], script[PATH_MAX], *tmp; 356d50fe489SSasha Levin 357d50fe489SSasha Levin snprintf(path, PATH_MAX, "%s%s/virt/sandbox.sh", kvm__get_dir(), guestfs_name); 358d50fe489SSasha Levin 359d50fe489SSasha Levin remove(path); 360d50fe489SSasha Levin 36147621338SSasha Levin if (kvm->cfg.sandbox == NULL) 362d50fe489SSasha Levin return 0; 363d50fe489SSasha Levin 36447621338SSasha Levin tmp = realpath(kvm->cfg.sandbox, NULL); 365d50fe489SSasha Levin if (tmp == NULL) 366d50fe489SSasha Levin return -ENOMEM; 367d50fe489SSasha Levin 368d50fe489SSasha Levin snprintf(script, PATH_MAX, "/host/%s", tmp); 369d50fe489SSasha Levin free(tmp); 370d50fe489SSasha Levin 371d50fe489SSasha Levin return symlink(script, path); 372d50fe489SSasha Levin } 373d50fe489SSasha Levin 3745173b4afSLai Jiangshan static void kvm_write_sandbox_cmd_exactly(int fd, const char *arg) 3755173b4afSLai Jiangshan { 3765173b4afSLai Jiangshan const char *single_quote; 3775173b4afSLai Jiangshan 3785173b4afSLai Jiangshan if (!*arg) { /* zero length string */ 3795173b4afSLai Jiangshan if (write(fd, "''", 2) <= 0) 3805173b4afSLai Jiangshan die("Failed writing sandbox script"); 3815173b4afSLai Jiangshan return; 3825173b4afSLai Jiangshan } 3835173b4afSLai Jiangshan 3845173b4afSLai Jiangshan while (*arg) { 3855173b4afSLai Jiangshan single_quote = strchrnul(arg, '\''); 3865173b4afSLai Jiangshan 3875173b4afSLai Jiangshan /* write non-single-quote string as #('string') */ 3885173b4afSLai Jiangshan if (arg != single_quote) { 3895173b4afSLai Jiangshan if (write(fd, "'", 1) <= 0 || 3905173b4afSLai Jiangshan write(fd, arg, single_quote - arg) <= 0 || 3915173b4afSLai Jiangshan write(fd, "'", 1) <= 0) 3925173b4afSLai Jiangshan die("Failed writing sandbox script"); 3935173b4afSLai Jiangshan } 3945173b4afSLai Jiangshan 3955173b4afSLai Jiangshan /* write single quote as #("'") */ 3965173b4afSLai Jiangshan if (*single_quote) { 3975173b4afSLai Jiangshan if (write(fd, "\"'\"", 3) <= 0) 3985173b4afSLai Jiangshan die("Failed writing sandbox script"); 3995173b4afSLai Jiangshan } else 4005173b4afSLai Jiangshan break; 4015173b4afSLai Jiangshan 4025173b4afSLai Jiangshan arg = single_quote + 1; 4035173b4afSLai Jiangshan } 4045173b4afSLai Jiangshan } 4055173b4afSLai Jiangshan 4065cd19aa0SPekka Enberg static void resolve_program(const char *src, char *dst, size_t len) 4075cd19aa0SPekka Enberg { 4085cd19aa0SPekka Enberg struct stat st; 409c2c742d9SPekka Enberg int err; 4105cd19aa0SPekka Enberg 411c2c742d9SPekka Enberg err = stat(src, &st); 4125cd19aa0SPekka Enberg 413c2c742d9SPekka Enberg if (!err && S_ISREG(st.st_mode)) { 4145cd19aa0SPekka Enberg char resolved_path[PATH_MAX]; 4155cd19aa0SPekka Enberg 416de3f75c9SPekka Enberg if (!realpath(src, resolved_path)) 417de3f75c9SPekka Enberg die("Unable to resolve program %s: %s\n", src, strerror(errno)); 4185cd19aa0SPekka Enberg 41996eda741SAnisse Astier if (snprintf(dst, len, "/host%s", resolved_path) >= (int)len) 42096eda741SAnisse Astier die("Pathname too long: %s -> %s\n", src, resolved_path); 42196eda741SAnisse Astier 4225cd19aa0SPekka Enberg } else 423266a0ed4SAndre Przywara strlcpy(dst, src, len); 4245cd19aa0SPekka Enberg } 4255cd19aa0SPekka Enberg 4264346fd8fSSasha Levin static void kvm_run_write_sandbox_cmd(struct kvm *kvm, const char **argv, int argc) 4273c29e2aaSSasha Levin { 4283c29e2aaSSasha Levin const char script_hdr[] = "#! /bin/bash\n\n"; 4295cd19aa0SPekka Enberg char program[PATH_MAX]; 4303c29e2aaSSasha Levin int fd; 4313c29e2aaSSasha Levin 43247621338SSasha Levin remove(kvm->cfg.sandbox); 4333c29e2aaSSasha Levin 43447621338SSasha Levin fd = open(kvm->cfg.sandbox, O_RDWR | O_CREAT, 0777); 4353c29e2aaSSasha Levin if (fd < 0) 4363c29e2aaSSasha Levin die("Failed creating sandbox script"); 4373c29e2aaSSasha Levin 4383c29e2aaSSasha Levin if (write(fd, script_hdr, sizeof(script_hdr) - 1) <= 0) 4393c29e2aaSSasha Levin die("Failed writing sandbox script"); 4403c29e2aaSSasha Levin 4415cd19aa0SPekka Enberg resolve_program(argv[0], program, PATH_MAX); 4425cd19aa0SPekka Enberg kvm_write_sandbox_cmd_exactly(fd, program); 4435cd19aa0SPekka Enberg 4445cd19aa0SPekka Enberg argv++; 4455cd19aa0SPekka Enberg argc--; 4465cd19aa0SPekka Enberg 4473c29e2aaSSasha Levin while (argc) { 4483c29e2aaSSasha Levin if (write(fd, " ", 1) <= 0) 4493c29e2aaSSasha Levin die("Failed writing sandbox script"); 4505cd19aa0SPekka Enberg 4515cd19aa0SPekka Enberg kvm_write_sandbox_cmd_exactly(fd, argv[0]); 4523c29e2aaSSasha Levin argv++; 4533c29e2aaSSasha Levin argc--; 4543c29e2aaSSasha Levin } 4553c29e2aaSSasha Levin if (write(fd, "\n", 1) <= 0) 4563c29e2aaSSasha Levin die("Failed writing sandbox script"); 4573c29e2aaSSasha Levin 4583c29e2aaSSasha Levin close(fd); 4593c29e2aaSSasha Levin } 4603c29e2aaSSasha Levin 461a5253f7cSAlexandru Elisei static void kvm_run_set_real_cmdline(struct kvm *kvm) 462a5253f7cSAlexandru Elisei { 463a5253f7cSAlexandru Elisei static char real_cmdline[2048]; 464a5253f7cSAlexandru Elisei bool video; 465a5253f7cSAlexandru Elisei 466a5253f7cSAlexandru Elisei video = kvm->cfg.vnc || kvm->cfg.sdl || kvm->cfg.gtk; 467a5253f7cSAlexandru Elisei 468a5253f7cSAlexandru Elisei memset(real_cmdline, 0, sizeof(real_cmdline)); 469a5253f7cSAlexandru Elisei kvm__arch_set_cmdline(real_cmdline, video); 470a5253f7cSAlexandru Elisei 471a5253f7cSAlexandru Elisei if (video) { 472a5253f7cSAlexandru Elisei strcat(real_cmdline, " console=tty0"); 473a5253f7cSAlexandru Elisei } else { 474a5253f7cSAlexandru Elisei switch (kvm->cfg.active_console) { 475a5253f7cSAlexandru Elisei case CONSOLE_HV: 476a5253f7cSAlexandru Elisei /* Fallthrough */ 477a5253f7cSAlexandru Elisei case CONSOLE_VIRTIO: 478a5253f7cSAlexandru Elisei strcat(real_cmdline, " console=hvc0"); 479a5253f7cSAlexandru Elisei break; 480a5253f7cSAlexandru Elisei case CONSOLE_8250: 481a5253f7cSAlexandru Elisei strcat(real_cmdline, " console=ttyS0"); 482a5253f7cSAlexandru Elisei break; 483a5253f7cSAlexandru Elisei } 484a5253f7cSAlexandru Elisei } 485a5253f7cSAlexandru Elisei 486a5253f7cSAlexandru Elisei if (kvm->cfg.using_rootfs) { 487a5253f7cSAlexandru Elisei strcat(real_cmdline, " rw rootflags=trans=virtio,version=9p2000.L,cache=loose rootfstype=9p"); 488a5253f7cSAlexandru Elisei if (kvm->cfg.custom_rootfs) { 489a5253f7cSAlexandru Elisei #ifdef CONFIG_GUEST_PRE_INIT 490a5253f7cSAlexandru Elisei strcat(real_cmdline, " init=/virt/pre_init"); 491a5253f7cSAlexandru Elisei #else 492a5253f7cSAlexandru Elisei strcat(real_cmdline, " init=/virt/init"); 493a5253f7cSAlexandru Elisei #endif 494a5253f7cSAlexandru Elisei if (!kvm->cfg.no_dhcp) 495a5253f7cSAlexandru Elisei strcat(real_cmdline, " ip=dhcp"); 496a5253f7cSAlexandru Elisei } 497a5253f7cSAlexandru Elisei } else if (!kvm->cfg.kernel_cmdline || !strstr(kvm->cfg.kernel_cmdline, "root=")) { 498a5253f7cSAlexandru Elisei strlcat(real_cmdline, " root=/dev/vda rw ", sizeof(real_cmdline)); 499a5253f7cSAlexandru Elisei } 500a5253f7cSAlexandru Elisei 501a5253f7cSAlexandru Elisei if (kvm->cfg.kernel_cmdline) { 502a5253f7cSAlexandru Elisei strcat(real_cmdline, " "); 503a5253f7cSAlexandru Elisei strlcat(real_cmdline, kvm->cfg.kernel_cmdline, sizeof(real_cmdline)); 504a5253f7cSAlexandru Elisei } 505a5253f7cSAlexandru Elisei 506a5253f7cSAlexandru Elisei kvm->cfg.real_cmdline = real_cmdline; 507a5253f7cSAlexandru Elisei } 508a5253f7cSAlexandru Elisei 509cce96164SAlexandru Elisei static void kvm_run_validate_cfg(struct kvm *kvm) 510cce96164SAlexandru Elisei { 511cce96164SAlexandru Elisei if (kvm->cfg.kernel_filename && kvm->cfg.firmware_filename) 512cce96164SAlexandru Elisei die("Only one of --kernel or --firmware can be specified"); 513cce96164SAlexandru Elisei 514cce96164SAlexandru Elisei if ((kvm->cfg.vnc && (kvm->cfg.sdl || kvm->cfg.gtk)) || 515cce96164SAlexandru Elisei (kvm->cfg.sdl && kvm->cfg.gtk)) 516cce96164SAlexandru Elisei die("Only one of --vnc, --sdl or --gtk can be specified"); 517cce96164SAlexandru Elisei 518cce96164SAlexandru Elisei if (kvm->cfg.firmware_filename && kvm->cfg.initrd_filename) 519cce96164SAlexandru Elisei pr_warning("Ignoring initrd file when loading a firmware image"); 520cce96164SAlexandru Elisei } 521cce96164SAlexandru Elisei 5224346fd8fSSasha Levin static struct kvm *kvm_cmd_run_init(int argc, const char **argv) 523f967c427SPrasad Joshi { 524a5253f7cSAlexandru Elisei static char default_name[20]; 525384922b3SPekka Enberg unsigned int nr_online_cpus; 5264346fd8fSSasha Levin struct kvm *kvm = kvm__new(); 52747621338SSasha Levin 52847621338SSasha Levin if (IS_ERR(kvm)) 5294346fd8fSSasha Levin return kvm; 530f967c427SPrasad Joshi 531cfd63bbbSSasha Levin nr_online_cpus = sysconf(_SC_NPROCESSORS_ONLN); 53247621338SSasha Levin kvm->cfg.custom_rootfs_name = "default"; 533cfd63bbbSSasha Levin 534f967c427SPrasad Joshi while (argc != 0) { 5353b55dcdeSSasha Levin BUILD_OPTIONS(options, &kvm->cfg, kvm); 536f967c427SPrasad Joshi argc = parse_options(argc, argv, options, run_usage, 5371a007c82SSasha Levin PARSE_OPT_STOP_AT_NON_OPTION | 5381a007c82SSasha Levin PARSE_OPT_KEEP_DASHDASH); 539f967c427SPrasad Joshi if (argc != 0) { 5401a007c82SSasha Levin /* Cusrom options, should have been handled elsewhere */ 5413c29e2aaSSasha Levin if (strcmp(argv[0], "--") == 0) { 5423c29e2aaSSasha Levin if (kvm_run_wrapper == KVM_RUN_SANDBOX) { 54347621338SSasha Levin kvm->cfg.sandbox = DEFAULT_SANDBOX_FILENAME; 5444346fd8fSSasha Levin kvm_run_write_sandbox_cmd(kvm, argv+1, argc-1); 5451a007c82SSasha Levin break; 5463c29e2aaSSasha Levin } 5473c29e2aaSSasha Levin } 5481a007c82SSasha Levin 54947621338SSasha Levin if ((kvm_run_wrapper == KVM_RUN_DEFAULT && kvm->cfg.kernel_filename) || 55047621338SSasha Levin (kvm_run_wrapper == KVM_RUN_SANDBOX && kvm->cfg.sandbox)) { 551f967c427SPrasad Joshi fprintf(stderr, "Cannot handle parameter: " 552f967c427SPrasad Joshi "%s\n", argv[0]); 553f967c427SPrasad Joshi usage_with_options(run_usage, options); 55447621338SSasha Levin free(kvm); 5554346fd8fSSasha Levin return ERR_PTR(-EINVAL); 556f967c427SPrasad Joshi } 557e0747665SSasha Levin if (kvm_run_wrapper == KVM_RUN_SANDBOX) { 558e0747665SSasha Levin /* 559e0747665SSasha Levin * first unhandled parameter is treated as 560e0747665SSasha Levin * sandbox command 561e0747665SSasha Levin */ 56247621338SSasha Levin kvm->cfg.sandbox = DEFAULT_SANDBOX_FILENAME; 5634346fd8fSSasha Levin kvm_run_write_sandbox_cmd(kvm, argv, argc); 564e0747665SSasha Levin } else { 565e0747665SSasha Levin /* 566e0747665SSasha Levin * first unhandled parameter is treated as a kernel 567e0747665SSasha Levin * image 568f967c427SPrasad Joshi */ 56947621338SSasha Levin kvm->cfg.kernel_filename = argv[0]; 570e0747665SSasha Levin } 571f967c427SPrasad Joshi argv++; 572f967c427SPrasad Joshi argc--; 573f967c427SPrasad Joshi } 574f967c427SPrasad Joshi 575f967c427SPrasad Joshi } 576f967c427SPrasad Joshi 577cce96164SAlexandru Elisei kvm_run_validate_cfg(kvm); 578cce96164SAlexandru Elisei 57913498576SJulien Thierry if (!kvm->cfg.kernel_filename && !kvm->cfg.firmware_filename) { 58047621338SSasha Levin kvm->cfg.kernel_filename = find_kernel(); 5818329f30bSPekka Enberg 58247621338SSasha Levin if (!kvm->cfg.kernel_filename) { 583e08c0896SPrasad Joshi kernel_usage_with_options(); 5844346fd8fSSasha Levin return ERR_PTR(-EINVAL); 5858329f30bSPekka Enberg } 58613498576SJulien Thierry } 5878329f30bSPekka Enberg 588638630c9SAlexandru Elisei if (kvm->cfg.kernel_filename) { 58947621338SSasha Levin kvm->cfg.vmlinux_filename = find_vmlinux(); 590084a1356SSasha Levin kvm->vmlinux = kvm->cfg.vmlinux_filename; 591638630c9SAlexandru Elisei } 592b0b42ba0SPekka Enberg 59300ebbe96SSasha Levin if (kvm->cfg.nrcpus == 0) 59400ebbe96SSasha Levin kvm->cfg.nrcpus = nr_online_cpus; 595d77a9efaSCyrill Gorcunov 59647621338SSasha Levin if (!kvm->cfg.ram_size) 59700ebbe96SSasha Levin kvm->cfg.ram_size = get_ram_size(kvm->cfg.nrcpus); 598fd834defSPekka Enberg 59947621338SSasha Levin if (kvm->cfg.ram_size > host_ram_size()) 60069f50425SAndreas Herrmann pr_warning("Guest memory size %lluMB exceeds host physical RAM size %lluMB", 60169f50425SAndreas Herrmann (unsigned long long)kvm->cfg.ram_size, 60269f50425SAndreas Herrmann (unsigned long long)host_ram_size()); 60360ded003SPekka Enberg 60447621338SSasha Levin kvm->cfg.ram_size <<= MB_SHIFT; 605f967c427SPrasad Joshi 60647621338SSasha Levin if (!kvm->cfg.dev) 60747621338SSasha Levin kvm->cfg.dev = DEFAULT_KVM_DEV; 608f967c427SPrasad Joshi 60947621338SSasha Levin if (!kvm->cfg.console) 61047621338SSasha Levin kvm->cfg.console = DEFAULT_CONSOLE; 6119aa4a0ebSAsias He 61247621338SSasha Levin if (!strncmp(kvm->cfg.console, "virtio", 6)) 6132651ea58SSasha Levin kvm->cfg.active_console = CONSOLE_VIRTIO; 61447621338SSasha Levin else if (!strncmp(kvm->cfg.console, "serial", 6)) 6152651ea58SSasha Levin kvm->cfg.active_console = CONSOLE_8250; 61647621338SSasha Levin else if (!strncmp(kvm->cfg.console, "hv", 2)) 6172651ea58SSasha Levin kvm->cfg.active_console = CONSOLE_HV; 6183bbc49b6SMatt Evans else 6193bbc49b6SMatt Evans pr_warning("No console!"); 620f967c427SPrasad Joshi 62147621338SSasha Levin if (!kvm->cfg.host_ip) 62247621338SSasha Levin kvm->cfg.host_ip = DEFAULT_HOST_ADDR; 6234d67c820SSasha Levin 62447621338SSasha Levin if (!kvm->cfg.guest_ip) 62547621338SSasha Levin kvm->cfg.guest_ip = DEFAULT_GUEST_ADDR; 626bb8ffd2fSAsias He 62747621338SSasha Levin if (!kvm->cfg.guest_mac) 62847621338SSasha Levin kvm->cfg.guest_mac = DEFAULT_GUEST_MAC; 629a4e724ddSSasha Levin 63047621338SSasha Levin if (!kvm->cfg.host_mac) 63147621338SSasha Levin kvm->cfg.host_mac = DEFAULT_HOST_MAC; 632d7098b9bSAsias He 63347621338SSasha Levin if (!kvm->cfg.script) 63447621338SSasha Levin kvm->cfg.script = DEFAULT_SCRIPT; 63573b7d038SAmos Kong 636cf5323a3SSasha Levin if (!kvm->cfg.network) 637cf5323a3SSasha Levin kvm->cfg.network = DEFAULT_NETWORK; 638cf5323a3SSasha Levin 63947621338SSasha Levin if (!kvm->cfg.guest_name) { 64047621338SSasha Levin if (kvm->cfg.custom_rootfs) { 64147621338SSasha Levin kvm->cfg.guest_name = kvm->cfg.custom_rootfs_name; 642587a4d17SLai Jiangshan } else { 6432d96f6b6SSasha Levin sprintf(default_name, "guest-%u", getpid()); 64447621338SSasha Levin kvm->cfg.guest_name = default_name; 6452d96f6b6SSasha Levin } 646587a4d17SLai Jiangshan } 6472d96f6b6SSasha Levin 648*5613ae26SAlexandru Elisei if (!kvm->cfg.nodefaults && 649*5613ae26SAlexandru Elisei !kvm->cfg.using_rootfs && 650*5613ae26SAlexandru Elisei !kvm->cfg.disk_image[0].filename && 651*5613ae26SAlexandru Elisei !kvm->cfg.initrd_filename) { 652c8675741SSasha Levin char tmp[PATH_MAX]; 6536df1471eSPekka Enberg 65447621338SSasha Levin kvm_setup_create_new(kvm->cfg.custom_rootfs_name); 65547621338SSasha Levin kvm_setup_resolv(kvm->cfg.custom_rootfs_name); 656c8675741SSasha Levin 6579667701cSPekka Enberg snprintf(tmp, PATH_MAX, "%s%s", kvm__get_dir(), "default"); 658c8675741SSasha Levin if (virtio_9p__register(kvm, tmp, "/dev/root") < 0) 659c8675741SSasha Levin die("Unable to initialize virtio 9p"); 660c8675741SSasha Levin if (virtio_9p__register(kvm, "/", "hostfs") < 0) 661c8675741SSasha Levin die("Unable to initialize virtio 9p"); 66247621338SSasha Levin kvm->cfg.using_rootfs = kvm->cfg.custom_rootfs = 1; 66326c853e4SPrasad Joshi } 66426c853e4SPrasad Joshi 66547621338SSasha Levin if (kvm->cfg.custom_rootfs) { 6664346fd8fSSasha Levin kvm_run_set_sandbox(kvm); 667cdce942cSDimitri John Ledkov if (kvm_setup_guest_init(kvm->cfg.custom_rootfs_name)) 668afc2c7c0SAsias He die("Failed to setup init for guest."); 669a8e6b4b9SSasha Levin } 67059aa2d30SSasha Levin 671*5613ae26SAlexandru Elisei if (kvm->cfg.nodefaults) 672*5613ae26SAlexandru Elisei kvm->cfg.real_cmdline = kvm->cfg.kernel_cmdline; 673*5613ae26SAlexandru Elisei else 674a5253f7cSAlexandru Elisei kvm_run_set_real_cmdline(kvm); 675084a1356SSasha Levin 67613498576SJulien Thierry if (kvm->cfg.kernel_filename) { 677084a1356SSasha Levin printf(" # %s run -k %s -m %Lu -c %d --name %s\n", KVM_BINARY_NAME, 67869f50425SAndreas Herrmann kvm->cfg.kernel_filename, 67969f50425SAndreas Herrmann (unsigned long long)kvm->cfg.ram_size / 1024 / 1024, 68069f50425SAndreas Herrmann kvm->cfg.nrcpus, kvm->cfg.guest_name); 68113498576SJulien Thierry } else if (kvm->cfg.firmware_filename) { 68213498576SJulien Thierry printf(" # %s run --firmware %s -m %Lu -c %d --name %s\n", KVM_BINARY_NAME, 68313498576SJulien Thierry kvm->cfg.firmware_filename, 68413498576SJulien Thierry (unsigned long long)kvm->cfg.ram_size / 1024 / 1024, 68513498576SJulien Thierry kvm->cfg.nrcpus, kvm->cfg.guest_name); 68613498576SJulien Thierry } 687084a1356SSasha Levin 6885b403dbfSWill Deacon if (init_list__init(kvm) < 0) 6895b403dbfSWill Deacon die ("Initialisation failed"); 6904346fd8fSSasha Levin 6914346fd8fSSasha Levin return kvm; 692e1e46fe6SSasha Levin } 693e1e46fe6SSasha Levin 6944346fd8fSSasha Levin static int kvm_cmd_run_work(struct kvm *kvm) 695e1e46fe6SSasha Levin { 696df4239fbSSasha Levin int i; 697e1e46fe6SSasha Levin 69800ebbe96SSasha Levin for (i = 0; i < kvm->nrcpus; i++) { 699df4239fbSSasha Levin if (pthread_create(&kvm->cpus[i]->thread, NULL, kvm_cpu_thread, kvm->cpus[i]) != 0) 7005ee154d1SPekka Enberg die("unable to create KVM VCPU thread"); 7015ee154d1SPekka Enberg } 7025ee154d1SPekka Enberg 70349e5227dSSasha Levin /* Only VCPU #0 is going to exit by itself when shutting down */ 704e8cb90fbSWill Deacon if (pthread_join(kvm->cpus[0]->thread, NULL) != 0) 705e8cb90fbSWill Deacon die("unable to join with vcpu 0"); 706e8cb90fbSWill Deacon 707e8cb90fbSWill Deacon return kvm_cpu__exit(kvm); 708e1e46fe6SSasha Levin } 709e1e46fe6SSasha Levin 7104346fd8fSSasha Levin static void kvm_cmd_run_exit(struct kvm *kvm, int guest_ret) 711e1e46fe6SSasha Levin { 712e6694207SSasha Levin compat__print_all_messages(); 713e6694207SSasha Levin 71449a8afd1SSasha Levin init_list__exit(kvm); 715f967c427SPrasad Joshi 716e1e46fe6SSasha Levin if (guest_ret == 0) 717f967c427SPrasad Joshi printf("\n # KVM session ended normally.\n"); 718e1e46fe6SSasha Levin } 719e1e46fe6SSasha Levin 720e1e46fe6SSasha Levin int kvm_cmd_run(int argc, const char **argv, const char *prefix) 721e1e46fe6SSasha Levin { 7224346fd8fSSasha Levin int ret = -EFAULT; 7234346fd8fSSasha Levin struct kvm *kvm; 724e1e46fe6SSasha Levin 7254346fd8fSSasha Levin kvm = kvm_cmd_run_init(argc, argv); 7264346fd8fSSasha Levin if (IS_ERR(kvm)) 7274346fd8fSSasha Levin return PTR_ERR(kvm); 728e1e46fe6SSasha Levin 7294346fd8fSSasha Levin ret = kvm_cmd_run_work(kvm); 7304346fd8fSSasha Levin kvm_cmd_run_exit(kvm, ret); 731e1e46fe6SSasha Levin 732e1e46fe6SSasha Levin return ret; 733f967c427SPrasad Joshi } 734