mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/stefanha/tags/tracing-pull-request' into staging
# gpg: Signature made Mon 18 Jul 2016 22:59:55 BST # gpg: using RSA key 0x9CA4ABB381AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" # Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35 775A 9CA4 ABB3 81AB 73C8 * remotes/stefanha/tags/tracing-pull-request: trace: Add QAPI/QMP interfaces to query and control per-vCPU tracing state trace: Allow event name pattern in "info trace-events" trace: Conditionally trace events based on their per-vCPU state trace: Add per-vCPU tracing states for events with the 'vcpu' property trace: Cosmetic changes on fast-path tracing disas: Remove unused macro '_' trace: Identify events with the 'vcpu' property trace: [bsd-user] Commandline arguments to control tracing trace: [linux-user] Commandline arguments to control tracing Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
+19
-3
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "qapi/error.h"
|
||||
#include "qemu.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "qemu/path.h"
|
||||
#include "qemu/help_option.h"
|
||||
/* For tb_lock */
|
||||
@@ -30,6 +31,8 @@
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/envlist.h"
|
||||
#include "exec/log.h"
|
||||
#include "trace/control.h"
|
||||
#include "glib-compat.h"
|
||||
|
||||
int singlestep;
|
||||
unsigned long mmap_min_addr;
|
||||
@@ -687,6 +690,8 @@ static void usage(void)
|
||||
"-p pagesize set the host page size to 'pagesize'\n"
|
||||
"-singlestep always run in singlestep mode\n"
|
||||
"-strace log system calls\n"
|
||||
"-trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
|
||||
" specify tracing options\n"
|
||||
"\n"
|
||||
"Environment variables:\n"
|
||||
"QEMU_STRACE Print system calls and arguments similar to the\n"
|
||||
@@ -735,6 +740,7 @@ int main(int argc, char **argv)
|
||||
int gdbstub_port = 0;
|
||||
char **target_environ, **wrk;
|
||||
envlist_t *envlist = NULL;
|
||||
char *trace_file = NULL;
|
||||
bsd_type = target_openbsd;
|
||||
|
||||
if (argc <= 1)
|
||||
@@ -754,8 +760,10 @@ int main(int argc, char **argv)
|
||||
|
||||
cpu_model = NULL;
|
||||
|
||||
qemu_add_opts(&qemu_trace_opts);
|
||||
|
||||
optind = 1;
|
||||
for(;;) {
|
||||
for (;;) {
|
||||
if (optind >= argc)
|
||||
break;
|
||||
r = argv[optind];
|
||||
@@ -840,8 +848,10 @@ int main(int argc, char **argv)
|
||||
singlestep = 1;
|
||||
} else if (!strcmp(r, "strace")) {
|
||||
do_strace = 1;
|
||||
} else
|
||||
{
|
||||
} else if (!strcmp(r, "trace")) {
|
||||
g_free(trace_file);
|
||||
trace_file = trace_opt_parse(optarg);
|
||||
} else {
|
||||
usage();
|
||||
}
|
||||
}
|
||||
@@ -865,6 +875,11 @@ int main(int argc, char **argv)
|
||||
}
|
||||
filename = argv[optind];
|
||||
|
||||
if (!trace_init_backends()) {
|
||||
exit(1);
|
||||
}
|
||||
trace_init_file(trace_file);
|
||||
|
||||
/* Zero out regs */
|
||||
memset(regs, 0, sizeof(struct target_pt_regs));
|
||||
|
||||
@@ -1116,6 +1131,7 @@ int main(int argc, char **argv)
|
||||
gdbserver_start (gdbstub_port);
|
||||
gdb_handlesig(cpu, 0);
|
||||
}
|
||||
trace_init_vcpu_events();
|
||||
cpu_loop(env);
|
||||
/* never exits */
|
||||
return 0;
|
||||
|
||||
+3
-3
@@ -521,7 +521,7 @@ static unsigned
|
||||
insert_bdisp(unsigned insn, int value, const char **errmsg)
|
||||
{
|
||||
if (errmsg != (const char **)NULL && (value & 3))
|
||||
*errmsg = _("branch operand unaligned");
|
||||
*errmsg = "branch operand unaligned";
|
||||
return insn | ((value / 4) & 0x1FFFFF);
|
||||
}
|
||||
|
||||
@@ -539,7 +539,7 @@ static unsigned
|
||||
insert_jhint(unsigned insn, int value, const char **errmsg)
|
||||
{
|
||||
if (errmsg != (const char **)NULL && (value & 3))
|
||||
*errmsg = _("jump hint unaligned");
|
||||
*errmsg = "jump hint unaligned";
|
||||
return insn | ((value / 4) & 0x3FFF);
|
||||
}
|
||||
|
||||
@@ -556,7 +556,7 @@ static unsigned
|
||||
insert_ev6hwjhint(unsigned insn, int value, const char **errmsg)
|
||||
{
|
||||
if (errmsg != (const char **)NULL && (value & 3))
|
||||
*errmsg = _("jump hint unaligned");
|
||||
*errmsg = "jump hint unaligned";
|
||||
return insn | ((value / 4) & 0x1FFF);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1817,7 +1817,7 @@ print_insn_coprocessor (bfd_vma pc, struct disassemble_info *info, long given,
|
||||
func (stream, "e");
|
||||
break;
|
||||
default:
|
||||
func (stream, _("<illegal precision>"));
|
||||
func (stream, "<illegal precision>");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
+1
-1
@@ -3406,7 +3406,7 @@ static const struct dis386 three_byte_table[][256] = {
|
||||
}
|
||||
};
|
||||
|
||||
#define INTERNAL_DISASSEMBLER_ERROR _("<internal disassembler error>")
|
||||
#define INTERNAL_DISASSEMBLER_ERROR "<internal disassembler error>"
|
||||
|
||||
static void
|
||||
ckprefix (void)
|
||||
|
||||
+2
-2
@@ -1676,7 +1676,7 @@ print_insn_arg (const char *d,
|
||||
(*info->fprintf_func) (info->stream, "%%sfc");
|
||||
else
|
||||
/* xgettext:c-format */
|
||||
(*info->fprintf_func) (info->stream, _("<function code %d>"), fc);
|
||||
(*info->fprintf_func) (info->stream, "<function code %d>", fc);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1827,7 +1827,7 @@ match_insn_m68k (bfd_vma memaddr,
|
||||
{
|
||||
info->fprintf_func (info->stream,
|
||||
/* xgettext:c-format */
|
||||
_("<internal error in opcode table: %s %s>\n"),
|
||||
"<internal error in opcode table: %s %s>\n",
|
||||
best->name, best->args);
|
||||
info->fprintf_func = save_printer;
|
||||
info->print_address_func = save_print_address;
|
||||
|
||||
+25
-25
@@ -4257,7 +4257,7 @@ print_insn_args (const char *d,
|
||||
case '\0':
|
||||
/* xgettext:c-format */
|
||||
(*info->fprintf_func) (info->stream,
|
||||
_("# internal error, incomplete extension sequence (+)"));
|
||||
"# internal error, incomplete extension sequence (+)");
|
||||
return;
|
||||
|
||||
case 'A':
|
||||
@@ -4515,7 +4515,7 @@ print_insn_args (const char *d,
|
||||
default:
|
||||
/* xgettext:c-format */
|
||||
(*info->fprintf_func) (info->stream,
|
||||
_("# internal error, undefined extension sequence (+%c)"),
|
||||
"# internal error, undefined extension sequence (+%c)",
|
||||
*d);
|
||||
return;
|
||||
}
|
||||
@@ -4875,7 +4875,7 @@ print_insn_args (const char *d,
|
||||
default:
|
||||
/* xgettext:c-format */
|
||||
(*info->fprintf_func) (info->stream,
|
||||
_("# internal error, undefined modifier(%c)"),
|
||||
"# internal error, undefined modifier(%c)",
|
||||
*d);
|
||||
return;
|
||||
}
|
||||
@@ -5739,7 +5739,7 @@ print_mips16_insn_arg (char type,
|
||||
/* xgettext:c-format */
|
||||
(*info->fprintf_func)
|
||||
(info->stream,
|
||||
_("# internal disassembler error, unrecognised modifier (%c)"),
|
||||
"# internal disassembler error, unrecognised modifier (%c)",
|
||||
type);
|
||||
abort ();
|
||||
}
|
||||
@@ -5750,51 +5750,51 @@ print_mips_disassembler_options (FILE *stream)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
fprintf (stream, _("\n\
|
||||
fprintf (stream, "\n\
|
||||
The following MIPS specific disassembler options are supported for use\n\
|
||||
with the -M switch (multiple options should be separated by commas):\n"));
|
||||
with the -M switch (multiple options should be separated by commas):\n");
|
||||
|
||||
fprintf (stream, _("\n\
|
||||
fprintf (stream, "\n\
|
||||
gpr-names=ABI Print GPR names according to specified ABI.\n\
|
||||
Default: based on binary being disassembled.\n"));
|
||||
Default: based on binary being disassembled.\n");
|
||||
|
||||
fprintf (stream, _("\n\
|
||||
fprintf (stream, "\n\
|
||||
fpr-names=ABI Print FPR names according to specified ABI.\n\
|
||||
Default: numeric.\n"));
|
||||
Default: numeric.\n");
|
||||
|
||||
fprintf (stream, _("\n\
|
||||
fprintf (stream, "\n\
|
||||
cp0-names=ARCH Print CP0 register names according to\n\
|
||||
specified architecture.\n\
|
||||
Default: based on binary being disassembled.\n"));
|
||||
Default: based on binary being disassembled.\n");
|
||||
|
||||
fprintf (stream, _("\n\
|
||||
fprintf (stream, "\n\
|
||||
hwr-names=ARCH Print HWR names according to specified\n\
|
||||
architecture.\n\
|
||||
Default: based on binary being disassembled.\n"));
|
||||
Default: based on binary being disassembled.\n");
|
||||
|
||||
fprintf (stream, _("\n\
|
||||
fprintf (stream, "\n\
|
||||
reg-names=ABI Print GPR and FPR names according to\n\
|
||||
specified ABI.\n"));
|
||||
specified ABI.\n");
|
||||
|
||||
fprintf (stream, _("\n\
|
||||
fprintf (stream, "\n\
|
||||
reg-names=ARCH Print CP0 register and HWR names according to\n\
|
||||
specified architecture.\n"));
|
||||
specified architecture.\n");
|
||||
|
||||
fprintf (stream, _("\n\
|
||||
fprintf (stream, "\n\
|
||||
For the options above, the following values are supported for \"ABI\":\n\
|
||||
"));
|
||||
");
|
||||
for (i = 0; i < ARRAY_SIZE (mips_abi_choices); i++)
|
||||
fprintf (stream, " %s", mips_abi_choices[i].name);
|
||||
fprintf (stream, _("\n"));
|
||||
fprintf (stream, "\n");
|
||||
|
||||
fprintf (stream, _("\n\
|
||||
fprintf (stream, "\n\
|
||||
For the options above, The following values are supported for \"ARCH\":\n\
|
||||
"));
|
||||
");
|
||||
for (i = 0; i < ARRAY_SIZE (mips_arch_choices); i++)
|
||||
if (*mips_arch_choices[i].name != '\0')
|
||||
fprintf (stream, " %s", mips_arch_choices[i].name);
|
||||
fprintf (stream, _("\n"));
|
||||
fprintf (stream, "\n");
|
||||
|
||||
fprintf (stream, _("\n"));
|
||||
fprintf (stream, "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
+11
-11
@@ -1120,7 +1120,7 @@ insert_bo (unsigned long insn,
|
||||
const char **errmsg)
|
||||
{
|
||||
if (!valid_bo (value, dialect, 0))
|
||||
*errmsg = _("invalid conditional option");
|
||||
*errmsg = "invalid conditional option";
|
||||
return insn | ((value & 0x1f) << 21);
|
||||
}
|
||||
|
||||
@@ -1148,9 +1148,9 @@ insert_boe (unsigned long insn,
|
||||
const char **errmsg)
|
||||
{
|
||||
if (!valid_bo (value, dialect, 0))
|
||||
*errmsg = _("invalid conditional option");
|
||||
*errmsg = "invalid conditional option";
|
||||
else if ((value & 1) != 0)
|
||||
*errmsg = _("attempt to set y bit when using + or - modifier");
|
||||
*errmsg = "attempt to set y bit when using + or - modifier";
|
||||
|
||||
return insn | ((value & 0x1f) << 21);
|
||||
}
|
||||
@@ -1182,7 +1182,7 @@ insert_fxm (unsigned long insn,
|
||||
{
|
||||
if (value == 0 || (value & -value) != value)
|
||||
{
|
||||
*errmsg = _("invalid mask field");
|
||||
*errmsg = "invalid mask field";
|
||||
value = 0;
|
||||
}
|
||||
}
|
||||
@@ -1208,7 +1208,7 @@ insert_fxm (unsigned long insn,
|
||||
/* Any other value on mfcr is an error. */
|
||||
else if ((insn & (0x3ff << 1)) == 19 << 1)
|
||||
{
|
||||
*errmsg = _("ignoring invalid mfcr mask");
|
||||
*errmsg = "ignoring invalid mfcr mask";
|
||||
value = 0;
|
||||
}
|
||||
|
||||
@@ -1258,7 +1258,7 @@ insert_mbe (unsigned long insn,
|
||||
|
||||
if (uval == 0)
|
||||
{
|
||||
*errmsg = _("illegal bitmask");
|
||||
*errmsg = "illegal bitmask";
|
||||
return insn;
|
||||
}
|
||||
|
||||
@@ -1293,7 +1293,7 @@ insert_mbe (unsigned long insn,
|
||||
me = 32;
|
||||
|
||||
if (count != 2 && (count != 0 || ! last))
|
||||
*errmsg = _("illegal bitmask");
|
||||
*errmsg = "illegal bitmask";
|
||||
|
||||
return insn | (mb << 6) | ((me - 1) << 1);
|
||||
}
|
||||
@@ -1413,7 +1413,7 @@ insert_ram (unsigned long insn,
|
||||
const char **errmsg)
|
||||
{
|
||||
if ((unsigned long) value >= ((insn >> 21) & 0x1f))
|
||||
*errmsg = _("index register in load range");
|
||||
*errmsg = "index register in load range";
|
||||
return insn | ((value & 0x1f) << 16);
|
||||
}
|
||||
|
||||
@@ -1429,7 +1429,7 @@ insert_raq (unsigned long insn,
|
||||
long rtvalue = (insn & RT_MASK) >> 21;
|
||||
|
||||
if (value == rtvalue)
|
||||
*errmsg = _("source and target register operands must be different");
|
||||
*errmsg = "source and target register operands must be different";
|
||||
return insn | ((value & 0x1f) << 16);
|
||||
}
|
||||
|
||||
@@ -1444,7 +1444,7 @@ insert_ras (unsigned long insn,
|
||||
const char **errmsg)
|
||||
{
|
||||
if (value == 0)
|
||||
*errmsg = _("invalid register operand when updating");
|
||||
*errmsg = "invalid register operand when updating";
|
||||
return insn | ((value & 0x1f) << 16);
|
||||
}
|
||||
|
||||
@@ -1526,7 +1526,7 @@ insert_sprg (unsigned long insn,
|
||||
if (value > 7
|
||||
|| (value > 3
|
||||
&& (dialect & (PPC_OPCODE_BOOKE | PPC_OPCODE_403)) == 0))
|
||||
*errmsg = _("invalid sprg number");
|
||||
*errmsg = "invalid sprg number";
|
||||
|
||||
/* If this is mfsprg4..7 then use spr 260..263 which can be read in
|
||||
user mode. Anything else must use spr 272..279. */
|
||||
|
||||
+3
-3
@@ -2494,7 +2494,7 @@ compare_opcodes (const void * a, const void * b)
|
||||
fprintf
|
||||
(stderr,
|
||||
/* xgettext:c-format */
|
||||
_("Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n"),
|
||||
"Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
|
||||
op0->name, match0, lose0);
|
||||
op0->lose &= ~op0->match;
|
||||
lose0 = op0->lose;
|
||||
@@ -2505,7 +2505,7 @@ compare_opcodes (const void * a, const void * b)
|
||||
fprintf
|
||||
(stderr,
|
||||
/* xgettext:c-format */
|
||||
_("Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n"),
|
||||
"Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
|
||||
op1->name, match1, lose1);
|
||||
op1->lose &= ~op1->match;
|
||||
lose1 = op1->lose;
|
||||
@@ -2555,7 +2555,7 @@ compare_opcodes (const void * a, const void * b)
|
||||
else
|
||||
fprintf (stderr,
|
||||
/* xgettext:c-format */
|
||||
_("Internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n"),
|
||||
"Internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n",
|
||||
op0->name, op1->name);
|
||||
}
|
||||
|
||||
|
||||
@@ -646,10 +646,12 @@ ETEXI
|
||||
|
||||
{
|
||||
.name = "trace-events",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show available trace-events & their state",
|
||||
.args_type = "name:s?,vcpu:i?",
|
||||
.params = "[name] [vcpu]",
|
||||
.help = "show available trace-events & their state "
|
||||
"(name: event name pattern; vcpu: vCPU to query, default is any)",
|
||||
.mhandler.cmd = hmp_info_trace_events,
|
||||
.command_completion = info_trace_events_completion,
|
||||
},
|
||||
|
||||
STEXI
|
||||
|
||||
+4
-3
@@ -281,9 +281,10 @@ ETEXI
|
||||
|
||||
{
|
||||
.name = "trace-event",
|
||||
.args_type = "name:s,option:b",
|
||||
.params = "name on|off",
|
||||
.help = "changes status of a specific trace event",
|
||||
.args_type = "name:s,option:b,vcpu:i?",
|
||||
.params = "name on|off [vcpu]",
|
||||
.help = "changes status of a specific trace event "
|
||||
"(vcpu: vCPU to set, default is all)",
|
||||
.mhandler.cmd = hmp_trace_event,
|
||||
.command_completion = trace_event_completion,
|
||||
},
|
||||
|
||||
@@ -115,6 +115,7 @@ void set_link_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||
void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||
void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||
void ringbuf_write_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||
void info_trace_events_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||
void trace_event_completion(ReadLineState *rs, int nb_args, const char *str);
|
||||
void watchdog_action_completion(ReadLineState *rs, int nb_args,
|
||||
const char *str);
|
||||
|
||||
@@ -477,7 +477,6 @@ int generic_symbol_at_address(bfd_vma, struct disassemble_info *);
|
||||
(INFO).disassembler_options = NULL, \
|
||||
(INFO).insn_info_valid = 0
|
||||
|
||||
#define _(x) x
|
||||
#define ATTRIBUTE_UNUSED __attribute__((unused))
|
||||
|
||||
/* from libbfd */
|
||||
|
||||
@@ -24,8 +24,10 @@
|
||||
#include "disas/bfd.h"
|
||||
#include "exec/hwaddr.h"
|
||||
#include "exec/memattrs.h"
|
||||
#include "qemu/bitmap.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "trace/generated-events.h"
|
||||
|
||||
typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size,
|
||||
void *opaque);
|
||||
@@ -280,6 +282,7 @@ struct qemu_work_item {
|
||||
* @kvm_fd: vCPU file descriptor for KVM.
|
||||
* @work_mutex: Lock to prevent multiple access to queued_work_*.
|
||||
* @queued_work_first: First asynchronous work pending.
|
||||
* @trace_dstate: Dynamic tracing state of events for this vCPU (bitmask).
|
||||
*
|
||||
* State of one CPU core or thread.
|
||||
*/
|
||||
@@ -347,6 +350,9 @@ struct CPUState {
|
||||
struct KVMState *kvm_state;
|
||||
struct kvm_run *kvm_run;
|
||||
|
||||
/* Used for events with 'vcpu' and *without* the 'disabled' properties */
|
||||
DECLARE_BITMAP(trace_dstate, TRACE_VCPU_EVENT_COUNT);
|
||||
|
||||
/* TODO Move common fields from CPUArchState here. */
|
||||
int cpu_index; /* used by alpha TCG */
|
||||
uint32_t halted; /* used by alpha, cris, ppc TCG */
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qemu.h"
|
||||
#include "qemu/path.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/help_option.h"
|
||||
#include "cpu.h"
|
||||
@@ -33,6 +34,8 @@
|
||||
#include "qemu/envlist.h"
|
||||
#include "elf.h"
|
||||
#include "exec/log.h"
|
||||
#include "trace/control.h"
|
||||
#include "glib-compat.h"
|
||||
|
||||
char *exec_path;
|
||||
|
||||
@@ -4001,6 +4004,13 @@ static void handle_arg_version(const char *arg)
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static char *trace_file;
|
||||
static void handle_arg_trace(const char *arg)
|
||||
{
|
||||
g_free(trace_file);
|
||||
trace_file = trace_opt_parse(arg);
|
||||
}
|
||||
|
||||
struct qemu_argument {
|
||||
const char *argv;
|
||||
const char *env;
|
||||
@@ -4048,6 +4058,8 @@ static const struct qemu_argument arg_table[] = {
|
||||
"", "log system calls"},
|
||||
{"seed", "QEMU_RAND_SEED", true, handle_arg_randseed,
|
||||
"", "Seed for pseudo-random number generator"},
|
||||
{"trace", "QEMU_TRACE", true, handle_arg_trace,
|
||||
"", "[[enable=]<pattern>][,events=<file>][,file=<file>]"},
|
||||
{"version", "QEMU_VERSION", false, handle_arg_version,
|
||||
"", "display version information and exit"},
|
||||
{NULL, NULL, false, NULL, NULL, NULL}
|
||||
@@ -4237,8 +4249,15 @@ int main(int argc, char **argv, char **envp)
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
qemu_add_opts(&qemu_trace_opts);
|
||||
|
||||
optind = parse_args(argc, argv);
|
||||
|
||||
if (!trace_init_backends()) {
|
||||
exit(1);
|
||||
}
|
||||
trace_init_file(trace_file);
|
||||
|
||||
/* Zero out regs */
|
||||
memset(regs, 0, sizeof(struct target_pt_regs));
|
||||
|
||||
@@ -4791,6 +4810,7 @@ int main(int argc, char **argv, char **envp)
|
||||
}
|
||||
gdb_handlesig(cpu, 0);
|
||||
}
|
||||
trace_init_vcpu_events();
|
||||
cpu_loop(env);
|
||||
/* never exits */
|
||||
return 0;
|
||||
|
||||
@@ -904,9 +904,16 @@ static void hmp_trace_event(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
const char *tp_name = qdict_get_str(qdict, "name");
|
||||
bool new_state = qdict_get_bool(qdict, "option");
|
||||
bool has_vcpu = qdict_haskey(qdict, "vcpu");
|
||||
int vcpu = qdict_get_try_int(qdict, "vcpu", 0);
|
||||
Error *local_err = NULL;
|
||||
|
||||
qmp_trace_event_set_state(tp_name, new_state, true, true, &local_err);
|
||||
if (vcpu < 0) {
|
||||
monitor_printf(mon, "argument vcpu must be positive");
|
||||
return;
|
||||
}
|
||||
|
||||
qmp_trace_event_set_state(tp_name, new_state, true, true, has_vcpu, vcpu, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
}
|
||||
@@ -1065,8 +1072,26 @@ static void hmp_info_cpustats(Monitor *mon, const QDict *qdict)
|
||||
|
||||
static void hmp_info_trace_events(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
TraceEventInfoList *events = qmp_trace_event_get_state("*", NULL);
|
||||
const char *name = qdict_get_try_str(qdict, "name");
|
||||
bool has_vcpu = qdict_haskey(qdict, "vcpu");
|
||||
int vcpu = qdict_get_try_int(qdict, "vcpu", 0);
|
||||
TraceEventInfoList *events;
|
||||
TraceEventInfoList *elem;
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (name == NULL) {
|
||||
name = "*";
|
||||
}
|
||||
if (vcpu < 0) {
|
||||
monitor_printf(mon, "argument vcpu must be positive");
|
||||
return;
|
||||
}
|
||||
|
||||
events = qmp_trace_event_get_state(name, has_vcpu, vcpu, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
for (elem = events; elem != NULL; elem = elem->next) {
|
||||
monitor_printf(mon, "%s : state %u\n",
|
||||
@@ -3296,6 +3321,23 @@ void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||
}
|
||||
}
|
||||
|
||||
void info_trace_events_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
len = strlen(str);
|
||||
readline_set_completion_index(rs, len);
|
||||
if (nb_args == 2) {
|
||||
TraceEventID id;
|
||||
for (id = 0; id < trace_event_count(); id++) {
|
||||
const char *event_name = trace_event_get_name(trace_event_id(id));
|
||||
if (!strncmp(str, event_name, len)) {
|
||||
readline_add_completion(rs, event_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void trace_event_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
+29
-4
@@ -1,6 +1,6 @@
|
||||
# -*- mode: python -*-
|
||||
#
|
||||
# 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.
|
||||
@@ -29,11 +29,15 @@
|
||||
#
|
||||
# @name: Event name.
|
||||
# @state: Tracing state.
|
||||
# @vcpu: Whether this is a per-vCPU event (since 2.7).
|
||||
#
|
||||
# An event is per-vCPU if it has the "vcpu" property in the "trace-events"
|
||||
# files.
|
||||
#
|
||||
# Since 2.2
|
||||
##
|
||||
{ 'struct': 'TraceEventInfo',
|
||||
'data': {'name': 'str', 'state': 'TraceEventState'} }
|
||||
'data': {'name': 'str', 'state': 'TraceEventState', 'vcpu': 'bool'} }
|
||||
|
||||
##
|
||||
# @trace-event-get-state:
|
||||
@@ -41,13 +45,23 @@
|
||||
# Query the state of events.
|
||||
#
|
||||
# @name: Event name pattern (case-sensitive glob).
|
||||
# @vcpu: #optional The vCPU to query (any by default; since 2.7).
|
||||
#
|
||||
# Returns: a list of @TraceEventInfo for the matching events
|
||||
#
|
||||
# An event is returned if:
|
||||
# - its name matches the @name pattern, and
|
||||
# - if @vcpu is given, the event has the "vcpu" property.
|
||||
#
|
||||
# Therefore, if @vcpu is given, the operation will only match per-vCPU events,
|
||||
# returning their state on the specified vCPU. Special case: if @name is an
|
||||
# exact match, @vcpu is given and the event does not have the "vcpu" property,
|
||||
# an error is returned.
|
||||
#
|
||||
# Since 2.2
|
||||
##
|
||||
{ 'command': 'trace-event-get-state',
|
||||
'data': {'name': 'str'},
|
||||
'data': {'name': 'str', '*vcpu': 'int'},
|
||||
'returns': ['TraceEventInfo'] }
|
||||
|
||||
##
|
||||
@@ -58,8 +72,19 @@
|
||||
# @name: Event name pattern (case-sensitive glob).
|
||||
# @enable: Whether to enable tracing.
|
||||
# @ignore-unavailable: #optional Do not match unavailable events with @name.
|
||||
# @vcpu: #optional The vCPU to act upon (all by default; since 2.7).
|
||||
#
|
||||
# An event's state is modified if:
|
||||
# - its name matches the @name pattern, and
|
||||
# - if @vcpu is given, the event has the "vcpu" property.
|
||||
#
|
||||
# Therefore, if @vcpu is given, the operation will only match per-vCPU events,
|
||||
# setting their state on the specified vCPU. Special case: if @name is an exact
|
||||
# match, @vcpu is given and the event does not have the "vcpu" property, an
|
||||
# error is returned.
|
||||
#
|
||||
# Since 2.2
|
||||
##
|
||||
{ 'command': 'trace-event-set-state',
|
||||
'data': {'name': 'str', 'enable': 'bool', '*ignore-unavailable': 'bool'} }
|
||||
'data': {'name': 'str', 'enable': 'bool', '*ignore-unavailable': 'bool',
|
||||
'*vcpu': 'int'} }
|
||||
|
||||
+33
-2
@@ -4715,7 +4715,7 @@ EQMP
|
||||
|
||||
{
|
||||
.name = "trace-event-get-state",
|
||||
.args_type = "name:s",
|
||||
.args_type = "name:s,vcpu:i?",
|
||||
.mhandler.cmd_new = qmp_marshal_trace_event_get_state,
|
||||
},
|
||||
|
||||
@@ -4725,6 +4725,20 @@ trace-event-get-state
|
||||
|
||||
Query the state of events.
|
||||
|
||||
Arguments:
|
||||
|
||||
- "name": Event name pattern (json-string).
|
||||
- "vcpu": The vCPU to query, any vCPU by default (json-int, optional).
|
||||
|
||||
An event is returned if:
|
||||
- its name matches the "name" pattern, and
|
||||
- if "vcpu" is given, the event has the "vcpu" property.
|
||||
|
||||
Therefore, if "vcpu" is given, the operation will only match per-vCPU events,
|
||||
returning their state on the specified vCPU. Special case: if "name" is an exact
|
||||
match, "vcpu" is given and the event does not have the "vcpu" property, an error
|
||||
is returned.
|
||||
|
||||
Example:
|
||||
|
||||
-> { "execute": "trace-event-get-state", "arguments": { "name": "qemu_memalign" } }
|
||||
@@ -4733,7 +4747,7 @@ EQMP
|
||||
|
||||
{
|
||||
.name = "trace-event-set-state",
|
||||
.args_type = "name:s,enable:b,ignore-unavailable:b?",
|
||||
.args_type = "name:s,enable:b,ignore-unavailable:b?,vcpu:i?",
|
||||
.mhandler.cmd_new = qmp_marshal_trace_event_set_state,
|
||||
},
|
||||
|
||||
@@ -4743,6 +4757,23 @@ trace-event-set-state
|
||||
|
||||
Set the state of events.
|
||||
|
||||
Arguments:
|
||||
|
||||
- "name": Event name pattern (json-string).
|
||||
- "enable": Whether to enable or disable the event (json-bool).
|
||||
- "ignore-unavailable": Whether to ignore errors for events that cannot be
|
||||
changed (json-bool, optional).
|
||||
- "vcpu": The vCPU to act upon, all vCPUs by default (json-int, optional).
|
||||
|
||||
An event's state is modified if:
|
||||
- its name matches the "name" pattern, and
|
||||
- if "vcpu" is given, the event has the "vcpu" property.
|
||||
|
||||
Therefore, if "vcpu" is given, the operation will only match per-vCPU events,
|
||||
setting their state on the specified vCPU. Special case: if "name" is an exact
|
||||
match, "vcpu" is given and the event does not have the "vcpu" property, an error
|
||||
is returned.
|
||||
|
||||
Example:
|
||||
|
||||
-> { "execute": "trace-event-set-state", "arguments": { "name": "qemu_memalign", "enable": "true" } }
|
||||
|
||||
@@ -345,6 +345,7 @@ static void cpu_common_initfn(Object *obj)
|
||||
qemu_mutex_init(&cpu->work_mutex);
|
||||
QTAILQ_INIT(&cpu->breakpoints);
|
||||
QTAILQ_INIT(&cpu->watchpoints);
|
||||
bitmap_zero(cpu->trace_dstate, TRACE_VCPU_EVENT_COUNT);
|
||||
}
|
||||
|
||||
static void cpu_common_finalize(Object *obj)
|
||||
|
||||
@@ -6,7 +6,7 @@ DTrace/SystemTAP backend.
|
||||
"""
|
||||
|
||||
__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"
|
||||
@@ -41,6 +41,6 @@ def generate_h_begin(events):
|
||||
|
||||
|
||||
def generate_h(event):
|
||||
out(' QEMU_%(uppername)s(%(argnames)s);',
|
||||
out(' QEMU_%(uppername)s(%(argnames)s);',
|
||||
uppername=event.name.upper(),
|
||||
argnames=", ".join(event.args.names()))
|
||||
|
||||
@@ -30,17 +30,17 @@ def generate_h(event):
|
||||
if len(event.args) > 0:
|
||||
argnames = ", " + argnames
|
||||
|
||||
out(' {',
|
||||
' char ftrace_buf[MAX_TRACE_STRLEN];',
|
||||
' int unused __attribute__ ((unused));',
|
||||
' int trlen;',
|
||||
' if (trace_event_get_state(%(event_id)s)) {',
|
||||
' 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);',
|
||||
out(' {',
|
||||
' char ftrace_buf[MAX_TRACE_STRLEN];',
|
||||
' int unused __attribute__ ((unused));',
|
||||
' int trlen;',
|
||||
' if (trace_event_get_state(%(event_id)s)) {',
|
||||
' 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=event.name,
|
||||
args=event.args,
|
||||
event_id="TRACE_" + event.name.upper(),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user