1 /* 2 * QMP commands for tracing events. 3 * 4 * Copyright (C) 2014-2016 Lluís Vilanova <vilanova@ac.upc.edu> 5 * 6 * This work is licensed under the terms of the GNU GPL, version 2 or later. 7 * See the COPYING file in the top-level directory. 8 */ 9 10 #include "qemu/osdep.h" 11 #include "qmp-commands.h" 12 #include "trace/control.h" 13 14 15 static CPUState *get_cpu(bool has_vcpu, int vcpu, Error **errp) 16 { 17 if (has_vcpu) { 18 CPUState *cpu = qemu_get_cpu(vcpu); 19 if (cpu == NULL) { 20 error_setg(errp, "invalid vCPU index %u", vcpu); 21 } 22 return cpu; 23 } else { 24 return NULL; 25 } 26 } 27 28 static bool check_events(bool has_vcpu, bool ignore_unavailable, bool is_pattern, 29 const char *name, Error **errp) 30 { 31 if (!is_pattern) { 32 TraceEvent *ev = trace_event_name(name); 33 34 /* error for non-existing event */ 35 if (ev == NULL) { 36 error_setg(errp, "unknown event \"%s\"", name); 37 return false; 38 } 39 40 /* error for non-vcpu event */ 41 if (has_vcpu && !trace_event_is_vcpu(ev)) { 42 error_setg(errp, "event \"%s\" is not vCPU-specific", name); 43 return false; 44 } 45 46 /* error for unavailable event */ 47 if (!ignore_unavailable && !trace_event_get_state_static(ev)) { 48 error_setg(errp, "event \"%s\" is disabled", name); 49 return false; 50 } 51 52 return true; 53 } else { 54 /* error for unavailable events */ 55 TraceEvent *ev = NULL; 56 while ((ev = trace_event_pattern(name, ev)) != NULL) { 57 if (!ignore_unavailable && !trace_event_get_state_static(ev)) { 58 error_setg(errp, "event \"%s\" is disabled", trace_event_get_name(ev)); 59 return false; 60 } 61 } 62 return true; 63 } 64 } 65 66 TraceEventInfoList *qmp_trace_event_get_state(const char *name, 67 bool has_vcpu, int64_t vcpu, 68 Error **errp) 69 { 70 Error *err = NULL; 71 TraceEventInfoList *events = NULL; 72 TraceEvent *ev; 73 bool is_pattern = trace_event_is_pattern(name); 74 CPUState *cpu; 75 76 /* Check provided vcpu */ 77 cpu = get_cpu(has_vcpu, vcpu, &err); 78 if (err) { 79 error_propagate(errp, err); 80 return NULL; 81 } 82 83 /* Check events */ 84 if (!check_events(has_vcpu, true, is_pattern, name, errp)) { 85 return NULL; 86 } 87 88 /* Get states (all errors checked above) */ 89 ev = NULL; 90 while ((ev = trace_event_pattern(name, ev)) != NULL) { 91 TraceEventInfoList *elem; 92 bool is_vcpu = trace_event_is_vcpu(ev); 93 if (has_vcpu && !is_vcpu) { 94 continue; 95 } 96 97 elem = g_new(TraceEventInfoList, 1); 98 elem->value = g_new(TraceEventInfo, 1); 99 elem->value->vcpu = is_vcpu; 100 elem->value->name = g_strdup(trace_event_get_name(ev)); 101 102 if (!trace_event_get_state_static(ev)) { 103 elem->value->state = TRACE_EVENT_STATE_UNAVAILABLE; 104 } else { 105 if (has_vcpu) { 106 if (is_vcpu) { 107 if (trace_event_get_vcpu_state_dynamic(cpu, ev)) { 108 elem->value->state = TRACE_EVENT_STATE_ENABLED; 109 } else { 110 elem->value->state = TRACE_EVENT_STATE_DISABLED; 111 } 112 } 113 /* else: already skipped above */ 114 } else { 115 if (trace_event_get_state_dynamic(ev)) { 116 elem->value->state = TRACE_EVENT_STATE_ENABLED; 117 } else { 118 elem->value->state = TRACE_EVENT_STATE_DISABLED; 119 } 120 } 121 } 122 elem->next = events; 123 events = elem; 124 } 125 126 return events; 127 } 128 129 void qmp_trace_event_set_state(const char *name, bool enable, 130 bool has_ignore_unavailable, bool ignore_unavailable, 131 bool has_vcpu, int64_t vcpu, 132 Error **errp) 133 { 134 Error *err = NULL; 135 TraceEvent *ev; 136 bool is_pattern = trace_event_is_pattern(name); 137 CPUState *cpu; 138 139 /* Check provided vcpu */ 140 cpu = get_cpu(has_vcpu, vcpu, &err); 141 if (err) { 142 error_propagate(errp, err); 143 return; 144 } 145 146 /* Check events */ 147 if (!check_events(has_vcpu, has_ignore_unavailable && ignore_unavailable, 148 is_pattern, name, errp)) { 149 return; 150 } 151 152 /* Apply changes (all errors checked above) */ 153 ev = NULL; 154 while ((ev = trace_event_pattern(name, ev)) != NULL) { 155 if (!trace_event_get_state_static(ev) || 156 (has_vcpu && !trace_event_is_vcpu(ev))) { 157 continue; 158 } 159 if (has_vcpu) { 160 trace_event_set_vcpu_state_dynamic(cpu, ev, enable); 161 } else { 162 trace_event_set_state_dynamic(ev, enable); 163 } 164 } 165 } 166