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;
19*226e727bSSasha Levin static const char *sysrq;
208d7b77f6SSasha Levin
21c9cba791SPekka Enberg static const char * const debug_usage[] = {
228d2ff5daSWanlong 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"),
30*226e727bSSasha Levin OPT_STRING('s', "sysrq", &sysrq, "sysrq", "Inject a sysrq"),
317070414aSSasha Levin OPT_GROUP("Instance options:"),
327070414aSSasha Levin OPT_BOOLEAN('a', "all", &all, "Debug all instances"),
337070414aSSasha Levin OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
34c9cba791SPekka Enberg OPT_END()
35c9cba791SPekka Enberg };
36c9cba791SPekka Enberg
parse_debug_options(int argc,const char ** argv)378d7b77f6SSasha Levin static void parse_debug_options(int argc, const char **argv)
388d7b77f6SSasha Levin {
398d7b77f6SSasha Levin while (argc != 0) {
408d7b77f6SSasha Levin argc = parse_options(argc, argv, debug_options, debug_usage,
418d7b77f6SSasha Levin PARSE_OPT_STOP_AT_NON_OPTION);
428d7b77f6SSasha Levin if (argc != 0)
438d7b77f6SSasha Levin kvm_debug_help();
448d7b77f6SSasha Levin }
458d7b77f6SSasha Levin }
468d7b77f6SSasha Levin
kvm_debug_help(void)470725673aSSasha Levin void kvm_debug_help(void)
480725673aSSasha Levin {
490725673aSSasha Levin usage_with_options(debug_usage, debug_options);
500725673aSSasha Levin }
510725673aSSasha Levin
do_debug(const char * name,int sock)524b1addaeSSasha Levin static int do_debug(const char *name, int sock)
5324e7dbbaSSasha Levin {
54b7d2f013SSasha Levin char buff[BUFFER_SIZE];
55a59cdf44SLai Jiangshan struct debug_cmd_params cmd = {.dbg_type = 0};
564b1addaeSSasha Levin int r;
574b1addaeSSasha Levin
584b1c6f6eSSasha Levin if (dump)
59a59cdf44SLai Jiangshan cmd.dbg_type |= KVM_DEBUG_CMD_TYPE_DUMP;
604b1c6f6eSSasha Levin
614b1c6f6eSSasha Levin if (nmi != -1) {
62a59cdf44SLai Jiangshan cmd.dbg_type |= KVM_DEBUG_CMD_TYPE_NMI;
63a59cdf44SLai Jiangshan cmd.cpu = nmi;
644b1c6f6eSSasha Levin }
654b1c6f6eSSasha Levin
66*226e727bSSasha Levin if (sysrq) {
67*226e727bSSasha Levin cmd.dbg_type |= KVM_DEBUG_CMD_TYPE_SYSRQ;
68*226e727bSSasha Levin cmd.sysrq = sysrq[0];
69*226e727bSSasha Levin }
70*226e727bSSasha Levin
71a59cdf44SLai Jiangshan r = kvm_ipc__send_msg(sock, KVM_IPC_DEBUG, sizeof(cmd), (u8 *)&cmd);
724b1addaeSSasha Levin if (r < 0)
734b1addaeSSasha Levin return r;
744b1addaeSSasha Levin
754b1c6f6eSSasha Levin if (!dump)
764b1c6f6eSSasha Levin return 0;
774b1c6f6eSSasha Levin
78b7d2f013SSasha Levin do {
79b7d2f013SSasha Levin r = xread(sock, buff, BUFFER_SIZE);
80b7d2f013SSasha Levin if (r < 0)
81b7d2f013SSasha Levin return 0;
82b7d2f013SSasha Levin printf("%.*s", r, buff);
83b7d2f013SSasha Levin } while (r > 0);
84b7d2f013SSasha Levin
854b1addaeSSasha Levin return 0;
8624e7dbbaSSasha Levin }
8724e7dbbaSSasha Levin
kvm_cmd_debug(int argc,const char ** argv,const char * prefix)88ca379b83SPekka Enberg int kvm_cmd_debug(int argc, const char **argv, const char *prefix)
89ca379b83SPekka Enberg {
908d7b77f6SSasha Levin parse_debug_options(argc, argv);
91b4a90c80SLai Jiangshan int instance;
92b4a90c80SLai Jiangshan int r;
936c757e71SSasha Levin
948d7b77f6SSasha Levin if (all)
958d7b77f6SSasha Levin return kvm__enumerate_instances(do_debug);
968d7b77f6SSasha Levin
97b4a90c80SLai Jiangshan if (instance_name == NULL)
980725673aSSasha Levin kvm_debug_help();
996c757e71SSasha Levin
1004b1addaeSSasha Levin instance = kvm__get_sock_by_instance(instance_name);
10124e7dbbaSSasha Levin
1024b1addaeSSasha Levin if (instance <= 0)
1038d7b77f6SSasha Levin die("Failed locating instance");
1046c757e71SSasha Levin
105b4a90c80SLai Jiangshan r = do_debug(instance_name, instance);
106b4a90c80SLai Jiangshan
107b4a90c80SLai Jiangshan close(instance);
108b4a90c80SLai Jiangshan
109b4a90c80SLai Jiangshan return r;
110ca379b83SPekka Enberg }
111