Commit 3d211d9f authored by Lluís Vilanova's avatar Lluís Vilanova Committed by Stefan Hajnoczi
Browse files

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: default avatarLluís Vilanova <vilanova@ac.upc.edu>
Message-id: 145641861797.30295.6991314023181842105.stgit@localhost
Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
parent b23197f9
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -344,3 +344,44 @@ This will immediately call:
and will generate the TCG code to call:

    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
+9 −2
Original line number Diff line number Diff line
@@ -161,7 +161,7 @@ class Event(object):
                      "(?:(?:(?P<fmt_trans>\".+),)?\s*(?P<fmt>\".+))?"
                      "\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):
        """
@@ -230,7 +230,13 @@ class Event(object):
        if "tcg" in props and isinstance(fmt, str):
            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):
        """Evaluable string representation for this object."""
@@ -285,6 +291,7 @@ def _read_events(fobj):
            event_trans.name += "_trans"
            event_trans.properties += ["tcg-trans"]
            event_trans.fmt = event.fmt[0]
            # ignore TCG arguments
            args_trans = []
            for atrans, aorig in zip(
                    event_trans.transform(tracetool.transform.TCG_2_HOST).args,
+2 −1
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@ trace/generated-tracers.h
"""

__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"

__maintainer__ = "Stefan Hajnoczi"
@@ -23,6 +23,7 @@ def generate(events, backend):
        '#define TRACE__GENERATED_TRACERS_H',
        '',
        '#include "qemu-common.h"',
        '#include "qemu/typedefs.h"',
        '')

    backend.generate_begin(events)
+21 −10
Original line number Diff line number Diff line
@@ -13,7 +13,18 @@ __maintainer__ = "Stefan Hajnoczi"
__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):
@@ -35,21 +46,21 @@ def generate(events, backend):
        if "tcg-trans" not in e.properties:
            continue

        # get the original event definition
        e = e.original

        out('static inline void %(name_tcg)s(%(args)s)',
            '{',
            name_tcg=e.api(e.QEMU_TRACE_TCG),
            args=e.args)
            name_tcg=e.original.api(e.QEMU_TRACE_TCG),
            args=tracetool.vcpu.transform_args("tcg_h", e.original))

        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);',
                '    gen_helper_%(name_exec)s(%(argnames_exec)s);',
                name_trans=e.event_trans.api(e.QEMU_TRACE),
                name_exec=e.event_exec.api(e.QEMU_TRACE),
                argnames_trans=", ".join(e.event_trans.args.names()),
                argnames_exec=", ".join(e.event_exec.args.names()))
                name_trans=e.original.event_trans.api(e.QEMU_TRACE),
                name_exec=e.original.event_exec.api(e.QEMU_TRACE),
                argnames_trans=", ".join(args_trans.names()),
                argnames_exec=", ".join(args_exec.names()))

        out('}')

+34 −11
Original line number Diff line number Diff line
@@ -6,15 +6,38 @@ Generate trace/generated-helpers.c.
"""

__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"

__maintainer__ = "Stefan Hajnoczi"
__email__      = "stefanha@linux.vnet.ibm.com"


from tracetool import out
from tracetool import Arguments, out
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):
@@ -34,18 +57,18 @@ def generate(events, backend):
        if "tcg-exec" not in e.properties:
            continue

        # tracetool.generate always transforms types to host
        e_args = e.original.args

        values = ["(%s)%s" % (t, n)
                  for t, n in e.args.transform(TCG_2_TCG_HELPER_DEF)]
        e_args_api = tracetool.vcpu.transform_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")

        out('void %(name_tcg)s(%(args)s)',
        out('void %(name_tcg)s(%(args_api)s)',
            '{',
            '    %(name)s(%(values)s);',
            '    %(name)s(%(args_call)s);',
            '}',
            name_tcg="helper_%s_proxy" % e.api(),
            name=e.api(),
            args=e_args.transform(HOST_2_TCG_COMPAT, TCG_2_TCG_HELPER_DEF),
            values=", ".join(values),
            args_api=e_args_api,
            args_call=", ".join(e_args_call.casted()),
            )
Loading