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", \ 199*5f225124SSasha 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 221b5b501ccSIngo Molnar /* 222b5b501ccSIngo Molnar * Serialize debug printout so that the output of multiple vcpus does not 223b5b501ccSIngo Molnar * get mixed up: 224b5b501ccSIngo Molnar */ 225cffeab25SIngo Molnar static int printout_done; 226b5b501ccSIngo Molnar 22743119af7SPekka Enberg static void handle_sigusr1(int sig) 22843119af7SPekka Enberg { 22943119af7SPekka Enberg struct kvm_cpu *cpu = current_kvm_cpu; 230b7d2f013SSasha Levin int fd = kvm_cpu__get_debug_fd(); 23143119af7SPekka Enberg 2324b1c6f6eSSasha Levin if (!cpu || cpu->needs_nmi) 23343119af7SPekka Enberg return; 23443119af7SPekka Enberg 235b7d2f013SSasha Levin dprintf(fd, "\n #\n # vCPU #%ld's dump:\n #\n", cpu->cpu_id); 23643119af7SPekka Enberg kvm_cpu__show_registers(cpu); 23743119af7SPekka Enberg kvm_cpu__show_code(cpu); 23843119af7SPekka Enberg kvm_cpu__show_page_tables(cpu); 239b5b501ccSIngo Molnar fflush(stdout); 240cffeab25SIngo Molnar printout_done = 1; 241cffeab25SIngo Molnar mb(); 24243119af7SPekka Enberg } 24343119af7SPekka Enberg 244d94e22b9SSasha Levin /* Pause/resume the guest using SIGUSR2 */ 245d94e22b9SSasha Levin static int is_paused; 246d94e22b9SSasha Levin 2474b1addaeSSasha Levin static void handle_pause(int fd, u32 type, u32 len, u8 *msg) 248d94e22b9SSasha Levin { 2495aa502e4SLai Jiangshan if (WARN_ON(len)) 2505aa502e4SLai Jiangshan return; 2515aa502e4SLai Jiangshan 2527021c50bSAsias He if (type == KVM_IPC_RESUME && is_paused) { 2537021c50bSAsias He kvm->vm_state = KVM_VMSTATE_RUNNING; 254d94e22b9SSasha Levin kvm__continue(); 2557021c50bSAsias He } else if (type == KVM_IPC_PAUSE && !is_paused) { 2567021c50bSAsias He kvm->vm_state = KVM_VMSTATE_PAUSED; 257eb8dad9dSSasha Levin ioctl(kvm->vm_fd, KVM_KVMCLOCK_CTRL); 258d94e22b9SSasha Levin kvm__pause(); 2597021c50bSAsias He } else { 26002317b74SSasha Levin return; 2615aa502e4SLai Jiangshan } 262d94e22b9SSasha Levin 263d94e22b9SSasha Levin is_paused = !is_paused; 264d94e22b9SSasha Levin } 265d94e22b9SSasha Levin 2667021c50bSAsias He static void handle_vmstate(int fd, u32 type, u32 len, u8 *msg) 2677021c50bSAsias He { 2687021c50bSAsias He int r = 0; 2697021c50bSAsias He 2707021c50bSAsias He if (type == KVM_IPC_VMSTATE) 2717021c50bSAsias He r = write(fd, &kvm->vm_state, sizeof(kvm->vm_state)); 2727021c50bSAsias He 2737021c50bSAsias He if (r < 0) 2747021c50bSAsias He pr_warning("Failed sending VMSTATE"); 2757021c50bSAsias He } 2767021c50bSAsias He 2774b1addaeSSasha Levin static void handle_debug(int fd, u32 type, u32 len, u8 *msg) 2789e854d1aSPekka Enberg { 2799e854d1aSPekka Enberg int i; 280a59cdf44SLai Jiangshan struct debug_cmd_params *params; 281a59cdf44SLai Jiangshan u32 dbg_type; 282a59cdf44SLai Jiangshan u32 vcpu; 283a59cdf44SLai Jiangshan 284a59cdf44SLai Jiangshan if (WARN_ON(type != KVM_IPC_DEBUG || len != sizeof(*params))) 285a59cdf44SLai Jiangshan return; 286a59cdf44SLai Jiangshan 287a59cdf44SLai Jiangshan params = (void *)msg; 288a59cdf44SLai Jiangshan dbg_type = params->dbg_type; 289a59cdf44SLai Jiangshan vcpu = params->cpu; 2904b1c6f6eSSasha Levin 291226e727bSSasha Levin if (dbg_type & KVM_DEBUG_CMD_TYPE_SYSRQ) 292226e727bSSasha Levin serial8250__inject_sysrq(kvm, params->sysrq); 293226e727bSSasha Levin 2944b1c6f6eSSasha Levin if (dbg_type & KVM_DEBUG_CMD_TYPE_NMI) { 2957070414aSSasha Levin if ((int)vcpu >= kvm->nrcpus) 2964b1c6f6eSSasha Levin return; 2974b1c6f6eSSasha Levin 298df4239fbSSasha Levin kvm->cpus[vcpu]->needs_nmi = 1; 299df4239fbSSasha Levin pthread_kill(kvm->cpus[vcpu]->thread, SIGUSR1); 3004b1c6f6eSSasha Levin } 3014b1c6f6eSSasha Levin 3024b1c6f6eSSasha Levin if (!(dbg_type & KVM_DEBUG_CMD_TYPE_DUMP)) 3034b1c6f6eSSasha Levin return; 3049e854d1aSPekka Enberg 30500ebbe96SSasha Levin for (i = 0; i < kvm->nrcpus; i++) { 306df4239fbSSasha Levin struct kvm_cpu *cpu = kvm->cpus[i]; 3079e854d1aSPekka Enberg 30843119af7SPekka Enberg if (!cpu) 30943119af7SPekka Enberg continue; 31043119af7SPekka Enberg 311cffeab25SIngo Molnar printout_done = 0; 312b7d2f013SSasha Levin 313b7d2f013SSasha Levin kvm_cpu__set_debug_fd(fd); 31443119af7SPekka Enberg pthread_kill(cpu->thread, SIGUSR1); 315cffeab25SIngo Molnar /* 316cffeab25SIngo Molnar * Wait for the vCPU to dump state before signalling 317cffeab25SIngo Molnar * the next thread. Since this is debug code it does 318cffeab25SIngo Molnar * not matter that we are burning CPU time a bit: 319cffeab25SIngo Molnar */ 320cffeab25SIngo Molnar while (!printout_done) 321cffeab25SIngo Molnar mb(); 3229e854d1aSPekka Enberg } 3239e854d1aSPekka Enberg 324b7d2f013SSasha Levin close(fd); 325b7d2f013SSasha Levin 326226e727bSSasha Levin serial8250__inject_sysrq(kvm, 'p'); 3279e854d1aSPekka Enberg } 3289e854d1aSPekka Enberg 3299e854d1aSPekka Enberg static void handle_sigalrm(int sig) 3309e854d1aSPekka Enberg { 3310b69bdefSMatt Evans kvm__arch_periodic_poll(kvm); 3329e854d1aSPekka Enberg } 3339e854d1aSPekka Enberg 3344b1addaeSSasha Levin static void handle_stop(int fd, u32 type, u32 len, u8 *msg) 335daf4cb5aSSasha Levin { 336e333e41aSLai Jiangshan if (WARN_ON(type != KVM_IPC_STOP || len)) 337e333e41aSLai Jiangshan return; 338e333e41aSLai Jiangshan 339df4239fbSSasha Levin kvm_cpu__reboot(kvm); 340daf4cb5aSSasha Levin } 341daf4cb5aSSasha Levin 3425ee154d1SPekka Enberg static void *kvm_cpu_thread(void *arg) 3435ee154d1SPekka Enberg { 344d77a9efaSCyrill Gorcunov current_kvm_cpu = arg; 3455ee154d1SPekka Enberg 346d77a9efaSCyrill Gorcunov if (kvm_cpu__start(current_kvm_cpu)) 3475ee154d1SPekka Enberg goto panic_kvm; 3485ee154d1SPekka Enberg 3495ee154d1SPekka Enberg return (void *) (intptr_t) 0; 3505ee154d1SPekka Enberg 3515ee154d1SPekka Enberg panic_kvm: 3523fdf659dSSasha Levin fprintf(stderr, "KVM exit reason: %u (\"%s\")\n", 353d77a9efaSCyrill Gorcunov current_kvm_cpu->kvm_run->exit_reason, 354d77a9efaSCyrill Gorcunov kvm_exit_reasons[current_kvm_cpu->kvm_run->exit_reason]); 355d77a9efaSCyrill Gorcunov if (current_kvm_cpu->kvm_run->exit_reason == KVM_EXIT_UNKNOWN) 3565ee154d1SPekka Enberg fprintf(stderr, "KVM exit code: 0x%Lu\n", 357d77a9efaSCyrill Gorcunov current_kvm_cpu->kvm_run->hw.hardware_exit_reason); 3588e5accedSPekka Enberg 359b7d2f013SSasha Levin kvm_cpu__set_debug_fd(STDOUT_FILENO); 360d77a9efaSCyrill Gorcunov kvm_cpu__show_registers(current_kvm_cpu); 361d77a9efaSCyrill Gorcunov kvm_cpu__show_code(current_kvm_cpu); 362d77a9efaSCyrill Gorcunov kvm_cpu__show_page_tables(current_kvm_cpu); 3635ee154d1SPekka Enberg 3645ee154d1SPekka Enberg return (void *) (intptr_t) 1; 3655ee154d1SPekka Enberg } 3665ee154d1SPekka Enberg 367e08c0896SPrasad Joshi static char kernel[PATH_MAX]; 368b0b42ba0SPekka Enberg 369b0b42ba0SPekka Enberg static const char *host_kernels[] = { 370e08c0896SPrasad Joshi "/boot/vmlinuz", 371e08c0896SPrasad Joshi "/boot/bzImage", 372e08c0896SPrasad Joshi NULL 373e08c0896SPrasad Joshi }; 374b0b42ba0SPekka Enberg 375b0b42ba0SPekka Enberg static const char *default_kernels[] = { 376e08c0896SPrasad Joshi "./bzImage", 377b03af790SKonstantin Khlebnikov "arch/" BUILD_ARCH "/boot/bzImage", 378af7b0868SMatt Evans "../../arch/" BUILD_ARCH "/boot/bzImage", 379e08c0896SPrasad Joshi NULL 380e08c0896SPrasad Joshi }; 3818329f30bSPekka Enberg 382b0b42ba0SPekka Enberg static const char *default_vmlinux[] = { 383b03af790SKonstantin Khlebnikov "vmlinux", 384b0b42ba0SPekka Enberg "../../../vmlinux", 385b0b42ba0SPekka Enberg "../../vmlinux", 386b0b42ba0SPekka Enberg NULL 387b0b42ba0SPekka Enberg }; 388b0b42ba0SPekka Enberg 389e08c0896SPrasad Joshi static void kernel_usage_with_options(void) 3908329f30bSPekka Enberg { 391e08c0896SPrasad Joshi const char **k; 3928329f30bSPekka Enberg struct utsname uts; 393e08c0896SPrasad Joshi 394e08c0896SPrasad Joshi fprintf(stderr, "Fatal: could not find default kernel image in:\n"); 39565182f37SPrasad Joshi k = &default_kernels[0]; 396e08c0896SPrasad Joshi while (*k) { 397e08c0896SPrasad Joshi fprintf(stderr, "\t%s\n", *k); 398e08c0896SPrasad Joshi k++; 399e08c0896SPrasad Joshi } 400e08c0896SPrasad Joshi 401e08c0896SPrasad Joshi if (uname(&uts) < 0) 402e08c0896SPrasad Joshi return; 403e08c0896SPrasad Joshi 404e08c0896SPrasad Joshi k = &host_kernels[0]; 405e08c0896SPrasad Joshi while (*k) { 406e08c0896SPrasad Joshi if (snprintf(kernel, PATH_MAX, "%s-%s", *k, uts.release) < 0) 407e08c0896SPrasad Joshi return; 408e08c0896SPrasad Joshi fprintf(stderr, "\t%s\n", kernel); 409e08c0896SPrasad Joshi k++; 410e08c0896SPrasad Joshi } 411ee8b1456SWanlong Gao fprintf(stderr, "\nPlease see '%s run --help' for more options.\n\n", 412ee8b1456SWanlong Gao KVM_BINARY_NAME); 413e08c0896SPrasad Joshi } 414e08c0896SPrasad Joshi 41560ded003SPekka Enberg static u64 host_ram_size(void) 41660ded003SPekka Enberg { 41760ded003SPekka Enberg long page_size; 41860ded003SPekka Enberg long nr_pages; 41960ded003SPekka Enberg 42060ded003SPekka Enberg nr_pages = sysconf(_SC_PHYS_PAGES); 421d63c5ce6SPekka Enberg if (nr_pages < 0) { 4224542f276SCyrill Gorcunov pr_warning("sysconf(_SC_PHYS_PAGES) failed"); 423d63c5ce6SPekka Enberg return 0; 424d63c5ce6SPekka Enberg } 42560ded003SPekka Enberg 42660ded003SPekka Enberg page_size = sysconf(_SC_PAGE_SIZE); 427d63c5ce6SPekka Enberg if (page_size < 0) { 4284542f276SCyrill Gorcunov pr_warning("sysconf(_SC_PAGE_SIZE) failed"); 429d63c5ce6SPekka Enberg return 0; 430d63c5ce6SPekka Enberg } 43160ded003SPekka Enberg 43260ded003SPekka Enberg return (nr_pages * page_size) >> MB_SHIFT; 43360ded003SPekka Enberg } 43460ded003SPekka Enberg 43518bd8c3bSPekka Enberg /* 43618bd8c3bSPekka Enberg * If user didn't specify how much memory it wants to allocate for the guest, 43718bd8c3bSPekka Enberg * avoid filling the whole host RAM. 43818bd8c3bSPekka Enberg */ 43918bd8c3bSPekka Enberg #define RAM_SIZE_RATIO 0.8 44018bd8c3bSPekka Enberg 441fd834defSPekka Enberg static u64 get_ram_size(int nr_cpus) 442fd834defSPekka Enberg { 44306761c76SPekka Enberg u64 available; 44406761c76SPekka Enberg u64 ram_size; 445fd834defSPekka Enberg 446fd834defSPekka Enberg ram_size = 64 * (nr_cpus + 3); 447fd834defSPekka Enberg 44860ded003SPekka Enberg available = host_ram_size() * RAM_SIZE_RATIO; 449d63c5ce6SPekka Enberg if (!available) 450d63c5ce6SPekka Enberg available = MIN_RAM_SIZE_MB; 451fd834defSPekka Enberg 452fd834defSPekka Enberg if (ram_size > available) 453fd834defSPekka Enberg ram_size = available; 454fd834defSPekka Enberg 455fd834defSPekka Enberg return ram_size; 456fd834defSPekka Enberg } 457fd834defSPekka Enberg 458e08c0896SPrasad Joshi static const char *find_kernel(void) 459e08c0896SPrasad Joshi { 460e08c0896SPrasad Joshi const char **k; 4618329f30bSPekka Enberg struct stat st; 462e08c0896SPrasad Joshi struct utsname uts; 463e08c0896SPrasad Joshi 46465182f37SPrasad Joshi k = &default_kernels[0]; 465e08c0896SPrasad Joshi while (*k) { 466e08c0896SPrasad Joshi if (stat(*k, &st) < 0 || !S_ISREG(st.st_mode)) { 467e08c0896SPrasad Joshi k++; 468e08c0896SPrasad Joshi continue; 469e08c0896SPrasad Joshi } 470e08c0896SPrasad Joshi strncpy(kernel, *k, PATH_MAX); 471e08c0896SPrasad Joshi return kernel; 472e08c0896SPrasad Joshi } 4738329f30bSPekka Enberg 4748329f30bSPekka Enberg if (uname(&uts) < 0) 4758329f30bSPekka Enberg return NULL; 4768329f30bSPekka Enberg 477e08c0896SPrasad Joshi k = &host_kernels[0]; 478e08c0896SPrasad Joshi while (*k) { 479e08c0896SPrasad Joshi if (snprintf(kernel, PATH_MAX, "%s-%s", *k, uts.release) < 0) 4808329f30bSPekka Enberg return NULL; 4818329f30bSPekka Enberg 482e08c0896SPrasad Joshi if (stat(kernel, &st) < 0 || !S_ISREG(st.st_mode)) { 483e08c0896SPrasad Joshi k++; 484e08c0896SPrasad Joshi continue; 485e08c0896SPrasad Joshi } 486e08c0896SPrasad Joshi return kernel; 4878329f30bSPekka Enberg 488e08c0896SPrasad Joshi } 4898329f30bSPekka Enberg return NULL; 4908329f30bSPekka Enberg } 4918329f30bSPekka Enberg 492b0b42ba0SPekka Enberg static const char *find_vmlinux(void) 493b0b42ba0SPekka Enberg { 494b0b42ba0SPekka Enberg const char **vmlinux; 495b0b42ba0SPekka Enberg 496b0b42ba0SPekka Enberg vmlinux = &default_vmlinux[0]; 497b0b42ba0SPekka Enberg while (*vmlinux) { 498b0b42ba0SPekka Enberg struct stat st; 499b0b42ba0SPekka Enberg 500b0b42ba0SPekka Enberg if (stat(*vmlinux, &st) < 0 || !S_ISREG(st.st_mode)) { 501b0b42ba0SPekka Enberg vmlinux++; 502b0b42ba0SPekka Enberg continue; 503b0b42ba0SPekka Enberg } 504b0b42ba0SPekka Enberg return *vmlinux; 505b0b42ba0SPekka Enberg } 506b0b42ba0SPekka Enberg return NULL; 507b0b42ba0SPekka Enberg } 508b0b42ba0SPekka Enberg 509f6677a1dSAmerigo Wang void kvm_run_help(void) 510f6677a1dSAmerigo Wang { 5113b55dcdeSSasha Levin BUILD_OPTIONS(options, &kvm->cfg, kvm); 512f6677a1dSAmerigo Wang usage_with_options(run_usage, options); 513f6677a1dSAmerigo Wang } 514f6677a1dSAmerigo Wang 515afc2c7c0SAsias He static int kvm_setup_guest_init(void) 5169cec19c8SSasha Levin { 51747621338SSasha Levin const char *rootfs = kvm->cfg.custom_rootfs_name; 518afc2c7c0SAsias He char tmp[PATH_MAX]; 519afc2c7c0SAsias He size_t size; 520afc2c7c0SAsias He int fd, ret; 521afc2c7c0SAsias He char *data; 5229cec19c8SSasha Levin 523afc2c7c0SAsias He /* Setup /virt/init */ 524afc2c7c0SAsias He size = (size_t)&_binary_guest_init_size; 525afc2c7c0SAsias He data = (char *)&_binary_guest_init_start; 526afc2c7c0SAsias He snprintf(tmp, PATH_MAX, "%s%s/virt/init", kvm__get_dir(), rootfs); 527afc2c7c0SAsias He remove(tmp); 528afc2c7c0SAsias He fd = open(tmp, O_CREAT | O_WRONLY, 0755); 529afc2c7c0SAsias He if (fd < 0) 530afc2c7c0SAsias He die("Fail to setup %s", tmp); 531afc2c7c0SAsias He ret = xwrite(fd, data, size); 532afc2c7c0SAsias He if (ret < 0) 533afc2c7c0SAsias He die("Fail to setup %s", tmp); 534afc2c7c0SAsias He close(fd); 5359cec19c8SSasha Levin 536afc2c7c0SAsias He return 0; 5379cec19c8SSasha Levin } 5389cec19c8SSasha Levin 539d50fe489SSasha Levin static int kvm_run_set_sandbox(void) 540d50fe489SSasha Levin { 54147621338SSasha Levin const char *guestfs_name = kvm->cfg.custom_rootfs_name; 542d50fe489SSasha Levin char path[PATH_MAX], script[PATH_MAX], *tmp; 543d50fe489SSasha Levin 544d50fe489SSasha Levin snprintf(path, PATH_MAX, "%s%s/virt/sandbox.sh", kvm__get_dir(), guestfs_name); 545d50fe489SSasha Levin 546d50fe489SSasha Levin remove(path); 547d50fe489SSasha Levin 54847621338SSasha Levin if (kvm->cfg.sandbox == NULL) 549d50fe489SSasha Levin return 0; 550d50fe489SSasha Levin 55147621338SSasha Levin tmp = realpath(kvm->cfg.sandbox, NULL); 552d50fe489SSasha Levin if (tmp == NULL) 553d50fe489SSasha Levin return -ENOMEM; 554d50fe489SSasha Levin 555d50fe489SSasha Levin snprintf(script, PATH_MAX, "/host/%s", tmp); 556d50fe489SSasha Levin free(tmp); 557d50fe489SSasha Levin 558d50fe489SSasha Levin return symlink(script, path); 559d50fe489SSasha Levin } 560d50fe489SSasha Levin 5615173b4afSLai Jiangshan static void kvm_write_sandbox_cmd_exactly(int fd, const char *arg) 5625173b4afSLai Jiangshan { 5635173b4afSLai Jiangshan const char *single_quote; 5645173b4afSLai Jiangshan 5655173b4afSLai Jiangshan if (!*arg) { /* zero length string */ 5665173b4afSLai Jiangshan if (write(fd, "''", 2) <= 0) 5675173b4afSLai Jiangshan die("Failed writing sandbox script"); 5685173b4afSLai Jiangshan return; 5695173b4afSLai Jiangshan } 5705173b4afSLai Jiangshan 5715173b4afSLai Jiangshan while (*arg) { 5725173b4afSLai Jiangshan single_quote = strchrnul(arg, '\''); 5735173b4afSLai Jiangshan 5745173b4afSLai Jiangshan /* write non-single-quote string as #('string') */ 5755173b4afSLai Jiangshan if (arg != single_quote) { 5765173b4afSLai Jiangshan if (write(fd, "'", 1) <= 0 || 5775173b4afSLai Jiangshan write(fd, arg, single_quote - arg) <= 0 || 5785173b4afSLai Jiangshan write(fd, "'", 1) <= 0) 5795173b4afSLai Jiangshan die("Failed writing sandbox script"); 5805173b4afSLai Jiangshan } 5815173b4afSLai Jiangshan 5825173b4afSLai Jiangshan /* write single quote as #("'") */ 5835173b4afSLai Jiangshan if (*single_quote) { 5845173b4afSLai Jiangshan if (write(fd, "\"'\"", 3) <= 0) 5855173b4afSLai Jiangshan die("Failed writing sandbox script"); 5865173b4afSLai Jiangshan } else 5875173b4afSLai Jiangshan break; 5885173b4afSLai Jiangshan 5895173b4afSLai Jiangshan arg = single_quote + 1; 5905173b4afSLai Jiangshan } 5915173b4afSLai Jiangshan } 5925173b4afSLai Jiangshan 5935cd19aa0SPekka Enberg static void resolve_program(const char *src, char *dst, size_t len) 5945cd19aa0SPekka Enberg { 5955cd19aa0SPekka Enberg struct stat st; 596c2c742d9SPekka Enberg int err; 5975cd19aa0SPekka Enberg 598c2c742d9SPekka Enberg err = stat(src, &st); 5995cd19aa0SPekka Enberg 600c2c742d9SPekka Enberg if (!err && S_ISREG(st.st_mode)) { 6015cd19aa0SPekka Enberg char resolved_path[PATH_MAX]; 6025cd19aa0SPekka Enberg 603de3f75c9SPekka Enberg if (!realpath(src, resolved_path)) 604de3f75c9SPekka Enberg die("Unable to resolve program %s: %s\n", src, strerror(errno)); 6055cd19aa0SPekka Enberg 6065cd19aa0SPekka Enberg snprintf(dst, len, "/host%s", resolved_path); 6075cd19aa0SPekka Enberg } else 6085cd19aa0SPekka Enberg strncpy(dst, src, len); 6095cd19aa0SPekka Enberg } 6105cd19aa0SPekka Enberg 6113c29e2aaSSasha Levin static void kvm_run_write_sandbox_cmd(const char **argv, int argc) 6123c29e2aaSSasha Levin { 6133c29e2aaSSasha Levin const char script_hdr[] = "#! /bin/bash\n\n"; 6145cd19aa0SPekka Enberg char program[PATH_MAX]; 6153c29e2aaSSasha Levin int fd; 6163c29e2aaSSasha Levin 61747621338SSasha Levin remove(kvm->cfg.sandbox); 6183c29e2aaSSasha Levin 61947621338SSasha Levin fd = open(kvm->cfg.sandbox, O_RDWR | O_CREAT, 0777); 6203c29e2aaSSasha Levin if (fd < 0) 6213c29e2aaSSasha Levin die("Failed creating sandbox script"); 6223c29e2aaSSasha Levin 6233c29e2aaSSasha Levin if (write(fd, script_hdr, sizeof(script_hdr) - 1) <= 0) 6243c29e2aaSSasha Levin die("Failed writing sandbox script"); 6253c29e2aaSSasha Levin 6265cd19aa0SPekka Enberg resolve_program(argv[0], program, PATH_MAX); 6275cd19aa0SPekka Enberg kvm_write_sandbox_cmd_exactly(fd, program); 6285cd19aa0SPekka Enberg 6295cd19aa0SPekka Enberg argv++; 6305cd19aa0SPekka Enberg argc--; 6315cd19aa0SPekka Enberg 6323c29e2aaSSasha Levin while (argc) { 6333c29e2aaSSasha Levin if (write(fd, " ", 1) <= 0) 6343c29e2aaSSasha Levin die("Failed writing sandbox script"); 6355cd19aa0SPekka Enberg 6365cd19aa0SPekka Enberg kvm_write_sandbox_cmd_exactly(fd, argv[0]); 6373c29e2aaSSasha Levin argv++; 6383c29e2aaSSasha Levin argc--; 6393c29e2aaSSasha Levin } 6403c29e2aaSSasha Levin if (write(fd, "\n", 1) <= 0) 6413c29e2aaSSasha Levin die("Failed writing sandbox script"); 6423c29e2aaSSasha Levin 6433c29e2aaSSasha Levin close(fd); 6443c29e2aaSSasha Levin } 6453c29e2aaSSasha Levin 646e1e46fe6SSasha Levin static int kvm_cmd_run_init(int argc, const char **argv) 647f967c427SPrasad Joshi { 6482d96f6b6SSasha Levin static char real_cmdline[2048], default_name[20]; 649aba1efa5SPekka Enberg struct framebuffer *fb = NULL; 650384922b3SPekka Enberg unsigned int nr_online_cpus; 651*5f225124SSasha Levin int r; 65247621338SSasha Levin 65347621338SSasha Levin kvm = kvm__new(); 65447621338SSasha Levin if (IS_ERR(kvm)) 65547621338SSasha Levin return PTR_ERR(kvm); 656f967c427SPrasad Joshi 6575ee154d1SPekka Enberg signal(SIGALRM, handle_sigalrm); 6584b1addaeSSasha Levin kvm_ipc__register_handler(KVM_IPC_DEBUG, handle_debug); 65943119af7SPekka Enberg signal(SIGUSR1, handle_sigusr1); 6604b1addaeSSasha Levin kvm_ipc__register_handler(KVM_IPC_PAUSE, handle_pause); 6614b1addaeSSasha Levin kvm_ipc__register_handler(KVM_IPC_RESUME, handle_pause); 6624b1addaeSSasha Levin kvm_ipc__register_handler(KVM_IPC_STOP, handle_stop); 6637021c50bSAsias He kvm_ipc__register_handler(KVM_IPC_VMSTATE, handle_vmstate); 664f967c427SPrasad Joshi 665cfd63bbbSSasha Levin nr_online_cpus = sysconf(_SC_NPROCESSORS_ONLN); 66647621338SSasha Levin kvm->cfg.custom_rootfs_name = "default"; 667cfd63bbbSSasha Levin 668f967c427SPrasad Joshi while (argc != 0) { 6693b55dcdeSSasha Levin BUILD_OPTIONS(options, &kvm->cfg, kvm); 670f967c427SPrasad Joshi argc = parse_options(argc, argv, options, run_usage, 6711a007c82SSasha Levin PARSE_OPT_STOP_AT_NON_OPTION | 6721a007c82SSasha Levin PARSE_OPT_KEEP_DASHDASH); 673f967c427SPrasad Joshi if (argc != 0) { 6741a007c82SSasha Levin /* Cusrom options, should have been handled elsewhere */ 6753c29e2aaSSasha Levin if (strcmp(argv[0], "--") == 0) { 6763c29e2aaSSasha Levin if (kvm_run_wrapper == KVM_RUN_SANDBOX) { 67747621338SSasha Levin kvm->cfg.sandbox = DEFAULT_SANDBOX_FILENAME; 6783c29e2aaSSasha Levin kvm_run_write_sandbox_cmd(argv+1, argc-1); 6791a007c82SSasha Levin break; 6803c29e2aaSSasha Levin } 6813c29e2aaSSasha Levin } 6821a007c82SSasha Levin 68347621338SSasha Levin if ((kvm_run_wrapper == KVM_RUN_DEFAULT && kvm->cfg.kernel_filename) || 68447621338SSasha Levin (kvm_run_wrapper == KVM_RUN_SANDBOX && kvm->cfg.sandbox)) { 685f967c427SPrasad Joshi fprintf(stderr, "Cannot handle parameter: " 686f967c427SPrasad Joshi "%s\n", argv[0]); 687f967c427SPrasad Joshi usage_with_options(run_usage, options); 68847621338SSasha Levin free(kvm); 689e120b624SPaul Neumann return -EINVAL; 690f967c427SPrasad Joshi } 691e0747665SSasha Levin if (kvm_run_wrapper == KVM_RUN_SANDBOX) { 692e0747665SSasha Levin /* 693e0747665SSasha Levin * first unhandled parameter is treated as 694e0747665SSasha Levin * sandbox command 695e0747665SSasha Levin */ 69647621338SSasha Levin kvm->cfg.sandbox = DEFAULT_SANDBOX_FILENAME; 697e0747665SSasha Levin kvm_run_write_sandbox_cmd(argv, argc); 698e0747665SSasha Levin } else { 699e0747665SSasha Levin /* 700e0747665SSasha Levin * first unhandled parameter is treated as a kernel 701e0747665SSasha Levin * image 702f967c427SPrasad Joshi */ 70347621338SSasha Levin kvm->cfg.kernel_filename = argv[0]; 704e0747665SSasha Levin } 705f967c427SPrasad Joshi argv++; 706f967c427SPrasad Joshi argc--; 707f967c427SPrasad Joshi } 708f967c427SPrasad Joshi 709f967c427SPrasad Joshi } 710f967c427SPrasad Joshi 7113b55dcdeSSasha Levin kvm->nr_disks = kvm->cfg.image_count; 7123b55dcdeSSasha Levin 71347621338SSasha Levin if (!kvm->cfg.kernel_filename) 71447621338SSasha Levin kvm->cfg.kernel_filename = find_kernel(); 7158329f30bSPekka Enberg 71647621338SSasha Levin if (!kvm->cfg.kernel_filename) { 717e08c0896SPrasad Joshi kernel_usage_with_options(); 718e120b624SPaul Neumann return -EINVAL; 7198329f30bSPekka Enberg } 7208329f30bSPekka Enberg 72147621338SSasha Levin kvm->cfg.vmlinux_filename = find_vmlinux(); 722b0b42ba0SPekka Enberg 72300ebbe96SSasha Levin if (kvm->cfg.nrcpus == 0) 72400ebbe96SSasha Levin kvm->cfg.nrcpus = nr_online_cpus; 725d77a9efaSCyrill Gorcunov 72647621338SSasha Levin if (!kvm->cfg.ram_size) 72700ebbe96SSasha Levin kvm->cfg.ram_size = get_ram_size(kvm->cfg.nrcpus); 728fd834defSPekka Enberg 72947621338SSasha Levin if (kvm->cfg.ram_size < MIN_RAM_SIZE_MB) 73047621338SSasha Levin die("Not enough memory specified: %lluMB (min %lluMB)", kvm->cfg.ram_size, MIN_RAM_SIZE_MB); 731a2a002f9SIngo Molnar 73247621338SSasha Levin if (kvm->cfg.ram_size > host_ram_size()) 73347621338SSasha Levin pr_warning("Guest memory size %lluMB exceeds host physical RAM size %lluMB", kvm->cfg.ram_size, host_ram_size()); 73460ded003SPekka Enberg 73547621338SSasha Levin kvm->cfg.ram_size <<= MB_SHIFT; 736f967c427SPrasad Joshi 73747621338SSasha Levin if (!kvm->cfg.dev) 73847621338SSasha Levin kvm->cfg.dev = DEFAULT_KVM_DEV; 739f967c427SPrasad Joshi 74047621338SSasha Levin if (!kvm->cfg.console) 74147621338SSasha Levin kvm->cfg.console = DEFAULT_CONSOLE; 7429aa4a0ebSAsias He 74347621338SSasha Levin if (!strncmp(kvm->cfg.console, "virtio", 6)) 7442651ea58SSasha Levin kvm->cfg.active_console = CONSOLE_VIRTIO; 74547621338SSasha Levin else if (!strncmp(kvm->cfg.console, "serial", 6)) 7462651ea58SSasha Levin kvm->cfg.active_console = CONSOLE_8250; 74747621338SSasha Levin else if (!strncmp(kvm->cfg.console, "hv", 2)) 7482651ea58SSasha Levin kvm->cfg.active_console = CONSOLE_HV; 7493bbc49b6SMatt Evans else 7503bbc49b6SMatt Evans pr_warning("No console!"); 751f967c427SPrasad Joshi 75247621338SSasha Levin if (!kvm->cfg.host_ip) 75347621338SSasha Levin kvm->cfg.host_ip = DEFAULT_HOST_ADDR; 7544d67c820SSasha Levin 75547621338SSasha Levin if (!kvm->cfg.guest_ip) 75647621338SSasha Levin kvm->cfg.guest_ip = DEFAULT_GUEST_ADDR; 757bb8ffd2fSAsias He 75847621338SSasha Levin if (!kvm->cfg.guest_mac) 75947621338SSasha Levin kvm->cfg.guest_mac = DEFAULT_GUEST_MAC; 760a4e724ddSSasha Levin 76147621338SSasha Levin if (!kvm->cfg.host_mac) 76247621338SSasha Levin kvm->cfg.host_mac = DEFAULT_HOST_MAC; 763d7098b9bSAsias He 76447621338SSasha Levin if (!kvm->cfg.script) 76547621338SSasha Levin kvm->cfg.script = DEFAULT_SCRIPT; 76673b7d038SAmos Kong 767dca745e4SSasha Levin r = term_init(kvm); 768dca745e4SSasha Levin if (r < 0) { 769dca745e4SSasha Levin pr_err("term_init() failed with error %d\n", r); 770dca745e4SSasha Levin goto fail; 771dca745e4SSasha Levin } 772f967c427SPrasad Joshi 77347621338SSasha Levin if (!kvm->cfg.guest_name) { 77447621338SSasha Levin if (kvm->cfg.custom_rootfs) { 77547621338SSasha Levin kvm->cfg.guest_name = kvm->cfg.custom_rootfs_name; 776587a4d17SLai Jiangshan } else { 7772d96f6b6SSasha Levin sprintf(default_name, "guest-%u", getpid()); 77847621338SSasha Levin kvm->cfg.guest_name = default_name; 7792d96f6b6SSasha Levin } 780587a4d17SLai Jiangshan } 7812d96f6b6SSasha Levin 78247621338SSasha Levin r = kvm__init(kvm); 78347621338SSasha Levin if (r) 784d648dbf5SCyrill Gorcunov goto fail; 785f967c427SPrasad Joshi 786ea6eeb1cSSasha Levin r = ioeventfd__init(kvm); 787ea6eeb1cSSasha Levin if (r < 0) { 788ea6eeb1cSSasha Levin pr_err("ioeventfd__init() failed with error %d\n", r); 789ea6eeb1cSSasha Levin goto fail; 790ea6eeb1cSSasha Levin } 79137f3d50eSSasha Levin 792df4239fbSSasha Levin r = kvm_cpu__init(kvm); 793df4239fbSSasha Levin if (r < 0) { 794df4239fbSSasha Levin pr_err("kvm_cpu__init() failed with error %d\n", r); 795df4239fbSSasha Levin goto fail; 796384922b3SPekka Enberg } 797384922b3SPekka Enberg 798e3c4f8aaSSasha Levin r = irq__init(kvm); 799e3c4f8aaSSasha Levin if (r < 0) { 800e3c4f8aaSSasha Levin pr_err("irq__init() failed with error %d\n", r); 801e3c4f8aaSSasha Levin goto fail; 802e3c4f8aaSSasha Levin } 80319e6c8b8SMatt Evans 8046d987703SSasha Levin r = pci__init(kvm); 8056d987703SSasha Levin if (r < 0) { 8066d987703SSasha Levin pr_err("pci__init() failed with error %d\n", r); 8076d987703SSasha Levin goto fail; 8086d987703SSasha Levin } 809b91be965SMatt Evans 8107af40b91SSasha Levin r = ioport__init(kvm); 8117af40b91SSasha Levin if (r < 0) { 8127af40b91SSasha Levin pr_err("ioport__init() failed with error %d\n", r); 8137af40b91SSasha Levin goto fail; 8147af40b91SSasha Levin } 8157af40b91SSasha Levin 816890364f8SCyrill Gorcunov /* 817890364f8SCyrill Gorcunov * vidmode should be either specified 818890364f8SCyrill Gorcunov * either set by default 819890364f8SCyrill Gorcunov */ 82047621338SSasha Levin if (kvm->cfg.vnc || kvm->cfg.sdl) { 821890364f8SCyrill Gorcunov if (vidmode == -1) 822890364f8SCyrill Gorcunov vidmode = 0x312; 82348d9e01aSSasha Levin } else { 824890364f8SCyrill Gorcunov vidmode = 0; 82548d9e01aSSasha Levin } 826890364f8SCyrill Gorcunov 82726c853e4SPrasad Joshi memset(real_cmdline, 0, sizeof(real_cmdline)); 82847621338SSasha Levin kvm__arch_set_cmdline(real_cmdline, kvm->cfg.vnc || kvm->cfg.sdl); 8298e704a7aSMatt Evans 8308e704a7aSMatt Evans if (strlen(real_cmdline) > 0) 831d74181ccSSasha Levin strcat(real_cmdline, " "); 8328e704a7aSMatt Evans 83347621338SSasha Levin if (kvm->cfg.kernel_cmdline) 83447621338SSasha Levin strlcat(real_cmdline, kvm->cfg.kernel_cmdline, sizeof(real_cmdline)); 83526c853e4SPrasad Joshi 83647621338SSasha Levin if (!kvm->cfg.using_rootfs && !kvm->cfg.disk_image[0].filename && !kvm->cfg.initrd_filename) { 837c8675741SSasha Levin char tmp[PATH_MAX]; 8386df1471eSPekka Enberg 83947621338SSasha Levin kvm_setup_create_new(kvm->cfg.custom_rootfs_name); 84047621338SSasha Levin kvm_setup_resolv(kvm->cfg.custom_rootfs_name); 841c8675741SSasha Levin 8429667701cSPekka Enberg snprintf(tmp, PATH_MAX, "%s%s", kvm__get_dir(), "default"); 843c8675741SSasha Levin if (virtio_9p__register(kvm, tmp, "/dev/root") < 0) 844c8675741SSasha Levin die("Unable to initialize virtio 9p"); 845c8675741SSasha Levin if (virtio_9p__register(kvm, "/", "hostfs") < 0) 846c8675741SSasha Levin die("Unable to initialize virtio 9p"); 84747621338SSasha Levin kvm->cfg.using_rootfs = kvm->cfg.custom_rootfs = 1; 84826c853e4SPrasad Joshi } 84926c853e4SPrasad Joshi 85047621338SSasha Levin if (kvm->cfg.using_rootfs) { 851ff42603fSSasha Levin strcat(real_cmdline, " root=/dev/root rw rootflags=rw,trans=virtio,version=9p2000.L rootfstype=9p"); 85247621338SSasha Levin if (kvm->cfg.custom_rootfs) { 853d50fe489SSasha Levin kvm_run_set_sandbox(); 854d50fe489SSasha Levin 855a8e6b4b9SSasha Levin strcat(real_cmdline, " init=/virt/init"); 856d50fe489SSasha Levin 85747621338SSasha Levin if (!kvm->cfg.no_dhcp) 858a8e6b4b9SSasha Levin strcat(real_cmdline, " ip=dhcp"); 859afc2c7c0SAsias He if (kvm_setup_guest_init()) 860afc2c7c0SAsias He die("Failed to setup init for guest."); 861a8e6b4b9SSasha Levin } 86282d65b5eSSasha Levin } else if (!strstr(real_cmdline, "root=")) { 863ff42603fSSasha Levin strlcat(real_cmdline, " root=/dev/vda rw ", sizeof(real_cmdline)); 86482d65b5eSSasha Levin } 86559aa2d30SSasha Levin 8663b55dcdeSSasha Levin r = disk_image__init(kvm); 8673b55dcdeSSasha Levin if (r < 0) { 8683b55dcdeSSasha Levin pr_err("disk_image__init() failed with error %d\n", r); 8699f9207c5SSasha Levin goto fail; 8709f9207c5SSasha Levin } 871c1ed214eSPrasad Joshi 872ee8b1456SWanlong Gao printf(" # %s run -k %s -m %Lu -c %d --name %s\n", KVM_BINARY_NAME, 87300ebbe96SSasha Levin kvm->cfg.kernel_filename, kvm->cfg.ram_size / 1024 / 1024, kvm->cfg.nrcpus, kvm->cfg.guest_name); 874471c6facSPekka Enberg 87547621338SSasha Levin if (!kvm->cfg.firmware_filename) { 87647621338SSasha Levin if (!kvm__load_kernel(kvm, kvm->cfg.kernel_filename, 87747621338SSasha Levin kvm->cfg.initrd_filename, real_cmdline, vidmode)) 87847621338SSasha Levin die("unable to load kernel %s", kvm->cfg.kernel_filename); 879f967c427SPrasad Joshi 88047621338SSasha Levin kvm->vmlinux = kvm->cfg.vmlinux_filename; 881807b77b9SCyrill Gorcunov r = symbol_init(kvm); 882b56f1728SCyrill Gorcunov if (r < 0) 883c4b716ecSPekka Enberg pr_debug("symbol_init() failed with error %d\n", r); 8845ad8db5eSPekka Enberg } 885b0b42ba0SPekka Enberg 886af7b0868SMatt Evans ioport__setup_arch(); 887ac38f433SPekka Enberg 88820c39545SSasha Levin r = rtc__init(kvm); 88920c39545SSasha Levin if (r < 0) { 89020c39545SSasha Levin pr_err("rtc__init() failed with error %d\n", r); 89120c39545SSasha Levin goto fail; 89220c39545SSasha Levin } 89364136c1cSPekka Enberg 89420715a22SSasha Levin r = serial8250__init(kvm); 89520715a22SSasha Levin if (r < 0) { 89620715a22SSasha Levin pr_err("serial__init() failed with error %d\n", r); 89720715a22SSasha Levin goto fail; 89820715a22SSasha Levin } 899f967c427SPrasad Joshi 9009f9207c5SSasha Levin r = virtio_blk__init(kvm); 9019f9207c5SSasha Levin if (r < 0) { 9029f9207c5SSasha Levin pr_err("virtio_blk__init() failed with error %d\n", r); 9039f9207c5SSasha Levin goto fail; 9049f9207c5SSasha Levin } 9059f9207c5SSasha Levin 906a67da3beSAsias He r = virtio_scsi_init(kvm); 907a67da3beSAsias He if (r < 0) { 908a67da3beSAsias He pr_err("virtio_scsi_init() failed with error %d\n", r); 909a67da3beSAsias He goto fail; 910a67da3beSAsias He } 911a67da3beSAsias He 912a3fa3f86SSasha Levin r = virtio_console__init(kvm); 913a3fa3f86SSasha Levin if (r < 0) { 914a3fa3f86SSasha Levin pr_err("virtio_console__init() failed with error %d\n", r); 915a3fa3f86SSasha Levin goto fail; 916a3fa3f86SSasha Levin } 917f967c427SPrasad Joshi 918f16653adSSasha Levin r = virtio_rng__init(kvm); 919f16653adSSasha Levin if (r < 0) { 920f16653adSSasha Levin pr_err("virtio_rng__init() failed with error %d\n", r); 921f16653adSSasha Levin goto fail; 922f16653adSSasha Levin } 92353eca082SSasha Levin 924d06db2fdSSasha Levin r = virtio_bln__init(kvm); 925d06db2fdSSasha Levin if (r < 0) { 926d06db2fdSSasha Levin pr_err("virtio_rng__init() failed with error %d\n", r); 927d06db2fdSSasha Levin goto fail; 928d06db2fdSSasha Levin } 92982d2f21eSSasha Levin 93047621338SSasha Levin if (!kvm->cfg.network) 93147621338SSasha Levin kvm->cfg.network = DEFAULT_NETWORK; 9324f56d42cSAsias He 933c7838fbdSSasha Levin virtio_9p__init(kvm); 934c7838fbdSSasha Levin 935*5f225124SSasha Levin r = virtio_net__init(kvm); 936*5f225124SSasha Levin if (r < 0) { 937*5f225124SSasha Levin pr_err("virtio_net__init() failed with error %d\n", r); 938*5f225124SSasha Levin goto fail; 939bdfcfca6SSasha Levin } 9404f56d42cSAsias He 941839051d9SSasha Levin kvm__init_ram(kvm); 942839051d9SSasha Levin 94357d7832bSMatt Evans #ifdef CONFIG_X86 944714e5b7fSSasha Levin kbd__init(kvm); 94557d7832bSMatt Evans #endif 946714e5b7fSSasha Levin 9478cec93dbSSasha Levin r = pci_shmem__init(kvm); 9488cec93dbSSasha Levin if (r < 0) { 9498cec93dbSSasha Levin pr_err("pci_shmem__init() failed with error %d\n", r); 9508cec93dbSSasha Levin goto fail; 9518cec93dbSSasha Levin } 95295d13a52SSasha Levin 95347621338SSasha Levin if (kvm->cfg.vnc || kvm->cfg.sdl) { 9543f838fecSPekka Enberg fb = vesa__init(kvm); 95548d9e01aSSasha Levin if (IS_ERR(fb)) { 95648d9e01aSSasha Levin pr_err("vesa__init() failed with error %ld\n", PTR_ERR(fb)); 95748d9e01aSSasha Levin goto fail; 95848d9e01aSSasha Levin } 9593f838fecSPekka Enberg } 9603f838fecSPekka Enberg 96147621338SSasha Levin if (kvm->cfg.vnc && fb) { 96248d9e01aSSasha Levin r = vnc__init(fb); 96348d9e01aSSasha Levin if (r < 0) { 96448d9e01aSSasha Levin pr_err("vnc__init() failed with error %d\n", r); 96548d9e01aSSasha Levin goto fail; 96648d9e01aSSasha Levin } 96748d9e01aSSasha Levin } 96848d9e01aSSasha Levin 96947621338SSasha Levin if (kvm->cfg.sdl && fb) { 9703f838fecSPekka Enberg sdl__init(fb); 97148d9e01aSSasha Levin if (r < 0) { 97248d9e01aSSasha Levin pr_err("sdl__init() failed with error %d\n", r); 97348d9e01aSSasha Levin goto fail; 97448d9e01aSSasha Levin } 9753f838fecSPekka Enberg } 976aba1efa5SPekka Enberg 977ba46fe53SSasha Levin r = fb__init(kvm); 97848d9e01aSSasha Levin if (r < 0) { 97948d9e01aSSasha Levin pr_err("fb__init() failed with error %d\n", r); 98048d9e01aSSasha Levin goto fail; 98148d9e01aSSasha Levin } 982aba1efa5SPekka Enberg 983df4239fbSSasha Levin /* 984df4239fbSSasha Levin * Device init all done; firmware init must 98525af47eeSMatt Evans * come after this (it may set up device trees etc.) 98625af47eeSMatt Evans */ 98725af47eeSMatt Evans 988b4532ca9SSasha Levin r = kvm_timer__init(kvm); 989b4532ca9SSasha Levin if (r < 0) { 990b4532ca9SSasha Levin pr_err("kvm_timer__init() failed with error %d\n", r); 991b4532ca9SSasha Levin goto fail; 992b4532ca9SSasha Levin } 99325af47eeSMatt Evans 99447621338SSasha Levin if (kvm->cfg.firmware_filename) { 99547621338SSasha Levin if (!kvm__load_firmware(kvm, kvm->cfg.firmware_filename)) 99647621338SSasha Levin die("unable to load firmware image %s: %s", kvm->cfg.firmware_filename, strerror(errno)); 9975ad8db5eSPekka Enberg } else { 998e1e46fe6SSasha Levin kvm__arch_setup_firmware(kvm); 9991add9f73SSasha Levin if (r < 0) { 10001add9f73SSasha Levin pr_err("kvm__arch_setup_firmware() failed with error %d\n", r); 10011add9f73SSasha Levin goto fail; 10021add9f73SSasha Levin } 10035ad8db5eSPekka Enberg } 100425af47eeSMatt Evans 1005f6a3c571SSasha Levin r = thread_pool__init(kvm); 1006f6a3c571SSasha Levin if (r < 0) { 1007f6a3c571SSasha Levin pr_err("thread_pool__init() failed with error %d\n", r); 1008f6a3c571SSasha Levin goto fail; 1009f6a3c571SSasha Levin } 1010f6a3c571SSasha Levin 10114932d174SSasha Levin fail: 10124932d174SSasha Levin return r; 1013e1e46fe6SSasha Levin } 1014e1e46fe6SSasha Levin 1015e1e46fe6SSasha Levin static int kvm_cmd_run_work(void) 1016e1e46fe6SSasha Levin { 1017df4239fbSSasha Levin int i; 1018e1e46fe6SSasha Levin void *ret = NULL; 1019e1e46fe6SSasha Levin 102000ebbe96SSasha Levin for (i = 0; i < kvm->nrcpus; i++) { 1021df4239fbSSasha Levin if (pthread_create(&kvm->cpus[i]->thread, NULL, kvm_cpu_thread, kvm->cpus[i]) != 0) 10225ee154d1SPekka Enberg die("unable to create KVM VCPU thread"); 10235ee154d1SPekka Enberg } 10245ee154d1SPekka Enberg 102549e5227dSSasha Levin /* Only VCPU #0 is going to exit by itself when shutting down */ 1026df4239fbSSasha Levin return pthread_join(kvm->cpus[0]->thread, &ret); 1027e1e46fe6SSasha Levin } 1028e1e46fe6SSasha Levin 10294932d174SSasha Levin static void kvm_cmd_run_exit(int guest_ret) 1030e1e46fe6SSasha Levin { 10314932d174SSasha Levin int r = 0; 10324932d174SSasha Levin 1033e6694207SSasha Levin compat__print_all_messages(); 1034e6694207SSasha Levin 1035df4239fbSSasha Levin r = kvm_cpu__exit(kvm); 1036df4239fbSSasha Levin if (r < 0) 1037df4239fbSSasha Levin pr_warning("kvm_cpu__exit() failed with error %d\n", r); 1038df4239fbSSasha Levin 1039807b77b9SCyrill Gorcunov r = symbol_exit(kvm); 10404932d174SSasha Levin if (r < 0) 1041807b77b9SCyrill Gorcunov pr_warning("symbol_exit() failed with error %d\n", r); 10424932d174SSasha Levin 1043e3c4f8aaSSasha Levin r = irq__exit(kvm); 1044e3c4f8aaSSasha Levin if (r < 0) 1045e3c4f8aaSSasha Levin pr_warning("irq__exit() failed with error %d\n", r); 1046e3c4f8aaSSasha Levin 1047b4532ca9SSasha Levin r = kvm_timer__exit(kvm); 1048b4532ca9SSasha Levin if (r < 0) 1049b4532ca9SSasha Levin pr_warning("kvm_timer__exit() failed with error %d\n", r); 1050b4532ca9SSasha Levin 1051ba46fe53SSasha Levin r = fb__exit(kvm); 1052ba46fe53SSasha Levin if (r < 0) 1053b4532ca9SSasha Levin pr_warning("kvm_timer__exit() failed with error %d\n", r); 1054aba1efa5SPekka Enberg 1055*5f225124SSasha Levin r = virtio_net__exit(kvm); 1056*5f225124SSasha Levin if (r < 0) 1057*5f225124SSasha Levin pr_warning("virtio_net__exit() failed with error %d\n", r); 1058*5f225124SSasha Levin 1059a67da3beSAsias He r = virtio_scsi_exit(kvm); 1060a67da3beSAsias He if (r < 0) 1061a67da3beSAsias He pr_warning("virtio_scsi_exit() failed with error %d\n", r); 1062a67da3beSAsias He 10639f9207c5SSasha Levin r = virtio_blk__exit(kvm); 10649f9207c5SSasha Levin if (r < 0) 10659f9207c5SSasha Levin pr_warning("virtio_blk__exit() failed with error %d\n", r); 10669f9207c5SSasha Levin 1067495fbd4eSSasha Levin r = virtio_rng__exit(kvm); 1068495fbd4eSSasha Levin if (r < 0) 1069495fbd4eSSasha Levin pr_warning("virtio_rng__exit() failed with error %d\n", r); 1070a0a1e3c2SPrasad Joshi 1071d06db2fdSSasha Levin r = virtio_bln__exit(kvm); 1072d06db2fdSSasha Levin if (r < 0) 1073d06db2fdSSasha Levin pr_warning("virtio_bln__exit() failed with error %d\n", r); 1074d06db2fdSSasha Levin 1075a3fa3f86SSasha Levin r = virtio_console__exit(kvm); 1076a3fa3f86SSasha Levin if (r < 0) 1077a3fa3f86SSasha Levin pr_warning("virtio_console__exit() failed with error %d\n", r); 1078a3fa3f86SSasha Levin 10798cec93dbSSasha Levin r = pci_shmem__exit(kvm); 10808cec93dbSSasha Levin if (r < 0) 10818cec93dbSSasha Levin pr_warning("pci_shmem__exit() failed with error %d\n", r); 10828cec93dbSSasha Levin 10833b55dcdeSSasha Levin r = disk_image__exit(kvm); 10849f9207c5SSasha Levin if (r < 0) 10853b55dcdeSSasha Levin pr_warning("disk_image__exit() failed with error %d\n", r); 10867af40b91SSasha Levin 108720715a22SSasha Levin r = serial8250__exit(kvm); 108820715a22SSasha Levin if (r < 0) 108920715a22SSasha Levin pr_warning("serial8250__exit() failed with error %d\n", r); 109020715a22SSasha Levin 109120c39545SSasha Levin r = rtc__exit(kvm); 109220c39545SSasha Levin if (r < 0) 109320c39545SSasha Levin pr_warning("rtc__exit() failed with error %d\n", r); 109420c39545SSasha Levin 10951add9f73SSasha Levin r = kvm__arch_free_firmware(kvm); 10961add9f73SSasha Levin if (r < 0) 10971add9f73SSasha Levin pr_warning("kvm__arch_free_firmware() failed with error %d\n", r); 10981add9f73SSasha Levin 10997af40b91SSasha Levin r = ioport__exit(kvm); 11007af40b91SSasha Levin if (r < 0) 11017af40b91SSasha Levin pr_warning("ioport__exit() failed with error %d\n", r); 11027af40b91SSasha Levin 1103ea6eeb1cSSasha Levin r = ioeventfd__exit(kvm); 1104ea6eeb1cSSasha Levin if (r < 0) 1105ea6eeb1cSSasha Levin pr_warning("ioeventfd__exit() failed with error %d\n", r); 1106ea6eeb1cSSasha Levin 11076d987703SSasha Levin r = pci__exit(kvm); 11086d987703SSasha Levin if (r < 0) 11096d987703SSasha Levin pr_warning("pci__exit() failed with error %d\n", r); 11106d987703SSasha Levin 1111dca745e4SSasha Levin r = term_exit(kvm); 1112dca745e4SSasha Levin if (r < 0) 1113dca745e4SSasha Levin pr_warning("pci__exit() failed with error %d\n", r); 1114dca745e4SSasha Levin 1115f6a3c571SSasha Levin r = thread_pool__exit(kvm); 1116f6a3c571SSasha Levin if (r < 0) 1117f6a3c571SSasha Levin pr_warning("thread_pool__exit() failed with error %d\n", r); 1118f6a3c571SSasha Levin 1119495fbd4eSSasha Levin r = kvm__exit(kvm); 1120495fbd4eSSasha Levin if (r < 0) 1121495fbd4eSSasha Levin pr_warning("pci__exit() failed with error %d\n", r); 1122f967c427SPrasad Joshi 1123e1e46fe6SSasha Levin if (guest_ret == 0) 1124f967c427SPrasad Joshi printf("\n # KVM session ended normally.\n"); 1125e1e46fe6SSasha Levin } 1126e1e46fe6SSasha Levin 1127e1e46fe6SSasha Levin int kvm_cmd_run(int argc, const char **argv, const char *prefix) 1128e1e46fe6SSasha Levin { 11294932d174SSasha Levin int r, ret = -EFAULT; 1130e1e46fe6SSasha Levin 1131e1e46fe6SSasha Levin r = kvm_cmd_run_init(argc, argv); 1132e1e46fe6SSasha Levin if (r < 0) 1133e1e46fe6SSasha Levin return r; 1134e1e46fe6SSasha Levin 1135e1e46fe6SSasha Levin ret = kvm_cmd_run_work(); 1136e1e46fe6SSasha Levin kvm_cmd_run_exit(ret); 1137e1e46fe6SSasha Levin 1138e1e46fe6SSasha Levin return ret; 1139f967c427SPrasad Joshi } 1140