#include "qemu/osdep.h"
#include "trace/control.h"
#include "qemu/help_option.h"
+#include "qemu/option.h"
#ifdef CONFIG_TRACE_SIMPLE
#include "trace/simple.h"
#endif
#include "qemu/error-report.h"
#include "qemu/config-file.h"
#include "monitor/monitor.h"
+#include "trace-root.h"
int trace_events_enabled_count;
-/*
- * Interpretation depends on wether the event has the 'vcpu' property:
- * - false: Boolean value indicating whether the event is active.
- * - true : Integral counting the number of vCPUs that have this event enabled.
- */
-uint16_t trace_events_dstate[TRACE_EVENT_COUNT];
+
+typedef struct TraceEventGroup {
+ TraceEvent **events;
+} TraceEventGroup;
+
+static TraceEventGroup *event_groups;
+static size_t nevent_groups;
+static uint32_t next_id;
+static uint32_t next_vcpu_id;
QemuOptsList qemu_trace_opts = {
.name = "trace",
};
+void trace_event_register_group(TraceEvent **events)
+{
+ size_t i;
+ for (i = 0; events[i] != NULL; i++) {
+ events[i]->id = next_id++;
+ if (events[i]->vcpu_id == TRACE_VCPU_EVENT_NONE) {
+ continue;
+ }
+
+ if (likely(next_vcpu_id < CPU_TRACE_DSTATE_MAX_EVENTS)) {
+ events[i]->vcpu_id = next_vcpu_id++;
+ } else {
+ warn_report("too many vcpu trace events; dropping '%s'",
+ events[i]->name);
+ }
+ }
+ event_groups = g_renew(TraceEventGroup, event_groups, nevent_groups + 1);
+ event_groups[nevent_groups].events = events;
+ nevent_groups++;
+}
+
+
TraceEvent *trace_event_name(const char *name)
{
assert(name != NULL);
void trace_event_iter_init(TraceEventIter *iter, const char *pattern)
{
iter->event = 0;
+ iter->group = 0;
iter->pattern = pattern;
}
TraceEvent *trace_event_iter_next(TraceEventIter *iter)
{
- while (iter->event < TRACE_EVENT_COUNT) {
- TraceEvent *ev = &(trace_events[iter->event]);
+ while (iter->group < nevent_groups &&
+ event_groups[iter->group].events[iter->event] != NULL) {
+ TraceEvent *ev = event_groups[iter->group].events[iter->event];
iter->event++;
+ if (event_groups[iter->group].events[iter->event] == NULL) {
+ iter->event = 0;
+ iter->group++;
+ }
if (!iter->pattern ||
pattern_glob(iter->pattern,
trace_event_get_name(ev))) {
while ((ev = trace_event_iter_next(&iter)) != NULL) {
if (!trace_event_get_state_static(ev)) {
if (!is_pattern) {
- error_report("WARNING: trace event '%s' is not traceable",
- line_ptr);
+ warn_report("trace event '%s' is not traceable",
+ line_ptr);
return;
}
continue;
}
if (!is_pattern) {
- error_report("WARNING: trace event '%s' does not exist",
- line_ptr);
+ warn_report("trace event '%s' does not exist",
+ line_ptr);
}
}
#ifdef CONFIG_TRACE_SIMPLE
st_set_trace_file(file);
#elif defined CONFIG_TRACE_LOG
- /* If both the simple and the log backends are enabled, "-trace file"
+ /* If both the simple and the log backends are enabled, "--trace file"
* only applies to the simple backend; use "-D" for the log backend.
*/
if (file) {
}
#else
if (file) {
- fprintf(stderr, "error: -trace file=...: "
+ fprintf(stderr, "error: --trace file=...: "
"option not supported by the selected tracing backends\n");
exit(1);
}
#endif
}
+void trace_fini_vcpu(CPUState *vcpu)
+{
+ TraceEventIter iter;
+ TraceEvent *ev;
+
+ trace_guest_cpu_exit(vcpu);
+
+ trace_event_iter_init(&iter, NULL);
+ while ((ev = trace_event_iter_next(&iter)) != NULL) {
+ if (trace_event_is_vcpu(ev) &&
+ trace_event_get_state_static(ev) &&
+ trace_event_get_vcpu_state_dynamic(vcpu, ev)) {
+ /* must disable to affect the global counter */
+ trace_event_set_vcpu_state_dynamic(vcpu, ev, false);
+ }
+ }
+}
+
bool trace_init_backends(void)
{
#ifdef CONFIG_TRACE_SIMPLE
return trace_file;
}
+
+uint32_t trace_get_vcpu_event_count(void)
+{
+ return next_vcpu_id;
+}