From patchwork Thu Feb 25 15:03:18 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Llu=C3=ADs_Vilanova?= X-Patchwork-Id: 8424311 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 7684F9F314 for ; Thu, 25 Feb 2016 15:05:09 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C7CEE2034C for ; Thu, 25 Feb 2016 15:05:08 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id ED2AD2028D for ; Thu, 25 Feb 2016 15:05:07 +0000 (UTC) Received: from localhost ([::1]:43815 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aYxTX-0003Ef-AV for patchwork-qemu-devel@patchwork.kernel.org; Thu, 25 Feb 2016 10:05:07 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36908) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aYxRq-0000Oh-PS for qemu-devel@nongnu.org; Thu, 25 Feb 2016 10:03:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aYxRn-0008Ul-Ip for qemu-devel@nongnu.org; Thu, 25 Feb 2016 10:03:22 -0500 Received: from roura.ac.upc.edu ([147.83.33.10]:37973 helo=roura.ac.upc.es) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aYxRn-0008UT-3e for qemu-devel@nongnu.org; Thu, 25 Feb 2016 10:03:19 -0500 Received: from gw-3.ac.upc.es (gw-3.ac.upc.es [147.83.30.9]) by roura.ac.upc.es (8.13.8/8.13.8) with ESMTP id u1PF3IWR031005; Thu, 25 Feb 2016 16:03:18 +0100 Received: from localhost (unknown [84.88.51.85]) by gw-3.ac.upc.es (Postfix) with ESMTPSA id 3406C1F3; Thu, 25 Feb 2016 16:03:18 +0100 (CET) From: =?utf-8?b?TGx1w61z?= Vilanova To: qemu-devel@nongnu.org Date: Thu, 25 Feb 2016 16:03:18 +0100 Message-Id: <145641259776.30097.4785269283671764840.stgit@localhost> X-Mailer: git-send-email 2.7.0 In-Reply-To: <145641255678.30097.2919142707547689749.stgit@localhost> References: <145641255678.30097.2919142707547689749.stgit@localhost> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-MIME-Autoconverted: from 8bit to quoted-printable by roura.ac.upc.es id u1PF3IWR031005 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 147.83.33.10 Cc: Luiz Capitulino , Eduardo Habkost , Stefan Hajnoczi , Markus Armbruster Subject: [Qemu-devel] [PATCH 6/6] trace: Add QAPI/QMP interfaces to query and control per-vCPU tracing state X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Signed-off-by: Lluís Vilanova Reviewed-by: Stefan Hajnoczi --- monitor.c | 4 +- qapi/trace.json | 20 ++++++-- qmp-commands.hx | 18 ++++++- trace/qmp.c | 143 ++++++++++++++++++++++++++++++++++++++++++++----------- 4 files changed, 147 insertions(+), 38 deletions(-) diff --git a/monitor.c b/monitor.c index 73eac17..0d090c8 100644 --- a/monitor.c +++ b/monitor.c @@ -888,7 +888,7 @@ static void hmp_trace_event(Monitor *mon, const QDict *qdict) bool new_state = qdict_get_bool(qdict, "option"); Error *local_err = NULL; - qmp_trace_event_set_state(tp_name, new_state, true, true, &local_err); + qmp_trace_event_set_state(tp_name, new_state, true, true, false, 0, &local_err); if (local_err) { error_report_err(local_err); } @@ -1047,7 +1047,7 @@ static void hmp_info_cpustats(Monitor *mon, const QDict *qdict) static void hmp_info_trace_events(Monitor *mon, const QDict *qdict) { - TraceEventInfoList *events = qmp_trace_event_get_state("*", NULL); + TraceEventInfoList *events = qmp_trace_event_get_state("*", false, 0, NULL); TraceEventInfoList *elem; for (elem = events; elem != NULL; elem = elem->next) { diff --git a/qapi/trace.json b/qapi/trace.json index 01b0a52..b9f2e65 100644 --- a/qapi/trace.json +++ b/qapi/trace.json @@ -1,6 +1,6 @@ # -*- mode: python -*- # -# Copyright (C) 2011-2014 Lluís Vilanova +# Copyright (C) 2011-2016 Lluís Vilanova # # This work is licensed under the terms of the GNU GPL, version 2 or later. # See the COPYING file in the top-level directory. @@ -29,11 +29,12 @@ # # @name: Event name. # @state: Tracing state. +# @vcpu: Whether this is a per-vCPU event (since 2.6). # # Since 2.2 ## { 'struct': 'TraceEventInfo', - 'data': {'name': 'str', 'state': 'TraceEventState'} } + 'data': {'name': 'str', 'state': 'TraceEventState', 'vcpu': 'bool'} } ## # @trace-event-get-state: @@ -41,13 +42,18 @@ # Query the state of events. # # @name: Event name pattern (case-sensitive glob). +# @vcpu: #optional The vCPU to check (any by default; since 2.6). # # Returns: a list of @TraceEventInfo for the matching events # +# For any event without the "vcpu" property: +# - If @name is a pattern and @vcpu is set, events are ignored. +# - If @name is not a pattern and @vcpu is set, an error is raised. +# # Since 2.2 ## { 'command': 'trace-event-get-state', - 'data': {'name': 'str'}, + 'data': {'name': 'str', '*vcpu': 'int'}, 'returns': ['TraceEventInfo'] } ## @@ -58,8 +64,14 @@ # @name: Event name pattern (case-sensitive glob). # @enable: Whether to enable tracing. # @ignore-unavailable: #optional Do not match unavailable events with @name. +# @vcpu: #optional The vCPU to act upon (all by default; since 2.6). +# +# For any event without the "vcpu" property: +# - If @name is a pattern and @vcpu is set, events are ignored. +# - If @name is not a pattern and @vcpu is set, an error is raised. # # Since 2.2 ## { 'command': 'trace-event-set-state', - 'data': {'name': 'str', 'enable': 'bool', '*ignore-unavailable': 'bool'} } + 'data': {'name': 'str', 'enable': 'bool', '*ignore-unavailable': 'bool', + '*vcpu': 'int'} } diff --git a/qmp-commands.hx b/qmp-commands.hx index 085dc7d..1e4f9a7 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -4596,7 +4596,7 @@ EQMP { .name = "trace-event-get-state", - .args_type = "name:s", + .args_type = "name:s,vcpu:i?", .mhandler.cmd_new = qmp_marshal_trace_event_get_state, }, @@ -4606,6 +4606,11 @@ trace-event-get-state Query the state of events. +Arguments: + +- "name": Event name pattern (json-string). +- "vcpu": Specific vCPU to query, any vCPU by default (json-int, optional). + Example: -> { "execute": "trace-event-get-state", "arguments": { "name": "qemu_memalign" } } @@ -4614,7 +4619,7 @@ EQMP { .name = "trace-event-set-state", - .args_type = "name:s,enable:b,ignore-unavailable:b?", + .args_type = "name:s,enable:b,ignore-unavailable:b?,vcpu:i?", .mhandler.cmd_new = qmp_marshal_trace_event_set_state, }, @@ -4624,6 +4629,14 @@ trace-event-set-state Set the state of events. +Arguments: + +- "name": Event name pattern (json-string). +- "enable": Whether to enable or disable the event (json-bool). +- "ignore-unavailable": Whether to ignore errors for events that cannot be + changed (json-bool, optional). +- "vcpu": Specific vCPU to set, all vCPUs by default (json-int, optional). + Example: -> { "execute": "trace-event-set-state", "arguments": { "name": "qemu_memalign", "enable": "true" } } @@ -4692,7 +4705,6 @@ Move mouse pointer to absolute coordinates (20000, 400). { "type": "abs", "data" : { "axis": "X", "value" : 20000 } }, { "type": "abs", "data" : { "axis": "Y", "value" : 400 } } ] } } <- { "return": {} } - EQMP { diff --git a/trace/qmp.c b/trace/qmp.c index 6320b4b..876e789 100644 --- a/trace/qmp.c +++ b/trace/qmp.c @@ -1,7 +1,7 @@ /* * QMP commands for tracing events. * - * Copyright (C) 2014 Lluís Vilanova + * Copyright (C) 2014-2016 Lluís Vilanova * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. @@ -13,63 +13,148 @@ #include "trace/control.h" -TraceEventInfoList *qmp_trace_event_get_state(const char *name, Error **errp) +static bool get_cpu(bool has_vcpu, int vcpu, CPUState **cpu, Error **errp) +{ + if (has_vcpu) { + *cpu = qemu_get_cpu(vcpu); + if (*cpu == NULL) { + error_setg(errp, "invalid vCPU index %u", vcpu); + return false; + } + } else { + *cpu = NULL; + } + return true; +} + +static bool check_events(bool has_vcpu, bool ignore_unavailable, bool is_pattern, + const char *name, Error **errp) +{ + if (!is_pattern) { + TraceEvent *ev = trace_event_name(name); + + /* error for non-existing event */ + if (ev == NULL) { + error_setg(errp, "unknown event \"%s\"", name); + return false; + } + + /* error for non-vcpu event */ + if (has_vcpu && trace_event_get_cpu_id(ev) == trace_event_cpu_count()) { + error_setg(errp, "event \"%s\" is not vCPU-specific", name); + return false; + } + + /* error for unavailable event */ + if (!ignore_unavailable && !trace_event_get_state_static(ev)) { + error_setg(errp, "event \"%s\" is disabled", name); + return false; + } + + return true; + } else { + /* error for unavailable events */ + TraceEvent *ev = NULL; + while ((ev = trace_event_pattern(name, ev)) != NULL) { + if (!ignore_unavailable && !trace_event_get_state_static(ev)) { + error_setg(errp, "event \"%s\" is disabled", trace_event_get_name(ev)); + return false; + } + } + return true; + } +} + +TraceEventInfoList *qmp_trace_event_get_state(const char *name, + bool has_vcpu, int64_t vcpu, + Error **errp) { TraceEventInfoList *events = NULL; - bool found = false; TraceEvent *ev; + bool is_pattern = trace_event_is_pattern(name); + CPUState *cpu; + /* Check provided vcpu */ + if (!get_cpu(has_vcpu, vcpu, &cpu, errp)) { + return NULL; + } + + /* Check events */ + if (!check_events(has_vcpu, true, is_pattern, name, errp)) { + return NULL; + } + + /* Get states (all errors checked above) */ ev = NULL; while ((ev = trace_event_pattern(name, ev)) != NULL) { - TraceEventInfoList *elem = g_new(TraceEventInfoList, 1); + TraceEventInfoList *elem; + bool is_vcpu = trace_event_get_cpu_id(ev) != trace_event_cpu_count(); + if (has_vcpu && !is_vcpu) { + continue; + } + + elem = g_new(TraceEventInfoList, 1); elem->value = g_new(TraceEventInfo, 1); + elem->value->vcpu = is_vcpu; elem->value->name = g_strdup(trace_event_get_name(ev)); + if (!trace_event_get_state_static(ev)) { elem->value->state = TRACE_EVENT_STATE_UNAVAILABLE; - } else if (!trace_event_get_state_dynamic(ev)) { - elem->value->state = TRACE_EVENT_STATE_DISABLED; } else { - elem->value->state = TRACE_EVENT_STATE_ENABLED; + if (has_vcpu) { + if (is_vcpu) { + if (trace_event_get_cpu_state_dynamic(cpu, ev)) { + elem->value->state = TRACE_EVENT_STATE_ENABLED; + } else { + elem->value->state = TRACE_EVENT_STATE_DISABLED; + } + } + /* else: already skipped above */ + } else { + if (trace_event_get_state_dynamic(ev)) { + elem->value->state = TRACE_EVENT_STATE_ENABLED; + } else { + elem->value->state = TRACE_EVENT_STATE_DISABLED; + } + } } elem->next = events; events = elem; - found = true; - } - - if (!found && !trace_event_is_pattern(name)) { - error_setg(errp, "unknown event \"%s\"", name); } return events; } void qmp_trace_event_set_state(const char *name, bool enable, - bool has_ignore_unavailable, - bool ignore_unavailable, Error **errp) + bool has_ignore_unavailable, bool ignore_unavailable, + bool has_vcpu, int64_t vcpu, + Error **errp) { - bool found = false; TraceEvent *ev; + bool is_pattern = trace_event_is_pattern(name); + CPUState *cpu; - /* Check all selected events are dynamic */ - ev = NULL; - while ((ev = trace_event_pattern(name, ev)) != NULL) { - found = true; - if (!(has_ignore_unavailable && ignore_unavailable) && - !trace_event_get_state_static(ev)) { - error_setg(errp, "cannot set dynamic tracing state for \"%s\"", - trace_event_get_name(ev)); - return; - } + /* Check provided vcpu */ + if (!get_cpu(has_vcpu, vcpu, &cpu, errp)) { + return; } - if (!found && !trace_event_is_pattern(name)) { - error_setg(errp, "unknown event \"%s\"", name); + + /* Check events */ + if (!check_events(has_vcpu, has_ignore_unavailable && ignore_unavailable, + is_pattern, name, errp)) { return; } - /* Apply changes */ + /* Apply changes (all errors checked above) */ ev = NULL; while ((ev = trace_event_pattern(name, ev)) != NULL) { - if (trace_event_get_state_static(ev)) { + if (!trace_event_get_state_static(ev) || + (has_vcpu && trace_event_get_cpu_id(ev) == trace_event_cpu_count())) { + continue; + } + if (has_vcpu) { + trace_event_set_cpu_state_dynamic(cpu, ev, enable); + } else { trace_event_set_state_dynamic(ev, enable); } }