Merge remote-tracking branch 'stefanha/tracing' into staging

# By Eiichi Tsukata (2) and Kazuya Saito (2)
# Via Stefan Hajnoczi
* stefanha/tracing:
  trace: document ftrace backend
  trace: Add ftrace tracing backend
  kvm-all: add kvm_run_exit tracepoint
  kvm-all: add kvm_ioctl, kvm_vm_ioctl, kvm_vcpu_ioctl tracepoints

Message-id: 1367582485-15579-1-git-send-email-stefanha@redhat.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Anthony Liguori 2013-05-03 11:20:15 -05:00
commit 743bddb4b3
8 changed files with 203 additions and 0 deletions

8
configure vendored
View file

@ -4004,6 +4004,14 @@ if test "$trace_backend" = "dtrace"; then
echo "CONFIG_TRACE_SYSTEMTAP=y" >> $config_host_mak
fi
fi
if test "$trace_backend" = "ftrace"; then
if test "$linux" = "yes" ; then
echo "CONFIG_TRACE_FTRACE=y" >> $config_host_mak
trace_default=no
else
feature_not_found "ftrace(trace backend)"
fi
fi
echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak
if test "$trace_default" = "yes"; then
echo "CONFIG_TRACE_DEFAULT=y" >> $config_host_mak

View file

@ -175,6 +175,22 @@ unless you have specific needs for more advanced backends.
The "simple" backend currently does not capture string arguments, it simply
records the char* pointer value instead of the string that is pointed to.
=== Ftrace ===
The "ftrace" backend writes trace data to ftrace marker. This effectively
sends trace events to ftrace ring buffer, and you can compare qemu trace
data and kernel(especially kvm.ko when using KVM) trace data.
if you use KVM, enable kvm events in ftrace:
# echo 1 > /sys/kernel/debug/tracing/events/kvm/enable
After running qemu by root user, you can get the trace:
# cat /sys/kernel/debug/tracing/trace
Restriction: "ftrace" backend is restricted to Linux only.
==== Monitor commands ====
* trace-file on|off|flush|set <path>

View file

@ -33,6 +33,7 @@
#include "exec/memory.h"
#include "exec/address-spaces.h"
#include "qemu/event_notifier.h"
#include "trace.h"
/* This check must be after config-host.h is included */
#ifdef CONFIG_EVENTFD
@ -1626,6 +1627,7 @@ int kvm_cpu_exec(CPUArchState *env)
abort();
}
trace_kvm_run_exit(cpu->cpu_index, run->exit_reason);
switch (run->exit_reason) {
case KVM_EXIT_IO:
DPRINTF("handle_io\n");
@ -1687,6 +1689,7 @@ int kvm_ioctl(KVMState *s, int type, ...)
arg = va_arg(ap, void *);
va_end(ap);
trace_kvm_ioctl(type, arg);
ret = ioctl(s->fd, type, arg);
if (ret == -1) {
ret = -errno;
@ -1704,6 +1707,7 @@ int kvm_vm_ioctl(KVMState *s, int type, ...)
arg = va_arg(ap, void *);
va_end(ap);
trace_kvm_vm_ioctl(type, arg);
ret = ioctl(s->vmfd, type, arg);
if (ret == -1) {
ret = -errno;
@ -1721,6 +1725,7 @@ int kvm_vcpu_ioctl(CPUState *cpu, int type, ...)
arg = va_arg(ap, void *);
va_end(ap);
trace_kvm_vcpu_ioctl(cpu->cpu_index, type, arg);
ret = ioctl(cpu->kvm_fd, type, arg);
if (ret == -1) {
ret = -errno;

View file

@ -0,0 +1,54 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Ftrace built-in backend.
"""
__author__ = "Eiichi Tsukata <eiichi.tsukata.xh@hitachi.com>"
__copyright__ = "Copyright (C) 2013 Hitachi, Ltd."
__license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi"
__email__ = "stefanha@redhat.com"
from tracetool import out
PUBLIC = True
def c(events):
pass
def h(events):
out('#include "trace/ftrace.h"',
'#include "trace/control.h"',
'',
)
for e in events:
argnames = ", ".join(e.args.names())
if len(e.args) > 0:
argnames = ", " + argnames
out('static inline void trace_%(name)s(%(args)s)',
'{',
' char ftrace_buf[MAX_TRACE_STRLEN];',
' int unused __attribute__ ((unused));',
' int trlen;',
' bool _state = trace_event_get_state(%(event_id)s);',
' if (_state) {',
' trlen = snprintf(ftrace_buf, MAX_TRACE_STRLEN,',
' "%(name)s " %(fmt)s "\\n" %(argnames)s);',
' trlen = MIN(trlen, MAX_TRACE_STRLEN - 1);',
' unused = write(trace_marker_fd, ftrace_buf, trlen);',
' }',
'}',
name = e.name,
args = e.args,
event_id = "TRACE_" + e.name.upper(),
fmt = e.fmt.rstrip("\n"),
argnames = argnames,
)

View file

@ -1153,3 +1153,10 @@ virtio_ccw_new_device(int cssid, int ssid, int schid, int devno, const char *dev
# migration.c
migrate_set_state(int new_state) "new state %d"
# kvm-all.c
kvm_ioctl(int type, void *arg) "type %d, arg %p"
kvm_vm_ioctl(int type, void *arg) "type %d, arg %p"
kvm_vcpu_ioctl(int cpu_index, int type, void *arg) "cpu_index %d, type %d, arg %p"
kvm_run_exit(int cpu_index, uint32_t reason) "cpu_index %d, reason %d"

View file

@ -76,5 +76,6 @@ endif
util-obj-$(CONFIG_TRACE_DEFAULT) += default.o
util-obj-$(CONFIG_TRACE_SIMPLE) += simple.o
util-obj-$(CONFIG_TRACE_STDERR) += stderr.o
util-obj-$(CONFIG_TRACE_FTRACE) += ftrace.o
util-obj-y += control.o
util-obj-y += generated-tracers.o

102
trace/ftrace.c Normal file
View file

@ -0,0 +1,102 @@
/*
* Ftrace trace backend
*
* Copyright (C) 2013 Hitachi, Ltd.
* Created by Eiichi Tsukata <eiichi.tsukata.xh@hitachi.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*
*/
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include "trace.h"
#include "trace/control.h"
int trace_marker_fd;
static int find_debugfs(char *debugfs)
{
char type[100];
FILE *fp;
fp = fopen("/proc/mounts", "r");
if (fp == NULL) {
return 0;
}
while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
debugfs, type) == 2) {
if (strcmp(type, "debugfs") == 0) {
break;
}
}
fclose(fp);
if (strcmp(type, "debugfs") != 0) {
return 0;
}
return 1;
}
void trace_print_events(FILE *stream, fprintf_function stream_printf)
{
TraceEventID i;
for (i = 0; i < trace_event_count(); i++) {
TraceEvent *ev = trace_event_id(i);
stream_printf(stream, "%s [Event ID %u] : state %u\n",
trace_event_get_name(ev), i, trace_event_get_state_dynamic(ev));
}
}
void trace_event_set_state_dynamic_backend(TraceEvent *ev, bool state)
{
ev->dstate = state;
}
bool trace_backend_init(const char *events, const char *file)
{
char debugfs[PATH_MAX];
char path[PATH_MAX];
int debugfs_found;
int trace_fd = -1;
if (file) {
fprintf(stderr, "error: -trace file=...: "
"option not supported by the selected tracing backend\n");
return false;
}
debugfs_found = find_debugfs(debugfs);
if (debugfs_found) {
snprintf(path, PATH_MAX, "%s/tracing/tracing_on", debugfs);
trace_fd = open(path, O_WRONLY);
if (trace_fd < 0) {
perror("Could not open ftrace 'tracing_on' file");
return false;
} else {
if (write(trace_fd, "1", 1) < 0) {
perror("Could not write to 'tracing_on' file");
close(trace_fd);
return false;
}
close(trace_fd);
}
snprintf(path, PATH_MAX, "%s/tracing/trace_marker", debugfs);
trace_marker_fd = open(path, O_WRONLY);
if (trace_marker_fd < 0) {
perror("Could not open ftrace 'trace_marker' file");
return false;
}
} else {
fprintf(stderr, "debugfs is not mounted\n");
return false;
}
trace_backend_init_events(events);
return true;
}

10
trace/ftrace.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef TRACE_FTRACE_H
#define TRACE_FTRACE_H
#define MAX_TRACE_STRLEN 512
#define _STR(x) #x
#define STR(x) _STR(x)
extern int trace_marker_fd;
#endif /* ! TRACE_FTRACE_H */