Commit ed6128eb authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/stefanha/tags/tracing-pull-request' into staging



# gpg: Signature made Tue 01 Mar 2016 15:48:04 GMT using RSA key ID 81AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg:                 aka "Stefan Hajnoczi <stefanha@gmail.com>"

* remotes/stefanha/tags/tracing-pull-request:
  trace: Add a proper API to manage auto-generated events from the 'tcg' property
  trace: Add 'vcpu' event property to trace guest vCPU
  typedefs: Add CPUState
  trace: Add helper function to cast event arguments
  tcg: Move definition of type TCGv
  tcg: Add type for vCPU pointers
  trace: Remove unnecessary intermediate event copies
  trace: Extend API to manage event arguments
  vl: fix tracing initialization
  trace: use addresses instead of offsets in memory tracepoints
  trace: split subpage MMIOs into their own trace events.
  trace: docs: "simple" backend does support strings
  trace: drop trailing empty strings

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 9c279bec 4ade0541
Loading
Loading
Loading
Loading
+41 −3
Original line number Diff line number Diff line
@@ -172,9 +172,6 @@ source tree. It may not be as powerful as platform-specific or third-party
trace backends but it is portable.  This is the recommended trace backend
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
@@ -347,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
+1 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ typedef struct BusState BusState;
typedef struct CharDriverState CharDriverState;
typedef struct CompatProperty CompatProperty;
typedef struct CPUAddressSpace CPUAddressSpace;
typedef struct CPUState CPUState;
typedef struct DeviceListener DeviceListener;
typedef struct DeviceState DeviceState;
typedef struct DisplayChangeListener DisplayChangeListener;
+0 −1
Original line number Diff line number Diff line
@@ -62,7 +62,6 @@ typedef uint64_t vaddr;
#define CPU_CLASS(class) OBJECT_CLASS_CHECK(CPUClass, (class), TYPE_CPU)
#define CPU_GET_CLASS(obj) OBJECT_GET_CLASS(CPUClass, (obj), TYPE_CPU)

typedef struct CPUState CPUState;
typedef struct CPUWatchpoint CPUWatchpoint;

typedef void (*CPUUnassignedAccess)(CPUState *cpu, hwaddr addr,
+50 −6
Original line number Diff line number Diff line
@@ -372,6 +372,20 @@ static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size)
    }
}

static hwaddr memory_region_to_absolute_addr(MemoryRegion *mr, hwaddr offset)
{
    MemoryRegion *root;
    hwaddr abs_addr = offset;

    abs_addr += mr->addr;
    for (root = mr; root->container; ) {
        root = root->container;
        abs_addr += root->addr;
    }

    return abs_addr;
}

static MemTxResult memory_region_oldmmio_read_accessor(MemoryRegion *mr,
                                                       hwaddr addr,
                                                       uint64_t *value,
@@ -383,7 +397,12 @@ static MemTxResult memory_region_oldmmio_read_accessor(MemoryRegion *mr,
    uint64_t tmp;

    tmp = mr->ops->old_mmio.read[ctz32(size)](mr->opaque, addr);
    trace_memory_region_ops_read(mr, addr, tmp, size);
    if (mr->subpage) {
        trace_memory_region_subpage_read(mr, addr, tmp, size);
    } else if (TRACE_MEMORY_REGION_OPS_READ_ENABLED) {
        hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr);
        trace_memory_region_ops_read(mr, abs_addr, tmp, size);
    }
    *value |= (tmp & mask) << shift;
    return MEMTX_OK;
}
@@ -399,7 +418,12 @@ static MemTxResult memory_region_read_accessor(MemoryRegion *mr,
    uint64_t tmp;

    tmp = mr->ops->read(mr->opaque, addr, size);
    trace_memory_region_ops_read(mr, addr, tmp, size);
    if (mr->subpage) {
        trace_memory_region_subpage_read(mr, addr, tmp, size);
    } else if (TRACE_MEMORY_REGION_OPS_READ_ENABLED) {
        hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr);
        trace_memory_region_ops_read(mr, abs_addr, tmp, size);
    }
    *value |= (tmp & mask) << shift;
    return MEMTX_OK;
}
@@ -416,7 +440,12 @@ static MemTxResult memory_region_read_with_attrs_accessor(MemoryRegion *mr,
    MemTxResult r;

    r = mr->ops->read_with_attrs(mr->opaque, addr, &tmp, size, attrs);
    trace_memory_region_ops_read(mr, addr, tmp, size);
    if (mr->subpage) {
        trace_memory_region_subpage_read(mr, addr, tmp, size);
    } else if (TRACE_MEMORY_REGION_OPS_READ_ENABLED) {
        hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr);
        trace_memory_region_ops_read(mr, abs_addr, tmp, size);
    }
    *value |= (tmp & mask) << shift;
    return r;
}
@@ -432,7 +461,12 @@ static MemTxResult memory_region_oldmmio_write_accessor(MemoryRegion *mr,
    uint64_t tmp;

    tmp = (*value >> shift) & mask;
    trace_memory_region_ops_write(mr, addr, tmp, size);
    if (mr->subpage) {
        trace_memory_region_subpage_write(mr, addr, tmp, size);
    } else if (TRACE_MEMORY_REGION_OPS_WRITE_ENABLED) {
        hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr);
        trace_memory_region_ops_write(mr, abs_addr, tmp, size);
    }
    mr->ops->old_mmio.write[ctz32(size)](mr->opaque, addr, tmp);
    return MEMTX_OK;
}
@@ -448,7 +482,12 @@ static MemTxResult memory_region_write_accessor(MemoryRegion *mr,
    uint64_t tmp;

    tmp = (*value >> shift) & mask;
    trace_memory_region_ops_write(mr, addr, tmp, size);
    if (mr->subpage) {
        trace_memory_region_subpage_write(mr, addr, tmp, size);
    } else if (TRACE_MEMORY_REGION_OPS_WRITE_ENABLED) {
        hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr);
        trace_memory_region_ops_write(mr, abs_addr, tmp, size);
    }
    mr->ops->write(mr->opaque, addr, tmp, size);
    return MEMTX_OK;
}
@@ -464,7 +503,12 @@ static MemTxResult memory_region_write_with_attrs_accessor(MemoryRegion *mr,
    uint64_t tmp;

    tmp = (*value >> shift) & mask;
    trace_memory_region_ops_write(mr, addr, tmp, size);
    if (mr->subpage) {
        trace_memory_region_subpage_write(mr, addr, tmp, size);
    } else if (TRACE_MEMORY_REGION_OPS_WRITE_ENABLED) {
        hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr);
        trace_memory_region_ops_write(mr, abs_addr, tmp, size);
    }
    return mr->ops->write_with_attrs(mr->opaque, addr, tmp, size, attrs);
}

+38 −10
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@ Machinery for generating tracing-related intermediate files.
"""

__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"
@@ -50,9 +50,14 @@ class Arguments:
        Parameters
        ----------
        args :
            List of (type, name) tuples.
            List of (type, name) tuples or Arguments objects.
        """
        self._args = args
        self._args = []
        for arg in args:
            if isinstance(arg, Arguments):
                self._args.extend(arg._args)
            else:
                self._args.append(arg)

    def copy(self):
        """Create a new copy."""
@@ -83,6 +88,12 @@ class Arguments:
            res.append((arg_type, identifier))
        return Arguments(res)

    def __getitem__(self, index):
        if isinstance(index, slice):
            return Arguments(self._args[index])
        else:
            return self._args[index]

    def __iter__(self):
        """Iterate over the (type, name) pairs."""
        return iter(self._args)
@@ -110,6 +121,10 @@ class Arguments:
        """List of argument types."""
        return [ type_ for type_, _ in self._args ]

    def casted(self):
        """List of argument names casted to their type."""
        return ["(%s)%s" % (type_, name) for type_, name in self._args]

    def transform(self, *trans):
        """Return a new Arguments instance with transformed types.

@@ -146,9 +161,10 @@ 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):
    def __init__(self, name, props, fmt, args, orig=None,
                 event_trans=None, event_exec=None):
        """
        Parameters
        ----------
@@ -161,13 +177,19 @@ class Event(object):
        args : Arguments
            Event arguments.
        orig : Event or None
            Original Event before transformation.
            Original Event before transformation/generation.
        event_trans : Event or None
            Generated translation-time event ("tcg" property).
        event_exec : Event or None
            Generated execution-time event ("tcg" property).

        """
        self.name = name
        self.properties = props
        self.fmt = fmt
        self.args = args
        self.event_trans = event_trans
        self.event_exec = event_exec

        if orig is None:
            self.original = weakref.ref(self)
@@ -183,7 +205,7 @@ class Event(object):
    def copy(self):
        """Create a new copy."""
        return Event(self.name, list(self.properties), self.fmt,
                     self.args.copy(), self)
                     self.args.copy(), self, self.event_trans, self.event_exec)

    @staticmethod
    def build(line_str):
@@ -215,7 +237,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."""
@@ -270,6 +298,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,
@@ -277,13 +306,12 @@ def _read_events(fobj):
                if atrans == aorig:
                    args_trans.append(atrans)
            event_trans.args = Arguments(args_trans)
            event_trans = event_trans.copy()

            event_exec = event.copy()
            event_exec.name += "_exec"
            event_exec.properties += ["tcg-exec"]
            event_exec.fmt = event.fmt[1]
            event_exec = event_exec.transform(tracetool.transform.TCG_2_HOST)
            event_exec.args = event_exec.args.transform(tracetool.transform.TCG_2_HOST)

            new_event = [event_trans, event_exec]
            event.event_trans, event.event_exec = new_event
Loading