From mboxrd@z Thu Jan 1 00:00:00 1970 From: Sasha Levin Subject: [PATCH] kvm tools: Add 'kvm nmi' command Date: Tue, 6 Dec 2011 22:42:55 +0200 Message-ID: <1323204175-17234-1-git-send-email-levinsasha928@gmail.com> Cc: mingo@elte.hu, gorcunov@gmail.com, asias.hejun@gmail.com, kvm@vger.kernel.org, Sasha Levin To: penberg@kernel.org Return-path: Received: from mail-bw0-f46.google.com ([209.85.214.46]:43420 "EHLO mail-bw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753210Ab1LFUnS (ORCPT ); Tue, 6 Dec 2011 15:43:18 -0500 Received: by bkbzv3 with SMTP id zv3so3968417bkb.19 for ; Tue, 06 Dec 2011 12:43:17 -0800 (PST) Sender: kvm-owner@vger.kernel.org List-ID: This patch adds a 'kvm nmi' command which can be used to trigger NMIs in guests. Mostly useful for debugging purposes. Signed-off-by: Sasha Levin --- tools/kvm/Documentation/kvm-nmi.txt | 16 +++++++ tools/kvm/Makefile | 3 +- tools/kvm/builtin-nmi.c | 80 +++++++++++++++++++++++++++++++++++ tools/kvm/builtin-run.c | 9 ++++ tools/kvm/command-list.txt | 1 + tools/kvm/include/kvm/builtin-nmi.h | 15 +++++++ tools/kvm/include/kvm/kvm-ipc.h | 1 + tools/kvm/kvm-cmd.c | 2 + 8 files changed, 126 insertions(+), 1 deletions(-) create mode 100644 tools/kvm/Documentation/kvm-nmi.txt create mode 100644 tools/kvm/builtin-nmi.c create mode 100644 tools/kvm/include/kvm/builtin-nmi.h diff --git a/tools/kvm/Documentation/kvm-nmi.txt b/tools/kvm/Documentation/kvm-nmi.txt new file mode 100644 index 0000000..d562abc --- /dev/null +++ b/tools/kvm/Documentation/kvm-nmi.txt @@ -0,0 +1,16 @@ +kvm-nmi(1) +================ + +NAME +---- +kvm-nmi - Trigger an NMI on a specific cpu in the guest + +SYNOPSIS +-------- +[verse] +'kvm nmi [instance] -c [cpu]' + +DESCRIPTION +----------- +The command triggers a NMI on cpu 'cpu' in the guest. +For a list of running instances see 'kvm list'. diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile index 243886e..b5a76e2 100644 --- a/tools/kvm/Makefile +++ b/tools/kvm/Makefile @@ -80,6 +80,7 @@ OBJS += hw/vesa.o OBJS += hw/i8042.o OBJS += hw/pci-shmem.o OBJS += kvm-ipc.o +OBJS += builtin-nmi.o FLAGS_BFD := $(CFLAGS) -lbfd has_bfd := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD)) @@ -176,7 +177,7 @@ DEFINES += -DKVMTOOLS_VERSION='"$(KVMTOOLS_VERSION)"' DEFINES += -DBUILD_ARCH='"$(ARCH)"' KVM_INCLUDE := include -CFLAGS += $(CPPFLAGS) $(DEFINES) -I$(KVM_INCLUDE) -I$(ARCH_INCLUDE) -I../../include -I../../arch/$(ARCH)/include/ -Os -g +CFLAGS += $(CPPFLAGS) $(DEFINES) -I$(KVM_INCLUDE) -I$(ARCH_INCLUDE) -I../../include -I../../arch/$(ARCH)/include/ -O0 -g ifneq ($(WERROR),0) WARNINGS += -Werror diff --git a/tools/kvm/builtin-nmi.c b/tools/kvm/builtin-nmi.c new file mode 100644 index 0000000..ad60ac2 --- /dev/null +++ b/tools/kvm/builtin-nmi.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static bool all; +static int instance; +static int cpu = -1; +static const char *instance_name; + +static const char * const nmi_usage[] = { + "kvm nmi [--all] [-n name] -c cpu", + NULL +}; + +static const struct option nmi_options[] = { + OPT_GROUP("General options:"), + OPT_BOOLEAN('a', "all", &all, "Send NMI to all instances"), + OPT_STRING('n', "name", &instance_name, "name", "Instance name"), + OPT_INTEGER('c', "cpu", &cpu, "CPU which will receive NMI"), + OPT_END() +}; + +static void parse_nmi_options(int argc, const char **argv) +{ + while (argc != 0) { + argc = parse_options(argc, argv, nmi_options, nmi_usage, + PARSE_OPT_STOP_AT_NON_OPTION); + if (argc != 0) + kvm_nmi_help(); + } +} + +void kvm_nmi_help(void) +{ + usage_with_options(nmi_usage, nmi_options); +} + +static int do_nmi(const char *name, int sock) +{ + struct nmi_cmd cmd = {KVM_IPC_NMI, sizeof(u32)}; + int r; + + r = xwrite(sock, &cmd, sizeof(cmd)); + if (r < 0) + return r; + + pr_info("NMI sent to %s!\n", name); + + return 0; +} + +int kvm_cmd_nmi(int argc, const char **argv, const char *prefix) +{ + parse_nmi_options(argc, argv); + + if (all) + return kvm__enumerate_instances(do_nmi); + + if (instance_name == NULL && + instance == 0) + kvm_nmi_help(); + + if (cpu == -1) + kvm_nmi_help(); + + if (instance_name) + instance = kvm__get_sock_by_instance(instance_name); + + if (instance <= 0) + die("Failed locating instance"); + + return do_nmi(instance_name, instance); +} diff --git a/tools/kvm/builtin-run.c b/tools/kvm/builtin-run.c index 9148d83..b8743cd 100644 --- a/tools/kvm/builtin-run.c +++ b/tools/kvm/builtin-run.c @@ -31,6 +31,7 @@ #include "kvm/guest_compat.h" #include "kvm/pci-shmem.h" #include "kvm/kvm-ipc.h" +#include "kvm/builtin-nmi.h" #include @@ -529,6 +530,13 @@ static void handle_stop(int fd, u32 type, u32 len, u8 *msg) kvm_cpu__reboot(); } +static void handle_nmi(int fd, u32 type, u32 len, u8 *msg) +{ + u32 vcpu = *(u32 *)msg; + + ioctl(kvm_cpus[vcpu]->vcpu_fd, KVM_NMI); +} + static void *kvm_cpu_thread(void *arg) { current_kvm_cpu = arg; @@ -718,6 +726,7 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix) kvm_ipc__register_handler(KVM_IPC_PAUSE, handle_pause); kvm_ipc__register_handler(KVM_IPC_RESUME, handle_pause); kvm_ipc__register_handler(KVM_IPC_STOP, handle_stop); + kvm_ipc__register_handler(KVM_IPC_NMI, handle_nmi); nr_online_cpus = sysconf(_SC_NPROCESSORS_ONLN); diff --git a/tools/kvm/command-list.txt b/tools/kvm/command-list.txt index 0d16c62..e9ab8e4 100644 --- a/tools/kvm/command-list.txt +++ b/tools/kvm/command-list.txt @@ -12,3 +12,4 @@ kvm-debug common kvm-balloon common kvm-stop common kvm-stat common +kvm-nmi common diff --git a/tools/kvm/include/kvm/builtin-nmi.h b/tools/kvm/include/kvm/builtin-nmi.h new file mode 100644 index 0000000..ffdc288 --- /dev/null +++ b/tools/kvm/include/kvm/builtin-nmi.h @@ -0,0 +1,15 @@ +#ifndef KVM__NMI_H +#define KVM__NMI_H + +#include + +struct nmi_cmd { + u32 type; + u32 len; + u32 cpu; +}; + +int kvm_cmd_nmi(int argc, const char **argv, const char *prefix); +void kvm_nmi_help(void); + +#endif diff --git a/tools/kvm/include/kvm/kvm-ipc.h b/tools/kvm/include/kvm/kvm-ipc.h index 731767f..366f54e 100644 --- a/tools/kvm/include/kvm/kvm-ipc.h +++ b/tools/kvm/include/kvm/kvm-ipc.h @@ -17,6 +17,7 @@ enum { KVM_IPC_RESUME = 5, KVM_IPC_STOP = 6, KVM_IPC_PID = 7, + KVM_IPC_NMI = 8, }; int kvm_ipc__register_handler(u32 type, void (*cb)(int fd, u32 type, u32 len, u8 *msg)); diff --git a/tools/kvm/kvm-cmd.c b/tools/kvm/kvm-cmd.c index 96108a8..6ab9897 100644 --- a/tools/kvm/kvm-cmd.c +++ b/tools/kvm/kvm-cmd.c @@ -15,6 +15,7 @@ #include "kvm/builtin-stop.h" #include "kvm/builtin-stat.h" #include "kvm/builtin-help.h" +#include "kvm/builtin-nmi.h" #include "kvm/kvm-cmd.h" #include "kvm/builtin-run.h" #include "kvm/util.h" @@ -31,6 +32,7 @@ struct cmd_struct kvm_commands[] = { { "stat", kvm_cmd_stat, kvm_stat_help, 0 }, { "help", kvm_cmd_help, NULL, 0 }, { "setup", kvm_cmd_setup, kvm_setup_help, 0 }, + { "nmi", kvm_cmd_nmi, kvm_nmi_help, 0 }, { "run", kvm_cmd_run, kvm_run_help, 0 }, { NULL, NULL, NULL, 0 }, }; -- 1.7.8