aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xconfigure3
-rw-r--r--monitor.c40
-rw-r--r--qemu-monitor.hx25
-rw-r--r--simpletrace.c51
-rw-r--r--simpletrace.h10
-rwxr-xr-xtracetool24
6 files changed, 149 insertions, 4 deletions
diff --git a/configure b/configure
index 6729dbe0bb..5afb3b5ef1 100755
--- a/configure
+++ b/configure
@@ -2468,6 +2468,9 @@ bsd)
esac
echo "TRACE_BACKEND=$trace_backend" >> $config_host_mak
+if test "$trace_backend" = "simple"; then
+ echo "CONFIG_SIMPLE_TRACE=y" >> $config_host_mak
+fi
echo "TOOLS=$tools" >> $config_host_mak
echo "ROMS=$roms" >> $config_host_mak
echo "MAKE=$make" >> $config_host_mak
diff --git a/monitor.c b/monitor.c
index e27f8d8d3b..0e69bc8b9d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -56,6 +56,9 @@
#include "json-parser.h"
#include "osdep.h"
#include "exec-all.h"
+#ifdef CONFIG_SIMPLE_TRACE
+#include "trace.h"
+#endif
//#define DEBUG
//#define DEBUG_COMPLETION
@@ -539,6 +542,15 @@ static void do_help_cmd(Monitor *mon, const QDict *qdict)
help_cmd(mon, qdict_get_try_str(qdict, "name"));
}
+#ifdef CONFIG_SIMPLE_TRACE
+static void do_change_trace_event_state(Monitor *mon, const QDict *qdict)
+{
+ const char *tp_name = qdict_get_str(qdict, "name");
+ bool new_state = qdict_get_bool(qdict, "option");
+ st_change_trace_event_state(tp_name, new_state);
+}
+#endif
+
static void user_monitor_complete(void *opaque, QObject *ret_data)
{
MonitorCompletionData *data = (MonitorCompletionData *)opaque;
@@ -938,6 +950,18 @@ static void do_info_cpu_stats(Monitor *mon)
}
#endif
+#if defined(CONFIG_SIMPLE_TRACE)
+static void do_info_trace(Monitor *mon)
+{
+ st_print_trace((FILE *)mon, &monitor_fprintf);
+}
+
+static void do_info_trace_events(Monitor *mon)
+{
+ st_print_trace_events((FILE *)mon, &monitor_fprintf);
+}
+#endif
+
/**
* do_quit(): Quit QEMU execution
*/
@@ -2594,6 +2618,22 @@ static const mon_cmd_t info_cmds[] = {
.help = "show roms",
.mhandler.info = do_info_roms,
},
+#if defined(CONFIG_SIMPLE_TRACE)
+ {
+ .name = "trace",
+ .args_type = "",
+ .params = "",
+ .help = "show current contents of trace buffer",
+ .mhandler.info = do_info_trace,
+ },
+ {
+ .name = "trace-events",
+ .args_type = "",
+ .params = "",
+ .help = "show available trace-events & their state",
+ .mhandler.info = do_info_trace_events,
+ },
+#endif
{
.name = NULL,
},
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index 5c1da3398e..c264c7d539 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -281,6 +281,22 @@ STEXI
Output logs to @var{filename}.
ETEXI
+#ifdef CONFIG_SIMPLE_TRACE
+ {
+ .name = "trace-event",
+ .args_type = "name:s,option:b",
+ .params = "name on|off",
+ .help = "changes status of a specific trace event",
+ .mhandler.cmd = do_change_trace_event_state,
+ },
+
+STEXI
+@item trace-event
+@findex trace-event
+changes status of a trace event
+ETEXI
+#endif
+
{
.name = "log",
.args_type = "items:s",
@@ -2529,6 +2545,15 @@ show roms
@end table
ETEXI
+#ifdef CONFIG_SIMPLE_TRACE
+STEXI
+@item info trace
+show contents of trace buffer
+@item info trace-events
+show available trace events and their state
+ETEXI
+#endif
+
HXCOMM DO NOT add new commands after 'info', move your addition before it!
STEXI
diff --git a/simpletrace.c b/simpletrace.c
index 477730871c..688959a9fe 100644
--- a/simpletrace.c
+++ b/simpletrace.c
@@ -101,6 +101,10 @@ static void trace(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3,
*/
clock_gettime(CLOCK_MONOTONIC, &ts);
+ if (!trace_list[event].state) {
+ return;
+ }
+
rec->event = event;
rec->timestamp_ns = ts.tv_sec * 1000000000LL + ts.tv_nsec;
rec->x1 = x1;
@@ -157,3 +161,50 @@ static void __attribute__((constructor)) st_init(void)
{
atexit(st_flush_trace_buffer);
}
+
+void st_print_trace(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...))
+{
+ unsigned int i;
+
+ for (i = 0; i < trace_idx; i++) {
+ stream_printf(stream, "Event %lu : %lx %lx %lx %lx %lx\n",
+ trace_buf[i].event, trace_buf[i].x1, trace_buf[i].x2,
+ trace_buf[i].x3, trace_buf[i].x4, trace_buf[i].x5);
+ }
+}
+
+void st_print_trace_events(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...))
+{
+ unsigned int i;
+
+ for (i = 0; i < NR_TRACE_EVENTS; i++) {
+ stream_printf(stream, "%s [Event ID %u] : state %u\n",
+ trace_list[i].tp_name, i, trace_list[i].state);
+ }
+}
+
+static TraceEvent* find_trace_event_by_name(const char *tname)
+{
+ unsigned int i;
+
+ if (!tname) {
+ return NULL;
+ }
+
+ for (i = 0; i < NR_TRACE_EVENTS; i++) {
+ if (!strcmp(trace_list[i].tp_name, tname)) {
+ return &trace_list[i];
+ }
+ }
+ return NULL; /* indicates end of list reached without a match */
+}
+
+void st_change_trace_event_state(const char *tname, bool tstate)
+{
+ TraceEvent *tp;
+
+ tp = find_trace_event_by_name(tname);
+ if (tp) {
+ tp->state = tstate;
+ }
+}
diff --git a/simpletrace.h b/simpletrace.h
index 7d0661b720..b0161d1ff4 100644
--- a/simpletrace.h
+++ b/simpletrace.h
@@ -12,9 +12,16 @@
#define SIMPLETRACE_H
#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
typedef uint64_t TraceEventID;
+typedef struct {
+ const char *tp_name;
+ bool state;
+} TraceEvent;
+
void trace0(TraceEventID event);
void trace1(TraceEventID event, uint64_t x1);
void trace2(TraceEventID event, uint64_t x1, uint64_t x2);
@@ -22,5 +29,8 @@ void trace3(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3);
void trace4(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4);
void trace5(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5);
void trace6(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5, uint64_t x6);
+void st_print_trace(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...));
+void st_print_trace_events(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...));
+void st_change_trace_event_state(const char *tname, bool tstate);
#endif /* SIMPLETRACE_H */
diff --git a/tracetool b/tracetool
index 19b1659bc0..2e2e37dbd3 100755
--- a/tracetool
+++ b/tracetool
@@ -169,22 +169,38 @@ EOF
linetoh_end_simple()
{
- return
+ cat <<EOF
+#define NR_TRACE_EVENTS $simple_event_num
+extern TraceEvent trace_list[NR_TRACE_EVENTS];
+EOF
}
linetoc_begin_simple()
{
- return
+ cat <<EOF
+#include "trace.h"
+
+TraceEvent trace_list[] = {
+EOF
+ simple_event_num=0
+
}
linetoc_simple()
{
- return
+ local name
+ name=$(get_name "$1")
+ cat <<EOF
+{.tp_name = "$name", .state=0},
+EOF
+ simple_event_num=$((simple_event_num + 1))
}
linetoc_end_simple()
{
- return
+ cat <<EOF
+};
+EOF
}
# Process stdin by calling begin, line, and end functions for the backend