xref: /kvmtool/builtin-debug.c (revision b4a90c80bdcc74c60d8a551ae200ee923c005047)
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;
164b1c6f6eSSasha Levin static int nmi = -1;
174b1c6f6eSSasha Levin static bool dump;
188d7b77f6SSasha Levin static const char *instance_name;
198d7b77f6SSasha Levin 
20c9cba791SPekka Enberg static const char * const debug_usage[] = {
218d2ff5daSWanlong Gao 	"lkvm debug [--all] [-n name] [-d] [-m vcpu]",
22c9cba791SPekka Enberg 	NULL
23c9cba791SPekka Enberg };
24c9cba791SPekka Enberg 
25c9cba791SPekka Enberg static const struct option debug_options[] = {
268d7b77f6SSasha Levin 	OPT_GROUP("General options:"),
274b1c6f6eSSasha Levin 	OPT_BOOLEAN('d', "dump", &dump, "Generate a debug dump from guest"),
284b1c6f6eSSasha Levin 	OPT_INTEGER('m', "nmi", &nmi, "Generate NMI on VCPU"),
297070414aSSasha Levin 	OPT_GROUP("Instance options:"),
307070414aSSasha Levin 	OPT_BOOLEAN('a', "all", &all, "Debug all instances"),
317070414aSSasha Levin 	OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
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];
534b1c6f6eSSasha Levin 	struct debug_cmd cmd = {KVM_IPC_DEBUG, 2 * sizeof(u32)};
544b1addaeSSasha Levin 	int r;
554b1addaeSSasha Levin 
564b1c6f6eSSasha Levin 	if (dump)
577070414aSSasha Levin 		cmd.params.dbg_type |= KVM_DEBUG_CMD_TYPE_DUMP;
584b1c6f6eSSasha Levin 
594b1c6f6eSSasha Levin 	if (nmi != -1) {
607070414aSSasha Levin 		cmd.params.dbg_type |= KVM_DEBUG_CMD_TYPE_NMI;
617070414aSSasha Levin 		cmd.params.cpu = nmi;
624b1c6f6eSSasha Levin 	}
634b1c6f6eSSasha Levin 
64b7d2f013SSasha Levin 	r = xwrite(sock, &cmd, sizeof(cmd));
654b1addaeSSasha Levin 	if (r < 0)
664b1addaeSSasha Levin 		return r;
674b1addaeSSasha Levin 
684b1c6f6eSSasha Levin 	if (!dump)
694b1c6f6eSSasha Levin 		return 0;
704b1c6f6eSSasha 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);
84*b4a90c80SLai Jiangshan 	int instance;
85*b4a90c80SLai Jiangshan 	int r;
866c757e71SSasha Levin 
878d7b77f6SSasha Levin 	if (all)
888d7b77f6SSasha Levin 		return kvm__enumerate_instances(do_debug);
898d7b77f6SSasha Levin 
90*b4a90c80SLai Jiangshan 	if (instance_name == NULL)
910725673aSSasha Levin 		kvm_debug_help();
926c757e71SSasha Levin 
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 
98*b4a90c80SLai Jiangshan 	r = do_debug(instance_name, instance);
99*b4a90c80SLai Jiangshan 
100*b4a90c80SLai Jiangshan 	close(instance);
101*b4a90c80SLai Jiangshan 
102*b4a90c80SLai Jiangshan 	return r;
103ca379b83SPekka Enberg }
104