CPUState *cpu gets added to the cpus list during cpu_exec_init(). It should be removed from cpu_exec_exit().
cpu_exec_init() is called from generic CPU::instance_finalize and some archs like PowerPC call it from CPU unrealizefn. So ensure that we dequeue the cpu only once. Instead of introducing a new field CPUState.queued, I could have used CPUState.cpu_index to check if the cpu is already dequeued from the list. Since that doesn't work for CONFIG_USER_ONLY, I had to add a new field. Signed-off-by: Bharata B Rao <bhar...@linux.vnet.ibm.com> --- exec.c | 11 +++++++++++ include/qom/cpu.h | 1 + 2 files changed, 12 insertions(+) diff --git a/exec.c b/exec.c index 0a4a0c5..b196d68 100644 --- a/exec.c +++ b/exec.c @@ -550,6 +550,10 @@ void cpu_exec_exit(CPUState *cpu) return; } + if (cpu->queued) { + QTAILQ_REMOVE(&cpus, cpu, node); + cpu->queued = false; + } bitmap_clear(cpu_index_map, cpu->cpu_index, 1); cpu->cpu_index = -1; } @@ -568,6 +572,12 @@ static int cpu_get_free_index(Error **errp) void cpu_exec_exit(CPUState *cpu) { + cpu_list_lock(); + if (cpu->queued) { + QTAILQ_REMOVE(&cpus, cpu, node); + cpu->queued = false; + } + cpu_list_unlock(); } #endif @@ -595,6 +605,7 @@ void cpu_exec_init(CPUState *cpu, Error **errp) return; } QTAILQ_INSERT_TAIL(&cpus, cpu, node); + cpu->queued = true; #if defined(CONFIG_USER_ONLY) cpu_list_unlock(); #endif diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 20aabc9..a00e3a8 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -284,6 +284,7 @@ struct CPUState { int gdb_num_regs; int gdb_num_g_regs; QTAILQ_ENTRY(CPUState) node; + bool queued; /* ice debug support */ QTAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints; -- 2.1.0