diff options
Diffstat (limited to 'trace/qmp.c')
-rw-r--r-- | trace/qmp.c | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/trace/qmp.c b/trace/qmp.c new file mode 100644 index 000000000..3b4f4702b --- /dev/null +++ b/trace/qmp.c @@ -0,0 +1,168 @@ +/* + * QMP commands for tracing events. + * + * Copyright (C) 2014-2016 LluĂs Vilanova <vilanova@ac.upc.edu> + * + * 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 "qemu/osdep.h" +#include "qapi/error.h" +#include "qapi/qapi-commands-trace.h" +#include "control-vcpu.h" + + +static CPUState *get_cpu(bool has_vcpu, int vcpu, Error **errp) +{ + if (has_vcpu) { + CPUState *cpu = qemu_get_cpu(vcpu); + if (cpu == NULL) { + error_setg(errp, "invalid vCPU index %u", vcpu); + } + return cpu; + } else { + return NULL; + } +} + +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_is_vcpu(ev)) { + 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 */ + TraceEventIter iter; + TraceEvent *ev; + trace_event_iter_init_pattern(&iter, name); + while ((ev = trace_event_iter_next(&iter)) != 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) +{ + Error *err = NULL; + TraceEventInfoList *events = NULL; + TraceEventIter iter; + TraceEvent *ev; + bool is_pattern = trace_event_is_pattern(name); + CPUState *cpu; + + /* Check provided vcpu */ + cpu = get_cpu(has_vcpu, vcpu, &err); + if (err) { + error_propagate(errp, err); + return NULL; + } + + /* Check events */ + if (!check_events(has_vcpu, true, is_pattern, name, errp)) { + return NULL; + } + + /* Get states (all errors checked above) */ + trace_event_iter_init_pattern(&iter, name); + while ((ev = trace_event_iter_next(&iter)) != NULL) { + TraceEventInfo *value; + bool is_vcpu = trace_event_is_vcpu(ev); + if (has_vcpu && !is_vcpu) { + continue; + } + + value = g_new(TraceEventInfo, 1); + value->vcpu = is_vcpu; + value->name = g_strdup(trace_event_get_name(ev)); + + if (!trace_event_get_state_static(ev)) { + value->state = TRACE_EVENT_STATE_UNAVAILABLE; + } else { + if (has_vcpu) { + if (is_vcpu) { + if (trace_event_get_vcpu_state_dynamic(cpu, ev)) { + value->state = TRACE_EVENT_STATE_ENABLED; + } else { + value->state = TRACE_EVENT_STATE_DISABLED; + } + } + /* else: already skipped above */ + } else { + if (trace_event_get_state_dynamic(ev)) { + value->state = TRACE_EVENT_STATE_ENABLED; + } else { + value->state = TRACE_EVENT_STATE_DISABLED; + } + } + } + QAPI_LIST_PREPEND(events, value); + } + + return events; +} + +void qmp_trace_event_set_state(const char *name, bool enable, + bool has_ignore_unavailable, bool ignore_unavailable, + bool has_vcpu, int64_t vcpu, + Error **errp) +{ + Error *err = NULL; + TraceEventIter iter; + TraceEvent *ev; + bool is_pattern = trace_event_is_pattern(name); + CPUState *cpu; + + /* Check provided vcpu */ + cpu = get_cpu(has_vcpu, vcpu, &err); + if (err) { + error_propagate(errp, err); + return; + } + + /* Check events */ + if (!check_events(has_vcpu, has_ignore_unavailable && ignore_unavailable, + is_pattern, name, errp)) { + return; + } + + /* Apply changes (all errors checked above) */ + trace_event_iter_init_pattern(&iter, name); + while ((ev = trace_event_iter_next(&iter)) != NULL) { + if (!trace_event_get_state_static(ev) || + (has_vcpu && !trace_event_is_vcpu(ev))) { + continue; + } + if (has_vcpu) { + trace_event_set_vcpu_state_dynamic(cpu, ev, enable); + } else { + trace_event_set_state_dynamic(ev, enable); + } + } +} |