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:
parent
b23197f9cf
commit
3d211d9f4d
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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('}')
|
||||
|
||||
|
@ -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
|
||||
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")
|
||||
|
||||
values = ["(%s)%s" % (t, n)
|
||||
for t, n in e.args.transform(TCG_2_TCG_HELPER_DEF)]
|
||||
|
||||
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()),
|
||||
)
|
||||
|
@ -6,7 +6,7 @@ Generate trace/generated-helpers.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"
|
||||
@ -15,6 +15,7 @@ __email__ = "stefanha@linux.vnet.ibm.com"
|
||||
|
||||
from tracetool import out
|
||||
from tracetool.transform import *
|
||||
import tracetool.vcpu
|
||||
|
||||
|
||||
def generate(events, backend):
|
||||
@ -29,11 +30,9 @@ def generate(events, backend):
|
||||
if "tcg-exec" not in e.properties:
|
||||
continue
|
||||
|
||||
# tracetool.generate always transforms types to host
|
||||
e_args = e.original.args
|
||||
|
||||
# TCG helper proxy declaration
|
||||
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,
|
||||
TCG_2_TCG_HELPER_DECL)
|
||||
types = ", ".join(args.types())
|
||||
|
@ -6,7 +6,7 @@ Generate trace/generated-helpers-wrappers.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"
|
||||
@ -15,6 +15,7 @@ __email__ = "stefanha@linux.vnet.ibm.com"
|
||||
|
||||
from tracetool import out
|
||||
from tracetool.transform import *
|
||||
import tracetool.vcpu
|
||||
|
||||
|
||||
def generate(events, backend):
|
||||
@ -33,7 +34,7 @@ def generate(events, backend):
|
||||
continue
|
||||
|
||||
# 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
|
||||
args_tcg_compat = e_args.transform(HOST_2_TCG_COMPAT)
|
||||
|
@ -32,4 +32,5 @@ def generate(events, backend):
|
||||
' */',
|
||||
'#pragma GCC diagnostic ignored "-Wredundant-decls"',
|
||||
'',
|
||||
'#include "qemu/typedefs.h"',
|
||||
'#include "generated-ust-provider.h"')
|
||||
|
@ -6,7 +6,7 @@ Type-transformation rules.
|
||||
"""
|
||||
|
||||
__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"
|
||||
@ -98,6 +98,7 @@ HOST_2_TCG = {
|
||||
"uint32_t": "TCGv_i32",
|
||||
"uint64_t": "TCGv_i64",
|
||||
"void *" : "TCGv_ptr",
|
||||
"CPUArchState *": "TCGv_env",
|
||||
None: _host_2_tcg,
|
||||
}
|
||||
|
||||
@ -130,6 +131,7 @@ TCG_2_TCG_HELPER_DECL = {
|
||||
"TCGv_ptr": "ptr",
|
||||
"TCGv_i32": "i32",
|
||||
"TCGv_i64": "i64",
|
||||
"TCGv_env": "env",
|
||||
None: _tcg_2_tcg_helper_decl_error,
|
||||
}
|
||||
|
||||
|
70
scripts/tracetool/vcpu.py
Normal file
70
scripts/tracetool/vcpu.py
Normal 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
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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.
|
||||
* See the COPYING file in the top-level directory.
|
||||
@ -11,6 +11,7 @@
|
||||
#define TRACE__CONTROL_H
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/typedefs.h"
|
||||
#include "trace/generated-events.h"
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user