xref: /kvmtool/main.c (revision 9ef4c68e330b55289d777c44dadd8942c1624d51)
1ae1fae34SPekka Enberg #include "kvm/kvm.h"
2ae1fae34SPekka Enberg 
3f3150089SPekka Enberg #include "kvm/util.h"
47fb218bdSPekka Enberg 
5ae1fae34SPekka Enberg #include <inttypes.h>
6ae1fae34SPekka Enberg #include <stdint.h>
7ae1fae34SPekka Enberg #include <stdlib.h>
8f3150089SPekka Enberg #include <string.h>
9ae1fae34SPekka Enberg #include <stdio.h>
10ae1fae34SPekka Enberg 
11ae1fae34SPekka Enberg static void usage(char *argv[])
12ae1fae34SPekka Enberg {
1364f06a2bSPekka Enberg 	fprintf(stderr, "  usage: %s [--single-step] [--kernel=]<kernel-image>\n",
145645c7a9SCyrill Gorcunov 		argv[0]);
15ae1fae34SPekka Enberg 	exit(1);
16ae1fae34SPekka Enberg }
17ae1fae34SPekka Enberg 
18ae1fae34SPekka Enberg int main(int argc, char *argv[])
19ae1fae34SPekka Enberg {
205645c7a9SCyrill Gorcunov 	const char *kernel_filename = NULL;
216d1f350dSCyrill Gorcunov 	const char *kernel_cmdline = NULL;
2264f06a2bSPekka Enberg 	bool single_step = false;
23ae1fae34SPekka Enberg 	struct kvm *kvm;
245645c7a9SCyrill Gorcunov 	int i;
25ae1fae34SPekka Enberg 
265645c7a9SCyrill Gorcunov 	for (i = 1; i < argc; i++) {
275645c7a9SCyrill Gorcunov 		if (!strncmp("--kernel=", argv[i], 9)) {
285645c7a9SCyrill Gorcunov 			kernel_filename = &argv[i][9];
295645c7a9SCyrill Gorcunov 			continue;
306d1f350dSCyrill Gorcunov 		} else if (!strncmp("--params=", argv[i], 9)) {
316d1f350dSCyrill Gorcunov 			kernel_cmdline = &argv[i][9];
326d1f350dSCyrill Gorcunov 			continue;
3364f06a2bSPekka Enberg 		} else if (!strncmp("--single-step", argv[i], 13)) {
3464f06a2bSPekka Enberg 			single_step = true;
3564f06a2bSPekka Enberg 			continue;
365645c7a9SCyrill Gorcunov 		} else {
375645c7a9SCyrill Gorcunov 			/* any unspecified arg is kernel image */
385645c7a9SCyrill Gorcunov 			if (argv[i][0] != '-')
395645c7a9SCyrill Gorcunov 				kernel_filename = argv[i];
405645c7a9SCyrill Gorcunov 			else
415645c7a9SCyrill Gorcunov 				warning("Unknown option: %s", argv[i]);
425645c7a9SCyrill Gorcunov 		}
435645c7a9SCyrill Gorcunov 	}
445645c7a9SCyrill Gorcunov 
455645c7a9SCyrill Gorcunov 	/* at least we should have kernel image passed */
465645c7a9SCyrill Gorcunov 	if (!kernel_filename)
47ae1fae34SPekka Enberg 		usage(argv);
48ae1fae34SPekka Enberg 
49ae1fae34SPekka Enberg 	kvm = kvm__init();
50ae1fae34SPekka Enberg 
51a1fe6bc5SPekka Enberg 	kvm__setup_cpuid(kvm);
52a1fe6bc5SPekka Enberg 
536d1f350dSCyrill Gorcunov 	if (!kvm__load_kernel(kvm, kernel_filename, kernel_cmdline))
547fb218bdSPekka Enberg 		die("unable to load kernel %s", kernel_filename);
55ae1fae34SPekka Enberg 
567fb218bdSPekka Enberg 	kvm__reset_vcpu(kvm);
57ae1fae34SPekka Enberg 
5864f06a2bSPekka Enberg 	if (single_step)
59ae1fae34SPekka Enberg 		kvm__enable_singlestep(kvm);
60ae1fae34SPekka Enberg 
61ae1fae34SPekka Enberg 	for (;;) {
62ae1fae34SPekka Enberg 		kvm__run(kvm);
63ae1fae34SPekka Enberg 
64ae1fae34SPekka Enberg 		switch (kvm->kvm_run->exit_reason) {
65fe806d65SPekka Enberg 		case KVM_EXIT_DEBUG:
66fe806d65SPekka Enberg 			kvm__show_registers(kvm);
67fe806d65SPekka Enberg 			kvm__show_code(kvm);
68fe806d65SPekka Enberg 			break;
692049569dSPekka Enberg 		case KVM_EXIT_IO: {
702049569dSPekka Enberg 			bool ret;
712049569dSPekka Enberg 
722049569dSPekka Enberg 			ret = kvm__emulate_io(kvm,
73ae1fae34SPekka Enberg 					kvm->kvm_run->io.port,
74ae1fae34SPekka Enberg 					(uint8_t *)kvm->kvm_run + kvm->kvm_run->io.data_offset,
75ae1fae34SPekka Enberg 					kvm->kvm_run->io.direction,
76ae1fae34SPekka Enberg 					kvm->kvm_run->io.size,
77ae1fae34SPekka Enberg 					kvm->kvm_run->io.count);
782049569dSPekka Enberg 
792049569dSPekka Enberg 			if (!ret)
802049569dSPekka Enberg 				goto exit_kvm;
81ae1fae34SPekka Enberg 			break;
822049569dSPekka Enberg 		}
83ae1fae34SPekka Enberg 		default:
84ae1fae34SPekka Enberg 			goto exit_kvm;
85ae1fae34SPekka Enberg 		}
86ae1fae34SPekka Enberg 	}
87ae1fae34SPekka Enberg 
88ae1fae34SPekka Enberg exit_kvm:
89ae1fae34SPekka Enberg 	fprintf(stderr, "KVM exit reason: %" PRIu32 " (\"%s\")\n",
90ae1fae34SPekka Enberg 		kvm->kvm_run->exit_reason, kvm_exit_reasons[kvm->kvm_run->exit_reason]);
91ae1fae34SPekka Enberg 
92ae1fae34SPekka Enberg 	kvm__show_registers(kvm);
93ae1fae34SPekka Enberg 	kvm__show_code(kvm);
94ae1fae34SPekka Enberg 
95*9ef4c68eSPekka Enberg 	kvm__delete(kvm);
96*9ef4c68eSPekka Enberg 
97ae1fae34SPekka Enberg 	return 0;
98ae1fae34SPekka Enberg }
99