11dde0f48SLluís Vilanova /* 21dde0f48SLluís Vilanova * QMP commands for tracing events. 31dde0f48SLluís Vilanova * 477e2b172SLluís Vilanova * Copyright (C) 2014-2016 Lluís Vilanova <vilanova@ac.upc.edu> 51dde0f48SLluís Vilanova * 61dde0f48SLluís Vilanova * This work is licensed under the terms of the GNU GPL, version 2 or later. 71dde0f48SLluís Vilanova * See the COPYING file in the top-level directory. 81dde0f48SLluís Vilanova */ 91dde0f48SLluís Vilanova 10d38ea87aSPeter Maydell #include "qemu/osdep.h" 11*e688df6bSMarkus Armbruster #include "qapi/error.h" 121dde0f48SLluís Vilanova #include "qmp-commands.h" 131dde0f48SLluís Vilanova #include "trace/control.h" 141dde0f48SLluís Vilanova 151dde0f48SLluís Vilanova 1677e2b172SLluís Vilanova static CPUState *get_cpu(bool has_vcpu, int vcpu, Error **errp) 171dde0f48SLluís Vilanova { 1877e2b172SLluís Vilanova if (has_vcpu) { 1977e2b172SLluís Vilanova CPUState *cpu = qemu_get_cpu(vcpu); 2077e2b172SLluís Vilanova if (cpu == NULL) { 2177e2b172SLluís Vilanova error_setg(errp, "invalid vCPU index %u", vcpu); 2277e2b172SLluís Vilanova } 2377e2b172SLluís Vilanova return cpu; 2477e2b172SLluís Vilanova } else { 2577e2b172SLluís Vilanova return NULL; 2677e2b172SLluís Vilanova } 2777e2b172SLluís Vilanova } 281dde0f48SLluís Vilanova 2977e2b172SLluís Vilanova static bool check_events(bool has_vcpu, bool ignore_unavailable, bool is_pattern, 3077e2b172SLluís Vilanova const char *name, Error **errp) 3177e2b172SLluís Vilanova { 3277e2b172SLluís Vilanova if (!is_pattern) { 3377e2b172SLluís Vilanova TraceEvent *ev = trace_event_name(name); 3477e2b172SLluís Vilanova 3577e2b172SLluís Vilanova /* error for non-existing event */ 3677e2b172SLluís Vilanova if (ev == NULL) { 3777e2b172SLluís Vilanova error_setg(errp, "unknown event \"%s\"", name); 3877e2b172SLluís Vilanova return false; 3977e2b172SLluís Vilanova } 4077e2b172SLluís Vilanova 4177e2b172SLluís Vilanova /* error for non-vcpu event */ 4277e2b172SLluís Vilanova if (has_vcpu && !trace_event_is_vcpu(ev)) { 4377e2b172SLluís Vilanova error_setg(errp, "event \"%s\" is not vCPU-specific", name); 4477e2b172SLluís Vilanova return false; 4577e2b172SLluís Vilanova } 4677e2b172SLluís Vilanova 4777e2b172SLluís Vilanova /* error for unavailable event */ 4877e2b172SLluís Vilanova if (!ignore_unavailable && !trace_event_get_state_static(ev)) { 4977e2b172SLluís Vilanova error_setg(errp, "event \"%s\" is disabled", name); 5077e2b172SLluís Vilanova return false; 5177e2b172SLluís Vilanova } 5277e2b172SLluís Vilanova 5377e2b172SLluís Vilanova return true; 5477e2b172SLluís Vilanova } else { 5577e2b172SLluís Vilanova /* error for unavailable events */ 560d4e995cSDaniel P. Berrange TraceEventIter iter; 570d4e995cSDaniel P. Berrange TraceEvent *ev; 580d4e995cSDaniel P. Berrange trace_event_iter_init(&iter, name); 590d4e995cSDaniel P. Berrange while ((ev = trace_event_iter_next(&iter)) != NULL) { 6077e2b172SLluís Vilanova if (!ignore_unavailable && !trace_event_get_state_static(ev)) { 6177e2b172SLluís Vilanova error_setg(errp, "event \"%s\" is disabled", trace_event_get_name(ev)); 6277e2b172SLluís Vilanova return false; 6377e2b172SLluís Vilanova } 6477e2b172SLluís Vilanova } 6577e2b172SLluís Vilanova return true; 6677e2b172SLluís Vilanova } 6777e2b172SLluís Vilanova } 6877e2b172SLluís Vilanova 6977e2b172SLluís Vilanova TraceEventInfoList *qmp_trace_event_get_state(const char *name, 7077e2b172SLluís Vilanova bool has_vcpu, int64_t vcpu, 7177e2b172SLluís Vilanova Error **errp) 7277e2b172SLluís Vilanova { 7377e2b172SLluís Vilanova Error *err = NULL; 7477e2b172SLluís Vilanova TraceEventInfoList *events = NULL; 750d4e995cSDaniel P. Berrange TraceEventIter iter; 7677e2b172SLluís Vilanova TraceEvent *ev; 7777e2b172SLluís Vilanova bool is_pattern = trace_event_is_pattern(name); 7877e2b172SLluís Vilanova CPUState *cpu; 7977e2b172SLluís Vilanova 8077e2b172SLluís Vilanova /* Check provided vcpu */ 8177e2b172SLluís Vilanova cpu = get_cpu(has_vcpu, vcpu, &err); 8277e2b172SLluís Vilanova if (err) { 8377e2b172SLluís Vilanova error_propagate(errp, err); 8477e2b172SLluís Vilanova return NULL; 8577e2b172SLluís Vilanova } 8677e2b172SLluís Vilanova 8777e2b172SLluís Vilanova /* Check events */ 8877e2b172SLluís Vilanova if (!check_events(has_vcpu, true, is_pattern, name, errp)) { 8977e2b172SLluís Vilanova return NULL; 9077e2b172SLluís Vilanova } 9177e2b172SLluís Vilanova 9277e2b172SLluís Vilanova /* Get states (all errors checked above) */ 930d4e995cSDaniel P. Berrange trace_event_iter_init(&iter, name); 940d4e995cSDaniel P. Berrange while ((ev = trace_event_iter_next(&iter)) != NULL) { 9577e2b172SLluís Vilanova TraceEventInfoList *elem; 9677e2b172SLluís Vilanova bool is_vcpu = trace_event_is_vcpu(ev); 9777e2b172SLluís Vilanova if (has_vcpu && !is_vcpu) { 9877e2b172SLluís Vilanova continue; 9977e2b172SLluís Vilanova } 10077e2b172SLluís Vilanova 10177e2b172SLluís Vilanova elem = g_new(TraceEventInfoList, 1); 1021dde0f48SLluís Vilanova elem->value = g_new(TraceEventInfo, 1); 10377e2b172SLluís Vilanova elem->value->vcpu = is_vcpu; 1041dde0f48SLluís Vilanova elem->value->name = g_strdup(trace_event_get_name(ev)); 10577e2b172SLluís Vilanova 1061dde0f48SLluís Vilanova if (!trace_event_get_state_static(ev)) { 1071dde0f48SLluís Vilanova elem->value->state = TRACE_EVENT_STATE_UNAVAILABLE; 1081dde0f48SLluís Vilanova } else { 10977e2b172SLluís Vilanova if (has_vcpu) { 11077e2b172SLluís Vilanova if (is_vcpu) { 11177e2b172SLluís Vilanova if (trace_event_get_vcpu_state_dynamic(cpu, ev)) { 1121dde0f48SLluís Vilanova elem->value->state = TRACE_EVENT_STATE_ENABLED; 11377e2b172SLluís Vilanova } else { 11477e2b172SLluís Vilanova elem->value->state = TRACE_EVENT_STATE_DISABLED; 11577e2b172SLluís Vilanova } 11677e2b172SLluís Vilanova } 11777e2b172SLluís Vilanova /* else: already skipped above */ 11877e2b172SLluís Vilanova } else { 11977e2b172SLluís Vilanova if (trace_event_get_state_dynamic(ev)) { 12077e2b172SLluís Vilanova elem->value->state = TRACE_EVENT_STATE_ENABLED; 12177e2b172SLluís Vilanova } else { 12277e2b172SLluís Vilanova elem->value->state = TRACE_EVENT_STATE_DISABLED; 12377e2b172SLluís Vilanova } 12477e2b172SLluís Vilanova } 1251dde0f48SLluís Vilanova } 1261dde0f48SLluís Vilanova elem->next = events; 1271dde0f48SLluís Vilanova events = elem; 1281dde0f48SLluís Vilanova } 1291dde0f48SLluís Vilanova 1301dde0f48SLluís Vilanova return events; 1311dde0f48SLluís Vilanova } 1321dde0f48SLluís Vilanova 1331dde0f48SLluís Vilanova void qmp_trace_event_set_state(const char *name, bool enable, 13477e2b172SLluís Vilanova bool has_ignore_unavailable, bool ignore_unavailable, 13577e2b172SLluís Vilanova bool has_vcpu, int64_t vcpu, 13677e2b172SLluís Vilanova Error **errp) 1371dde0f48SLluís Vilanova { 13877e2b172SLluís Vilanova Error *err = NULL; 1390d4e995cSDaniel P. Berrange TraceEventIter iter; 1401dde0f48SLluís Vilanova TraceEvent *ev; 14177e2b172SLluís Vilanova bool is_pattern = trace_event_is_pattern(name); 14277e2b172SLluís Vilanova CPUState *cpu; 1431dde0f48SLluís Vilanova 14477e2b172SLluís Vilanova /* Check provided vcpu */ 14577e2b172SLluís Vilanova cpu = get_cpu(has_vcpu, vcpu, &err); 14677e2b172SLluís Vilanova if (err) { 14777e2b172SLluís Vilanova error_propagate(errp, err); 1481dde0f48SLluís Vilanova return; 1491dde0f48SLluís Vilanova } 1501dde0f48SLluís Vilanova 15177e2b172SLluís Vilanova /* Check events */ 15277e2b172SLluís Vilanova if (!check_events(has_vcpu, has_ignore_unavailable && ignore_unavailable, 15377e2b172SLluís Vilanova is_pattern, name, errp)) { 15477e2b172SLluís Vilanova return; 15577e2b172SLluís Vilanova } 15677e2b172SLluís Vilanova 15777e2b172SLluís Vilanova /* Apply changes (all errors checked above) */ 1580d4e995cSDaniel P. Berrange trace_event_iter_init(&iter, name); 1590d4e995cSDaniel P. Berrange while ((ev = trace_event_iter_next(&iter)) != NULL) { 16077e2b172SLluís Vilanova if (!trace_event_get_state_static(ev) || 16177e2b172SLluís Vilanova (has_vcpu && !trace_event_is_vcpu(ev))) { 16277e2b172SLluís Vilanova continue; 16377e2b172SLluís Vilanova } 16477e2b172SLluís Vilanova if (has_vcpu) { 16577e2b172SLluís Vilanova trace_event_set_vcpu_state_dynamic(cpu, ev, enable); 16677e2b172SLluís Vilanova } else { 1671dde0f48SLluís Vilanova trace_event_set_state_dynamic(ev, enable); 1681dde0f48SLluís Vilanova } 1691dde0f48SLluís Vilanova } 1701dde0f48SLluís Vilanova } 171