From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39730) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aK7Oj-0000Ur-Ug for qemu-devel@nongnu.org; Fri, 15 Jan 2016 11:38:52 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aK7Og-0004Xm-TA for qemu-devel@nongnu.org; Fri, 15 Jan 2016 11:38:49 -0500 Received: from roura.ac.upc.es ([147.83.33.10]:58124) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aK7Og-0004X1-8A for qemu-devel@nongnu.org; Fri, 15 Jan 2016 11:38:46 -0500 From: =?utf-8?b?TGx1w61z?= Vilanova Date: Fri, 15 Jan 2016 17:38:37 +0100 Message-Id: <145287591675.11400.12508957244344480632.stgit@localhost> In-Reply-To: <145287587081.11400.4178335509020334684.stgit@localhost> References: <145287587081.11400.4178335509020334684.stgit@localhost> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [PATCH v4 8/9] trace: [tcg] Add per-vCPU tracing states for events with the 'vcpu' property List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Eduardo Habkost , Peter Crosthwaite , Stefan Hajnoczi , Riku Voipio , Markus Armbruster , Luiz Capitulino , Blue Swirl , Stefan Hajnoczi , Paolo Bonzini , =?UTF-8?q?Andreas=20F=C3=A4rber?= , Richard Henderson 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=C3=ADs Vilanova --- Makefile.objs | 1=20 bsd-user/main.c | 2=20 include/qom/cpu.h | 10 ++ linux-user/main.c | 2=20 monitor.c | 4 - qapi/trace.json | 11 ++ qmp-commands.hx | 17 +++- scripts/tracetool/format/h.py | 1=20 scripts/tracetool/format/tcg_helper_c.py | 11 ++ trace/Makefile.objs | 2=20 trace/control-internal.h | 13 ++- trace/control-stub.c | 29 ++++++ trace/control-target.c | 69 +++++++++++++++ trace/control.c | 17 +++- trace/control.h | 55 ++++++++++++ trace/event-internal.h | 2=20 trace/qmp.c | 138 ++++++++++++++++++++++++= +----- translate-all.c | 1=20 vl.c | 1=20 19 files changed, 344 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 dac2c02..c268acb 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -103,6 +103,7 @@ version-lobj-$(CONFIG_WIN32) +=3D $(BUILD_DIR)/versio= n.lo # tracing util-obj-y +=3D trace/ target-obj-y +=3D trace/ +stub-obj-y +=3D trace/ =20 ###################################################################### # guest agent diff --git a/bsd-user/main.c b/bsd-user/main.c index 1ecaeb5..b57f9a9 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -31,6 +31,7 @@ /* For tb_lock */ #include "cpu.h" #include "tcg.h" +#include "trace/control.h" #include "qemu/timer.h" #include "qemu/envlist.h" =20 @@ -1121,6 +1122,7 @@ int main(int argc, char **argv) gdbserver_start (gdbstub_port); gdb_handlesig(cpu, 0); } + trace_init_vcpu_events(); cpu_loop(env); /* never exits */ return 0; diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 40962e0..d1cbd7a 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" =20 typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size, void *opaque); @@ -319,6 +320,15 @@ struct CPUState { unsigned int tb_phys_idx; unsigned int tb_phys_idx_req; =20 + /* + * Ensure 'tb_phys_idx' can encode event states as a bitmask. + * + * This limits the number of events with the 'tcg' property and *wit= hout* + * the 'disabled' property to 'sizeof(tb_phys_idx)*8'. + */ + 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/linux-user/main.c b/linux-user/main.c index ee12035..44f0536 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -30,6 +30,7 @@ #include "qemu-common.h" #include "cpu.h" #include "tcg.h" +#include "trace/control.h" #include "qemu/timer.h" #include "qemu/envlist.h" #include "elf.h" @@ -4654,6 +4655,7 @@ int main(int argc, char **argv, char **envp) } gdb_handlesig(cpu, 0); } + trace_init_vcpu_events(); cpu_loop(env); /* never exits */ return 0; diff --git a/monitor.c b/monitor.c index c53a453..7c42e78 100644 --- a/monitor.c +++ b/monitor.c @@ -888,7 +888,7 @@ static void hmp_trace_event(Monitor *mon, const QDict= *qdict) bool new_state =3D qdict_get_bool(qdict, "option"); Error *local_err =3D NULL; =20 - 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 Q= Dict *qdict) =20 static void hmp_info_trace_events(Monitor *mon, const QDict *qdict) { - TraceEventInfoList *events =3D qmp_trace_event_get_state("*", NULL); + TraceEventInfoList *events =3D qmp_trace_event_get_state("*", false,= 0, NULL); TraceEventInfoList *elem; =20 for (elem =3D events; elem !=3D NULL; elem =3D elem->next) { diff --git a/qapi/trace.json b/qapi/trace.json index 84c34dd..8708dba 100644 --- a/qapi/trace.json +++ b/qapi/trace.json @@ -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.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'] } =20 ## @@ -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 @n= ame. +# @vcpu: #optional The vCPU to act upon (all by default; since 2.6). # # 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 db072a6..ce6a419 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -4566,7 +4566,7 @@ EQMP =20 { .name =3D "trace-event-get-state", - .args_type =3D "name:s", + .args_type =3D "name:s,vcpu:i?", .mhandler.cmd_new =3D qmp_marshal_trace_event_get_state, }, =20 @@ -4576,6 +4576,11 @@ trace-event-get-state =20 Query the state of events. =20 +Arguments: + +- "name": Event name pattern (json-string). +- "vcpu": Specific vCPU to query, any vCPU by default (json-int, optiona= l). + Example: =20 -> { "execute": "trace-event-get-state", "arguments": { "name": "qemu_me= malign" } } @@ -4584,7 +4589,7 @@ EQMP =20 { .name =3D "trace-event-set-state", - .args_type =3D "name:s,enable:b,ignore-unavailable:b?", + .args_type =3D "name:s,enable:b,ignore-unavailable:b?,vcpu:i?", .mhandler.cmd_new =3D qmp_marshal_trace_event_set_state, }, =20 @@ -4594,6 +4599,13 @@ trace-event-set-state =20 Set the state of events. =20 +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: =20 -> { "execute": "trace-event-set-state", "arguments": { "name": "qemu_me= malign", "enable": "true" } } @@ -4662,7 +4674,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 =20 { diff --git a/scripts/tracetool/format/h.py b/scripts/tracetool/format/h.p= y index 2bd68a2..f98f26b 100644 --- a/scripts/tracetool/format/h.py +++ b/scripts/tracetool/format/h.py @@ -36,6 +36,7 @@ def generate(events, backend): args=3De.args) =20 if "disable" not in e.properties: + # NOTE: See note on 'trace_event_set_cpu_state()'. backend.generate(e) =20 out('}') diff --git a/scripts/tracetool/format/tcg_helper_c.py b/scripts/tracetool= /format/tcg_helper_c.py index 96655a0..e5dd3fe 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. """ =20 __author__ =3D "Llu=C3=ADs Vilanova " -__copyright__ =3D "Copyright 2012-2014, Llu=C3=ADs Vilanova " +__copyright__ =3D "Copyright 2012-2016, Llu=C3=ADs Vilanova " __license__ =3D "GPL version 2 or (at your option) any later version" =20 __maintainer__ =3D "Stefan Hajnoczi" @@ -36,8 +36,13 @@ def generate(events, backend): # tracetool.generate always transforms types to host e_args =3D e.original.args =20 - values =3D ["(%s)%s" % (t, n) - for t, n in e.args.transform(TCG_2_TCG_HELPER_DEF)] + values =3D [] + for (t_old, n), (t_new, _) in zip( + e.args, e.args.transform(TCG_2_TCG_HELPER_DEF)): + if t_old =3D=3D "CPUState *": + values.append("ENV_GET_CPU((CPUArchState*)%s)" % n) + else: + values.append("(%s)%s" % (t_new, n)) =20 out('void %(name_tcg)s(%(args)s)', '{', diff --git a/trace/Makefile.objs b/trace/Makefile.objs index 5145b34..a179d02 100644 --- a/trace/Makefile.objs +++ b/trace/Makefile.objs @@ -152,4 +152,6 @@ util-obj-$(CONFIG_TRACE_SIMPLE) +=3D simple.o generat= ed-tracers.o util-obj-$(CONFIG_TRACE_FTRACE) +=3D ftrace.o util-obj-$(CONFIG_TRACE_UST) +=3D generated-ust.o util-obj-y +=3D control.o +target-obj-y +=3D control-target.o +stub-obj-y +=3D control-stub.o util-obj-y +=3D qmp.o diff --git a/trace/control-internal.h b/trace/control-internal.h index ab42396..81e757f 100644 --- a/trace/control-internal.h +++ b/trace/control-internal.h @@ -12,6 +12,9 @@ =20 #include =20 +#include "qemu-common.h" +#include "qom/cpu.h" + =20 extern TraceEvent trace_events[]; =20 @@ -60,14 +63,16 @@ static inline bool trace_event_get_state_static(Trace= Event *ev) static inline bool trace_event_get_state_dynamic(TraceEvent *ev) { assert(ev !=3D NULL); - return ev->dstate; + /* no need to iterate over vCPUs, since the global dynamic state is = always set */ + return ev->dstate > 0; } =20 -static inline void trace_event_set_state_dynamic(TraceEvent *ev, bool st= ate) +static inline bool trace_event_get_cpu_state_dynamic(CPUState *cpu, + TraceEvent *ev) { + assert(cpu !=3D NULL); assert(ev !=3D NULL); - assert(trace_event_get_state_static(ev)); - ev->dstate =3D state; + return cpu->tb_phys_idx & (((unsigned long)1) << ev->cpu_id); } =20 #endif /* TRACE__CONTROL_INTERNAL_H */ diff --git a/trace/control-stub.c b/trace/control-stub.c new file mode 100644 index 0000000..784bc35 --- /dev/null +++ b/trace/control-stub.c @@ -0,0 +1,29 @@ +/* + * Interface for configuring and controlling the state of tracing events. + * + * Copyright (C) 2014-2016 Llu=C3=ADs Vilanova + * + * This work is licensed under the terms of the GNU GPL, version 2 or la= ter. + * 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 !=3D NULL); + assert(trace_event_get_state_static(ev)); + ev->dstate =3D 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..c256f54 --- /dev/null +++ b/trace/control-target.c @@ -0,0 +1,69 @@ +/* + * Interface for configuring and controlling the state of tracing events. + * + * Copyright (C) 2014-2016 Llu=C3=ADs Vilanova + * + * This work is licensed under the terms of the GNU GPL, version 2 or la= ter. + * 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 =3D 1; + TraceEvent *ev =3D NULL; + while ((ev =3D trace_event_pattern("*", ev)) !=3D NULL) { + if (trace_event_get_cpu_id(ev) =3D=3D TRACE_CPU_EVENT_COUNT) { + continue; + } + events <<=3D 1; + } + tb_caches_set(events); + tb_caches_apply(); +} + +void trace_event_set_state_dynamic(TraceEvent *ev, bool state) +{ + CPUState *cpu; + assert(ev !=3D NULL); + assert(trace_event_get_state_static(ev)); + if (trace_event_get_cpu_id(ev) !=3D TRACE_CPU_EVENT_COUNT) { + CPU_FOREACH(cpu) { + trace_event_set_cpu_state_dynamic(cpu, ev, state); + } + } else { + ev->dstate =3D state; + } +} + +void trace_event_set_cpu_state_dynamic(CPUState *cpu, + TraceEvent *ev, bool state) +{ + /* + * NOTE: Does not immediately apply changes on all affected vCPUs, s= o + * "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 !=3D NULL); + assert(ev !=3D NULL); + assert(trace_event_get_state_static(ev)); + assert(trace_event_get_cpu_id(ev) !=3D TRACE_CPU_EVENT_COUNT); + bit =3D ((unsigned long)1) << ev->cpu_id; + /* must use the requested TB index in case it's not yet synchronized= */ + state_pre =3D cpu->tb_phys_idx_req & bit; + if ((state_pre =3D=3D 0) !=3D (state =3D=3D 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.c b/trace/control.c index 995beb3..2bd5908 100644 --- a/trace/control.c +++ b/trace/control.c @@ -1,7 +1,7 @@ /* * Interface for configuring and controlling the state of tracing events. * - * Copyright (C) 2011-2014 Llu=C3=ADs Vilanova + * Copyright (C) 2011-2016 Llu=C3=ADs Vilanova * * This work is licensed under the terms of the GNU GPL, version 2 or la= ter. * See the COPYING file in the top-level directory. @@ -167,3 +167,18 @@ bool trace_init_backends(const char *events, const c= har *file) trace_init_events(events); return true; } + +void trace_init_vcpu_events(void) +{ + TraceEvent *ev =3D NULL; + /* + * Set per-vCPU tracing state according to initial event state. The = calls + * here affect al vCPUs in the system. + */ + while ((ev =3D trace_event_pattern("*", ev)) !=3D NULL) { + if (trace_event_get_cpu_id(ev) !=3D TRACE_CPU_EVENT_COUNT && + trace_event_get_state_dynamic(ev)) { + trace_event_set_state_dynamic(ev, true); + } + } +} diff --git a/trace/control.h b/trace/control.h index 860beed..1103a4c 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)= )) =20 /** + * trace_event_get_cpu_state: + * @id: Event identifier. + * + * Get the tracing state of an event (both static and dynamic) for the g= iven + * vCPU. + * + * If the event has the disabled property, the check will have no perfor= mance + * 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 vCP= Us. */ static bool trace_event_get_state_dynamic(TraceEvent *ev); =20 /** + * 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(TraceEven= t *ev); } while (0) =20 /** + * trace_event_set_cpu_state: + * + * Set the tracing state of an event for the given vCPU (only if possibl= e). + */ +#define trace_event_set_cpu_state(cpu, id, state) \ + do { \ + if ((id ##_ENABLED)) { \ + TraceEvent *_e =3D 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) =3D=3D 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) =3D=3D true + */ +void trace_event_set_cpu_state_dynamic(CPUState *cpu, + TraceEvent *ev, bool state); =20 =20 =20 @@ -169,6 +219,9 @@ static void trace_event_set_state_dynamic(TraceEvent = *ev, bool state); */ bool trace_init_backends(const char *events, const char *file); =20 +void trace_init_vcpu_tb_caches(void); +void trace_init_vcpu_events(void); + =20 #include "trace/control-internal.h" =20 diff --git a/trace/event-internal.h b/trace/event-internal.h index 258bcde..b785017 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; =20 =20 diff --git a/trace/qmp.c b/trace/qmp.c index be99496..8ee9b70 100644 --- a/trace/qmp.c +++ b/trace/qmp.c @@ -12,64 +12,152 @@ #include "trace/control.h" =20 =20 -TraceEventInfoList *qmp_trace_event_get_state(const char *name, Error **= errp) +static bool get_cpu_state(bool has_index, int index, CPUState **cpu, Err= or **errp) +{ + if (has_index) { + *cpu =3D qemu_get_cpu(index); + if (*cpu =3D=3D NULL) { + error_setg(errp, "invalid vCPU index %u", index); + return false; + } + } else { + *cpu =3D NULL; + } + return true; +} + +TraceEventInfoList *qmp_trace_event_get_state(const char *name, + bool has_vcpu, int64_t vcp= u, + Error **errp) { TraceEventInfoList *events =3D NULL; - bool found =3D false; TraceEvent *ev; + bool is_pattern =3D trace_event_is_pattern(name); + CPUState *cpu; + + if (!get_cpu_state(has_vcpu, vcpu, &cpu, errp)) { + return NULL; + } =20 ev =3D NULL; while ((ev =3D trace_event_pattern(name, ev)) !=3D NULL) { - TraceEventInfoList *elem =3D g_new(TraceEventInfoList, 1); + TraceEventInfoList *elem; + bool is_vcpu =3D trace_event_get_cpu_id(ev) !=3D TRACE_CPU_EVENT= _COUNT; + if (has_vcpu && !is_vcpu) { + if (!is_pattern) { + error_setg(errp, "event \"%s\" is not vCPU-specific", na= me); + } + /* else: ignore */ + continue; + } + + elem =3D g_new(TraceEventInfoList, 1); elem->value =3D g_new(TraceEventInfo, 1); - elem->value->vcpu =3D trace_event_get_cpu_id(ev) !=3D TRACE_CPU_= EVENT_COUNT; + elem->value->vcpu =3D is_vcpu; elem->value->name =3D g_strdup(trace_event_get_name(ev)); + if (!trace_event_get_state_static(ev)) { elem->value->state =3D TRACE_EVENT_STATE_UNAVAILABLE; - } else if (!trace_event_get_state_dynamic(ev)) { - elem->value->state =3D TRACE_EVENT_STATE_DISABLED; } else { - elem->value->state =3D TRACE_EVENT_STATE_ENABLED; + if (has_vcpu) { + if (is_vcpu) { + if (trace_event_get_cpu_state_dynamic(cpu, ev)) { + elem->value->state =3D TRACE_EVENT_STATE_ENABLED= ; + } else { + elem->value->state =3D TRACE_EVENT_STATE_DISABLE= D; + } + } + /* else: already handled above */ + } else { + if (trace_event_get_state_dynamic(ev)) { + elem->value->state =3D TRACE_EVENT_STATE_ENABLED; + } else { + elem->value->state =3D TRACE_EVENT_STATE_DISABLED; + } + } } elem->next =3D events; events =3D elem; - found =3D true; } =20 - if (!found && !trace_event_is_pattern(name)) { + if (events =3D=3D NULL && !is_pattern) { error_setg(errp, "unknown event \"%s\"", name); } =20 return events; } =20 + +static void check_events_are_dynamic(const char *name, bool per_cpu, + bool *found, bool error_check, + bool *error_found, Error **errp) +{ + TraceEvent *ev =3D NULL; + *found =3D false; + *error_found =3D false; + while ((ev =3D trace_event_pattern(name, ev)) !=3D NULL) { + if (per_cpu && trace_event_get_cpu_id(ev) =3D=3D TRACE_CPU_EVENT= _COUNT) { + if (error_check) { + Error *local_err =3D NULL; + error_setg(&local_err, "event \"%s\" is not vCPU-specifi= c", + trace_event_get_name(ev)); + error_propagate(errp, local_err); + *error_found =3D true; + } + continue; + } + if (!trace_event_get_state_static(ev)) { + if (error_check) { + Error *local_err =3D NULL; + error_setg(&local_err, "cannot set dynamic tracing state= for \"%s\"", + trace_event_get_name(ev)); + error_propagate(errp, local_err); + *error_found =3D true; + } + continue; + } + *found =3D 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 =3D false; - TraceEvent *ev; + bool error, found; + TraceEvent *ev =3D NULL; + CPUState *cpu; + + if (!get_cpu_state(has_vcpu, vcpu, &cpu, errp)) { + return; + } =20 /* Check all selected events are dynamic */ - ev =3D NULL; - while ((ev =3D trace_event_pattern(name, ev)) !=3D NULL) { - found =3D 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_unavaila= ble), + &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; } =20 /* Apply changes */ ev =3D NULL; while ((ev =3D trace_event_pattern(name, ev)) !=3D NULL) { - if (trace_event_get_state_static(ev)) { + if (!trace_event_get_state_static(ev) || + (has_vcpu && trace_event_get_cpu_id(ev) =3D=3D TRACE_CPU_EVE= NT_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 2395977..dab44ad 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 =3D 1; tcg_ctx.tb_ctx.tb_phys_hash =3D NULL; tb_caches_apply(); + trace_init_vcpu_tb_caches(); } =20 /* Encode VAL as a signed leb128 sequence at P. diff --git a/vl.c b/vl.c index b7a083e..dcba749 100644 --- a/vl.c +++ b/vl.c @@ -4659,6 +4659,7 @@ int main(int argc, char **argv, char **envp) } } =20 + trace_init_vcpu_events(); main_loop(); replay_disable_events(); =20