qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v2 09/10] trace: [tcg] Add per-vCPU tracing states f


From: Lluís Vilanova
Subject: [Qemu-devel] [PATCH v2 09/10] trace: [tcg] Add per-vCPU tracing states for events with the 'vcpu' property
Date: Tue, 24 Nov 2015 18:09:36 +0100
User-agent: StGit/0.17.1-dirty

Each event with the 'vcpu' property gets a per-vCPU dynamic tracing state.

The set of enabled events with the 'vcpu' and 'tcg' properties is used
to select a per-vCPU physical TB cache.  The number of events with both
properties is used to select the number of physical TB caches, and a
bitmap of the identifiers of such enabled events is used to select a
physical TB cache.

Signed-off-by: Lluís Vilanova <address@hidden>
---
 Makefile.objs                            |    1 
 include/qom/cpu.h                        |    5 +
 monitor.c                                |    4 -
 qapi/trace.json                          |   13 ++-
 qmp-commands.hx                          |   17 +++-
 qom/cpu.c                                |   12 +++
 scripts/tracetool/format/h.py            |    1 
 scripts/tracetool/format/tcg_helper_c.py |   11 ++
 trace/Makefile.objs                      |    2 
 trace/control-internal.h                 |   13 ++-
 trace/control-stub.c                     |   29 ++++++
 trace/control-target.c                   |   69 +++++++++++++++
 trace/control.h                          |   54 ++++++++++++
 trace/event-internal.h                   |    2 
 trace/qmp.c                              |  138 +++++++++++++++++++++++++-----
 translate-all.c                          |    1 
 16 files changed, 330 insertions(+), 42 deletions(-)
 create mode 100644 trace/control-stub.c
 create mode 100644 trace/control-target.c

diff --git a/Makefile.objs b/Makefile.objs
index d161060..6a6ccfd 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -98,6 +98,7 @@ version-lobj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.lo
 # tracing
 util-obj-y +=  trace/
 target-obj-y += trace/
+stub-obj-y += trace/
 
 ######################################################################
 # guest agent
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 40962e0..8cde56e 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -29,6 +29,7 @@
 #include "qemu/queue.h"
 #include "qemu/thread.h"
 #include "qemu/typedefs.h"
+#include "trace/generated-events.h"
 
 typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size,
                                      void *opaque);
@@ -319,6 +320,10 @@ struct CPUState {
     unsigned int tb_phys_idx;
     unsigned int tb_phys_idx_req;
 
+    /* Ensure 'tb_phys_idx' can encode event states as a bitmask */
+    bool too_many_tcg_vcpu_events[
+        TRACE_CPU_EVENT_COUNT > sizeof(unsigned int)*8 ? -1 : 0];
+
     /* TODO Move common fields from CPUArchState here. */
     int cpu_index; /* used by alpha TCG */
     uint32_t halted; /* used by alpha, cris, ppc TCG */
diff --git a/monitor.c b/monitor.c
index e4cf34e..d161895 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 71cb96f..fca70ee 100644
--- a/qapi/trace.json
+++ b/qapi/trace.json
@@ -29,7 +29,7 @@
 #
 # @name: Event name.
 # @state: Tracing state.
-# @vcpu: Whether this is a per-vCPU event (since 2.5).
+# @vcpu: #optional Whether this is a per-vCPU event (since 2.5).
 #
 # Since 2.2
 ##
@@ -42,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.5).
 #
 # 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'] }
 
 ##
@@ -59,8 +64,10 @@
 # @name: Event name pattern (case-sensitive glob).
 # @enable: Whether to enable tracing.
 # @ignore-unavailable: #optional Do not match unavailable events with @name.
+# @vcpu: The vCPU to act upon (all by default; since 2.5).
 #
 # 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 9d8b42f..72368ca 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -4510,7 +4510,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,
     },
 
@@ -4520,6 +4520,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" } }
@@ -4528,7 +4533,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,
     },
 
@@ -4538,6 +4543,13 @@ 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" } }
@@ -4606,7 +4618,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/qom/cpu.c b/qom/cpu.c
index bb7a618..bc27381 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -25,6 +25,7 @@
 #include "qemu/log.h"
 #include "qemu/error-report.h"
 #include "sysemu/sysemu.h"
+#include "trace/control.h"
 
 bool cpu_exists(int64_t id)
 {
@@ -227,6 +228,17 @@ void cpu_dump_statistics(CPUState *cpu, FILE *f, 
fprintf_function cpu_fprintf,
 void cpu_reset(CPUState *cpu)
 {
     CPUClass *klass = CPU_GET_CLASS(cpu);
+    TraceEvent *ev = NULL;
+
+    if (!qemu_initialized) {
+        /* trace enabled events on all initial vCPUs */
+        while ((ev = trace_event_pattern("*", ev)) != NULL) {
+            if (trace_event_get_cpu_id(ev) != TRACE_CPU_EVENT_COUNT &&
+                trace_event_get_state_dynamic(ev)) {
+                trace_event_set_state_dynamic(ev, true);
+            }
+        }
+    }
 
     if (klass->reset != NULL) {
         (*klass->reset)(cpu);
diff --git a/scripts/tracetool/format/h.py b/scripts/tracetool/format/h.py
index 01d8718..440f656 100644
--- a/scripts/tracetool/format/h.py
+++ b/scripts/tracetool/format/h.py
@@ -36,6 +36,7 @@ def generate(events, backend):
             args=e.args)
 
         if "disable" not in e.properties:
+            # NOTE: See note on 'trace_event_set_cpu_state()'.
             backend.generate(e)
 
         out('}')
diff --git a/scripts/tracetool/format/tcg_helper_c.py 
b/scripts/tracetool/format/tcg_helper_c.py
index 96655a0..0cb7f45 100644
--- a/scripts/tracetool/format/tcg_helper_c.py
+++ b/scripts/tracetool/format/tcg_helper_c.py
@@ -6,7 +6,7 @@ Generate trace/generated-helpers.c.
 """
 
 __author__     = "Lluís Vilanova <address@hidden>"
-__copyright__  = "Copyright 2012-2014, Lluís Vilanova <address@hidden>"
+__copyright__  = "Copyright 2012-2015, Lluís Vilanova <address@hidden>"
 __license__    = "GPL version 2 or (at your option) any later version"
 
 __maintainer__ = "Stefan Hajnoczi"
@@ -36,8 +36,13 @@ def generate(events, backend):
         # tracetool.generate always transforms types to host
         e_args = e.original.args
 
-        values = ["(%s)%s" % (t, n)
-                  for t, n in e.args.transform(TCG_2_TCG_HELPER_DEF)]
+        values = []
+        for (t_old, n), (t_new, _) in zip(
+                e.args, e.args.transform(TCG_2_TCG_HELPER_DEF)):
+            if t_old == "CPUState *":
+                values.append("ENV_GET_CPU((CPUArchState*)%s)" % n)
+            else:
+                values.append("(%s)%s" % (t_new, n))
 
         out('void %(name_tcg)s(%(args)s)',
             '{',
diff --git a/trace/Makefile.objs b/trace/Makefile.objs
index 32f7a32..15896de 100644
--- a/trace/Makefile.objs
+++ b/trace/Makefile.objs
@@ -144,4 +144,6 @@ util-obj-$(CONFIG_TRACE_SIMPLE) += simple.o 
generated-tracers.o
 util-obj-$(CONFIG_TRACE_FTRACE) += ftrace.o
 util-obj-$(CONFIG_TRACE_UST) += generated-ust.o
 util-obj-y += control.o
+target-obj-y += control-target.o
+stub-obj-y += control-stub.o
 util-obj-y += qmp.o
diff --git a/trace/control-internal.h b/trace/control-internal.h
index 70e55df..d551adf 100644
--- a/trace/control-internal.h
+++ b/trace/control-internal.h
@@ -12,6 +12,9 @@
 
 #include <string.h>
 
+#include "qemu-common.h"
+#include "qom/cpu.h"
+
 
 extern TraceEvent trace_events[];
 
@@ -60,14 +63,16 @@ static inline bool trace_event_get_state_static(TraceEvent 
*ev)
 static inline bool trace_event_get_state_dynamic(TraceEvent *ev)
 {
     assert(ev != NULL);
-    return ev->dstate;
+    /* no need to iterate over vCPUs, since the global dynamic state is always 
set */
+    return ev->dstate > 0;
 }
 
-static inline void trace_event_set_state_dynamic(TraceEvent *ev, bool state)
+static inline bool trace_event_get_cpu_state_dynamic(CPUState *cpu,
+                                                     TraceEvent *ev)
 {
+    assert(cpu != NULL);
     assert(ev != NULL);
-    assert(trace_event_get_state_static(ev));
-    ev->dstate = state;
+    return cpu->tb_phys_idx & (((unsigned long)1) << ev->cpu_id);
 }
 
 #endif  /* TRACE__CONTROL_INTERNAL_H */
diff --git a/trace/control-stub.c b/trace/control-stub.c
new file mode 100644
index 0000000..dd62d3b
--- /dev/null
+++ b/trace/control-stub.c
@@ -0,0 +1,29 @@
+/*
+ * Interface for configuring and controlling the state of tracing events.
+ *
+ * Copyright (C) 2014-2015 Lluís Vilanova <address@hidden>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "trace/control.h"
+
+
+void trace_init_vcpu_tb_caches(void)
+{
+}
+
+void trace_event_set_state_dynamic(TraceEvent *ev, bool state)
+{
+    assert(ev != NULL);
+    assert(trace_event_get_state_static(ev));
+    ev->dstate = state;
+}
+
+void trace_event_set_cpu_state_dynamic(CPUState *cpu,
+                                       TraceEvent *ev, bool state)
+{
+    /* should never be called on non-target binaries */
+    abort();
+}
diff --git a/trace/control-target.c b/trace/control-target.c
new file mode 100644
index 0000000..b586b4d
--- /dev/null
+++ b/trace/control-target.c
@@ -0,0 +1,69 @@
+/*
+ * Interface for configuring and controlling the state of tracing events.
+ *
+ * Copyright (C) 2014-2015 Lluís Vilanova <address@hidden>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "trace/control.h"
+#include "cpu.h"
+#include "translate-all.h"
+
+
+void trace_init_vcpu_tb_caches(void)
+{
+    unsigned int events = 1;
+    TraceEvent *ev = NULL;
+    while ((ev = trace_event_pattern("*", ev)) != NULL) {
+        if (trace_event_get_cpu_id(ev) == TRACE_CPU_EVENT_COUNT) {
+            continue;
+        }
+        events <<= 1;
+    }
+    tb_caches_set(events);
+    tb_caches_apply();
+}
+
+void trace_event_set_state_dynamic(TraceEvent *ev, bool state)
+{
+    CPUState *cpu;
+    assert(ev != NULL);
+    assert(trace_event_get_state_static(ev));
+    if (trace_event_get_cpu_id(ev) != TRACE_CPU_EVENT_COUNT) {
+        CPU_FOREACH(cpu) {
+            trace_event_set_cpu_state_dynamic(cpu, ev, state);
+        }
+    } else {
+        ev->dstate = state;
+    }
+}
+
+void trace_event_set_cpu_state_dynamic(CPUState *cpu,
+                                       TraceEvent *ev, bool state)
+{
+    /*
+     * NOTE: Does not immediately apply changes on all affected vCPUs, so
+     *       "tcg-exec" events might be generated after being disabled (until
+     *       the vCPU finishes a BBL and checks for event state changes).
+     */
+    unsigned int bit;
+    bool state_pre;
+    assert(cpu != NULL);
+    assert(ev != NULL);
+    assert(trace_event_get_state_static(ev));
+    assert(trace_event_get_cpu_id(ev) != TRACE_CPU_EVENT_COUNT);
+    bit = ((unsigned long)1) << ev->cpu_id;
+    /* must use the requested TB index in case it's not yet synchronized */
+    state_pre = cpu->tb_phys_idx_req & bit;
+    if ((state_pre == 0) != (state == 0)) {
+        if (state) {
+            cpu_tb_cache_set(cpu, (cpu->tb_phys_idx_req & ~bit) | bit);
+            ev->dstate++;
+        } else {
+            cpu_tb_cache_set(cpu, (cpu->tb_phys_idx_req & ~bit));
+            ev->dstate--;
+        }
+    }
+}
diff --git a/trace/control.h b/trace/control.h
index a0bfd3e..80501cd 100644
--- a/trace/control.h
+++ b/trace/control.h
@@ -115,6 +115,22 @@ static const char * trace_event_get_name(TraceEvent *ev);
     ((id ##_ENABLED) && trace_event_get_state_dynamic(trace_event_id(id)))
 
 /**
+ * trace_event_get_cpu_state:
+ * @id: Event identifier.
+ *
+ * Get the tracing state of an event (both static and dynamic) for the given
+ * vCPU.
+ *
+ * If the event has the disabled property, the check will have no performance
+ * impact.
+ *
+ * As a down side, you must always use an immediate #TraceEventID value.
+ */
+#define trace_event_get_cpu_state(cpu, id)                              \
+    ((id ##_ENABLED) && trace_event_get_cpu_state_dynamic(cpu,          \
+                                                          trace_event_id(id)))
+
+/**
  * trace_event_get_state_static:
  * @id: Event identifier.
  *
@@ -129,10 +145,19 @@ static bool trace_event_get_state_static(TraceEvent *ev);
  * trace_event_get_state_dynamic:
  *
  * Get the dynamic tracing state of an event.
+ *
+ * If the event has the 'vcpu' property, gets the OR'ed state of all vCPUs.
  */
 static bool trace_event_get_state_dynamic(TraceEvent *ev);
 
 /**
+ * trace_event_get_cpu_state_dynamic:
+ *
+ * Get the dynamic tracing state of an event for the given vCPU.
+ */
+static bool trace_event_get_cpu_state_dynamic(CPUState *cpu, TraceEvent *ev);
+
+/**
  * trace_event_set_state:
  *
  * Set the tracing state of an event (only if possible).
@@ -146,13 +171,38 @@ static bool trace_event_get_state_dynamic(TraceEvent *ev);
     } while (0)
 
 /**
+ * trace_event_set_cpu_state:
+ *
+ * Set the tracing state of an event for the given vCPU (only if possible).
+ */
+#define trace_event_set_cpu_state(cpu, id, state)               \
+    do {                                                        \
+        if ((id ##_ENABLED)) {                                  \
+            TraceEvent *_e = trace_event_id(id);                \
+            trace_event_set_cpu_state_dynamic(cpu, _e, state);  \
+        }                                                       \
+    } while (0)
+
+/**
  * trace_event_set_state_dynamic:
  *
  * Set the dynamic tracing state of an event.
  *
+ * If the event has the 'vcpu' property, sets the state on all vCPUs.
+ *
  * Pre-condition: trace_event_get_state_static(ev) == true
  */
-static void trace_event_set_state_dynamic(TraceEvent *ev, bool state);
+void trace_event_set_state_dynamic(TraceEvent *ev, bool state);
+
+/**
+ * trace_event_set_cpu_state_dynamic:
+ *
+ * Set the dynamic tracing state of an event for the given vCPU.
+ *
+ * Pre-condition: trace_event_get_cpu_state_static(ev) == true
+ */
+void trace_event_set_cpu_state_dynamic(CPUState *cpu,
+                                       TraceEvent *ev, bool state);
 
 
 
@@ -169,6 +219,8 @@ static void trace_event_set_state_dynamic(TraceEvent *ev, 
bool state);
  */
 bool trace_init_backends(const char *events, const char *file);
 
+void trace_init_vcpu_tb_caches(void);
+
 
 #include "trace/control-internal.h"
 
diff --git a/trace/event-internal.h b/trace/event-internal.h
index ae18b48..1e89210 100644
--- a/trace/event-internal.h
+++ b/trace/event-internal.h
@@ -28,7 +28,7 @@ typedef struct TraceEvent {
     TraceEventCPUID cpu_id;
     const char * name;
     const bool sstate;
-    bool dstate;
+    size_t dstate;
 } TraceEvent;
 
 
diff --git a/trace/qmp.c b/trace/qmp.c
index b5a5020..2d3515a 100644
--- a/trace/qmp.c
+++ b/trace/qmp.c
@@ -12,64 +12,152 @@
 #include "trace/control.h"
 
 
-TraceEventInfoList *qmp_trace_event_get_state(const char *name, Error **errp)
+static bool get_cpu_state(bool has_index, int index, CPUState **cpu, Error 
**errp)
+{
+    if (has_index) {
+        *cpu = qemu_get_cpu(index);
+        if (*cpu == NULL) {
+            error_setg(errp, "invalid vCPU index %u", index);
+            return false;
+        }
+    } else {
+        *cpu = NULL;
+    }
+    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;
+
+    if (!get_cpu_state(has_vcpu, vcpu, &cpu, errp)) {
+        return NULL;
+    }
 
     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_CPU_EVENT_COUNT;
+        if (has_vcpu && !is_vcpu) {
+            if (!is_pattern) {
+                error_setg(errp, "event \"%s\" is not vCPU-specific", name);
+            }
+            /* else: ignore */
+            continue;
+        }
+
+        elem = g_new(TraceEventInfoList, 1);
         elem->value = g_new(TraceEventInfo, 1);
-        elem->value->vcpu = trace_event_get_cpu_id(ev) != 
TRACE_CPU_EVENT_COUNT;
+        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 handled 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)) {
+    if (events == NULL && !is_pattern) {
         error_setg(errp, "unknown event \"%s\"", name);
     }
 
     return events;
 }
 
+
+static void check_events_are_dynamic(const char *name, bool per_cpu,
+                                     bool *found, bool error_check,
+                                     bool *error_found, Error **errp)
+{
+    TraceEvent *ev = NULL;
+    *found = false;
+    *error_found = false;
+    while ((ev = trace_event_pattern(name, ev)) != NULL) {
+        if (per_cpu && trace_event_get_cpu_id(ev) == TRACE_CPU_EVENT_COUNT) {
+            if (error_check) {
+                Error *local_err = NULL;
+                error_setg(&local_err, "event \"%s\" is not vCPU-specific",
+                           trace_event_get_name(ev));
+                error_propagate(errp, local_err);
+                *error_found = true;
+            }
+            continue;
+        }
+        if (!trace_event_get_state_static(ev)) {
+            if (error_check) {
+                Error *local_err = NULL;
+                error_setg(&local_err, "cannot set dynamic tracing state for 
\"%s\"",
+                           trace_event_get_name(ev));
+                error_propagate(errp, local_err);
+                *error_found = true;
+            }
+            continue;
+        }
+        *found = true;
+    }
+}
+
 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 error, found;
+    TraceEvent *ev = NULL;
+    CPUState *cpu;
+
+    if (!get_cpu_state(has_vcpu, vcpu, &cpu, errp)) {
+        return;
+    }
 
     /* 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_events_are_dynamic(name, has_vcpu, &found,
+                             !(has_ignore_unavailable && ignore_unavailable),
+                             &error, errp);
+    if (error) {
+        return;
     }
-    if (!found && !trace_event_is_pattern(name)) {
-        error_setg(errp, "unknown event \"%s\"", name);
+    if (!found) {
+        if (!trace_event_is_pattern(name)) {
+            error_setg(errp, "unknown event \"%s\"", name);
+        }
         return;
     }
 
     /* Apply changes */
     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_CPU_EVENT_COUNT)) 
{
+            /* if it were an error, it was catched by the check above */
+            continue;
+        }
+        if (has_vcpu) {
+            trace_event_set_cpu_state_dynamic(cpu, ev, enable);
+        } else {
             trace_event_set_state_dynamic(ev, enable);
         }
     }
diff --git a/translate-all.c b/translate-all.c
index decaadf..8eb966f 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -179,6 +179,7 @@ void cpu_gen_init(void)
     tcg_ctx.tb_ctx.tb_phys_hash_size_req = 1;
     tcg_ctx.tb_ctx.tb_phys_hash = NULL;
     tb_caches_apply();
+    trace_init_vcpu_tb_caches();
 }
 
 /* Encode VAL as a signed leb128 sequence at P.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]