xref: /kvmtool/main.c (revision 6fd7308d51741e1136261346a4b9e72849582b70)
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