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 13*62ef45dcSPekka Enberg extern bool ioport_debug; 14*62ef45dcSPekka Enberg 15ae1fae34SPekka Enberg static void usage(char *argv[]) 16ae1fae34SPekka Enberg { 17*62ef45dcSPekka Enberg fprintf(stderr, " usage: %s [--single-step] [--ioport-debug] [--params=<kernel-params>] [--kernel=]<kernel-image>\n", 185645c7a9SCyrill Gorcunov argv[0]); 19ae1fae34SPekka Enberg exit(1); 20ae1fae34SPekka Enberg } 21ae1fae34SPekka Enberg 220290405dSPekka Enberg static struct kvm *kvm; 230290405dSPekka Enberg 240290405dSPekka Enberg static void handle_sigquit(int sig) 250290405dSPekka Enberg { 260290405dSPekka Enberg kvm__show_registers(kvm); 270290405dSPekka Enberg kvm__show_code(kvm); 280290405dSPekka Enberg kvm__show_page_tables(kvm); 290290405dSPekka Enberg 300290405dSPekka Enberg kvm__delete(kvm); 310290405dSPekka Enberg 320290405dSPekka Enberg exit(1); 330290405dSPekka Enberg } 340290405dSPekka Enberg 356fd7308dSCyrill Gorcunov static char real_cmdline[2048]; 366fd7308dSCyrill Gorcunov 37aa2c2691SPekka Enberg static bool option_matches(char *arg, const char *option) 38aa2c2691SPekka Enberg { 39aa2c2691SPekka Enberg return !strncmp(arg, option, strlen(option)); 40aa2c2691SPekka Enberg } 41aa2c2691SPekka Enberg 42ae1fae34SPekka Enberg int main(int argc, char *argv[]) 43ae1fae34SPekka Enberg { 445645c7a9SCyrill Gorcunov const char *kernel_filename = NULL; 456d1f350dSCyrill Gorcunov const char *kernel_cmdline = NULL; 4664f06a2bSPekka Enberg bool single_step = false; 475645c7a9SCyrill Gorcunov int i; 48ae1fae34SPekka Enberg 490290405dSPekka Enberg signal(SIGQUIT, handle_sigquit); 500290405dSPekka Enberg 515645c7a9SCyrill Gorcunov for (i = 1; i < argc; i++) { 52aa2c2691SPekka Enberg if (option_matches(argv[i], "--kernel=")) { 535645c7a9SCyrill Gorcunov kernel_filename = &argv[i][9]; 545645c7a9SCyrill Gorcunov continue; 55aa2c2691SPekka Enberg } else if (option_matches(argv[i], "--params=")) { 566d1f350dSCyrill Gorcunov kernel_cmdline = &argv[i][9]; 576d1f350dSCyrill Gorcunov continue; 58aa2c2691SPekka Enberg } else if (option_matches(argv[i], "--single-step")) { 5964f06a2bSPekka Enberg single_step = true; 6064f06a2bSPekka Enberg continue; 61*62ef45dcSPekka Enberg } else if (option_matches(argv[i], "--ioport-debug")) { 62*62ef45dcSPekka Enberg ioport_debug = true; 63*62ef45dcSPekka Enberg continue; 645645c7a9SCyrill Gorcunov } else { 655645c7a9SCyrill Gorcunov /* any unspecified arg is kernel image */ 665645c7a9SCyrill Gorcunov if (argv[i][0] != '-') 675645c7a9SCyrill Gorcunov kernel_filename = argv[i]; 685645c7a9SCyrill Gorcunov else 695645c7a9SCyrill Gorcunov warning("Unknown option: %s", argv[i]); 705645c7a9SCyrill Gorcunov } 715645c7a9SCyrill Gorcunov } 725645c7a9SCyrill Gorcunov 735645c7a9SCyrill Gorcunov /* at least we should have kernel image passed */ 745645c7a9SCyrill Gorcunov if (!kernel_filename) 75ae1fae34SPekka Enberg usage(argv); 76ae1fae34SPekka Enberg 77ae1fae34SPekka Enberg kvm = kvm__init(); 78ae1fae34SPekka Enberg 79a1fe6bc5SPekka Enberg kvm__setup_cpuid(kvm); 80a1fe6bc5SPekka Enberg 813a5c54b1SPekka Enberg strcpy(real_cmdline, "notsc nolapic nosmp noacpi nopci pci=off earlyprintk=serial,keep "); 82f28c0a02SCyrill Gorcunov if (kernel_cmdline) { 830b322d96SCyrill Gorcunov strlcat(real_cmdline, kernel_cmdline, sizeof(real_cmdline)); 84f28c0a02SCyrill Gorcunov real_cmdline[sizeof(real_cmdline)-1] = '\0'; 85f28c0a02SCyrill Gorcunov } 862525eb1fSPekka Enberg 872525eb1fSPekka Enberg if (!kvm__load_kernel(kvm, kernel_filename, real_cmdline)) 887fb218bdSPekka Enberg die("unable to load kernel %s", kernel_filename); 89ae1fae34SPekka Enberg 907fb218bdSPekka Enberg kvm__reset_vcpu(kvm); 91ae1fae34SPekka Enberg 9264f06a2bSPekka Enberg if (single_step) 93ae1fae34SPekka Enberg kvm__enable_singlestep(kvm); 94ae1fae34SPekka Enberg 9513a7760fSPekka Enberg early_printk__init(); 9613a7760fSPekka Enberg 97ae1fae34SPekka Enberg for (;;) { 98ae1fae34SPekka Enberg kvm__run(kvm); 99ae1fae34SPekka Enberg 100ae1fae34SPekka Enberg switch (kvm->kvm_run->exit_reason) { 101fe806d65SPekka Enberg case KVM_EXIT_DEBUG: 102fe806d65SPekka Enberg kvm__show_registers(kvm); 103fe806d65SPekka Enberg kvm__show_code(kvm); 104fe806d65SPekka Enberg break; 1052049569dSPekka Enberg case KVM_EXIT_IO: { 1062049569dSPekka Enberg bool ret; 1072049569dSPekka Enberg 1082049569dSPekka Enberg ret = kvm__emulate_io(kvm, 109ae1fae34SPekka Enberg kvm->kvm_run->io.port, 110ae1fae34SPekka Enberg (uint8_t *)kvm->kvm_run + kvm->kvm_run->io.data_offset, 111ae1fae34SPekka Enberg kvm->kvm_run->io.direction, 112ae1fae34SPekka Enberg kvm->kvm_run->io.size, 113ae1fae34SPekka Enberg kvm->kvm_run->io.count); 1142049569dSPekka Enberg 1152049569dSPekka Enberg if (!ret) 1162049569dSPekka Enberg goto exit_kvm; 117ae1fae34SPekka Enberg break; 1182049569dSPekka Enberg } 11929443dabSPekka Enberg case KVM_EXIT_MMIO: { 12029443dabSPekka Enberg bool ret; 12129443dabSPekka Enberg 12229443dabSPekka Enberg ret = kvm__emulate_mmio(kvm, 12329443dabSPekka Enberg kvm->kvm_run->mmio.phys_addr, 12429443dabSPekka Enberg kvm->kvm_run->mmio.data, 12529443dabSPekka Enberg kvm->kvm_run->mmio.len, 12629443dabSPekka Enberg kvm->kvm_run->mmio.is_write); 12729443dabSPekka Enberg 12829443dabSPekka Enberg if (!ret) 12929443dabSPekka Enberg goto exit_kvm; 13029443dabSPekka Enberg break; 13129443dabSPekka Enberg 13229443dabSPekka Enberg } 133ae1fae34SPekka Enberg default: 134ae1fae34SPekka Enberg goto exit_kvm; 135ae1fae34SPekka Enberg } 136ae1fae34SPekka Enberg } 137ae1fae34SPekka Enberg 138ae1fae34SPekka Enberg exit_kvm: 1393db4f1beSCyrill Gorcunov 140ae1fae34SPekka Enberg fprintf(stderr, "KVM exit reason: %" PRIu32 " (\"%s\")\n", 141ae1fae34SPekka Enberg kvm->kvm_run->exit_reason, kvm_exit_reasons[kvm->kvm_run->exit_reason]); 142b9c0a0bcSCyrill Gorcunov if (kvm->kvm_run->exit_reason == KVM_EXIT_UNKNOWN) 143b9c0a0bcSCyrill Gorcunov fprintf(stderr, "KVM exit code: 0x%016llx\n", 144b9c0a0bcSCyrill Gorcunov kvm->kvm_run->hw.hardware_exit_reason); 145ae1fae34SPekka Enberg 146ae1fae34SPekka Enberg kvm__show_registers(kvm); 147ae1fae34SPekka Enberg kvm__show_code(kvm); 148f01944c8SPekka Enberg kvm__show_page_tables(kvm); 1493db4f1beSCyrill Gorcunov out: 1509ef4c68eSPekka Enberg kvm__delete(kvm); 1519ef4c68eSPekka Enberg 152ae1fae34SPekka Enberg return 0; 153ae1fae34SPekka Enberg } 154