Skip to content

Commit

Permalink
accel/tcg: Complete cpu initialization before registration
Browse files Browse the repository at this point in the history
Delay cpu_list_add until realize is complete, so that cross-cpu
interaction does not happen with incomplete cpu state.  For this,
we must delay plugin initialization out of tcg_exec_realizefn,
because no cpu_index has been assigned.

Fixes a problem with cross-cpu jump cache flushing, when the
jump cache has not yet been allocated.

Fixes: a976a99 ("include/hw/core: Create struct CPUJumpCache")
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
Reported-by: Ilya Leoshkevich <iii@linux.ibm.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
  • Loading branch information
rth7680 committed Oct 31, 2022
1 parent 6317933 commit 4e4fa6c
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 13 deletions.
8 changes: 5 additions & 3 deletions accel/tcg/cpu-exec.c
Expand Up @@ -1052,23 +1052,25 @@ void tcg_exec_realizefn(CPUState *cpu, Error **errp)
cc->tcg_ops->initialize();
tcg_target_initialized = true;
}
tlb_init(cpu);
qemu_plugin_vcpu_init_hook(cpu);

cpu->tb_jmp_cache = g_new0(CPUJumpCache, 1);
tlb_init(cpu);
#ifndef CONFIG_USER_ONLY
tcg_iommu_init_notifier_list(cpu);
#endif /* !CONFIG_USER_ONLY */
/* qemu_plugin_vcpu_init_hook delayed until cpu_index assigned. */
}

/* undo the initializations in reverse order */
void tcg_exec_unrealizefn(CPUState *cpu)
{
qemu_plugin_vcpu_exit_hook(cpu);
#ifndef CONFIG_USER_ONLY
tcg_iommu_free_notifier_list(cpu);
#endif /* !CONFIG_USER_ONLY */

qemu_plugin_vcpu_exit_hook(cpu);
tlb_destroy(cpu);
g_free(cpu->tb_jmp_cache);
}

#ifndef CONFIG_USER_ONLY
Expand Down
16 changes: 7 additions & 9 deletions accel/tcg/translate-all.c
Expand Up @@ -1580,15 +1580,13 @@ void tcg_flush_jmp_cache(CPUState *cpu)
{
CPUJumpCache *jc = cpu->tb_jmp_cache;

if (likely(jc)) {
for (int i = 0; i < TB_JMP_CACHE_SIZE; i++) {
qatomic_set(&jc->array[i].tb, NULL);
}
} else {
/* This should happen once during realize, and thus never race. */
jc = g_new0(CPUJumpCache, 1);
jc = qatomic_xchg(&cpu->tb_jmp_cache, jc);
assert(jc == NULL);
/* During early initialization, the cache may not yet be allocated. */
if (unlikely(jc == NULL)) {
return;
}

for (int i = 0; i < TB_JMP_CACHE_SIZE; i++) {
qatomic_set(&jc->array[i].tb, NULL);
}
}

Expand Down
10 changes: 9 additions & 1 deletion cpu.c
Expand Up @@ -134,15 +134,23 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
/* cache the cpu class for the hotpath */
cpu->cc = CPU_GET_CLASS(cpu);

cpu_list_add(cpu);
if (!accel_cpu_realizefn(cpu, errp)) {
return;
}

/* NB: errp parameter is unused currently */
if (tcg_enabled()) {
tcg_exec_realizefn(cpu, errp);
}

/* Wait until cpu initialization complete before exposing cpu. */
cpu_list_add(cpu);

/* Plugin initialization must wait until cpu_index assigned. */
if (tcg_enabled()) {
qemu_plugin_vcpu_init_hook(cpu);
}

#ifdef CONFIG_USER_ONLY
assert(qdev_get_vmsd(DEVICE(cpu)) == NULL ||
qdev_get_vmsd(DEVICE(cpu))->unmigratable);
Expand Down

0 comments on commit 4e4fa6c

Please sign in to comment.