xref: /kvmtool/builtin-debug.c (revision 4b1c6f6e947ba8c35c0dc49346916817e943786f)
1ca379b83SPekka Enberg #include <kvm/util.h>
2ca379b83SPekka Enberg #include <kvm/kvm-cmd.h>
32a24f96dSSasha Levin #include <kvm/builtin-debug.h>
46c757e71SSasha Levin #include <kvm/kvm.h>
5c9cba791SPekka Enberg #include <kvm/parse-options.h>
64b1addaeSSasha Levin #include <kvm/kvm-ipc.h>
7b7d2f013SSasha Levin #include <kvm/read-write.h>
86c757e71SSasha Levin 
96c757e71SSasha Levin #include <stdio.h>
106c757e71SSasha Levin #include <string.h>
116c757e71SSasha Levin #include <signal.h>
12ca379b83SPekka Enberg 
13b7d2f013SSasha Levin #define BUFFER_SIZE 100
14b7d2f013SSasha Levin 
158d7b77f6SSasha Levin static bool all;
164b1addaeSSasha Levin static int instance;
17*4b1c6f6eSSasha Levin static int nmi = -1;
18*4b1c6f6eSSasha Levin static bool dump;
198d7b77f6SSasha Levin static const char *instance_name;
208d7b77f6SSasha Levin 
21c9cba791SPekka Enberg static const char * const debug_usage[] = {
224b1addaeSSasha Levin 	"kvm debug [--all] [-n name]",
23c9cba791SPekka Enberg 	NULL
24c9cba791SPekka Enberg };
25c9cba791SPekka Enberg 
26c9cba791SPekka Enberg static const struct option debug_options[] = {
278d7b77f6SSasha Levin 	OPT_GROUP("General options:"),
288d7b77f6SSasha Levin 	OPT_BOOLEAN('a', "all", &all, "Debug all instances"),
298d7b77f6SSasha Levin 	OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
30*4b1c6f6eSSasha Levin 	OPT_BOOLEAN('d', "dump", &dump, "Generate a debug dump from guest"),
31*4b1c6f6eSSasha Levin 	OPT_INTEGER('m', "nmi", &nmi, "Generate NMI on VCPU"),
32c9cba791SPekka Enberg 	OPT_END()
33c9cba791SPekka Enberg };
34c9cba791SPekka Enberg 
358d7b77f6SSasha Levin static void parse_debug_options(int argc, const char **argv)
368d7b77f6SSasha Levin {
378d7b77f6SSasha Levin 	while (argc != 0) {
388d7b77f6SSasha Levin 		argc = parse_options(argc, argv, debug_options, debug_usage,
398d7b77f6SSasha Levin 				PARSE_OPT_STOP_AT_NON_OPTION);
408d7b77f6SSasha Levin 		if (argc != 0)
418d7b77f6SSasha Levin 			kvm_debug_help();
428d7b77f6SSasha Levin 	}
438d7b77f6SSasha Levin }
448d7b77f6SSasha Levin 
450725673aSSasha Levin void kvm_debug_help(void)
460725673aSSasha Levin {
470725673aSSasha Levin 	usage_with_options(debug_usage, debug_options);
480725673aSSasha Levin }
490725673aSSasha Levin 
504b1addaeSSasha Levin static int do_debug(const char *name, int sock)
5124e7dbbaSSasha Levin {
52b7d2f013SSasha Levin 	char buff[BUFFER_SIZE];
53*4b1c6f6eSSasha Levin 	struct debug_cmd cmd = {KVM_IPC_DEBUG, 2 * sizeof(u32)};
544b1addaeSSasha Levin 	int r;
554b1addaeSSasha Levin 
56*4b1c6f6eSSasha Levin 	if (dump)
57*4b1c6f6eSSasha Levin 		cmd.dbg_type |= KVM_DEBUG_CMD_TYPE_DUMP;
58*4b1c6f6eSSasha Levin 
59*4b1c6f6eSSasha Levin 	if (nmi != -1) {
60*4b1c6f6eSSasha Levin 		cmd.dbg_type |= KVM_DEBUG_CMD_TYPE_NMI;
61*4b1c6f6eSSasha Levin 		cmd.cpu = nmi;
62*4b1c6f6eSSasha Levin 	}
63*4b1c6f6eSSasha Levin 
64b7d2f013SSasha Levin 	r = xwrite(sock, &cmd, sizeof(cmd));
654b1addaeSSasha Levin 	if (r < 0)
664b1addaeSSasha Levin 		return r;
674b1addaeSSasha Levin 
68*4b1c6f6eSSasha Levin 	if (!dump)
69*4b1c6f6eSSasha Levin 		return 0;
70*4b1c6f6eSSasha Levin 
71b7d2f013SSasha Levin 	do {
72b7d2f013SSasha Levin 		r = xread(sock, buff, BUFFER_SIZE);
73b7d2f013SSasha Levin 		if (r < 0)
74b7d2f013SSasha Levin 			return 0;
75b7d2f013SSasha Levin 		printf("%.*s", r, buff);
76b7d2f013SSasha Levin 	} while (r > 0);
77b7d2f013SSasha Levin 
784b1addaeSSasha Levin 	return 0;
7924e7dbbaSSasha Levin }
8024e7dbbaSSasha Levin 
81ca379b83SPekka Enberg int kvm_cmd_debug(int argc, const char **argv, const char *prefix)
82ca379b83SPekka Enberg {
838d7b77f6SSasha Levin 	parse_debug_options(argc, argv);
846c757e71SSasha Levin 
858d7b77f6SSasha Levin 	if (all)
868d7b77f6SSasha Levin 		return kvm__enumerate_instances(do_debug);
878d7b77f6SSasha Levin 
888d7b77f6SSasha Levin 	if (instance_name == NULL &&
894b1addaeSSasha Levin 	    instance == 0)
900725673aSSasha Levin 		kvm_debug_help();
916c757e71SSasha Levin 
928d7b77f6SSasha Levin 	if (instance_name)
934b1addaeSSasha Levin 		instance = kvm__get_sock_by_instance(instance_name);
9424e7dbbaSSasha Levin 
954b1addaeSSasha Levin 	if (instance <= 0)
968d7b77f6SSasha Levin 		die("Failed locating instance");
976c757e71SSasha Levin 
984b1addaeSSasha Levin 	return do_debug(instance_name, instance);
99ca379b83SPekka Enberg }
100