1ae1fae34SPekka Enberg #include "kvm/kvm.h" 2ae1fae34SPekka Enberg 313a7760fSPekka Enberg #include "kvm/early_printk.h" 4f3150089SPekka Enberg #include "kvm/util.h" 57fb218bdSPekka Enberg 6ae1fae34SPekka Enberg #include <inttypes.h> 7ae1fae34SPekka Enberg #include <stdint.h> 8ae1fae34SPekka Enberg #include <stdlib.h> 9f3150089SPekka Enberg #include <string.h> 10ae1fae34SPekka Enberg #include <stdio.h> 11ae1fae34SPekka Enberg 12ae1fae34SPekka Enberg static void usage(char *argv[]) 13ae1fae34SPekka Enberg { 1464f06a2bSPekka Enberg fprintf(stderr, " usage: %s [--single-step] [--kernel=]<kernel-image>\n", 155645c7a9SCyrill Gorcunov argv[0]); 16ae1fae34SPekka Enberg exit(1); 17ae1fae34SPekka Enberg } 18ae1fae34SPekka Enberg 19ae1fae34SPekka Enberg int main(int argc, char *argv[]) 20ae1fae34SPekka Enberg { 215645c7a9SCyrill Gorcunov const char *kernel_filename = NULL; 226d1f350dSCyrill Gorcunov const char *kernel_cmdline = NULL; 2364f06a2bSPekka Enberg bool single_step = false; 242525eb1fSPekka Enberg char real_cmdline[128]; 25ae1fae34SPekka Enberg struct kvm *kvm; 265645c7a9SCyrill Gorcunov int i; 27ae1fae34SPekka Enberg 285645c7a9SCyrill Gorcunov for (i = 1; i < argc; i++) { 295645c7a9SCyrill Gorcunov if (!strncmp("--kernel=", argv[i], 9)) { 305645c7a9SCyrill Gorcunov kernel_filename = &argv[i][9]; 315645c7a9SCyrill Gorcunov continue; 326d1f350dSCyrill Gorcunov } else if (!strncmp("--params=", argv[i], 9)) { 336d1f350dSCyrill Gorcunov kernel_cmdline = &argv[i][9]; 346d1f350dSCyrill Gorcunov continue; 3564f06a2bSPekka Enberg } else if (!strncmp("--single-step", argv[i], 13)) { 3664f06a2bSPekka Enberg single_step = true; 3764f06a2bSPekka Enberg continue; 385645c7a9SCyrill Gorcunov } else { 395645c7a9SCyrill Gorcunov /* any unspecified arg is kernel image */ 405645c7a9SCyrill Gorcunov if (argv[i][0] != '-') 415645c7a9SCyrill Gorcunov kernel_filename = argv[i]; 425645c7a9SCyrill Gorcunov else 435645c7a9SCyrill Gorcunov warning("Unknown option: %s", argv[i]); 445645c7a9SCyrill Gorcunov } 455645c7a9SCyrill Gorcunov } 465645c7a9SCyrill Gorcunov 475645c7a9SCyrill Gorcunov /* at least we should have kernel image passed */ 485645c7a9SCyrill Gorcunov if (!kernel_filename) 49ae1fae34SPekka Enberg usage(argv); 50ae1fae34SPekka Enberg 51ae1fae34SPekka Enberg kvm = kvm__init(); 52ae1fae34SPekka Enberg 53a1fe6bc5SPekka Enberg kvm__setup_cpuid(kvm); 54a1fe6bc5SPekka Enberg 55*f28c0a02SCyrill Gorcunov strcpy(real_cmdline, "notsc nolapic nosmp noacpi earlyprintk=serial,keep"); 56*f28c0a02SCyrill Gorcunov if (kernel_cmdline) { 57*f28c0a02SCyrill Gorcunov strncat(real_cmdline, kernel_cmdline, sizeof(real_cmdline)); 58*f28c0a02SCyrill Gorcunov real_cmdline[sizeof(real_cmdline)-1] = '\0'; 59*f28c0a02SCyrill Gorcunov } 602525eb1fSPekka Enberg 612525eb1fSPekka Enberg if (!kvm__load_kernel(kvm, kernel_filename, real_cmdline)) 627fb218bdSPekka Enberg die("unable to load kernel %s", kernel_filename); 63ae1fae34SPekka Enberg 647fb218bdSPekka Enberg kvm__reset_vcpu(kvm); 65ae1fae34SPekka Enberg 6664f06a2bSPekka Enberg if (single_step) 67ae1fae34SPekka Enberg kvm__enable_singlestep(kvm); 68ae1fae34SPekka Enberg 6913a7760fSPekka Enberg early_printk__init(); 7013a7760fSPekka Enberg 71ae1fae34SPekka Enberg for (;;) { 72ae1fae34SPekka Enberg kvm__run(kvm); 73ae1fae34SPekka Enberg 74ae1fae34SPekka Enberg switch (kvm->kvm_run->exit_reason) { 75fe806d65SPekka Enberg case KVM_EXIT_DEBUG: 76fe806d65SPekka Enberg kvm__show_registers(kvm); 77fe806d65SPekka Enberg kvm__show_code(kvm); 78fe806d65SPekka Enberg break; 792049569dSPekka Enberg case KVM_EXIT_IO: { 802049569dSPekka Enberg bool ret; 812049569dSPekka Enberg 822049569dSPekka Enberg ret = kvm__emulate_io(kvm, 83ae1fae34SPekka Enberg kvm->kvm_run->io.port, 84ae1fae34SPekka Enberg (uint8_t *)kvm->kvm_run + kvm->kvm_run->io.data_offset, 85ae1fae34SPekka Enberg kvm->kvm_run->io.direction, 86ae1fae34SPekka Enberg kvm->kvm_run->io.size, 87ae1fae34SPekka Enberg kvm->kvm_run->io.count); 882049569dSPekka Enberg 892049569dSPekka Enberg if (!ret) 902049569dSPekka Enberg goto exit_kvm; 91ae1fae34SPekka Enberg break; 922049569dSPekka Enberg } 9329443dabSPekka Enberg case KVM_EXIT_MMIO: { 9429443dabSPekka Enberg bool ret; 9529443dabSPekka Enberg 9629443dabSPekka Enberg ret = kvm__emulate_mmio(kvm, 9729443dabSPekka Enberg kvm->kvm_run->mmio.phys_addr, 9829443dabSPekka Enberg kvm->kvm_run->mmio.data, 9929443dabSPekka Enberg kvm->kvm_run->mmio.len, 10029443dabSPekka Enberg kvm->kvm_run->mmio.is_write); 10129443dabSPekka Enberg 10229443dabSPekka Enberg if (!ret) 10329443dabSPekka Enberg goto exit_kvm; 10429443dabSPekka Enberg break; 10529443dabSPekka Enberg 10629443dabSPekka Enberg } 107ae1fae34SPekka Enberg default: 108ae1fae34SPekka Enberg goto exit_kvm; 109ae1fae34SPekka Enberg } 110ae1fae34SPekka Enberg } 111ae1fae34SPekka Enberg 112ae1fae34SPekka Enberg exit_kvm: 113ae1fae34SPekka Enberg fprintf(stderr, "KVM exit reason: %" PRIu32 " (\"%s\")\n", 114ae1fae34SPekka Enberg kvm->kvm_run->exit_reason, kvm_exit_reasons[kvm->kvm_run->exit_reason]); 115ae1fae34SPekka Enberg 116ae1fae34SPekka Enberg kvm__show_registers(kvm); 117ae1fae34SPekka Enberg kvm__show_code(kvm); 118f01944c8SPekka Enberg kvm__show_page_tables(kvm); 119ae1fae34SPekka Enberg 1209ef4c68eSPekka Enberg kvm__delete(kvm); 1219ef4c68eSPekka Enberg 122ae1fae34SPekka Enberg return 0; 123ae1fae34SPekka Enberg } 124