static struct kvm *kvm_cmd_run_init(int argc, const char **argv) { static char real_cmdline[2048], default_name[20]; unsigned int nr_online_cpus; struct sigaction sa; struct kvm *kvm = kvm__new(); if (IS_ERR(kvm)) return kvm; sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = handle_sigalrm; sigemptyset(&sa.sa_mask); sigaction(SIGALRM, &sa, NULL); nr_online_cpus = sysconf(_SC_NPROCESSORS_ONLN); kvm->cfg.custom_rootfs_name = "default"; while (argc != 0) { BUILD_OPTIONS(options, &kvm->cfg, kvm); argc = parse_options(argc, argv, options, run_usage, PARSE_OPT_STOP_AT_NON_OPTION | PARSE_OPT_KEEP_DASHDASH); if (argc != 0) { /* Cusrom options, should have been handled elsewhere */ if (strcmp(argv[0], "--") == 0) { if (kvm_run_wrapper == KVM_RUN_SANDBOX) { kvm->cfg.sandbox = DEFAULT_SANDBOX_FILENAME; kvm_run_write_sandbox_cmd(kvm, argv+1, argc-1); break; } } if ((kvm_run_wrapper == KVM_RUN_DEFAULT && kvm->cfg.kernel_filename) || (kvm_run_wrapper == KVM_RUN_SANDBOX && kvm->cfg.sandbox)) { fprintf(stderr, "Cannot handle parameter: " "%s\n", argv[0]); usage_with_options(run_usage, options); free(kvm); return ERR_PTR(-EINVAL); } if (kvm_run_wrapper == KVM_RUN_SANDBOX) { /* * first unhandled parameter is treated as * sandbox command */ kvm->cfg.sandbox = DEFAULT_SANDBOX_FILENAME; kvm_run_write_sandbox_cmd(kvm, argv, argc); } else { /* * first unhandled parameter is treated as a kernel * image */ kvm->cfg.kernel_filename = argv[0]; } argv++; argc--; } } kvm->nr_disks = kvm->cfg.image_count; if (!kvm->cfg.kernel_filename) kvm->cfg.kernel_filename = find_kernel(); if (!kvm->cfg.kernel_filename) { kernel_usage_with_options(); return ERR_PTR(-EINVAL); } kvm->cfg.vmlinux_filename = find_vmlinux(); kvm->vmlinux = kvm->cfg.vmlinux_filename; if (kvm->cfg.nrcpus == 0) kvm->cfg.nrcpus = nr_online_cpus; if (!kvm->cfg.ram_size) kvm->cfg.ram_size = get_ram_size(kvm->cfg.nrcpus); if (kvm->cfg.ram_size < MIN_RAM_SIZE_MB) die("Not enough memory specified: %lluMB (min %lluMB)", (unsigned long long)kvm->cfg.ram_size, MIN_RAM_SIZE_MB); if (kvm->cfg.ram_size > host_ram_size()) pr_warning("Guest memory size %lluMB exceeds host physical RAM size %lluMB", (unsigned long long)kvm->cfg.ram_size, (unsigned long long)host_ram_size()); kvm->cfg.ram_size <<= MB_SHIFT; if (!kvm->cfg.dev) kvm->cfg.dev = DEFAULT_KVM_DEV; if (!kvm->cfg.console) kvm->cfg.console = DEFAULT_CONSOLE; if (!strncmp(kvm->cfg.console, "virtio", 6)) kvm->cfg.active_console = CONSOLE_VIRTIO; else if (!strncmp(kvm->cfg.console, "serial", 6)) kvm->cfg.active_console = CONSOLE_8250; else if (!strncmp(kvm->cfg.console, "hv", 2)) kvm->cfg.active_console = CONSOLE_HV; else pr_warning("No console!"); if (!kvm->cfg.host_ip) kvm->cfg.host_ip = DEFAULT_HOST_ADDR; if (!kvm->cfg.guest_ip) kvm->cfg.guest_ip = DEFAULT_GUEST_ADDR; if (!kvm->cfg.guest_mac) kvm->cfg.guest_mac = DEFAULT_GUEST_MAC; if (!kvm->cfg.host_mac) kvm->cfg.host_mac = DEFAULT_HOST_MAC; if (!kvm->cfg.script) kvm->cfg.script = DEFAULT_SCRIPT; if (!kvm->cfg.network) kvm->cfg.network = DEFAULT_NETWORK; memset(real_cmdline, 0, sizeof(real_cmdline)); kvm__arch_set_cmdline(real_cmdline, kvm->cfg.vnc || kvm->cfg.sdl); if (strlen(real_cmdline) > 0) strcat(real_cmdline, " "); if (kvm->cfg.kernel_cmdline) strlcat(real_cmdline, kvm->cfg.kernel_cmdline, sizeof(real_cmdline)); if (!kvm->cfg.guest_name) { if (kvm->cfg.custom_rootfs) { kvm->cfg.guest_name = kvm->cfg.custom_rootfs_name; } else { sprintf(default_name, "guest-%u", getpid()); kvm->cfg.guest_name = default_name; } } if (!kvm->cfg.using_rootfs && !kvm->cfg.disk_image[0].filename && !kvm->cfg.initrd_filename) { char tmp[PATH_MAX]; kvm_setup_create_new(kvm->cfg.custom_rootfs_name); kvm_setup_resolv(kvm->cfg.custom_rootfs_name); snprintf(tmp, PATH_MAX, "%s%s", kvm__get_dir(), "default"); if (virtio_9p__register(kvm, tmp, "/dev/root") < 0) die("Unable to initialize virtio 9p"); if (virtio_9p__register(kvm, "/", "hostfs") < 0) die("Unable to initialize virtio 9p"); kvm->cfg.using_rootfs = kvm->cfg.custom_rootfs = 1; } #ifndef CONFIG_MIPS if (kvm->cfg.using_rootfs) { strcat(real_cmdline, " root=/dev/root rw rootflags=rw,trans=virtio,version=9p2000.L rootfstype=9p"); if (kvm->cfg.custom_rootfs) { kvm_run_set_sandbox(kvm); strcat(real_cmdline, " init=/virt/init"); if (!kvm->cfg.no_dhcp) strcat(real_cmdline, " ip=dhcp"); if (kvm_setup_guest_init(kvm)) die("Failed to setup init for guest."); } } else #endif if (!strstr(real_cmdline, "root=")) { strlcat(real_cmdline, " root=/dev/vda rw ", sizeof(real_cmdline)); } kvm->cfg.real_cmdline = real_cmdline; printf(" # %s run -k %s -m %u -c %d --name %s\n", KVM_BINARY_NAME, kvm->cfg.kernel_filename, (unsigned)(kvm->cfg.ram_size / 1024 / 1024), kvm->cfg.nrcpus, kvm->cfg.guest_name); if (init_list__init(kvm) < 0) die ("Initialisation failed"); return kvm; }
int kvm_cmd_run(int argc, const char **argv, const char *prefix) { struct virtio_net_parameters net_params; static char real_cmdline[2048]; struct framebuffer *fb = NULL; unsigned int nr_online_cpus; int exit_code = 0; int max_cpus; char *hi; int i; void *ret; signal(SIGALRM, handle_sigalrm); signal(SIGQUIT, handle_sigquit); signal(SIGUSR1, handle_sigusr1); signal(SIGUSR2, handle_sigusr2); nr_online_cpus = sysconf(_SC_NPROCESSORS_ONLN); while (argc != 0) { argc = parse_options(argc, argv, options, run_usage, PARSE_OPT_STOP_AT_NON_OPTION); if (argc != 0) { if (kernel_filename) { fprintf(stderr, "Cannot handle parameter: " "%s\n", argv[0]); usage_with_options(run_usage, options); return EINVAL; } /* first unhandled parameter is treated as a kernel image */ kernel_filename = argv[0]; argv++; argc--; } } if (!kernel_filename) kernel_filename = find_kernel(); if (!kernel_filename) { kernel_usage_with_options(); return EINVAL; } vmlinux_filename = find_vmlinux(); if (nrcpus == 0) nrcpus = nr_online_cpus; else if (nrcpus < 1 || nrcpus > KVM_NR_CPUS) die("Number of CPUs %d is out of [1;%d] range", nrcpus, KVM_NR_CPUS); if (!ram_size) ram_size = get_ram_size(nrcpus); if (ram_size < MIN_RAM_SIZE_MB) die("Not enough memory specified: %lluMB (min %lluMB)", ram_size, MIN_RAM_SIZE_MB); if (ram_size > host_ram_size()) pr_warning("Guest memory size %lluMB exceeds host physical RAM size %lluMB", ram_size, host_ram_size()); ram_size <<= MB_SHIFT; if (!kvm_dev) kvm_dev = DEFAULT_KVM_DEV; if (!console) console = DEFAULT_CONSOLE; if (!strncmp(console, "virtio", 6)) active_console = CONSOLE_VIRTIO; else active_console = CONSOLE_8250; if (!host_ip_addr) host_ip_addr = DEFAULT_HOST_ADDR; if (!guest_mac) guest_mac = DEFAULT_GUEST_MAC; if (!script) script = DEFAULT_SCRIPT; if (virtio_9p_dir) { char tmp[PATH_MAX]; if (realpath(virtio_9p_dir, tmp)) virtio_9p__init(kvm, tmp); else die("Failed resolving 9p path"); } symbol__init(vmlinux_filename); term_init(); kvm = kvm__init(kvm_dev, ram_size); ioeventfd__init(); max_cpus = kvm__max_cpus(kvm); if (nrcpus > max_cpus) { printf(" # Limit the number of CPUs to %d\n", max_cpus); kvm->nrcpus = max_cpus; } kvm->nrcpus = nrcpus; /* * vidmode should be either specified * either set by default */ if (vnc || sdl) { if (vidmode == -1) vidmode = 0x312; } else vidmode = 0; memset(real_cmdline, 0, sizeof(real_cmdline)); strcpy(real_cmdline, "notsc noapic noacpi pci=conf1"); if (vnc || sdl) { strcat(real_cmdline, " video=vesafb console=tty0"); } else strcat(real_cmdline, " console=ttyS0 earlyprintk=serial"); strcat(real_cmdline, " "); if (kernel_cmdline) strlcat(real_cmdline, kernel_cmdline, sizeof(real_cmdline)); hi = NULL; if (!image_filename[0]) { hi = host_image(real_cmdline, sizeof(real_cmdline)); if (hi) { image_filename[0] = hi; readonly_image[0] = true; image_count++; } } if (!strstr(real_cmdline, "root=")) strlcat(real_cmdline, " root=/dev/vda rw ", sizeof(real_cmdline)); if (image_count) { kvm->nr_disks = image_count; kvm->disks = disk_image__open_all(image_filename, readonly_image, image_count); if (!kvm->disks) die("Unable to load all disk images."); virtio_blk__init_all(kvm); } free(hi); printf(" # kvm run -k %s -m %Lu -c %d\n", kernel_filename, ram_size / 1024 / 1024, nrcpus); if (!kvm__load_kernel(kvm, kernel_filename, initrd_filename, real_cmdline, vidmode)) die("unable to load kernel %s", kernel_filename); kvm->vmlinux = vmlinux_filename; ioport__setup_legacy(); rtc__init(); serial8250__init(kvm); pci__init(); if (active_console == CONSOLE_VIRTIO) virtio_console__init(kvm); if (virtio_rng) while (virtio_rng--) virtio_rng__init(kvm); if (!network) network = DEFAULT_NETWORK; if (!strncmp(network, "virtio", 6)) { net_params = (struct virtio_net_parameters) { .host_ip = host_ip_addr, .kvm = kvm, .script = script }; sscanf(guest_mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", net_params.guest_mac, net_params.guest_mac+1, net_params.guest_mac+2, net_params.guest_mac+3, net_params.guest_mac+4, net_params.guest_mac+5); virtio_net__init(&net_params); }