trace: Add 'vcpu' event property to trace guest vCPU

This property identifies events that trace vCPU-specific information.

It adds a "CPUState*" argument to events with the property, identifying
the vCPU raising the event. TCG translation events also have a
"TCGv_env" implicit argument that is later used as the "CPUState*"
argument at execution time.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Message-id: 145641861797.30295.6991314023181842105.stgit@localhost
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Lluís Vilanova 2016-02-25 17:43:38 +01:00 committed by Stefan Hajnoczi
parent b23197f9cf
commit 3d211d9f4d
11 changed files with 189 additions and 32 deletions

View File

@ -344,3 +344,44 @@ This will immediately call:
and will generate the TCG code to call: and will generate the TCG code to call:
void trace_foo(uint8_t a1, uint32_t a2); void trace_foo(uint8_t a1, uint32_t a2);
=== "vcpu" ===
Identifies events that trace vCPU-specific information. It implicitly adds a
"CPUState*" argument, and extends the tracing print format to show the vCPU
information. If used together with the "tcg" property, it adds a second
"TCGv_env" argument that must point to the per-target global TCG register that
points to the vCPU when guest code is executed (usually the "cpu_env" variable).
The following example events:
foo(uint32_t a) "a=%x"
vcpu bar(uint32_t a) "a=%x"
tcg vcpu baz(uint32_t a) "a=%x", "a=%x"
Can be used as:
#include "trace-tcg.h"
CPUArchState *env;
TCGv_ptr cpu_env;
void some_disassembly_func(...)
{
/* trace emitted at this point */
trace_foo(0xd1);
/* trace emitted at this point */
trace_bar(ENV_GET_CPU(env), 0xd2);
/* trace emitted at this point (env) and when guest code is executed (cpu_env) */
trace_baz_tcg(ENV_GET_CPU(env), cpu_env, 0xd3);
}
If the translating vCPU has address 0xc1 and code is later executed by vCPU
0xc2, this would be an example output:
// at guest code translation
foo a=0xd1
bar cpu=0xc1 a=0xd2
baz_trans cpu=0xc1 a=0xd3
// at guest code execution
baz_exec cpu=0xc2 a=0xd3

View File

@ -161,7 +161,7 @@ class Event(object):
"(?:(?:(?P<fmt_trans>\".+),)?\s*(?P<fmt>\".+))?" "(?:(?:(?P<fmt_trans>\".+),)?\s*(?P<fmt>\".+))?"
"\s*") "\s*")
_VALID_PROPS = set(["disable", "tcg", "tcg-trans", "tcg-exec"]) _VALID_PROPS = set(["disable", "tcg", "tcg-trans", "tcg-exec", "vcpu"])
def __init__(self, name, props, fmt, args, orig=None): def __init__(self, name, props, fmt, args, orig=None):
""" """
@ -230,7 +230,13 @@ class Event(object):
if "tcg" in props and isinstance(fmt, str): if "tcg" in props and isinstance(fmt, str):
raise ValueError("Events with 'tcg' property must have two formats") raise ValueError("Events with 'tcg' property must have two formats")
return Event(name, props, fmt, args) event = Event(name, props, fmt, args)
# add implicit arguments when using the 'vcpu' property
import tracetool.vcpu
event = tracetool.vcpu.transform_event(event)
return event
def __repr__(self): def __repr__(self):
"""Evaluable string representation for this object.""" """Evaluable string representation for this object."""
@ -285,6 +291,7 @@ def _read_events(fobj):
event_trans.name += "_trans" event_trans.name += "_trans"
event_trans.properties += ["tcg-trans"] event_trans.properties += ["tcg-trans"]
event_trans.fmt = event.fmt[0] event_trans.fmt = event.fmt[0]
# ignore TCG arguments
args_trans = [] args_trans = []
for atrans, aorig in zip( for atrans, aorig in zip(
event_trans.transform(tracetool.transform.TCG_2_HOST).args, event_trans.transform(tracetool.transform.TCG_2_HOST).args,

View File

@ -6,7 +6,7 @@ trace/generated-tracers.h
""" """
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" __author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
__copyright__ = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>" __copyright__ = "Copyright 2012-2016, Lluís Vilanova <vilanova@ac.upc.edu>"
__license__ = "GPL version 2 or (at your option) any later version" __license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi" __maintainer__ = "Stefan Hajnoczi"
@ -23,6 +23,7 @@ def generate(events, backend):
'#define TRACE__GENERATED_TRACERS_H', '#define TRACE__GENERATED_TRACERS_H',
'', '',
'#include "qemu-common.h"', '#include "qemu-common.h"',
'#include "qemu/typedefs.h"',
'') '')
backend.generate_begin(events) backend.generate_begin(events)

View File

@ -13,7 +13,18 @@ __maintainer__ = "Stefan Hajnoczi"
__email__ = "stefanha@linux.vnet.ibm.com" __email__ = "stefanha@linux.vnet.ibm.com"
from tracetool import out from tracetool import out, Arguments
import tracetool.vcpu
def vcpu_transform_args(args):
assert len(args) == 1
return Arguments([
args,
# NOTE: this name must be kept in sync with the one in "tcg_h"
# NOTE: Current helper code uses TCGv_env (CPUArchState*)
("TCGv_env", "__tcg_" + args.names()[0]),
])
def generate(events, backend): def generate(events, backend):
@ -35,21 +46,21 @@ def generate(events, backend):
if "tcg-trans" not in e.properties: if "tcg-trans" not in e.properties:
continue continue
# get the original event definition
e = e.original
out('static inline void %(name_tcg)s(%(args)s)', out('static inline void %(name_tcg)s(%(args)s)',
'{', '{',
name_tcg=e.api(e.QEMU_TRACE_TCG), name_tcg=e.original.api(e.QEMU_TRACE_TCG),
args=e.args) args=tracetool.vcpu.transform_args("tcg_h", e.original))
if "disable" not in e.properties: if "disable" not in e.properties:
args_trans = e.original.event_trans.args
args_exec = tracetool.vcpu.transform_args(
"tcg_helper_c", e.original.event_exec, "wrapper")
out(' %(name_trans)s(%(argnames_trans)s);', out(' %(name_trans)s(%(argnames_trans)s);',
' gen_helper_%(name_exec)s(%(argnames_exec)s);', ' gen_helper_%(name_exec)s(%(argnames_exec)s);',
name_trans=e.event_trans.api(e.QEMU_TRACE), name_trans=e.original.event_trans.api(e.QEMU_TRACE),
name_exec=e.event_exec.api(e.QEMU_TRACE), name_exec=e.original.event_exec.api(e.QEMU_TRACE),
argnames_trans=", ".join(e.event_trans.args.names()), argnames_trans=", ".join(args_trans.names()),
argnames_exec=", ".join(e.event_exec.args.names())) argnames_exec=", ".join(args_exec.names()))
out('}') out('}')

View File

@ -6,15 +6,38 @@ Generate trace/generated-helpers.c.
""" """
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" __author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
__copyright__ = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>" __copyright__ = "Copyright 2012-2016, Lluís Vilanova <vilanova@ac.upc.edu>"
__license__ = "GPL version 2 or (at your option) any later version" __license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi" __maintainer__ = "Stefan Hajnoczi"
__email__ = "stefanha@linux.vnet.ibm.com" __email__ = "stefanha@linux.vnet.ibm.com"
from tracetool import out from tracetool import Arguments, out
from tracetool.transform import * from tracetool.transform import *
import tracetool.vcpu
def vcpu_transform_args(args, mode):
assert len(args) == 1
# NOTE: this name must be kept in sync with the one in "tcg_h"
args = Arguments([(args.types()[0], "__tcg_" + args.names()[0])])
if mode == "code":
return Arguments([
# Does cast from helper requirements to tracing types
("CPUState *", "ENV_GET_CPU(%s)" % args.names()[0]),
])
else:
args = Arguments([
# NOTE: Current helper code uses TCGv_env (CPUArchState*)
("CPUArchState *", args.names()[0]),
])
if mode == "header":
return args
elif mode == "wrapper":
return args.transform(HOST_2_TCG)
else:
assert False
def generate(events, backend): def generate(events, backend):
@ -34,18 +57,18 @@ def generate(events, backend):
if "tcg-exec" not in e.properties: if "tcg-exec" not in e.properties:
continue continue
# tracetool.generate always transforms types to host e_args_api = tracetool.vcpu.transform_args(
e_args = e.original.args "tcg_helper_c", e.original, "header").transform(
HOST_2_TCG_COMPAT, TCG_2_TCG_HELPER_DEF)
e_args_call = tracetool.vcpu.transform_args(
"tcg_helper_c", e, "code")
values = ["(%s)%s" % (t, n) out('void %(name_tcg)s(%(args_api)s)',
for t, n in e.args.transform(TCG_2_TCG_HELPER_DEF)]
out('void %(name_tcg)s(%(args)s)',
'{', '{',
' %(name)s(%(values)s);', ' %(name)s(%(args_call)s);',
'}', '}',
name_tcg="helper_%s_proxy" % e.api(), name_tcg="helper_%s_proxy" % e.api(),
name=e.api(), name=e.api(),
args=e_args.transform(HOST_2_TCG_COMPAT, TCG_2_TCG_HELPER_DEF), args_api=e_args_api,
values=", ".join(values), args_call=", ".join(e_args_call.casted()),
) )

View File

@ -6,7 +6,7 @@ Generate trace/generated-helpers.h.
""" """
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" __author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
__copyright__ = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>" __copyright__ = "Copyright 2012-2016, Lluís Vilanova <vilanova@ac.upc.edu>"
__license__ = "GPL version 2 or (at your option) any later version" __license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi" __maintainer__ = "Stefan Hajnoczi"
@ -15,6 +15,7 @@ __email__ = "stefanha@linux.vnet.ibm.com"
from tracetool import out from tracetool import out
from tracetool.transform import * from tracetool.transform import *
import tracetool.vcpu
def generate(events, backend): def generate(events, backend):
@ -29,11 +30,9 @@ def generate(events, backend):
if "tcg-exec" not in e.properties: if "tcg-exec" not in e.properties:
continue continue
# tracetool.generate always transforms types to host
e_args = e.original.args
# TCG helper proxy declaration # TCG helper proxy declaration
fmt = "DEF_HELPER_FLAGS_%(argc)d(%(name)s, %(flags)svoid%(types)s)" fmt = "DEF_HELPER_FLAGS_%(argc)d(%(name)s, %(flags)svoid%(types)s)"
e_args = tracetool.vcpu.transform_args("tcg_helper_c", e.original, "header")
args = e_args.transform(HOST_2_TCG_COMPAT, HOST_2_TCG, args = e_args.transform(HOST_2_TCG_COMPAT, HOST_2_TCG,
TCG_2_TCG_HELPER_DECL) TCG_2_TCG_HELPER_DECL)
types = ", ".join(args.types()) types = ", ".join(args.types())

View File

@ -6,7 +6,7 @@ Generate trace/generated-helpers-wrappers.h.
""" """
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" __author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
__copyright__ = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>" __copyright__ = "Copyright 2012-2016, Lluís Vilanova <vilanova@ac.upc.edu>"
__license__ = "GPL version 2 or (at your option) any later version" __license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi" __maintainer__ = "Stefan Hajnoczi"
@ -15,6 +15,7 @@ __email__ = "stefanha@linux.vnet.ibm.com"
from tracetool import out from tracetool import out
from tracetool.transform import * from tracetool.transform import *
import tracetool.vcpu
def generate(events, backend): def generate(events, backend):
@ -33,7 +34,7 @@ def generate(events, backend):
continue continue
# tracetool.generate always transforms types to host # tracetool.generate always transforms types to host
e_args = e.original.args e_args = tracetool.vcpu.transform_args("tcg_helper_c", e.original, "wrapper")
# mixed-type to TCG helper bridge # mixed-type to TCG helper bridge
args_tcg_compat = e_args.transform(HOST_2_TCG_COMPAT) args_tcg_compat = e_args.transform(HOST_2_TCG_COMPAT)

View File

@ -32,4 +32,5 @@ def generate(events, backend):
' */', ' */',
'#pragma GCC diagnostic ignored "-Wredundant-decls"', '#pragma GCC diagnostic ignored "-Wredundant-decls"',
'', '',
'#include "qemu/typedefs.h"',
'#include "generated-ust-provider.h"') '#include "generated-ust-provider.h"')

View File

@ -6,7 +6,7 @@ Type-transformation rules.
""" """
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>" __author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
__copyright__ = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>" __copyright__ = "Copyright 2012-2016, Lluís Vilanova <vilanova@ac.upc.edu>"
__license__ = "GPL version 2 or (at your option) any later version" __license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi" __maintainer__ = "Stefan Hajnoczi"
@ -98,6 +98,7 @@ HOST_2_TCG = {
"uint32_t": "TCGv_i32", "uint32_t": "TCGv_i32",
"uint64_t": "TCGv_i64", "uint64_t": "TCGv_i64",
"void *" : "TCGv_ptr", "void *" : "TCGv_ptr",
"CPUArchState *": "TCGv_env",
None: _host_2_tcg, None: _host_2_tcg,
} }
@ -130,6 +131,7 @@ TCG_2_TCG_HELPER_DECL = {
"TCGv_ptr": "ptr", "TCGv_ptr": "ptr",
"TCGv_i32": "i32", "TCGv_i32": "i32",
"TCGv_i64": "i64", "TCGv_i64": "i64",
"TCGv_env": "env",
None: _tcg_2_tcg_helper_decl_error, None: _tcg_2_tcg_helper_decl_error,
} }

70
scripts/tracetool/vcpu.py Normal file
View File

@ -0,0 +1,70 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Generic management for the 'vcpu' property.
"""
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
__copyright__ = "Copyright 2016, Lluís Vilanova <vilanova@ac.upc.edu>"
__license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi"
__email__ = "stefanha@linux.vnet.ibm.com"
from tracetool import Arguments, try_import
def transform_event(event):
"""Transform event to comply with the 'vcpu' property (if present)."""
if "vcpu" in event.properties:
# events with 'tcg-trans' and 'tcg-exec' are auto-generated from
# already-patched events
assert "tcg-trans" not in event.properties
assert "tcg-exec" not in event.properties
event.args = Arguments([("CPUState *", "__cpu"), event.args])
if "tcg" in event.properties:
fmt = "\"cpu=%p \""
event.fmt = [fmt + event.fmt[0],
fmt + event.fmt[1]]
else:
fmt = "\"cpu=%p \""
event.fmt = fmt + event.fmt
return event
def transform_args(format, event, *args, **kwargs):
"""Transforms the arguments to suit the specified format.
The format module must implement function 'vcpu_args', which receives the
implicit arguments added by the 'vcpu' property, and must return suitable
arguments for the given format.
The function is only called for events with the 'vcpu' property.
Parameters
==========
format : str
Format module name.
event : Event
args, kwargs
Passed to 'vcpu_transform_args'.
Returns
=======
Arguments
The transformed arguments, including the non-implicit ones.
"""
if "vcpu" in event.properties:
ok, func = try_import("tracetool.format." + format,
"vcpu_transform_args")
assert ok
assert func
return Arguments([func(event.args[:1], *args, **kwargs),
event.args[1:]])
else:
return event.args

View File

@ -1,7 +1,7 @@
/* /*
* Interface for configuring and controlling the state of tracing events. * Interface for configuring and controlling the state of tracing events.
* *
* Copyright (C) 2011-2014 Lluís Vilanova <vilanova@ac.upc.edu> * Copyright (C) 2011-2016 Lluís Vilanova <vilanova@ac.upc.edu>
* *
* This work is licensed under the terms of the GNU GPL, version 2 or later. * This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory. * See the COPYING file in the top-level directory.
@ -11,6 +11,7 @@
#define TRACE__CONTROL_H #define TRACE__CONTROL_H
#include "qemu-common.h" #include "qemu-common.h"
#include "qemu/typedefs.h"
#include "trace/generated-events.h" #include "trace/generated-events.h"