This keeps consistency across all decisions taken during translation when the dynamic state of a vCPU is changed in the middle of translating some guest code.
Signed-off-by: Lluís Vilanova <vilan...@ac.upc.edu> --- include/qom/cpu.h | 3 +++ qom/cpu.c | 2 ++ trace/control-target.c | 21 ++++++++++++++++++--- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 3f79a8e955..31c3e6018d 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -295,6 +295,8 @@ 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_delayed: Delayed changes to trace_dstate (includes all changes + * to @trace_dstate). * @trace_dstate: Dynamic tracing state of events for this vCPU (bitmask). * * State of one CPU core or thread. @@ -370,6 +372,7 @@ struct CPUState { * Dynamically allocated based on bitmap requried to hold up to * trace_get_vcpu_event_count() entries. */ + unsigned long *trace_dstate_delayed; unsigned long *trace_dstate; /* TODO Move common fields from CPUArchState here. */ diff --git a/qom/cpu.c b/qom/cpu.c index 03d9190f8c..8e981ac6c7 100644 --- a/qom/cpu.c +++ b/qom/cpu.c @@ -367,6 +367,7 @@ static void cpu_common_initfn(Object *obj) QTAILQ_INIT(&cpu->breakpoints); QTAILQ_INIT(&cpu->watchpoints); + cpu->trace_dstate_delayed = bitmap_new(trace_get_vcpu_event_count()); cpu->trace_dstate = bitmap_new(trace_get_vcpu_event_count()); cpu_exec_initfn(cpu); @@ -375,6 +376,7 @@ static void cpu_common_initfn(Object *obj) static void cpu_common_finalize(Object *obj) { CPUState *cpu = CPU(obj); + g_free(cpu->trace_dstate_delayed); g_free(cpu->trace_dstate); } diff --git a/trace/control-target.c b/trace/control-target.c index 7ebf6e0bcb..dba3b21bb0 100644 --- a/trace/control-target.c +++ b/trace/control-target.c @@ -1,13 +1,14 @@ /* * Interface for configuring and controlling the state of tracing events. * - * Copyright (C) 2014-2016 Lluís Vilanova <vilan...@ac.upc.edu> + * Copyright (C) 2014-2017 Lluís Vilanova <vilan...@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. */ #include "qemu/osdep.h" +#include "qom/cpu.h" #include "cpu.h" #include "trace.h" #include "trace/control.h" @@ -57,6 +58,13 @@ void trace_event_set_state_dynamic(TraceEvent *ev, bool state) } } +static void trace_event_synchronize_vcpu_state_dynamic( + CPUState *vcpu, run_on_cpu_data ignored) +{ + bitmap_copy(vcpu->trace_dstate, vcpu->trace_dstate_delayed, + trace_get_vcpu_event_count()); +} + void trace_event_set_vcpu_state_dynamic(CPUState *vcpu, TraceEvent *ev, bool state) { @@ -69,13 +77,20 @@ void trace_event_set_vcpu_state_dynamic(CPUState *vcpu, if (state_pre != state) { if (state) { trace_events_enabled_count++; - set_bit(vcpu_id, vcpu->trace_dstate); + set_bit(vcpu_id, vcpu->trace_dstate_delayed); (*ev->dstate)++; } else { trace_events_enabled_count--; - clear_bit(vcpu_id, vcpu->trace_dstate); + clear_bit(vcpu_id, vcpu->trace_dstate_delayed); (*ev->dstate)--; } + /* + * Delay changes until next TB; we want all TBs to be built from a + * single set of dstate values to ensure consistency of generated + * tracing code. + */ + async_run_on_cpu(vcpu, trace_event_synchronize_vcpu_state_dynamic, + RUN_ON_CPU_NULL); } }