1 #include <stdio.h> 2 #include <string.h> 3 #include <signal.h> 4 #include <stdint.h> 5 #include <unistd.h> 6 #include <inttypes.h> 7 #include <stdlib.h> 8 #include <termios.h> 9 #include <sys/utsname.h> 10 #include <sys/types.h> 11 #include <sys/stat.h> 12 13 /* user defined header files */ 14 #include <linux/types.h> 15 #include <kvm/kvm.h> 16 #include <kvm/kvm-cpu.h> 17 #include <kvm/8250-serial.h> 18 #include <kvm/virtio-blk.h> 19 #include <kvm/virtio-net.h> 20 #include <kvm/virtio-console.h> 21 #include <kvm/disk-image.h> 22 #include <kvm/util.h> 23 #include <kvm/pci.h> 24 #include <kvm/term.h> 25 #include <kvm/ioport.h> 26 27 /* header files for gitish interface */ 28 #include <kvm/kvm-run.h> 29 #include <kvm/parse-options.h> 30 31 #define DEFAULT_KVM_DEV "/dev/kvm" 32 #define DEFAULT_CONSOLE "serial" 33 #define DEFAULT_NETWORK "virtio" 34 #define DEFAULT_HOST_ADDR "192.168.33.2" 35 36 #define MB_SHIFT (20) 37 #define MIN_RAM_SIZE_MB (64ULL) 38 #define MIN_RAM_SIZE_BYTE (MIN_RAM_SIZE_MB << MB_SHIFT) 39 40 #define KVM_NR_CPUS (255) 41 42 static struct kvm *kvm; 43 static struct kvm_cpu *kvm_cpus[KVM_NR_CPUS]; 44 static __thread struct kvm_cpu *current_kvm_cpu; 45 46 static void handle_sigquit(int sig) 47 { 48 serial8250__inject_sysrq(kvm); 49 } 50 51 static void handle_sigalrm(int sig) 52 { 53 serial8250__inject_interrupt(kvm); 54 virtio_console__inject_interrupt(kvm); 55 } 56 57 static u64 ram_size = MIN_RAM_SIZE_MB; 58 static const char *kernel_cmdline; 59 static const char *kernel_filename; 60 static const char *initrd_filename; 61 static const char *image_filename; 62 static const char *console; 63 static const char *kvm_dev; 64 static const char *network; 65 static const char *host_ip_addr; 66 static bool single_step; 67 static bool readonly_image; 68 extern bool ioport_debug; 69 extern int active_console; 70 71 static int nrcpus = 1; 72 73 static const char * const run_usage[] = { 74 "kvm run [<options>] [<kernel image>]", 75 NULL 76 }; 77 78 static const struct option options[] = { 79 OPT_GROUP("Basic options:"), 80 OPT_INTEGER('\0', "cpus", &nrcpus, "Number of CPUs"), 81 OPT_U64('m', "mem", &ram_size, "Virtual machine memory size in MiB."), 82 OPT_STRING('i', "image", &image_filename, "image", "Disk image"), 83 OPT_BOOLEAN('\0', "readonly", &readonly_image, 84 "Don't write changes back to disk image"), 85 OPT_STRING('c', "console", &console, "serial or virtio", 86 "Console to use"), 87 88 OPT_GROUP("Kernel options:"), 89 OPT_STRING('k', "kernel", &kernel_filename, "kernel", 90 "Kernel to boot in virtual machine"), 91 OPT_STRING('r', "initrd", &initrd_filename, "initrd", 92 "Initial RAM disk image"), 93 OPT_STRING('p', "params", &kernel_cmdline, "params", 94 "Kernel command line arguments"), 95 96 OPT_GROUP("Networking options:"), 97 OPT_STRING('n', "network", &network, "virtio", 98 "Network to use"), 99 OPT_STRING('\0', "host-ip-addr", &host_ip_addr, "a.b.c.d", 100 "Assign this address to the host side networking"), 101 102 OPT_GROUP("Debug options:"), 103 OPT_STRING('d', "kvm-dev", &kvm_dev, "kvm-dev", "KVM device file"), 104 OPT_BOOLEAN('s', "single-step", &single_step, 105 "Enable single stepping"), 106 OPT_BOOLEAN('g', "ioport-debug", &ioport_debug, 107 "Enable ioport debugging"), 108 OPT_END() 109 }; 110 111 static void *kvm_cpu_thread(void *arg) 112 { 113 current_kvm_cpu = arg; 114 115 if (kvm_cpu__start(current_kvm_cpu)) 116 goto panic_kvm; 117 118 kvm_cpu__delete(current_kvm_cpu); 119 120 return (void *) (intptr_t) 0; 121 122 panic_kvm: 123 fprintf(stderr, "KVM exit reason: %" PRIu32 " (\"%s\")\n", 124 current_kvm_cpu->kvm_run->exit_reason, 125 kvm_exit_reasons[current_kvm_cpu->kvm_run->exit_reason]); 126 if (current_kvm_cpu->kvm_run->exit_reason == KVM_EXIT_UNKNOWN) 127 fprintf(stderr, "KVM exit code: 0x%Lu\n", 128 current_kvm_cpu->kvm_run->hw.hardware_exit_reason); 129 disk_image__close(kvm->disk_image); 130 kvm_cpu__show_registers(current_kvm_cpu); 131 kvm_cpu__show_code(current_kvm_cpu); 132 kvm_cpu__show_page_tables(current_kvm_cpu); 133 134 kvm_cpu__delete(current_kvm_cpu); 135 136 return (void *) (intptr_t) 1; 137 } 138 139 static char kernel[PATH_MAX]; 140 const char *host_kernels[] = { 141 "/boot/vmlinuz", 142 "/boot/bzImage", 143 NULL 144 }; 145 const char *defult_kernels[] = { 146 "./bzImage", 147 "../../arch/x86/boot/bzImage", 148 NULL 149 }; 150 151 static void kernel_usage_with_options(void) 152 { 153 const char **k; 154 struct utsname uts; 155 156 fprintf(stderr, "Fatal: could not find default kernel image in:\n"); 157 k = &defult_kernels[0]; 158 while (*k) { 159 fprintf(stderr, "\t%s\n", *k); 160 k++; 161 } 162 163 if (uname(&uts) < 0) 164 return; 165 166 k = &host_kernels[0]; 167 while (*k) { 168 if (snprintf(kernel, PATH_MAX, "%s-%s", *k, uts.release) < 0) 169 return; 170 fprintf(stderr, "\t%s\n", kernel); 171 k++; 172 } 173 usage_with_options(run_usage, options); 174 } 175 176 static const char *find_kernel(void) 177 { 178 const char **k; 179 struct stat st; 180 struct utsname uts; 181 182 k = &defult_kernels[0]; 183 while (*k) { 184 if (stat(*k, &st) < 0 || !S_ISREG(st.st_mode)) { 185 k++; 186 continue; 187 } 188 strncpy(kernel, *k, PATH_MAX); 189 return kernel; 190 } 191 192 if (uname(&uts) < 0) 193 return NULL; 194 195 k = &host_kernels[0]; 196 while (*k) { 197 if (snprintf(kernel, PATH_MAX, "%s-%s", *k, uts.release) < 0) 198 return NULL; 199 200 if (stat(kernel, &st) < 0 || !S_ISREG(st.st_mode)) { 201 k++; 202 continue; 203 } 204 return kernel; 205 206 } 207 return NULL; 208 } 209 210 int kvm_cmd_run(int argc, const char **argv, const char *prefix) 211 { 212 static char real_cmdline[2048]; 213 int exit_code = 0; 214 int i; 215 struct virtio_net_parameters net_params; 216 217 signal(SIGALRM, handle_sigalrm); 218 signal(SIGQUIT, handle_sigquit); 219 220 while (argc != 0) { 221 argc = parse_options(argc, argv, options, run_usage, 222 PARSE_OPT_STOP_AT_NON_OPTION); 223 if (argc != 0) { 224 if (kernel_filename) { 225 fprintf(stderr, "Cannot handle parameter: " 226 "%s\n", argv[0]); 227 usage_with_options(run_usage, options); 228 return EINVAL; 229 } 230 /* first unhandled parameter is treated as a kernel 231 image 232 */ 233 kernel_filename = argv[0]; 234 argv++; 235 argc--; 236 } 237 238 } 239 240 if (!kernel_filename) 241 kernel_filename = find_kernel(); 242 243 if (!kernel_filename) { 244 kernel_usage_with_options(); 245 return EINVAL; 246 } 247 248 if (nrcpus < 1 || nrcpus > KVM_NR_CPUS) 249 die("Number of CPUs %d is out of [1;%d] range", nrcpus, KVM_NR_CPUS); 250 251 /* FIXME: Remove as only SMP gets fully supported */ 252 if (nrcpus > 1) 253 warning("Limiting CPUs to 1, true SMP is not yet implemented"); 254 255 if (ram_size < MIN_RAM_SIZE_MB) 256 die("Not enough memory specified: %lluMB (min %lluMB)", ram_size, MIN_RAM_SIZE_MB); 257 258 ram_size <<= MB_SHIFT; 259 260 if (!kvm_dev) 261 kvm_dev = DEFAULT_KVM_DEV; 262 263 if (!console) 264 console = DEFAULT_CONSOLE; 265 266 if (!strncmp(console, "virtio", 6)) 267 active_console = CONSOLE_VIRTIO; 268 else 269 active_console = CONSOLE_8250; 270 271 if (!host_ip_addr) 272 host_ip_addr = DEFAULT_HOST_ADDR; 273 274 term_init(); 275 276 kvm = kvm__init(kvm_dev, ram_size); 277 278 if (image_filename) { 279 kvm->disk_image = disk_image__open(image_filename, readonly_image); 280 if (!kvm->disk_image) 281 die("unable to load disk image %s", image_filename); 282 } 283 284 strcpy(real_cmdline, "notsc nolapic noacpi pci=conf1 console=ttyS0 "); 285 if (!kernel_cmdline || !strstr(kernel_cmdline, "root=")) { 286 strlcat(real_cmdline, "root=/dev/vda rw ", 287 sizeof(real_cmdline)); 288 } 289 290 if (kernel_cmdline) { 291 strlcat(real_cmdline, kernel_cmdline, sizeof(real_cmdline)); 292 real_cmdline[sizeof(real_cmdline)-1] = '\0'; 293 } 294 295 if (!kvm__load_kernel(kvm, kernel_filename, initrd_filename, 296 real_cmdline)) 297 die("unable to load kernel %s", kernel_filename); 298 299 ioport__setup_legacy(); 300 301 kvm__setup_bios(kvm); 302 303 serial8250__init(kvm); 304 305 pci__init(); 306 307 virtio_blk__init(kvm); 308 309 virtio_console__init(kvm); 310 311 if (!network) 312 network = DEFAULT_NETWORK; 313 314 if (!strncmp(network, "virtio", 6)) { 315 net_params = (struct virtio_net_parameters) { 316 .host_ip = host_ip_addr, 317 .self = kvm 318 }; 319 virtio_net__init(&net_params); 320 } 321 322 kvm__start_timer(kvm); 323 324 for (i = 0; i < nrcpus; i++) { 325 kvm_cpus[i] = kvm_cpu__init(kvm, i); 326 if (!kvm_cpus[i]) 327 die("unable to initialize KVM VCPU"); 328 329 if (single_step) 330 kvm_cpu__enable_singlestep(kvm_cpus[i]); 331 332 if (pthread_create(&kvm_cpus[i]->thread, NULL, kvm_cpu_thread, kvm_cpus[i]) != 0) 333 die("unable to create KVM VCPU thread"); 334 } 335 336 for (i = 0; i < nrcpus; i++) { 337 void *ret; 338 339 if (pthread_join(kvm_cpus[i]->thread, &ret) != 0) 340 die("pthread_join"); 341 342 if (ret != NULL) 343 exit_code = 1; 344 } 345 346 disk_image__close(kvm->disk_image); 347 kvm__delete(kvm); 348 349 if (!exit_code) 350 printf("\n # KVM session ended normally.\n"); 351 352 return exit_code; 353 } 354