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 63afc2c7c0SAsias He extern char _binary_guest_init_start; 64afc2c7c0SAsias He extern char _binary_guest_init_size; 65afc2c7c0SAsias He 66f967c427SPrasad Joshi static const char * const run_usage[] = { 678d2ff5daSWanlong Gao "lkvm run [<options>] [<kernel image>]", 68f967c427SPrasad Joshi NULL 69f967c427SPrasad Joshi }; 70f967c427SPrasad Joshi 713c29e2aaSSasha Levin enum { 72e0747665SSasha Levin KVM_RUN_DEFAULT, 733c29e2aaSSasha Levin KVM_RUN_SANDBOX, 743c29e2aaSSasha Levin }; 753c29e2aaSSasha Levin 76a33979d8SSasha Levin static int img_name_parser(const struct option *opt, const char *arg, int unset) 77a33979d8SSasha Levin { 7882d65b5eSSasha Levin char path[PATH_MAX]; 795236b505SAsias He struct stat st; 80a33979d8SSasha Levin 819667701cSPekka Enberg snprintf(path, PATH_MAX, "%s%s", kvm__get_dir(), arg); 8282d65b5eSSasha Levin 83*cac9e8fdSSasha Levin if ((stat(arg, &st) == 0 && S_ISDIR(st.st_mode)) || 84*cac9e8fdSSasha Levin (stat(path, &st) == 0 && S_ISDIR(st.st_mode))) 85*cac9e8fdSSasha Levin return virtio_9p_img_name_parser(opt, arg, unset); 863b55dcdeSSasha Levin return disk_img_name_parser(opt, arg, unset); 87a67da3beSAsias He } 88a67da3beSAsias He 893b55dcdeSSasha Levin void kvm_run_set_wrapper_sandbox(void) 903b55dcdeSSasha Levin { 913b55dcdeSSasha Levin kvm_run_wrapper = KVM_RUN_SANDBOX; 92a33979d8SSasha Levin } 93a33979d8SSasha Levin 943b55dcdeSSasha Levin #define BUILD_OPTIONS(name, cfg, kvm) \ 95b816364aSSasha Levin struct option name[] = { \ 96b816364aSSasha Levin OPT_GROUP("Basic options:"), \ 97b816364aSSasha Levin OPT_STRING('\0', "name", &(cfg)->guest_name, "guest name", \ 98b816364aSSasha Levin "A name for the guest"), \ 9900ebbe96SSasha Levin OPT_INTEGER('c', "cpus", &(cfg)->nrcpus, "Number of CPUs"), \ 100b816364aSSasha Levin OPT_U64('m', "mem", &(cfg)->ram_size, "Virtual machine memory size\ 101b816364aSSasha Levin in MiB."), \ 102b816364aSSasha Levin OPT_CALLBACK('\0', "shmem", NULL, \ 103b816364aSSasha Levin "[pci:]<addr>:<size>[:handle=<handle>][:create]", \ 104b816364aSSasha Levin "Share host shmem with guest via pci device", \ 1051dc24dccSSasha Levin shmem_parser, NULL), \ 1061dc24dccSSasha Levin OPT_CALLBACK('d', "disk", kvm, "image or rootfs_dir", "Disk \ 1071dc24dccSSasha Levin image or rootfs directory", img_name_parser, \ 1083b55dcdeSSasha Levin kvm), \ 109b816364aSSasha Levin OPT_BOOLEAN('\0', "balloon", &(cfg)->balloon, "Enable virtio \ 110b816364aSSasha Levin balloon"), \ 111b816364aSSasha Levin OPT_BOOLEAN('\0', "vnc", &(cfg)->vnc, "Enable VNC framebuffer"),\ 112b816364aSSasha Levin OPT_BOOLEAN('\0', "sdl", &(cfg)->sdl, "Enable SDL framebuffer"),\ 113b816364aSSasha Levin OPT_BOOLEAN('\0', "rng", &(cfg)->virtio_rng, "Enable virtio Random\ 114b816364aSSasha Levin Number Generator"), \ 115b816364aSSasha Levin OPT_CALLBACK('\0', "9p", NULL, "dir_to_share,tag_name", \ 116b816364aSSasha Levin "Enable virtio 9p to share files between host and \ 117*cac9e8fdSSasha Levin guest", virtio_9p_rootdir_parser, kvm), \ 118b816364aSSasha Levin OPT_STRING('\0', "console", &(cfg)->console, "serial, virtio or \ 119b816364aSSasha Levin hv", "Console to use"), \ 120b816364aSSasha Levin OPT_STRING('\0', "dev", &(cfg)->dev, "device_file", \ 121b816364aSSasha Levin "KVM device file"), \ 122b816364aSSasha Levin OPT_CALLBACK('\0', "tty", NULL, "tty id", \ 123b816364aSSasha Levin "Remap guest TTY into a pty on the host", \ 1241dc24dccSSasha Levin tty_parser, NULL), \ 125b816364aSSasha Levin OPT_STRING('\0', "sandbox", &(cfg)->sandbox, "script", \ 126b816364aSSasha Levin "Run this script when booting into custom \ 127b816364aSSasha Levin rootfs"), \ 128b816364aSSasha Levin OPT_STRING('\0', "hugetlbfs", &(cfg)->hugetlbfs_path, "path", \ 129b816364aSSasha Levin "Hugetlbfs path"), \ 130b816364aSSasha Levin \ 131b816364aSSasha Levin OPT_GROUP("Kernel options:"), \ 132b816364aSSasha Levin OPT_STRING('k', "kernel", &(cfg)->kernel_filename, "kernel", \ 133b816364aSSasha Levin "Kernel to boot in virtual machine"), \ 134b816364aSSasha Levin OPT_STRING('i', "initrd", &(cfg)->initrd_filename, "initrd", \ 135b816364aSSasha Levin "Initial RAM disk image"), \ 136b816364aSSasha Levin OPT_STRING('p', "params", &(cfg)->kernel_cmdline, "params", \ 137b816364aSSasha Levin "Kernel command line arguments"), \ 138b816364aSSasha Levin OPT_STRING('f', "firmware", &(cfg)->firmware_filename, "firmware",\ 139b816364aSSasha Levin "Firmware image to boot in virtual machine"), \ 140b816364aSSasha Levin \ 141b816364aSSasha Levin OPT_GROUP("Networking options:"), \ 142b816364aSSasha Levin OPT_CALLBACK_DEFAULT('n', "network", NULL, "network params", \ 143b816364aSSasha Levin "Create a new guest NIC", \ 1445f225124SSasha Levin netdev_parser, NULL, kvm), \ 145b816364aSSasha Levin OPT_BOOLEAN('\0', "no-dhcp", &(cfg)->no_dhcp, "Disable kernel DHCP\ 146b816364aSSasha Levin in rootfs mode"), \ 147b816364aSSasha Levin \ 148b816364aSSasha Levin OPT_GROUP("BIOS options:"), \ 14907d52d77SSasha Levin OPT_INTEGER('\0', "vidmode", &(cfg)->vidmode, \ 150b816364aSSasha Levin "Video mode"), \ 151b816364aSSasha Levin \ 152b816364aSSasha Levin OPT_GROUP("Debug options:"), \ 153b816364aSSasha Levin OPT_BOOLEAN('\0', "debug", &do_debug_print, \ 154b816364aSSasha Levin "Enable debug messages"), \ 155b816364aSSasha Levin OPT_BOOLEAN('\0', "debug-single-step", &(cfg)->single_step, \ 156b816364aSSasha Levin "Enable single stepping"), \ 1575765977dSSasha Levin OPT_BOOLEAN('\0', "debug-ioport", &(cfg)->ioport_debug, \ 158b816364aSSasha Levin "Enable ioport debugging"), \ 159e830cce7SSasha Levin OPT_BOOLEAN('\0', "debug-mmio", &(cfg)->mmio_debug, \ 160b816364aSSasha Levin "Enable MMIO debugging"), \ 1613b55dcdeSSasha Levin OPT_INTEGER('\0', "debug-iodelay", &(cfg)->debug_iodelay, \ 162b816364aSSasha Levin "Delay IO by millisecond"), \ 163b816364aSSasha Levin OPT_END() \ 164f967c427SPrasad Joshi }; 165f967c427SPrasad Joshi 1669e854d1aSPekka Enberg static void handle_sigalrm(int sig) 1679e854d1aSPekka Enberg { 1680b69bdefSMatt Evans kvm__arch_periodic_poll(kvm); 1699e854d1aSPekka Enberg } 1709e854d1aSPekka Enberg 1715ee154d1SPekka Enberg static void *kvm_cpu_thread(void *arg) 1725ee154d1SPekka Enberg { 173d77a9efaSCyrill Gorcunov current_kvm_cpu = arg; 1745ee154d1SPekka Enberg 175d77a9efaSCyrill Gorcunov if (kvm_cpu__start(current_kvm_cpu)) 1765ee154d1SPekka Enberg goto panic_kvm; 1775ee154d1SPekka Enberg 1785ee154d1SPekka Enberg return (void *) (intptr_t) 0; 1795ee154d1SPekka Enberg 1805ee154d1SPekka Enberg panic_kvm: 1813fdf659dSSasha Levin fprintf(stderr, "KVM exit reason: %u (\"%s\")\n", 182d77a9efaSCyrill Gorcunov current_kvm_cpu->kvm_run->exit_reason, 183d77a9efaSCyrill Gorcunov kvm_exit_reasons[current_kvm_cpu->kvm_run->exit_reason]); 184d77a9efaSCyrill Gorcunov if (current_kvm_cpu->kvm_run->exit_reason == KVM_EXIT_UNKNOWN) 1855ee154d1SPekka Enberg fprintf(stderr, "KVM exit code: 0x%Lu\n", 186d77a9efaSCyrill Gorcunov current_kvm_cpu->kvm_run->hw.hardware_exit_reason); 1878e5accedSPekka Enberg 188b7d2f013SSasha Levin kvm_cpu__set_debug_fd(STDOUT_FILENO); 189d77a9efaSCyrill Gorcunov kvm_cpu__show_registers(current_kvm_cpu); 190d77a9efaSCyrill Gorcunov kvm_cpu__show_code(current_kvm_cpu); 191d77a9efaSCyrill Gorcunov kvm_cpu__show_page_tables(current_kvm_cpu); 1925ee154d1SPekka Enberg 1935ee154d1SPekka Enberg return (void *) (intptr_t) 1; 1945ee154d1SPekka Enberg } 1955ee154d1SPekka Enberg 196e08c0896SPrasad Joshi static char kernel[PATH_MAX]; 197b0b42ba0SPekka Enberg 198b0b42ba0SPekka Enberg static const char *host_kernels[] = { 199e08c0896SPrasad Joshi "/boot/vmlinuz", 200e08c0896SPrasad Joshi "/boot/bzImage", 201e08c0896SPrasad Joshi NULL 202e08c0896SPrasad Joshi }; 203b0b42ba0SPekka Enberg 204b0b42ba0SPekka Enberg static const char *default_kernels[] = { 205e08c0896SPrasad Joshi "./bzImage", 206b03af790SKonstantin Khlebnikov "arch/" BUILD_ARCH "/boot/bzImage", 207af7b0868SMatt Evans "../../arch/" BUILD_ARCH "/boot/bzImage", 208e08c0896SPrasad Joshi NULL 209e08c0896SPrasad Joshi }; 2108329f30bSPekka Enberg 211b0b42ba0SPekka Enberg static const char *default_vmlinux[] = { 212b03af790SKonstantin Khlebnikov "vmlinux", 213b0b42ba0SPekka Enberg "../../../vmlinux", 214b0b42ba0SPekka Enberg "../../vmlinux", 215b0b42ba0SPekka Enberg NULL 216b0b42ba0SPekka Enberg }; 217b0b42ba0SPekka Enberg 218e08c0896SPrasad Joshi static void kernel_usage_with_options(void) 2198329f30bSPekka Enberg { 220e08c0896SPrasad Joshi const char **k; 2218329f30bSPekka Enberg struct utsname uts; 222e08c0896SPrasad Joshi 223e08c0896SPrasad Joshi fprintf(stderr, "Fatal: could not find default kernel image in:\n"); 22465182f37SPrasad Joshi k = &default_kernels[0]; 225e08c0896SPrasad Joshi while (*k) { 226e08c0896SPrasad Joshi fprintf(stderr, "\t%s\n", *k); 227e08c0896SPrasad Joshi k++; 228e08c0896SPrasad Joshi } 229e08c0896SPrasad Joshi 230e08c0896SPrasad Joshi if (uname(&uts) < 0) 231e08c0896SPrasad Joshi return; 232e08c0896SPrasad Joshi 233e08c0896SPrasad Joshi k = &host_kernels[0]; 234e08c0896SPrasad Joshi while (*k) { 235e08c0896SPrasad Joshi if (snprintf(kernel, PATH_MAX, "%s-%s", *k, uts.release) < 0) 236e08c0896SPrasad Joshi return; 237e08c0896SPrasad Joshi fprintf(stderr, "\t%s\n", kernel); 238e08c0896SPrasad Joshi k++; 239e08c0896SPrasad Joshi } 240ee8b1456SWanlong Gao fprintf(stderr, "\nPlease see '%s run --help' for more options.\n\n", 241ee8b1456SWanlong Gao KVM_BINARY_NAME); 242e08c0896SPrasad Joshi } 243e08c0896SPrasad Joshi 24460ded003SPekka Enberg static u64 host_ram_size(void) 24560ded003SPekka Enberg { 24660ded003SPekka Enberg long page_size; 24760ded003SPekka Enberg long nr_pages; 24860ded003SPekka Enberg 24960ded003SPekka Enberg nr_pages = sysconf(_SC_PHYS_PAGES); 250d63c5ce6SPekka Enberg if (nr_pages < 0) { 2514542f276SCyrill Gorcunov pr_warning("sysconf(_SC_PHYS_PAGES) failed"); 252d63c5ce6SPekka Enberg return 0; 253d63c5ce6SPekka Enberg } 25460ded003SPekka Enberg 25560ded003SPekka Enberg page_size = sysconf(_SC_PAGE_SIZE); 256d63c5ce6SPekka Enberg if (page_size < 0) { 2574542f276SCyrill Gorcunov pr_warning("sysconf(_SC_PAGE_SIZE) failed"); 258d63c5ce6SPekka Enberg return 0; 259d63c5ce6SPekka Enberg } 26060ded003SPekka Enberg 26160ded003SPekka Enberg return (nr_pages * page_size) >> MB_SHIFT; 26260ded003SPekka Enberg } 26360ded003SPekka Enberg 26418bd8c3bSPekka Enberg /* 26518bd8c3bSPekka Enberg * If user didn't specify how much memory it wants to allocate for the guest, 26618bd8c3bSPekka Enberg * avoid filling the whole host RAM. 26718bd8c3bSPekka Enberg */ 26818bd8c3bSPekka Enberg #define RAM_SIZE_RATIO 0.8 26918bd8c3bSPekka Enberg 270fd834defSPekka Enberg static u64 get_ram_size(int nr_cpus) 271fd834defSPekka Enberg { 27206761c76SPekka Enberg u64 available; 27306761c76SPekka Enberg u64 ram_size; 274fd834defSPekka Enberg 275fd834defSPekka Enberg ram_size = 64 * (nr_cpus + 3); 276fd834defSPekka Enberg 27760ded003SPekka Enberg available = host_ram_size() * RAM_SIZE_RATIO; 278d63c5ce6SPekka Enberg if (!available) 279d63c5ce6SPekka Enberg available = MIN_RAM_SIZE_MB; 280fd834defSPekka Enberg 281fd834defSPekka Enberg if (ram_size > available) 282fd834defSPekka Enberg ram_size = available; 283fd834defSPekka Enberg 284fd834defSPekka Enberg return ram_size; 285fd834defSPekka Enberg } 286fd834defSPekka Enberg 287e08c0896SPrasad Joshi static const char *find_kernel(void) 288e08c0896SPrasad Joshi { 289e08c0896SPrasad Joshi const char **k; 2908329f30bSPekka Enberg struct stat st; 291e08c0896SPrasad Joshi struct utsname uts; 292e08c0896SPrasad Joshi 29365182f37SPrasad Joshi k = &default_kernels[0]; 294e08c0896SPrasad Joshi while (*k) { 295e08c0896SPrasad Joshi if (stat(*k, &st) < 0 || !S_ISREG(st.st_mode)) { 296e08c0896SPrasad Joshi k++; 297e08c0896SPrasad Joshi continue; 298e08c0896SPrasad Joshi } 299e08c0896SPrasad Joshi strncpy(kernel, *k, PATH_MAX); 300e08c0896SPrasad Joshi return kernel; 301e08c0896SPrasad Joshi } 3028329f30bSPekka Enberg 3038329f30bSPekka Enberg if (uname(&uts) < 0) 3048329f30bSPekka Enberg return NULL; 3058329f30bSPekka Enberg 306e08c0896SPrasad Joshi k = &host_kernels[0]; 307e08c0896SPrasad Joshi while (*k) { 308e08c0896SPrasad Joshi if (snprintf(kernel, PATH_MAX, "%s-%s", *k, uts.release) < 0) 3098329f30bSPekka Enberg return NULL; 3108329f30bSPekka Enberg 311e08c0896SPrasad Joshi if (stat(kernel, &st) < 0 || !S_ISREG(st.st_mode)) { 312e08c0896SPrasad Joshi k++; 313e08c0896SPrasad Joshi continue; 314e08c0896SPrasad Joshi } 315e08c0896SPrasad Joshi return kernel; 3168329f30bSPekka Enberg 317e08c0896SPrasad Joshi } 3188329f30bSPekka Enberg return NULL; 3198329f30bSPekka Enberg } 3208329f30bSPekka Enberg 321b0b42ba0SPekka Enberg static const char *find_vmlinux(void) 322b0b42ba0SPekka Enberg { 323b0b42ba0SPekka Enberg const char **vmlinux; 324b0b42ba0SPekka Enberg 325b0b42ba0SPekka Enberg vmlinux = &default_vmlinux[0]; 326b0b42ba0SPekka Enberg while (*vmlinux) { 327b0b42ba0SPekka Enberg struct stat st; 328b0b42ba0SPekka Enberg 329b0b42ba0SPekka Enberg if (stat(*vmlinux, &st) < 0 || !S_ISREG(st.st_mode)) { 330b0b42ba0SPekka Enberg vmlinux++; 331b0b42ba0SPekka Enberg continue; 332b0b42ba0SPekka Enberg } 333b0b42ba0SPekka Enberg return *vmlinux; 334b0b42ba0SPekka Enberg } 335b0b42ba0SPekka Enberg return NULL; 336b0b42ba0SPekka Enberg } 337b0b42ba0SPekka Enberg 338f6677a1dSAmerigo Wang void kvm_run_help(void) 339f6677a1dSAmerigo Wang { 3403b55dcdeSSasha Levin BUILD_OPTIONS(options, &kvm->cfg, kvm); 341f6677a1dSAmerigo Wang usage_with_options(run_usage, options); 342f6677a1dSAmerigo Wang } 343f6677a1dSAmerigo Wang 344afc2c7c0SAsias He static int kvm_setup_guest_init(void) 3459cec19c8SSasha Levin { 34647621338SSasha Levin const char *rootfs = kvm->cfg.custom_rootfs_name; 347afc2c7c0SAsias He char tmp[PATH_MAX]; 348afc2c7c0SAsias He size_t size; 349afc2c7c0SAsias He int fd, ret; 350afc2c7c0SAsias He char *data; 3519cec19c8SSasha Levin 352afc2c7c0SAsias He /* Setup /virt/init */ 353afc2c7c0SAsias He size = (size_t)&_binary_guest_init_size; 354afc2c7c0SAsias He data = (char *)&_binary_guest_init_start; 355afc2c7c0SAsias He snprintf(tmp, PATH_MAX, "%s%s/virt/init", kvm__get_dir(), rootfs); 356afc2c7c0SAsias He remove(tmp); 357afc2c7c0SAsias He fd = open(tmp, O_CREAT | O_WRONLY, 0755); 358afc2c7c0SAsias He if (fd < 0) 359afc2c7c0SAsias He die("Fail to setup %s", tmp); 360afc2c7c0SAsias He ret = xwrite(fd, data, size); 361afc2c7c0SAsias He if (ret < 0) 362afc2c7c0SAsias He die("Fail to setup %s", tmp); 363afc2c7c0SAsias He close(fd); 3649cec19c8SSasha Levin 365afc2c7c0SAsias He return 0; 3669cec19c8SSasha Levin } 3679cec19c8SSasha Levin 368d50fe489SSasha Levin static int kvm_run_set_sandbox(void) 369d50fe489SSasha Levin { 37047621338SSasha Levin const char *guestfs_name = kvm->cfg.custom_rootfs_name; 371d50fe489SSasha Levin char path[PATH_MAX], script[PATH_MAX], *tmp; 372d50fe489SSasha Levin 373d50fe489SSasha Levin snprintf(path, PATH_MAX, "%s%s/virt/sandbox.sh", kvm__get_dir(), guestfs_name); 374d50fe489SSasha Levin 375d50fe489SSasha Levin remove(path); 376d50fe489SSasha Levin 37747621338SSasha Levin if (kvm->cfg.sandbox == NULL) 378d50fe489SSasha Levin return 0; 379d50fe489SSasha Levin 38047621338SSasha Levin tmp = realpath(kvm->cfg.sandbox, NULL); 381d50fe489SSasha Levin if (tmp == NULL) 382d50fe489SSasha Levin return -ENOMEM; 383d50fe489SSasha Levin 384d50fe489SSasha Levin snprintf(script, PATH_MAX, "/host/%s", tmp); 385d50fe489SSasha Levin free(tmp); 386d50fe489SSasha Levin 387d50fe489SSasha Levin return symlink(script, path); 388d50fe489SSasha Levin } 389d50fe489SSasha Levin 3905173b4afSLai Jiangshan static void kvm_write_sandbox_cmd_exactly(int fd, const char *arg) 3915173b4afSLai Jiangshan { 3925173b4afSLai Jiangshan const char *single_quote; 3935173b4afSLai Jiangshan 3945173b4afSLai Jiangshan if (!*arg) { /* zero length string */ 3955173b4afSLai Jiangshan if (write(fd, "''", 2) <= 0) 3965173b4afSLai Jiangshan die("Failed writing sandbox script"); 3975173b4afSLai Jiangshan return; 3985173b4afSLai Jiangshan } 3995173b4afSLai Jiangshan 4005173b4afSLai Jiangshan while (*arg) { 4015173b4afSLai Jiangshan single_quote = strchrnul(arg, '\''); 4025173b4afSLai Jiangshan 4035173b4afSLai Jiangshan /* write non-single-quote string as #('string') */ 4045173b4afSLai Jiangshan if (arg != single_quote) { 4055173b4afSLai Jiangshan if (write(fd, "'", 1) <= 0 || 4065173b4afSLai Jiangshan write(fd, arg, single_quote - arg) <= 0 || 4075173b4afSLai Jiangshan write(fd, "'", 1) <= 0) 4085173b4afSLai Jiangshan die("Failed writing sandbox script"); 4095173b4afSLai Jiangshan } 4105173b4afSLai Jiangshan 4115173b4afSLai Jiangshan /* write single quote as #("'") */ 4125173b4afSLai Jiangshan if (*single_quote) { 4135173b4afSLai Jiangshan if (write(fd, "\"'\"", 3) <= 0) 4145173b4afSLai Jiangshan die("Failed writing sandbox script"); 4155173b4afSLai Jiangshan } else 4165173b4afSLai Jiangshan break; 4175173b4afSLai Jiangshan 4185173b4afSLai Jiangshan arg = single_quote + 1; 4195173b4afSLai Jiangshan } 4205173b4afSLai Jiangshan } 4215173b4afSLai Jiangshan 4225cd19aa0SPekka Enberg static void resolve_program(const char *src, char *dst, size_t len) 4235cd19aa0SPekka Enberg { 4245cd19aa0SPekka Enberg struct stat st; 425c2c742d9SPekka Enberg int err; 4265cd19aa0SPekka Enberg 427c2c742d9SPekka Enberg err = stat(src, &st); 4285cd19aa0SPekka Enberg 429c2c742d9SPekka Enberg if (!err && S_ISREG(st.st_mode)) { 4305cd19aa0SPekka Enberg char resolved_path[PATH_MAX]; 4315cd19aa0SPekka Enberg 432de3f75c9SPekka Enberg if (!realpath(src, resolved_path)) 433de3f75c9SPekka Enberg die("Unable to resolve program %s: %s\n", src, strerror(errno)); 4345cd19aa0SPekka Enberg 4355cd19aa0SPekka Enberg snprintf(dst, len, "/host%s", resolved_path); 4365cd19aa0SPekka Enberg } else 4375cd19aa0SPekka Enberg strncpy(dst, src, len); 4385cd19aa0SPekka Enberg } 4395cd19aa0SPekka Enberg 4403c29e2aaSSasha Levin static void kvm_run_write_sandbox_cmd(const char **argv, int argc) 4413c29e2aaSSasha Levin { 4423c29e2aaSSasha Levin const char script_hdr[] = "#! /bin/bash\n\n"; 4435cd19aa0SPekka Enberg char program[PATH_MAX]; 4443c29e2aaSSasha Levin int fd; 4453c29e2aaSSasha Levin 44647621338SSasha Levin remove(kvm->cfg.sandbox); 4473c29e2aaSSasha Levin 44847621338SSasha Levin fd = open(kvm->cfg.sandbox, O_RDWR | O_CREAT, 0777); 4493c29e2aaSSasha Levin if (fd < 0) 4503c29e2aaSSasha Levin die("Failed creating sandbox script"); 4513c29e2aaSSasha Levin 4523c29e2aaSSasha Levin if (write(fd, script_hdr, sizeof(script_hdr) - 1) <= 0) 4533c29e2aaSSasha Levin die("Failed writing sandbox script"); 4543c29e2aaSSasha Levin 4555cd19aa0SPekka Enberg resolve_program(argv[0], program, PATH_MAX); 4565cd19aa0SPekka Enberg kvm_write_sandbox_cmd_exactly(fd, program); 4575cd19aa0SPekka Enberg 4585cd19aa0SPekka Enberg argv++; 4595cd19aa0SPekka Enberg argc--; 4605cd19aa0SPekka Enberg 4613c29e2aaSSasha Levin while (argc) { 4623c29e2aaSSasha Levin if (write(fd, " ", 1) <= 0) 4633c29e2aaSSasha Levin die("Failed writing sandbox script"); 4645cd19aa0SPekka Enberg 4655cd19aa0SPekka Enberg kvm_write_sandbox_cmd_exactly(fd, argv[0]); 4663c29e2aaSSasha Levin argv++; 4673c29e2aaSSasha Levin argc--; 4683c29e2aaSSasha Levin } 4693c29e2aaSSasha Levin if (write(fd, "\n", 1) <= 0) 4703c29e2aaSSasha Levin die("Failed writing sandbox script"); 4713c29e2aaSSasha Levin 4723c29e2aaSSasha Levin close(fd); 4733c29e2aaSSasha Levin } 4743c29e2aaSSasha Levin 475e1e46fe6SSasha Levin static int kvm_cmd_run_init(int argc, const char **argv) 476f967c427SPrasad Joshi { 4772d96f6b6SSasha Levin static char real_cmdline[2048], default_name[20]; 478384922b3SPekka Enberg unsigned int nr_online_cpus; 4795f225124SSasha Levin int r; 48047621338SSasha Levin 48147621338SSasha Levin kvm = kvm__new(); 48247621338SSasha Levin if (IS_ERR(kvm)) 48347621338SSasha Levin return PTR_ERR(kvm); 484f967c427SPrasad Joshi 4855ee154d1SPekka Enberg signal(SIGALRM, handle_sigalrm); 486f967c427SPrasad Joshi 487cfd63bbbSSasha Levin nr_online_cpus = sysconf(_SC_NPROCESSORS_ONLN); 48847621338SSasha Levin kvm->cfg.custom_rootfs_name = "default"; 489cfd63bbbSSasha Levin 490f967c427SPrasad Joshi while (argc != 0) { 4913b55dcdeSSasha Levin BUILD_OPTIONS(options, &kvm->cfg, kvm); 492f967c427SPrasad Joshi argc = parse_options(argc, argv, options, run_usage, 4931a007c82SSasha Levin PARSE_OPT_STOP_AT_NON_OPTION | 4941a007c82SSasha Levin PARSE_OPT_KEEP_DASHDASH); 495f967c427SPrasad Joshi if (argc != 0) { 4961a007c82SSasha Levin /* Cusrom options, should have been handled elsewhere */ 4973c29e2aaSSasha Levin if (strcmp(argv[0], "--") == 0) { 4983c29e2aaSSasha Levin if (kvm_run_wrapper == KVM_RUN_SANDBOX) { 49947621338SSasha Levin kvm->cfg.sandbox = DEFAULT_SANDBOX_FILENAME; 5003c29e2aaSSasha Levin kvm_run_write_sandbox_cmd(argv+1, argc-1); 5011a007c82SSasha Levin break; 5023c29e2aaSSasha Levin } 5033c29e2aaSSasha Levin } 5041a007c82SSasha Levin 50547621338SSasha Levin if ((kvm_run_wrapper == KVM_RUN_DEFAULT && kvm->cfg.kernel_filename) || 50647621338SSasha Levin (kvm_run_wrapper == KVM_RUN_SANDBOX && kvm->cfg.sandbox)) { 507f967c427SPrasad Joshi fprintf(stderr, "Cannot handle parameter: " 508f967c427SPrasad Joshi "%s\n", argv[0]); 509f967c427SPrasad Joshi usage_with_options(run_usage, options); 51047621338SSasha Levin free(kvm); 511e120b624SPaul Neumann return -EINVAL; 512f967c427SPrasad Joshi } 513e0747665SSasha Levin if (kvm_run_wrapper == KVM_RUN_SANDBOX) { 514e0747665SSasha Levin /* 515e0747665SSasha Levin * first unhandled parameter is treated as 516e0747665SSasha Levin * sandbox command 517e0747665SSasha Levin */ 51847621338SSasha Levin kvm->cfg.sandbox = DEFAULT_SANDBOX_FILENAME; 519e0747665SSasha Levin kvm_run_write_sandbox_cmd(argv, argc); 520e0747665SSasha Levin } else { 521e0747665SSasha Levin /* 522e0747665SSasha Levin * first unhandled parameter is treated as a kernel 523e0747665SSasha Levin * image 524f967c427SPrasad Joshi */ 52547621338SSasha Levin kvm->cfg.kernel_filename = argv[0]; 526e0747665SSasha Levin } 527f967c427SPrasad Joshi argv++; 528f967c427SPrasad Joshi argc--; 529f967c427SPrasad Joshi } 530f967c427SPrasad Joshi 531f967c427SPrasad Joshi } 532f967c427SPrasad Joshi 5333b55dcdeSSasha Levin kvm->nr_disks = kvm->cfg.image_count; 5343b55dcdeSSasha Levin 53547621338SSasha Levin if (!kvm->cfg.kernel_filename) 53647621338SSasha Levin kvm->cfg.kernel_filename = find_kernel(); 5378329f30bSPekka Enberg 53847621338SSasha Levin if (!kvm->cfg.kernel_filename) { 539e08c0896SPrasad Joshi kernel_usage_with_options(); 540e120b624SPaul Neumann return -EINVAL; 5418329f30bSPekka Enberg } 5428329f30bSPekka Enberg 54347621338SSasha Levin kvm->cfg.vmlinux_filename = find_vmlinux(); 544084a1356SSasha Levin kvm->vmlinux = kvm->cfg.vmlinux_filename; 545b0b42ba0SPekka Enberg 54600ebbe96SSasha Levin if (kvm->cfg.nrcpus == 0) 54700ebbe96SSasha Levin kvm->cfg.nrcpus = nr_online_cpus; 548d77a9efaSCyrill Gorcunov 54947621338SSasha Levin if (!kvm->cfg.ram_size) 55000ebbe96SSasha Levin kvm->cfg.ram_size = get_ram_size(kvm->cfg.nrcpus); 551fd834defSPekka Enberg 55247621338SSasha Levin if (kvm->cfg.ram_size < MIN_RAM_SIZE_MB) 55347621338SSasha Levin die("Not enough memory specified: %lluMB (min %lluMB)", kvm->cfg.ram_size, MIN_RAM_SIZE_MB); 554a2a002f9SIngo Molnar 55547621338SSasha Levin if (kvm->cfg.ram_size > host_ram_size()) 55647621338SSasha Levin pr_warning("Guest memory size %lluMB exceeds host physical RAM size %lluMB", kvm->cfg.ram_size, host_ram_size()); 55760ded003SPekka Enberg 55847621338SSasha Levin kvm->cfg.ram_size <<= MB_SHIFT; 559f967c427SPrasad Joshi 56047621338SSasha Levin if (!kvm->cfg.dev) 56147621338SSasha Levin kvm->cfg.dev = DEFAULT_KVM_DEV; 562f967c427SPrasad Joshi 56347621338SSasha Levin if (!kvm->cfg.console) 56447621338SSasha Levin kvm->cfg.console = DEFAULT_CONSOLE; 5659aa4a0ebSAsias He 56647621338SSasha Levin if (!strncmp(kvm->cfg.console, "virtio", 6)) 5672651ea58SSasha Levin kvm->cfg.active_console = CONSOLE_VIRTIO; 56847621338SSasha Levin else if (!strncmp(kvm->cfg.console, "serial", 6)) 5692651ea58SSasha Levin kvm->cfg.active_console = CONSOLE_8250; 57047621338SSasha Levin else if (!strncmp(kvm->cfg.console, "hv", 2)) 5712651ea58SSasha Levin kvm->cfg.active_console = CONSOLE_HV; 5723bbc49b6SMatt Evans else 5733bbc49b6SMatt Evans pr_warning("No console!"); 574f967c427SPrasad Joshi 57547621338SSasha Levin if (!kvm->cfg.host_ip) 57647621338SSasha Levin kvm->cfg.host_ip = DEFAULT_HOST_ADDR; 5774d67c820SSasha Levin 57847621338SSasha Levin if (!kvm->cfg.guest_ip) 57947621338SSasha Levin kvm->cfg.guest_ip = DEFAULT_GUEST_ADDR; 580bb8ffd2fSAsias He 58147621338SSasha Levin if (!kvm->cfg.guest_mac) 58247621338SSasha Levin kvm->cfg.guest_mac = DEFAULT_GUEST_MAC; 583a4e724ddSSasha Levin 58447621338SSasha Levin if (!kvm->cfg.host_mac) 58547621338SSasha Levin kvm->cfg.host_mac = DEFAULT_HOST_MAC; 586d7098b9bSAsias He 58747621338SSasha Levin if (!kvm->cfg.script) 58847621338SSasha Levin kvm->cfg.script = DEFAULT_SCRIPT; 58973b7d038SAmos Kong 59007d52d77SSasha Levin if (!kvm->cfg.vnc && !kvm->cfg.sdl) 59107d52d77SSasha Levin kvm->cfg.vidmode = -1; 59207d52d77SSasha Levin 593cf5323a3SSasha Levin if (!kvm->cfg.network) 594cf5323a3SSasha Levin kvm->cfg.network = DEFAULT_NETWORK; 595cf5323a3SSasha Levin 596084a1356SSasha Levin memset(real_cmdline, 0, sizeof(real_cmdline)); 597084a1356SSasha Levin kvm__arch_set_cmdline(real_cmdline, kvm->cfg.vnc || kvm->cfg.sdl); 598084a1356SSasha Levin 599084a1356SSasha Levin if (strlen(real_cmdline) > 0) 600084a1356SSasha Levin strcat(real_cmdline, " "); 601084a1356SSasha Levin 602084a1356SSasha Levin if (kvm->cfg.kernel_cmdline) 603084a1356SSasha Levin strlcat(real_cmdline, kvm->cfg.kernel_cmdline, sizeof(real_cmdline)); 604f967c427SPrasad Joshi 60547621338SSasha Levin if (!kvm->cfg.guest_name) { 60647621338SSasha Levin if (kvm->cfg.custom_rootfs) { 60747621338SSasha Levin kvm->cfg.guest_name = kvm->cfg.custom_rootfs_name; 608587a4d17SLai Jiangshan } else { 6092d96f6b6SSasha Levin sprintf(default_name, "guest-%u", getpid()); 61047621338SSasha Levin kvm->cfg.guest_name = default_name; 6112d96f6b6SSasha Levin } 612587a4d17SLai Jiangshan } 6132d96f6b6SSasha Levin 61447621338SSasha Levin if (!kvm->cfg.using_rootfs && !kvm->cfg.disk_image[0].filename && !kvm->cfg.initrd_filename) { 615c8675741SSasha Levin char tmp[PATH_MAX]; 6166df1471eSPekka Enberg 61747621338SSasha Levin kvm_setup_create_new(kvm->cfg.custom_rootfs_name); 61847621338SSasha Levin kvm_setup_resolv(kvm->cfg.custom_rootfs_name); 619c8675741SSasha Levin 6209667701cSPekka Enberg snprintf(tmp, PATH_MAX, "%s%s", kvm__get_dir(), "default"); 621c8675741SSasha Levin if (virtio_9p__register(kvm, tmp, "/dev/root") < 0) 622c8675741SSasha Levin die("Unable to initialize virtio 9p"); 623c8675741SSasha Levin if (virtio_9p__register(kvm, "/", "hostfs") < 0) 624c8675741SSasha Levin die("Unable to initialize virtio 9p"); 62547621338SSasha Levin kvm->cfg.using_rootfs = kvm->cfg.custom_rootfs = 1; 62626c853e4SPrasad Joshi } 62726c853e4SPrasad Joshi 62847621338SSasha Levin if (kvm->cfg.using_rootfs) { 629ff42603fSSasha Levin strcat(real_cmdline, " root=/dev/root rw rootflags=rw,trans=virtio,version=9p2000.L rootfstype=9p"); 63047621338SSasha Levin if (kvm->cfg.custom_rootfs) { 631d50fe489SSasha Levin kvm_run_set_sandbox(); 632d50fe489SSasha Levin 633a8e6b4b9SSasha Levin strcat(real_cmdline, " init=/virt/init"); 634d50fe489SSasha Levin 63547621338SSasha Levin if (!kvm->cfg.no_dhcp) 636a8e6b4b9SSasha Levin strcat(real_cmdline, " ip=dhcp"); 637afc2c7c0SAsias He if (kvm_setup_guest_init()) 638afc2c7c0SAsias He die("Failed to setup init for guest."); 639a8e6b4b9SSasha Levin } 64082d65b5eSSasha Levin } else if (!strstr(real_cmdline, "root=")) { 641ff42603fSSasha Levin strlcat(real_cmdline, " root=/dev/vda rw ", sizeof(real_cmdline)); 64282d65b5eSSasha Levin } 64359aa2d30SSasha Levin 644084a1356SSasha Levin kvm->cfg.real_cmdline = real_cmdline; 645084a1356SSasha Levin 646084a1356SSasha Levin printf(" # %s run -k %s -m %Lu -c %d --name %s\n", KVM_BINARY_NAME, 647084a1356SSasha Levin kvm->cfg.kernel_filename, kvm->cfg.ram_size / 1024 / 1024, kvm->cfg.nrcpus, kvm->cfg.guest_name); 648084a1356SSasha Levin 649084a1356SSasha Levin r = kvm__init(kvm); 650084a1356SSasha Levin if (r) 651084a1356SSasha Levin goto fail; 652084a1356SSasha Levin 653084a1356SSasha Levin r = term_init(kvm); 654084a1356SSasha Levin if (r < 0) { 655084a1356SSasha Levin pr_err("term_init() failed with error %d\n", r); 656084a1356SSasha Levin goto fail; 657084a1356SSasha Levin } 658084a1356SSasha Levin 659084a1356SSasha Levin 660084a1356SSasha Levin r = ioeventfd__init(kvm); 661084a1356SSasha Levin if (r < 0) { 662084a1356SSasha Levin pr_err("ioeventfd__init() failed with error %d\n", r); 663084a1356SSasha Levin goto fail; 664084a1356SSasha Levin } 665084a1356SSasha Levin 666084a1356SSasha Levin r = kvm_cpu__init(kvm); 667084a1356SSasha Levin if (r < 0) { 668084a1356SSasha Levin pr_err("kvm_cpu__init() failed with error %d\n", r); 669084a1356SSasha Levin goto fail; 670084a1356SSasha Levin } 671084a1356SSasha Levin 672084a1356SSasha Levin r = irq__init(kvm); 673084a1356SSasha Levin if (r < 0) { 674084a1356SSasha Levin pr_err("irq__init() failed with error %d\n", r); 675084a1356SSasha Levin goto fail; 676084a1356SSasha Levin } 677084a1356SSasha Levin 678084a1356SSasha Levin r = pci__init(kvm); 679084a1356SSasha Levin if (r < 0) { 680084a1356SSasha Levin pr_err("pci__init() failed with error %d\n", r); 681084a1356SSasha Levin goto fail; 682084a1356SSasha Levin } 683084a1356SSasha Levin 684084a1356SSasha Levin r = ioport__init(kvm); 685084a1356SSasha Levin if (r < 0) { 686084a1356SSasha Levin pr_err("ioport__init() failed with error %d\n", r); 687084a1356SSasha Levin goto fail; 688084a1356SSasha Levin } 689084a1356SSasha Levin 6903b55dcdeSSasha Levin r = disk_image__init(kvm); 6913b55dcdeSSasha Levin if (r < 0) { 6923b55dcdeSSasha Levin pr_err("disk_image__init() failed with error %d\n", r); 6939f9207c5SSasha Levin goto fail; 6949f9207c5SSasha Levin } 695c1ed214eSPrasad Joshi 696807b77b9SCyrill Gorcunov r = symbol_init(kvm); 697b56f1728SCyrill Gorcunov if (r < 0) 698c4b716ecSPekka Enberg pr_debug("symbol_init() failed with error %d\n", r); 699b0b42ba0SPekka Enberg 70020c39545SSasha Levin r = rtc__init(kvm); 70120c39545SSasha Levin if (r < 0) { 70220c39545SSasha Levin pr_err("rtc__init() failed with error %d\n", r); 70320c39545SSasha Levin goto fail; 70420c39545SSasha Levin } 70564136c1cSPekka Enberg 70620715a22SSasha Levin r = serial8250__init(kvm); 70720715a22SSasha Levin if (r < 0) { 70820715a22SSasha Levin pr_err("serial__init() failed with error %d\n", r); 70920715a22SSasha Levin goto fail; 71020715a22SSasha Levin } 711f967c427SPrasad Joshi 7129f9207c5SSasha Levin r = virtio_blk__init(kvm); 7139f9207c5SSasha Levin if (r < 0) { 7149f9207c5SSasha Levin pr_err("virtio_blk__init() failed with error %d\n", r); 7159f9207c5SSasha Levin goto fail; 7169f9207c5SSasha Levin } 7179f9207c5SSasha Levin 718a67da3beSAsias He r = virtio_scsi_init(kvm); 719a67da3beSAsias He if (r < 0) { 720a67da3beSAsias He pr_err("virtio_scsi_init() failed with error %d\n", r); 721a67da3beSAsias He goto fail; 722a67da3beSAsias He } 723a67da3beSAsias He 724a3fa3f86SSasha Levin r = virtio_console__init(kvm); 725a3fa3f86SSasha Levin if (r < 0) { 726a3fa3f86SSasha Levin pr_err("virtio_console__init() failed with error %d\n", r); 727a3fa3f86SSasha Levin goto fail; 728a3fa3f86SSasha Levin } 729f967c427SPrasad Joshi 730f16653adSSasha Levin r = virtio_rng__init(kvm); 731f16653adSSasha Levin if (r < 0) { 732f16653adSSasha Levin pr_err("virtio_rng__init() failed with error %d\n", r); 733f16653adSSasha Levin goto fail; 734f16653adSSasha Levin } 73553eca082SSasha Levin 736d06db2fdSSasha Levin r = virtio_bln__init(kvm); 737d06db2fdSSasha Levin if (r < 0) { 738d06db2fdSSasha Levin pr_err("virtio_rng__init() failed with error %d\n", r); 739d06db2fdSSasha Levin goto fail; 740d06db2fdSSasha Levin } 74182d2f21eSSasha Levin 742*cac9e8fdSSasha Levin r = virtio_9p__init(kvm); 743*cac9e8fdSSasha Levin if (r < 0) { 744*cac9e8fdSSasha Levin pr_err("virtio_9p__init() failed with error %d\n", r); 745*cac9e8fdSSasha Levin goto fail; 746*cac9e8fdSSasha Levin } 747c7838fbdSSasha Levin 7485f225124SSasha Levin r = virtio_net__init(kvm); 7495f225124SSasha Levin if (r < 0) { 7505f225124SSasha Levin pr_err("virtio_net__init() failed with error %d\n", r); 7515f225124SSasha Levin goto fail; 752bdfcfca6SSasha Levin } 7534f56d42cSAsias He 754be1eb89bSSasha Levin r = kbd__init(kvm); 755be1eb89bSSasha Levin if (r < 0) { 756be1eb89bSSasha Levin pr_err("kbd__init() failed with error %d\n", r); 757be1eb89bSSasha Levin goto fail; 758be1eb89bSSasha Levin } 759714e5b7fSSasha Levin 7608cec93dbSSasha Levin r = pci_shmem__init(kvm); 7618cec93dbSSasha Levin if (r < 0) { 7628cec93dbSSasha Levin pr_err("pci_shmem__init() failed with error %d\n", r); 7638cec93dbSSasha Levin goto fail; 7648cec93dbSSasha Levin } 76595d13a52SSasha Levin 76607d52d77SSasha Levin r = vnc__init(kvm); 76748d9e01aSSasha Levin if (r < 0) { 76848d9e01aSSasha Levin pr_err("vnc__init() failed with error %d\n", r); 76948d9e01aSSasha Levin goto fail; 77048d9e01aSSasha Levin } 77148d9e01aSSasha Levin 77207d52d77SSasha Levin r = sdl__init(kvm); 77348d9e01aSSasha Levin if (r < 0) { 77448d9e01aSSasha Levin pr_err("sdl__init() failed with error %d\n", r); 77548d9e01aSSasha Levin goto fail; 77648d9e01aSSasha Levin } 777aba1efa5SPekka Enberg 778ba46fe53SSasha Levin r = fb__init(kvm); 77948d9e01aSSasha Levin if (r < 0) { 78048d9e01aSSasha Levin pr_err("fb__init() failed with error %d\n", r); 78148d9e01aSSasha Levin goto fail; 78248d9e01aSSasha Levin } 783aba1efa5SPekka Enberg 784df4239fbSSasha Levin /* 785df4239fbSSasha Levin * Device init all done; firmware init must 78625af47eeSMatt Evans * come after this (it may set up device trees etc.) 78725af47eeSMatt Evans */ 78825af47eeSMatt Evans 789b4532ca9SSasha Levin r = kvm_timer__init(kvm); 790b4532ca9SSasha Levin if (r < 0) { 791b4532ca9SSasha Levin pr_err("kvm_timer__init() failed with error %d\n", r); 792b4532ca9SSasha Levin goto fail; 793b4532ca9SSasha Levin } 79425af47eeSMatt Evans 795f6a3c571SSasha Levin r = thread_pool__init(kvm); 796f6a3c571SSasha Levin if (r < 0) { 797f6a3c571SSasha Levin pr_err("thread_pool__init() failed with error %d\n", r); 798f6a3c571SSasha Levin goto fail; 799f6a3c571SSasha Levin } 800f6a3c571SSasha Levin 8014932d174SSasha Levin fail: 8024932d174SSasha Levin return r; 803e1e46fe6SSasha Levin } 804e1e46fe6SSasha Levin 805e1e46fe6SSasha Levin static int kvm_cmd_run_work(void) 806e1e46fe6SSasha Levin { 807df4239fbSSasha Levin int i; 808e1e46fe6SSasha Levin void *ret = NULL; 809e1e46fe6SSasha Levin 81000ebbe96SSasha Levin for (i = 0; i < kvm->nrcpus; i++) { 811df4239fbSSasha Levin if (pthread_create(&kvm->cpus[i]->thread, NULL, kvm_cpu_thread, kvm->cpus[i]) != 0) 8125ee154d1SPekka Enberg die("unable to create KVM VCPU thread"); 8135ee154d1SPekka Enberg } 8145ee154d1SPekka Enberg 81549e5227dSSasha Levin /* Only VCPU #0 is going to exit by itself when shutting down */ 816df4239fbSSasha Levin return pthread_join(kvm->cpus[0]->thread, &ret); 817e1e46fe6SSasha Levin } 818e1e46fe6SSasha Levin 8194932d174SSasha Levin static void kvm_cmd_run_exit(int guest_ret) 820e1e46fe6SSasha Levin { 8214932d174SSasha Levin int r = 0; 8224932d174SSasha Levin 823e6694207SSasha Levin compat__print_all_messages(); 824e6694207SSasha Levin 825df4239fbSSasha Levin r = kvm_cpu__exit(kvm); 826df4239fbSSasha Levin if (r < 0) 827df4239fbSSasha Levin pr_warning("kvm_cpu__exit() failed with error %d\n", r); 828df4239fbSSasha Levin 829807b77b9SCyrill Gorcunov r = symbol_exit(kvm); 8304932d174SSasha Levin if (r < 0) 831807b77b9SCyrill Gorcunov pr_warning("symbol_exit() failed with error %d\n", r); 8324932d174SSasha Levin 833e3c4f8aaSSasha Levin r = irq__exit(kvm); 834e3c4f8aaSSasha Levin if (r < 0) 835e3c4f8aaSSasha Levin pr_warning("irq__exit() failed with error %d\n", r); 836e3c4f8aaSSasha Levin 837b4532ca9SSasha Levin r = kvm_timer__exit(kvm); 838b4532ca9SSasha Levin if (r < 0) 839b4532ca9SSasha Levin pr_warning("kvm_timer__exit() failed with error %d\n", r); 840b4532ca9SSasha Levin 841ba46fe53SSasha Levin r = fb__exit(kvm); 842ba46fe53SSasha Levin if (r < 0) 843b4532ca9SSasha Levin pr_warning("kvm_timer__exit() failed with error %d\n", r); 844aba1efa5SPekka Enberg 8455f225124SSasha Levin r = virtio_net__exit(kvm); 8465f225124SSasha Levin if (r < 0) 8475f225124SSasha Levin pr_warning("virtio_net__exit() failed with error %d\n", r); 8485f225124SSasha Levin 849a67da3beSAsias He r = virtio_scsi_exit(kvm); 850a67da3beSAsias He if (r < 0) 851a67da3beSAsias He pr_warning("virtio_scsi_exit() failed with error %d\n", r); 852a67da3beSAsias He 8539f9207c5SSasha Levin r = virtio_blk__exit(kvm); 8549f9207c5SSasha Levin if (r < 0) 8559f9207c5SSasha Levin pr_warning("virtio_blk__exit() failed with error %d\n", r); 8569f9207c5SSasha Levin 857495fbd4eSSasha Levin r = virtio_rng__exit(kvm); 858495fbd4eSSasha Levin if (r < 0) 859495fbd4eSSasha Levin pr_warning("virtio_rng__exit() failed with error %d\n", r); 860a0a1e3c2SPrasad Joshi 861d06db2fdSSasha Levin r = virtio_bln__exit(kvm); 862d06db2fdSSasha Levin if (r < 0) 863d06db2fdSSasha Levin pr_warning("virtio_bln__exit() failed with error %d\n", r); 864d06db2fdSSasha Levin 865a3fa3f86SSasha Levin r = virtio_console__exit(kvm); 866a3fa3f86SSasha Levin if (r < 0) 867a3fa3f86SSasha Levin pr_warning("virtio_console__exit() failed with error %d\n", r); 868a3fa3f86SSasha Levin 8698cec93dbSSasha Levin r = pci_shmem__exit(kvm); 8708cec93dbSSasha Levin if (r < 0) 8718cec93dbSSasha Levin pr_warning("pci_shmem__exit() failed with error %d\n", r); 8728cec93dbSSasha Levin 8733b55dcdeSSasha Levin r = disk_image__exit(kvm); 8749f9207c5SSasha Levin if (r < 0) 8753b55dcdeSSasha Levin pr_warning("disk_image__exit() failed with error %d\n", r); 8767af40b91SSasha Levin 87720715a22SSasha Levin r = serial8250__exit(kvm); 87820715a22SSasha Levin if (r < 0) 87920715a22SSasha Levin pr_warning("serial8250__exit() failed with error %d\n", r); 88020715a22SSasha Levin 88120c39545SSasha Levin r = rtc__exit(kvm); 88220c39545SSasha Levin if (r < 0) 88320c39545SSasha Levin pr_warning("rtc__exit() failed with error %d\n", r); 88420c39545SSasha Levin 8851add9f73SSasha Levin r = kvm__arch_free_firmware(kvm); 8861add9f73SSasha Levin if (r < 0) 8871add9f73SSasha Levin pr_warning("kvm__arch_free_firmware() failed with error %d\n", r); 8881add9f73SSasha Levin 8897af40b91SSasha Levin r = ioport__exit(kvm); 8907af40b91SSasha Levin if (r < 0) 8917af40b91SSasha Levin pr_warning("ioport__exit() failed with error %d\n", r); 8927af40b91SSasha Levin 893ea6eeb1cSSasha Levin r = ioeventfd__exit(kvm); 894ea6eeb1cSSasha Levin if (r < 0) 895ea6eeb1cSSasha Levin pr_warning("ioeventfd__exit() failed with error %d\n", r); 896ea6eeb1cSSasha Levin 8976d987703SSasha Levin r = pci__exit(kvm); 8986d987703SSasha Levin if (r < 0) 8996d987703SSasha Levin pr_warning("pci__exit() failed with error %d\n", r); 9006d987703SSasha Levin 901dca745e4SSasha Levin r = term_exit(kvm); 902dca745e4SSasha Levin if (r < 0) 903dca745e4SSasha Levin pr_warning("pci__exit() failed with error %d\n", r); 904dca745e4SSasha Levin 905f6a3c571SSasha Levin r = thread_pool__exit(kvm); 906f6a3c571SSasha Levin if (r < 0) 907f6a3c571SSasha Levin pr_warning("thread_pool__exit() failed with error %d\n", r); 908f6a3c571SSasha Levin 909495fbd4eSSasha Levin r = kvm__exit(kvm); 910495fbd4eSSasha Levin if (r < 0) 911495fbd4eSSasha Levin pr_warning("pci__exit() failed with error %d\n", r); 912f967c427SPrasad Joshi 913e1e46fe6SSasha Levin if (guest_ret == 0) 914f967c427SPrasad Joshi printf("\n # KVM session ended normally.\n"); 915e1e46fe6SSasha Levin } 916e1e46fe6SSasha Levin 917e1e46fe6SSasha Levin int kvm_cmd_run(int argc, const char **argv, const char *prefix) 918e1e46fe6SSasha Levin { 9194932d174SSasha Levin int r, ret = -EFAULT; 920e1e46fe6SSasha Levin 921e1e46fe6SSasha Levin r = kvm_cmd_run_init(argc, argv); 922e1e46fe6SSasha Levin if (r < 0) 923e1e46fe6SSasha Levin return r; 924e1e46fe6SSasha Levin 925e1e46fe6SSasha Levin ret = kvm_cmd_run_work(); 926e1e46fe6SSasha Levin kvm_cmd_run_exit(ret); 927e1e46fe6SSasha Levin 928e1e46fe6SSasha Levin return ret; 929f967c427SPrasad Joshi } 930