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> 70290405dSPekka Enberg #include <signal.h> 8ae1fae34SPekka Enberg #include <stdint.h> 9ae1fae34SPekka Enberg #include <stdlib.h> 10f3150089SPekka Enberg #include <string.h> 11ae1fae34SPekka Enberg #include <stdio.h> 12ae1fae34SPekka Enberg 13ae1fae34SPekka Enberg static void usage(char *argv[]) 14ae1fae34SPekka Enberg { 1564f06a2bSPekka Enberg fprintf(stderr, " usage: %s [--single-step] [--kernel=]<kernel-image>\n", 165645c7a9SCyrill Gorcunov argv[0]); 17ae1fae34SPekka Enberg exit(1); 18ae1fae34SPekka Enberg } 19ae1fae34SPekka Enberg 200290405dSPekka Enberg static struct kvm *kvm; 210290405dSPekka Enberg 220290405dSPekka Enberg static void handle_sigquit(int sig) 230290405dSPekka Enberg { 240290405dSPekka Enberg kvm__show_registers(kvm); 250290405dSPekka Enberg kvm__show_code(kvm); 260290405dSPekka Enberg kvm__show_page_tables(kvm); 270290405dSPekka Enberg 280290405dSPekka Enberg kvm__delete(kvm); 290290405dSPekka Enberg 300290405dSPekka Enberg exit(1); 310290405dSPekka Enberg } 320290405dSPekka Enberg 33*6fd7308dSCyrill Gorcunov static char real_cmdline[2048]; 34*6fd7308dSCyrill Gorcunov 35ae1fae34SPekka Enberg int main(int argc, char *argv[]) 36ae1fae34SPekka Enberg { 375645c7a9SCyrill Gorcunov const char *kernel_filename = NULL; 386d1f350dSCyrill Gorcunov const char *kernel_cmdline = NULL; 3964f06a2bSPekka Enberg bool single_step = false; 405645c7a9SCyrill Gorcunov int i; 41ae1fae34SPekka Enberg 420290405dSPekka Enberg signal(SIGQUIT, handle_sigquit); 430290405dSPekka Enberg 445645c7a9SCyrill Gorcunov for (i = 1; i < argc; i++) { 455645c7a9SCyrill Gorcunov if (!strncmp("--kernel=", argv[i], 9)) { 465645c7a9SCyrill Gorcunov kernel_filename = &argv[i][9]; 475645c7a9SCyrill Gorcunov continue; 486d1f350dSCyrill Gorcunov } else if (!strncmp("--params=", argv[i], 9)) { 496d1f350dSCyrill Gorcunov kernel_cmdline = &argv[i][9]; 506d1f350dSCyrill Gorcunov continue; 5164f06a2bSPekka Enberg } else if (!strncmp("--single-step", argv[i], 13)) { 5264f06a2bSPekka Enberg single_step = true; 5364f06a2bSPekka Enberg continue; 545645c7a9SCyrill Gorcunov } else { 555645c7a9SCyrill Gorcunov /* any unspecified arg is kernel image */ 565645c7a9SCyrill Gorcunov if (argv[i][0] != '-') 575645c7a9SCyrill Gorcunov kernel_filename = argv[i]; 585645c7a9SCyrill Gorcunov else 595645c7a9SCyrill Gorcunov warning("Unknown option: %s", argv[i]); 605645c7a9SCyrill Gorcunov } 615645c7a9SCyrill Gorcunov } 625645c7a9SCyrill Gorcunov 635645c7a9SCyrill Gorcunov /* at least we should have kernel image passed */ 645645c7a9SCyrill Gorcunov if (!kernel_filename) 65ae1fae34SPekka Enberg usage(argv); 66ae1fae34SPekka Enberg 67ae1fae34SPekka Enberg kvm = kvm__init(); 68ae1fae34SPekka Enberg 69a1fe6bc5SPekka Enberg kvm__setup_cpuid(kvm); 70a1fe6bc5SPekka Enberg 71f28c0a02SCyrill Gorcunov strcpy(real_cmdline, "notsc nolapic nosmp noacpi earlyprintk=serial,keep "); 72f28c0a02SCyrill Gorcunov if (kernel_cmdline) { 730b322d96SCyrill Gorcunov strlcat(real_cmdline, kernel_cmdline, sizeof(real_cmdline)); 74f28c0a02SCyrill Gorcunov real_cmdline[sizeof(real_cmdline)-1] = '\0'; 75f28c0a02SCyrill Gorcunov } 762525eb1fSPekka Enberg 772525eb1fSPekka Enberg if (!kvm__load_kernel(kvm, kernel_filename, real_cmdline)) 787fb218bdSPekka Enberg die("unable to load kernel %s", kernel_filename); 79ae1fae34SPekka Enberg 807fb218bdSPekka Enberg kvm__reset_vcpu(kvm); 81ae1fae34SPekka Enberg 8264f06a2bSPekka Enberg if (single_step) 83ae1fae34SPekka Enberg kvm__enable_singlestep(kvm); 84ae1fae34SPekka Enberg 8513a7760fSPekka Enberg early_printk__init(); 8613a7760fSPekka Enberg 87ae1fae34SPekka Enberg for (;;) { 88ae1fae34SPekka Enberg kvm__run(kvm); 89ae1fae34SPekka Enberg 90ae1fae34SPekka Enberg switch (kvm->kvm_run->exit_reason) { 91fe806d65SPekka Enberg case KVM_EXIT_DEBUG: 92fe806d65SPekka Enberg kvm__show_registers(kvm); 93fe806d65SPekka Enberg kvm__show_code(kvm); 94fe806d65SPekka Enberg break; 952049569dSPekka Enberg case KVM_EXIT_IO: { 962049569dSPekka Enberg bool ret; 972049569dSPekka Enberg 982049569dSPekka Enberg ret = kvm__emulate_io(kvm, 99ae1fae34SPekka Enberg kvm->kvm_run->io.port, 100ae1fae34SPekka Enberg (uint8_t *)kvm->kvm_run + kvm->kvm_run->io.data_offset, 101ae1fae34SPekka Enberg kvm->kvm_run->io.direction, 102ae1fae34SPekka Enberg kvm->kvm_run->io.size, 103ae1fae34SPekka Enberg kvm->kvm_run->io.count); 1042049569dSPekka Enberg 1052049569dSPekka Enberg if (!ret) 1062049569dSPekka Enberg goto exit_kvm; 107ae1fae34SPekka Enberg break; 1082049569dSPekka Enberg } 10929443dabSPekka Enberg case KVM_EXIT_MMIO: { 11029443dabSPekka Enberg bool ret; 11129443dabSPekka Enberg 11229443dabSPekka Enberg ret = kvm__emulate_mmio(kvm, 11329443dabSPekka Enberg kvm->kvm_run->mmio.phys_addr, 11429443dabSPekka Enberg kvm->kvm_run->mmio.data, 11529443dabSPekka Enberg kvm->kvm_run->mmio.len, 11629443dabSPekka Enberg kvm->kvm_run->mmio.is_write); 11729443dabSPekka Enberg 11829443dabSPekka Enberg if (!ret) 11929443dabSPekka Enberg goto exit_kvm; 12029443dabSPekka Enberg break; 12129443dabSPekka Enberg 12229443dabSPekka Enberg } 123ae1fae34SPekka Enberg default: 124ae1fae34SPekka Enberg goto exit_kvm; 125ae1fae34SPekka Enberg } 126ae1fae34SPekka Enberg } 127ae1fae34SPekka Enberg 128ae1fae34SPekka Enberg exit_kvm: 129ae1fae34SPekka Enberg fprintf(stderr, "KVM exit reason: %" PRIu32 " (\"%s\")\n", 130ae1fae34SPekka Enberg kvm->kvm_run->exit_reason, kvm_exit_reasons[kvm->kvm_run->exit_reason]); 131b9c0a0bcSCyrill Gorcunov if (kvm->kvm_run->exit_reason == KVM_EXIT_UNKNOWN) 132b9c0a0bcSCyrill Gorcunov fprintf(stderr, "KVM exit code: 0x%016llx\n", 133b9c0a0bcSCyrill Gorcunov kvm->kvm_run->hw.hardware_exit_reason); 134ae1fae34SPekka Enberg 135ae1fae34SPekka Enberg kvm__show_registers(kvm); 136ae1fae34SPekka Enberg kvm__show_code(kvm); 137f01944c8SPekka Enberg kvm__show_page_tables(kvm); 138ae1fae34SPekka Enberg 1399ef4c68eSPekka Enberg kvm__delete(kvm); 1409ef4c68eSPekka Enberg 141ae1fae34SPekka Enberg return 0; 142ae1fae34SPekka Enberg } 143