11dde0f48SLluís Vilanova /* 21dde0f48SLluís Vilanova * QMP commands for tracing events. 31dde0f48SLluís Vilanova * 4*77e2b172SLluí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" 111dde0f48SLluís Vilanova #include "qmp-commands.h" 121dde0f48SLluís Vilanova #include "trace/control.h" 131dde0f48SLluís Vilanova 141dde0f48SLluís Vilanova 15*77e2b172SLluís Vilanova static CPUState *get_cpu(bool has_vcpu, int vcpu, Error **errp) 161dde0f48SLluís Vilanova { 17*77e2b172SLluís Vilanova if (has_vcpu) { 18*77e2b172SLluís Vilanova CPUState *cpu = qemu_get_cpu(vcpu); 19*77e2b172SLluís Vilanova if (cpu == NULL) { 20*77e2b172SLluís Vilanova error_setg(errp, "invalid vCPU index %u", vcpu); 21*77e2b172SLluís Vilanova } 22*77e2b172SLluís Vilanova return cpu; 23*77e2b172SLluís Vilanova } else { 24*77e2b172SLluís Vilanova return NULL; 25*77e2b172SLluís Vilanova } 26*77e2b172SLluís Vilanova } 271dde0f48SLluís Vilanova 28*77e2b172SLluís Vilanova static bool check_events(bool has_vcpu, bool ignore_unavailable, bool is_pattern, 29*77e2b172SLluís Vilanova const char *name, Error **errp) 30*77e2b172SLluís Vilanova { 31*77e2b172SLluís Vilanova if (!is_pattern) { 32*77e2b172SLluís Vilanova TraceEvent *ev = trace_event_name(name); 33*77e2b172SLluís Vilanova 34*77e2b172SLluís Vilanova /* error for non-existing event */ 35*77e2b172SLluís Vilanova if (ev == NULL) { 36*77e2b172SLluís Vilanova error_setg(errp, "unknown event \"%s\"", name); 37*77e2b172SLluís Vilanova return false; 38*77e2b172SLluís Vilanova } 39*77e2b172SLluís Vilanova 40*77e2b172SLluís Vilanova /* error for non-vcpu event */ 41*77e2b172SLluís Vilanova if (has_vcpu && !trace_event_is_vcpu(ev)) { 42*77e2b172SLluís Vilanova error_setg(errp, "event \"%s\" is not vCPU-specific", name); 43*77e2b172SLluís Vilanova return false; 44*77e2b172SLluís Vilanova } 45*77e2b172SLluís Vilanova 46*77e2b172SLluís Vilanova /* error for unavailable event */ 47*77e2b172SLluís Vilanova if (!ignore_unavailable && !trace_event_get_state_static(ev)) { 48*77e2b172SLluís Vilanova error_setg(errp, "event \"%s\" is disabled", name); 49*77e2b172SLluís Vilanova return false; 50*77e2b172SLluís Vilanova } 51*77e2b172SLluís Vilanova 52*77e2b172SLluís Vilanova return true; 53*77e2b172SLluís Vilanova } else { 54*77e2b172SLluís Vilanova /* error for unavailable events */ 55*77e2b172SLluís Vilanova TraceEvent *ev = NULL; 56*77e2b172SLluís Vilanova while ((ev = trace_event_pattern(name, ev)) != NULL) { 57*77e2b172SLluís Vilanova if (!ignore_unavailable && !trace_event_get_state_static(ev)) { 58*77e2b172SLluís Vilanova error_setg(errp, "event \"%s\" is disabled", trace_event_get_name(ev)); 59*77e2b172SLluís Vilanova return false; 60*77e2b172SLluís Vilanova } 61*77e2b172SLluís Vilanova } 62*77e2b172SLluís Vilanova return true; 63*77e2b172SLluís Vilanova } 64*77e2b172SLluís Vilanova } 65*77e2b172SLluís Vilanova 66*77e2b172SLluís Vilanova TraceEventInfoList *qmp_trace_event_get_state(const char *name, 67*77e2b172SLluís Vilanova bool has_vcpu, int64_t vcpu, 68*77e2b172SLluís Vilanova Error **errp) 69*77e2b172SLluís Vilanova { 70*77e2b172SLluís Vilanova Error *err = NULL; 71*77e2b172SLluís Vilanova TraceEventInfoList *events = NULL; 72*77e2b172SLluís Vilanova TraceEvent *ev; 73*77e2b172SLluís Vilanova bool is_pattern = trace_event_is_pattern(name); 74*77e2b172SLluís Vilanova CPUState *cpu; 75*77e2b172SLluís Vilanova 76*77e2b172SLluís Vilanova /* Check provided vcpu */ 77*77e2b172SLluís Vilanova cpu = get_cpu(has_vcpu, vcpu, &err); 78*77e2b172SLluís Vilanova if (err) { 79*77e2b172SLluís Vilanova error_propagate(errp, err); 80*77e2b172SLluís Vilanova return NULL; 81*77e2b172SLluís Vilanova } 82*77e2b172SLluís Vilanova 83*77e2b172SLluís Vilanova /* Check events */ 84*77e2b172SLluís Vilanova if (!check_events(has_vcpu, true, is_pattern, name, errp)) { 85*77e2b172SLluís Vilanova return NULL; 86*77e2b172SLluís Vilanova } 87*77e2b172SLluís Vilanova 88*77e2b172SLluís Vilanova /* Get states (all errors checked above) */ 891dde0f48SLluís Vilanova ev = NULL; 901dde0f48SLluís Vilanova while ((ev = trace_event_pattern(name, ev)) != NULL) { 91*77e2b172SLluís Vilanova TraceEventInfoList *elem; 92*77e2b172SLluís Vilanova bool is_vcpu = trace_event_is_vcpu(ev); 93*77e2b172SLluís Vilanova if (has_vcpu && !is_vcpu) { 94*77e2b172SLluís Vilanova continue; 95*77e2b172SLluís Vilanova } 96*77e2b172SLluís Vilanova 97*77e2b172SLluís Vilanova elem = g_new(TraceEventInfoList, 1); 981dde0f48SLluís Vilanova elem->value = g_new(TraceEventInfo, 1); 99*77e2b172SLluís Vilanova elem->value->vcpu = is_vcpu; 1001dde0f48SLluís Vilanova elem->value->name = g_strdup(trace_event_get_name(ev)); 101*77e2b172SLluís Vilanova 1021dde0f48SLluís Vilanova if (!trace_event_get_state_static(ev)) { 1031dde0f48SLluís Vilanova elem->value->state = TRACE_EVENT_STATE_UNAVAILABLE; 1041dde0f48SLluís Vilanova } else { 105*77e2b172SLluís Vilanova if (has_vcpu) { 106*77e2b172SLluís Vilanova if (is_vcpu) { 107*77e2b172SLluís Vilanova if (trace_event_get_vcpu_state_dynamic(cpu, ev)) { 1081dde0f48SLluís Vilanova elem->value->state = TRACE_EVENT_STATE_ENABLED; 109*77e2b172SLluís Vilanova } else { 110*77e2b172SLluís Vilanova elem->value->state = TRACE_EVENT_STATE_DISABLED; 111*77e2b172SLluís Vilanova } 112*77e2b172SLluís Vilanova } 113*77e2b172SLluís Vilanova /* else: already skipped above */ 114*77e2b172SLluís Vilanova } else { 115*77e2b172SLluís Vilanova if (trace_event_get_state_dynamic(ev)) { 116*77e2b172SLluís Vilanova elem->value->state = TRACE_EVENT_STATE_ENABLED; 117*77e2b172SLluís Vilanova } else { 118*77e2b172SLluís Vilanova elem->value->state = TRACE_EVENT_STATE_DISABLED; 119*77e2b172SLluís Vilanova } 120*77e2b172SLluís Vilanova } 1211dde0f48SLluís Vilanova } 1221dde0f48SLluís Vilanova elem->next = events; 1231dde0f48SLluís Vilanova events = elem; 1241dde0f48SLluís Vilanova } 1251dde0f48SLluís Vilanova 1261dde0f48SLluís Vilanova return events; 1271dde0f48SLluís Vilanova } 1281dde0f48SLluís Vilanova 1291dde0f48SLluís Vilanova void qmp_trace_event_set_state(const char *name, bool enable, 130*77e2b172SLluís Vilanova bool has_ignore_unavailable, bool ignore_unavailable, 131*77e2b172SLluís Vilanova bool has_vcpu, int64_t vcpu, 132*77e2b172SLluís Vilanova Error **errp) 1331dde0f48SLluís Vilanova { 134*77e2b172SLluís Vilanova Error *err = NULL; 1351dde0f48SLluís Vilanova TraceEvent *ev; 136*77e2b172SLluís Vilanova bool is_pattern = trace_event_is_pattern(name); 137*77e2b172SLluís Vilanova CPUState *cpu; 1381dde0f48SLluís Vilanova 139*77e2b172SLluís Vilanova /* Check provided vcpu */ 140*77e2b172SLluís Vilanova cpu = get_cpu(has_vcpu, vcpu, &err); 141*77e2b172SLluís Vilanova if (err) { 142*77e2b172SLluís Vilanova error_propagate(errp, err); 1431dde0f48SLluís Vilanova return; 1441dde0f48SLluís Vilanova } 1451dde0f48SLluís Vilanova 146*77e2b172SLluís Vilanova /* Check events */ 147*77e2b172SLluís Vilanova if (!check_events(has_vcpu, has_ignore_unavailable && ignore_unavailable, 148*77e2b172SLluís Vilanova is_pattern, name, errp)) { 149*77e2b172SLluís Vilanova return; 150*77e2b172SLluís Vilanova } 151*77e2b172SLluís Vilanova 152*77e2b172SLluís Vilanova /* Apply changes (all errors checked above) */ 1531dde0f48SLluís Vilanova ev = NULL; 1541dde0f48SLluís Vilanova while ((ev = trace_event_pattern(name, ev)) != NULL) { 155*77e2b172SLluís Vilanova if (!trace_event_get_state_static(ev) || 156*77e2b172SLluís Vilanova (has_vcpu && !trace_event_is_vcpu(ev))) { 157*77e2b172SLluís Vilanova continue; 158*77e2b172SLluís Vilanova } 159*77e2b172SLluís Vilanova if (has_vcpu) { 160*77e2b172SLluís Vilanova trace_event_set_vcpu_state_dynamic(cpu, ev, enable); 161*77e2b172SLluís Vilanova } else { 1621dde0f48SLluís Vilanova trace_event_set_state_dynamic(ev, enable); 1631dde0f48SLluís Vilanova } 1641dde0f48SLluís Vilanova } 1651dde0f48SLluís Vilanova } 166