Signed-off-by: Lluís Vilanova <vilan...@ac.upc.edu> --- .gitignore | 1 Makefile | 3 + instrument/Makefile.objs | 1 instrument/error.h | 6 ++ instrument/qemu-instr/types.h | 51 +++++++++++++++ instrument/qemu-instr/types.inc.h | 15 ++++ instrument/trace.c | 125 +++++++++++++++++++++++++++++++++++++ trace/control.h | 1 8 files changed, 203 insertions(+) create mode 100644 instrument/qemu-instr/types.h create mode 100644 instrument/qemu-instr/types.inc.h create mode 100644 instrument/trace.c
diff --git a/.gitignore b/.gitignore index cf65316863..5ffcb9a091 100644 --- a/.gitignore +++ b/.gitignore @@ -134,3 +134,4 @@ trace-dtrace-root.h trace-dtrace-root.dtrace trace-ust-all.h trace-ust-all.c +!/instrument/* diff --git a/Makefile b/Makefile index 6171661458..6f4de75f79 100644 --- a/Makefile +++ b/Makefile @@ -592,6 +592,9 @@ endif ifdef CONFIG_INSTRUMENT $(INSTALL_DIR) "$(DESTDIR)$(includedir)/qemu-instr/" $(INSTALL_DATA) $(SRC_PATH)/instrument/qemu-instr/control.h "$(DESTDIR)$(includedir)/qemu-instr/" + $(INSTALL_DATA) $(SRC_PATH)/instrument/qemu-instr/trace.h "$(DESTDIR)$(includedir)/qemu-instr/" + $(INSTALL_DATA) $(SRC_PATH)/instrument/qemu-instr/types.h "$(DESTDIR)$(includedir)/qemu-instr/" + $(INSTALL_DATA) $(SRC_PATH)/instrument/qemu-instr/types.inc.h "$(DESTDIR)$(includedir)/qemu-instr/" $(INSTALL_DATA) $(SRC_PATH)/instrument/qemu-instr/visibility.h "$(DESTDIR)$(includedir)/qemu-instr/" endif diff --git a/instrument/Makefile.objs b/instrument/Makefile.objs index 9b7e1c03aa..8258dbfa79 100644 --- a/instrument/Makefile.objs +++ b/instrument/Makefile.objs @@ -5,3 +5,4 @@ target-obj-$(CONFIG_INSTRUMENT) += load.o target-obj-y += qmp.o target-obj-$(CONFIG_INSTRUMENT) += control.o +target-obj-$(CONFIG_INSTRUMENT) += trace.o diff --git a/instrument/error.h b/instrument/error.h index f8d1dd4b16..7a51d62fdb 100644 --- a/instrument/error.h +++ b/instrument/error.h @@ -25,4 +25,10 @@ return; \ } +#define ERROR_IF_RET(cond, ret, msg, args...) \ + if (unlikely(cond)) { \ + _ERROR(msg, ##args); \ + return ret; \ + } \ + #endif /* INSTRUMENT_ERROR_H */ diff --git a/instrument/qemu-instr/types.h b/instrument/qemu-instr/types.h new file mode 100644 index 0000000000..ea3a032b4f --- /dev/null +++ b/instrument/qemu-instr/types.h @@ -0,0 +1,51 @@ +/* + * QEMU-specific types for instrumentation clients. + * + * Copyright (C) 2012-2017 Lluís Vilanova <vilan...@ac.upc.edu> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef QI__TYPES_H +#define QI__TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * SECTION: types + * @section_id: qi-types + * @title: Common types + */ + +/** + * QITraceEvent: + * + * Opaque structure defining a tracing event. + */ +typedef struct QITraceEvent QITraceEvent; + +/** + * QITraceEventIter: + * + * Opaque structure defining a tracing event iterator. + */ +typedef struct QITraceEventIter QITraceEventIter; + +/** + * QICPU: + * + * Opaque guest CPU pointer. + */ +typedef struct QICPU_d *QICPU; + + +#include <qemu-instr/types.inc.h> + +#ifdef __cplusplus +} +#endif + +#endif /* QI__TYPES_H */ diff --git a/instrument/qemu-instr/types.inc.h b/instrument/qemu-instr/types.inc.h new file mode 100644 index 0000000000..0d99ea59a2 --- /dev/null +++ b/instrument/qemu-instr/types.inc.h @@ -0,0 +1,15 @@ +/* + * QEMU-specific types for instrumentation clients. + * + * Copyright (C) 2012-2017 Lluís Vilanova <vilan...@ac.upc.edu> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include <stdlib.h> + + +struct QITraceEventIter { + char buffer[(sizeof(size_t) * 2) + sizeof(char *)]; +}; diff --git a/instrument/trace.c b/instrument/trace.c new file mode 100644 index 0000000000..a73fcdf50a --- /dev/null +++ b/instrument/trace.c @@ -0,0 +1,125 @@ +/* + * API for QEMU's tracing events. + * + * Copyright (C) 2012-2017 Lluís Vilanova <vilan...@ac.upc.edu> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "instrument/error.h" +#include "qemu-instr/trace.h" +#include "qemu-instr/visibility.h" +#include "trace/control.h" + + +QI_VPUBLIC +QITraceEvent *qi_trace_event_name(const char *name) +{ + ERROR_IF_RET(!name, NULL, "must provide a name"); + return (QITraceEvent *)trace_event_name(name); +} + +QI_VPUBLIC +void qi_trace_event_iter_init(QITraceEventIter *iter, const char *pattern) +{ + TraceEventIter *iter_ = (TraceEventIter *)iter; + ERROR_IF(!iter_, "must provide an iterator"); + trace_event_iter_init(iter_, pattern); +} + +QI_VPUBLIC +QITraceEvent *qi_trace_event_iter_next(QITraceEventIter *iter) +{ + TraceEventIter *iter_ = (TraceEventIter *)iter; + ERROR_IF_RET(!iter_, NULL, "must provide an iterator"); + return (QITraceEvent *)trace_event_iter_next(iter_); +} + + +QI_VPUBLIC +bool qi_trace_event_is_vcpu(QITraceEvent *ev) +{ + TraceEvent *ev_ = (TraceEvent *)ev; + ERROR_IF_RET(!ev_, false, "must provide an event"); + return trace_event_is_vcpu(ev_); +} + +QI_VPUBLIC +const char * qi_trace_event_get_name(QITraceEvent *ev) +{ + TraceEvent *ev_ = (TraceEvent *)ev; + ERROR_IF_RET(!ev_, false, "must provide an event"); + return trace_event_get_name(ev_); +} + + +QI_VPUBLIC +bool qi_trace_event_get_state(QITraceEvent *ev) +{ + TraceEvent *ev_ = (TraceEvent *)ev; + ERROR_IF_RET(!ev_, false, "must provide an event"); + return trace_event_get_state_static(ev_) && + trace_event_get_state_dynamic(ev_); +} + +QI_VPUBLIC +bool qi_trace_event_get_vcpu_state(QICPU *vcpu, QITraceEvent *ev) +{ + CPUState *vcpu_ = (CPUState *)vcpu; + TraceEvent *ev_ = (TraceEvent *)ev; + ERROR_IF_RET(!vcpu_, false, "must provide a vCPU"); + ERROR_IF_RET(!ev_, false, "must provide an event"); + return trace_event_get_state_static(ev_) && + trace_event_get_vcpu_state_dynamic(vcpu_, ev_); +} + +QI_VPUBLIC +bool qi_trace_event_get_state_static(QITraceEvent *ev) +{ + TraceEvent *ev_ = (TraceEvent *)ev; + ERROR_IF_RET(!ev_, false, "must provide an event"); + return trace_event_get_state_static(ev_); +} + +QI_VPUBLIC +bool qi_trace_event_get_state_dynamic(QITraceEvent *ev) +{ + TraceEvent *ev_ = (TraceEvent *)ev; + ERROR_IF_RET(!ev_, false, "must provide an event"); + return trace_event_get_state_dynamic(ev_); +} + +QI_VPUBLIC +bool qi_trace_event_get_vcpu_state_dynamic(QICPU *vcpu, QITraceEvent *ev) +{ + CPUState *vcpu_ = (CPUState *)vcpu; + TraceEvent *ev_ = (TraceEvent *)ev; + ERROR_IF_RET(!vcpu_, false, "must provide a vCPU"); + ERROR_IF_RET(!ev_, false, "must provide an event"); + return trace_event_get_vcpu_state_dynamic(vcpu_, ev_); +} + +QI_VPUBLIC +void qi_trace_event_set_state_dynamic(QITraceEvent *ev, bool state) +{ + TraceEvent *ev_ = (TraceEvent *)ev; + ERROR_IF(!ev_, "must provide an event"); + ERROR_IF(!trace_event_get_state_static(ev_), + "event must be statically enabled"); + trace_event_set_state_dynamic(ev_, state); +} + +QI_VPUBLIC +void qi_trace_event_set_vcpu_state_dynamic(QICPU *vcpu, + QITraceEvent *ev, bool state) +{ + CPUState *vcpu_ = (CPUState *)vcpu; + TraceEvent *ev_ = (TraceEvent *)ev; + ERROR_IF(!vcpu_, "must provide a vCPU"); + ERROR_IF(!ev_, "must provide an event"); + ERROR_IF(!trace_event_get_state_static(ev_), + "event must be statically enabled"); + trace_event_set_vcpu_state_dynamic(vcpu_, ev_, state); +} diff --git a/trace/control.h b/trace/control.h index 1903e22975..3e6da24c98 100644 --- a/trace/control.h +++ b/trace/control.h @@ -13,6 +13,7 @@ #include "qemu-common.h" #include "event-internal.h" +/* NOTE: Keep in sync with size of QITraceEventIter */ typedef struct TraceEventIter { size_t event; size_t group;