Signed-off-by: Lluís Vilanova <vilan...@ac.upc.edu> --- docs/instrumentation.txt | 142 ++++++++++++++++++++++++++++++++++++++++++++++ docs/tracing.txt | 9 +++ 2 files changed, 151 insertions(+), 0 deletions(-) create mode 100644 docs/instrumentation.txt
diff --git a/docs/instrumentation.txt b/docs/instrumentation.txt new file mode 100644 index 0000000..f9f3ce1 --- /dev/null +++ b/docs/instrumentation.txt @@ -0,0 +1,142 @@ += Trace instrumentation = + +== Introduction == + +This document describes how the events provided by the tracing infrastructure +described in the document "tracing.txt" can be extended with user-defined code +that is compiled into QEMU. + +The "instrument" property provides means to statically override and/or wrap the +backend-specific tracing code on a per-event basis when compiling QEMU +(regardless of the tracing backend). + +As opposed to using tracing backends that can dynamically load user-defined code +into the tracing events (e.g., "dtrace"), trace instrumentation is performed at +compile time and thus provides means for the tracing hooks to directly interact +with QEMU internals. + +Static trace instrumentation trades the ease and flexibility of existing tracing +backends with the ability to directly interact with the internal routines of +QEMU, as well as the ability to embed highly performant and ad-hoc analyses +based on QEMU's tracing events directly into QEMU itself. + + +== Quickstart == + +1. Declare which tracing events to instrument: + + sed -i -e "s/qemu_vmalloc(/instrument qemu_vmalloc(/g" trace-events + +2. Create the trace instrumentation header ("trace-instrument.h") with the + headers for the instrumented tracing events: + + cat > /tmp/my-instrument/trace-instrument.h <<EOF + void qemu_vmalloc(size_t size, void *ptr); + EOF + +3. Create the "Makefile" to build the trace intrumentation library: + + cat > /tmp/my-intrument/Makefile <<EOF + include $(BUILD_DIR)/config-host.mak + include $(BUILD_DIR)/$(TARGET_DIR)../config-target.mak + include $(SRC_PATH)/rules.mak + + vpath %.c /tmp/my-instrument + + libtrace-instrument.a: instrument.o + + # Include automatically generated dependency files + -include $(wildcard *.d) + EOF + +4. Create the necessary source code files to implement the event instrumentation: + + cat > /tmp/my-instrument/instrument.c <<EOF + #include "trace.h" + + void trace_qemu_vmalloc(size_t size, void *ptr) + { + /* ... */ + } + EOF + +5. Build QEMU with trace intrumentation enabled: + + ./configure --with-trace-instrument=/tmp/my-instrument + make + + +== Compilation notes == + +The instrumentation library is compiled during the compilation of the +target-dependant code. This means that the instrumentation code is able to use +any target-specific code and access target-specific vCPU state. This includes +access to a per-vCPU opaque pointer ("instrument") that is reserved for the use +of the instrumentation code. + +In addition, the path to the static trace instrumentation library is added into +the list of directories to search for includes, so that any user-provided +headers can be included from the instrumentation headers, as well as any other +header from QEMU itself can be included in the intrumentation code. + + +== User-provided headers == + +The user must provide a set of headers in the directory identified by the +'--with-trace-instrument' configure option. These headers establish how and what +to do when a tracing routine for an instrumented event is invoked. + +=== "trace-instrument.h" === + +This file is included from the "trace.h" file whenever instrumentation is enabled. + +Usually, this file will only contain a declaration of the tracing routines for +the instrumented events, just as the "trace.h" would do if an event was not +instrumented. + +Still, if some part of the instrumentation is performance-critical, the header +could provide an inlined implementation of the fast path in the header, and +implement the slow path in the instrumentation library itself: + + void trace_qemu_vmalloc_slow(size_t size, void *ptr); + + static inline void trace_qemu_vmalloc(size_t size, void *ptr) + { + if (/* ... performance-critical condition ... */) { + /* ... performance-critical code ... */ + } else { + trace_qemu_vmalloc_slow(size, ptr); + } + } + + +== Mixing existing tracing backends and instrumentation == + +When enabling static trace instrumentation, you can still use the currently +selected tracing backend by invoking the tracing function with the '_backend' +suffix. + +Note that some of the tracing backends provide an interface for programmatically +controlling the tracing state of each event. Thus you can provide code to +control when the tracing must take place: + + void trace_qemu_vmalloc(size_t size, void *ptr) + { + /* only trace one malloc every 10 */ + /* note that this code is not thread-safe */ + static int i = 0; + static bool state = true; + if (i++ % 10 == 0) { + trace_event_set_state("qemu_vmalloc", state); + state = !state; + } + + /* call the original backend-specific tracing routine */ + trace_qemu_vmalloc_backend(size, ptr); + } + + +== Performance notes == + +The "trace-instrument.h" header can be used to inline the implementation of the +tracing routines for those events that have the "instrument" property. diff --git a/docs/tracing.txt b/docs/tracing.txt index a92716f..a1d3ce2 100644 --- a/docs/tracing.txt +++ b/docs/tracing.txt @@ -268,3 +268,12 @@ guard such computations and avoid its compilation when the event is disabled: } return ptr; } + +=== "instrument" === + +When compiling QEMU with trace instrumentation enabled, the "instrument" +property will force the user to provide an implementation for that trace +event. This implementation can override and/or wrap the backend-specific tracing +code at compile time (regardless of the tracing backend). + +See the document "instrumentation.txt" for more information.