On 10/07/2015 11:47, alvise rigo wrote:
I tried to use it, but it would then create a deadlock at a very early
stage of the stress test.
The problem is likely related to the fact that flush_queued_work
happens with the global mutex locked.
As Frederick suggested, we can use the newly introduced
flush_queued_safe_work for this.
Regards,
alvise
It depends on the purpose.
async safe work will requires all VCPU to be exited (eg: like your
rendez-vous).
async work doesn't it will just do the work when it's outside cpu-exec().
Theorically this is required only when a VCPU flushes the TLB of an
other VCPU.
That's the behaviour in tlb_flush_all tlb_page_flush_all. The "normal"
tlb_flush should
just work as it only plays with it's own CPUState.
Fred
On Fri, Jul 10, 2015 at 11:36 AM, Paolo Bonzini <pbonz...@redhat.com> wrote:
On 10/07/2015 10:23, Alvise Rigo wrote:
In order to perfom "lazy" TLB invalidation requests, introduce a
queue of callbacks at every vCPU disposal that will be fired just
before entering the next TB.
Suggested-by: Jani Kokkonen <jani.kokko...@huawei.com>
Suggested-by: Claudio Fontana <claudio.font...@huawei.com>
Signed-off-by: Alvise Rigo <a.r...@virtualopensystems.com>
Why is async_run_on_cpu not enough?
Paolo
---
cpus.c | 34 ++++++++++++++++++++++++++++++++++
exec.c | 1 +
include/qom/cpu.h | 20 ++++++++++++++++++++
3 files changed, 55 insertions(+)
diff --git a/cpus.c b/cpus.c
index f4d938e..b9f0329 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1421,6 +1421,7 @@ static int tcg_cpu_exec(CPUArchState *env)
cpu->icount_extra = count;
}
qemu_mutex_unlock_iothread();
+ cpu_exit_callbacks_call_all(cpu);
ret = cpu_exec(env);
cpu->tcg_executing = 0;
@@ -1469,6 +1470,39 @@ static void tcg_exec_all(CPUState *cpu)
cpu->exit_request = 0;
}
+void cpu_exit_callback_add(CPUState *cpu, CPUExitCallback callback,
+ void *opaque)
+{
+ CPUExitCB *cb;
+
+ cb = g_malloc(sizeof(*cb));
+ cb->callback = callback;
+ cb->opaque = opaque;
+
+ qemu_mutex_lock(&cpu->exit_cbs.mutex);
+ QTAILQ_INSERT_TAIL(&cpu->exit_cbs.exit_callbacks, cb, entry);
+ qemu_mutex_unlock(&cpu->exit_cbs.mutex);
+}
+
+void cpu_exit_callbacks_call_all(CPUState *cpu)
+{
+ CPUExitCB *cb, *next;
+
+ if (QTAILQ_EMPTY(&cpu->exit_cbs.exit_callbacks)) {
+ return;
+ }
+
+ QTAILQ_FOREACH_SAFE(cb, &cpu->exit_cbs.exit_callbacks, entry, next) {
+ cb->callback(cpu, cb->opaque);
+
+ /* one-shot callbacks, remove it after using it */
+ qemu_mutex_lock(&cpu->exit_cbs.mutex);
+ QTAILQ_REMOVE(&cpu->exit_cbs.exit_callbacks, cb, entry);
+ g_free(cb);
+ qemu_mutex_unlock(&cpu->exit_cbs.mutex);
+ }
+}
+
void list_cpus(FILE *f, fprintf_function cpu_fprintf, const char *optarg)
{
/* XXX: implement xxx_cpu_list for targets that still miss it */
diff --git a/exec.c b/exec.c
index 51958ed..322f2c6 100644
--- a/exec.c
+++ b/exec.c
@@ -531,6 +531,7 @@ void cpu_exec_init(CPUArchState *env)
cpu->numa_node = 0;
QTAILQ_INIT(&cpu->breakpoints);
QTAILQ_INIT(&cpu->watchpoints);
+ QTAILQ_INIT(&cpu->exit_cbs.exit_callbacks);
#ifndef CONFIG_USER_ONLY
cpu->as = &address_space_memory;
cpu->thread_id = qemu_get_thread_id();
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 8d121b3..0ec020b 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -201,6 +201,24 @@ typedef struct CPUWatchpoint {
QTAILQ_ENTRY(CPUWatchpoint) entry;
} CPUWatchpoint;
+/* vCPU exit callbacks */
+typedef void (*CPUExitCallback)(CPUState *cpu, void *opaque);
+struct CPUExitCBs {
+ QemuMutex mutex;
+ QTAILQ_HEAD(exit_callbacks_head, CPUExitCB) exit_callbacks;
+};
+
+typedef struct CPUExitCB {
+ CPUExitCallback callback;
+ void *opaque;
+
+ QTAILQ_ENTRY(CPUExitCB) entry;
+} CPUExitCB;
+
+void cpu_exit_callback_add(CPUState *cpu, CPUExitCallback callback,
+ void *opaque);
+void cpu_exit_callbacks_call_all(CPUState *cpu);
+
/* Rendezvous support */
#define TCG_RDV_POLLING_PERIOD 10
typedef struct CpuExitRendezvous {
@@ -305,6 +323,8 @@ struct CPUState {
void *opaque;
+ /* One-shot callbacks for stopping requests. */
+ struct CPUExitCBs exit_cbs;
volatile int pending_rdv;
/* In order to avoid passing too many arguments to the MMIO helpers,