xref: /kvmtool/builtin-debug.c (revision 8d2ff5da21a87617d8c0646914293b47f333cbc4)
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;
174b1c6f6eSSasha Levin static int nmi = -1;
184b1c6f6eSSasha Levin static bool dump;
198d7b77f6SSasha Levin static const char *instance_name;
208d7b77f6SSasha Levin 
21c9cba791SPekka Enberg static const char * const debug_usage[] = {
22*8d2ff5daSWanlong Gao 	"lkvm debug [--all] [-n name] [-d] [-m vcpu]",
23c9cba791SPekka Enberg 	NULL
24c9cba791SPekka Enberg };
25c9cba791SPekka Enberg 
26c9cba791SPekka Enberg static const struct option debug_options[] = {
278d7b77f6SSasha Levin 	OPT_GROUP("General options:"),
284b1c6f6eSSasha Levin 	OPT_BOOLEAN('d', "dump", &dump, "Generate a debug dump from guest"),
294b1c6f6eSSasha Levin 	OPT_INTEGER('m', "nmi", &nmi, "Generate NMI on VCPU"),
307070414aSSasha Levin 	OPT_GROUP("Instance options:"),
317070414aSSasha Levin 	OPT_BOOLEAN('a', "all", &all, "Debug all instances"),
327070414aSSasha Levin 	OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
33c9cba791SPekka Enberg 	OPT_END()
34c9cba791SPekka Enberg };
35c9cba791SPekka Enberg 
368d7b77f6SSasha Levin static void parse_debug_options(int argc, const char **argv)
378d7b77f6SSasha Levin {
388d7b77f6SSasha Levin 	while (argc != 0) {
398d7b77f6SSasha Levin 		argc = parse_options(argc, argv, debug_options, debug_usage,
408d7b77f6SSasha Levin 				PARSE_OPT_STOP_AT_NON_OPTION);
418d7b77f6SSasha Levin 		if (argc != 0)
428d7b77f6SSasha Levin 			kvm_debug_help();
438d7b77f6SSasha Levin 	}
448d7b77f6SSasha Levin }
458d7b77f6SSasha Levin 
460725673aSSasha Levin void kvm_debug_help(void)
470725673aSSasha Levin {
480725673aSSasha Levin 	usage_with_options(debug_usage, debug_options);
490725673aSSasha Levin }
500725673aSSasha Levin 
514b1addaeSSasha Levin static int do_debug(const char *name, int sock)
5224e7dbbaSSasha Levin {
53b7d2f013SSasha Levin 	char buff[BUFFER_SIZE];
544b1c6f6eSSasha Levin 	struct debug_cmd cmd = {KVM_IPC_DEBUG, 2 * sizeof(u32)};
554b1addaeSSasha Levin 	int r;
564b1addaeSSasha Levin 
574b1c6f6eSSasha Levin 	if (dump)
587070414aSSasha Levin 		cmd.params.dbg_type |= KVM_DEBUG_CMD_TYPE_DUMP;
594b1c6f6eSSasha Levin 
604b1c6f6eSSasha Levin 	if (nmi != -1) {
617070414aSSasha Levin 		cmd.params.dbg_type |= KVM_DEBUG_CMD_TYPE_NMI;
627070414aSSasha Levin 		cmd.params.cpu = nmi;
634b1c6f6eSSasha Levin 	}
644b1c6f6eSSasha Levin 
65b7d2f013SSasha Levin 	r = xwrite(sock, &cmd, sizeof(cmd));
664b1addaeSSasha Levin 	if (r < 0)
674b1addaeSSasha Levin 		return r;
684b1addaeSSasha Levin 
694b1c6f6eSSasha Levin 	if (!dump)
704b1c6f6eSSasha Levin 		return 0;
714b1c6f6eSSasha Levin 
72b7d2f013SSasha Levin 	do {
73b7d2f013SSasha Levin 		r = xread(sock, buff, BUFFER_SIZE);
74b7d2f013SSasha Levin 		if (r < 0)
75b7d2f013SSasha Levin 			return 0;
76b7d2f013SSasha Levin 		printf("%.*s", r, buff);
77b7d2f013SSasha Levin 	} while (r > 0);
78b7d2f013SSasha Levin 
794b1addaeSSasha Levin 	return 0;
8024e7dbbaSSasha Levin }
8124e7dbbaSSasha Levin 
82ca379b83SPekka Enberg int kvm_cmd_debug(int argc, const char **argv, const char *prefix)
83ca379b83SPekka Enberg {
848d7b77f6SSasha Levin 	parse_debug_options(argc, argv);
856c757e71SSasha Levin 
868d7b77f6SSasha Levin 	if (all)
878d7b77f6SSasha Levin 		return kvm__enumerate_instances(do_debug);
888d7b77f6SSasha Levin 
898d7b77f6SSasha Levin 	if (instance_name == NULL &&
904b1addaeSSasha Levin 	    instance == 0)
910725673aSSasha Levin 		kvm_debug_help();
926c757e71SSasha Levin 
938d7b77f6SSasha Levin 	if (instance_name)
944b1addaeSSasha Levin 		instance = kvm__get_sock_by_instance(instance_name);
9524e7dbbaSSasha Levin 
964b1addaeSSasha Levin 	if (instance <= 0)
978d7b77f6SSasha Levin 		die("Failed locating instance");
986c757e71SSasha Levin 
994b1addaeSSasha Levin 	return do_debug(instance_name, instance);
100ca379b83SPekka Enberg }
101