mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-26 21:10:42 +00:00
accel/tcg: Complete cpu initialization before registration
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: a976a99a29
("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>
This commit is contained in:
parent
6317933086
commit
4e4fa6c12d
@ -1052,23 +1052,25 @@ void tcg_exec_realizefn(CPUState *cpu, Error **errp)
|
|||||||
cc->tcg_ops->initialize();
|
cc->tcg_ops->initialize();
|
||||||
tcg_target_initialized = true;
|
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
|
#ifndef CONFIG_USER_ONLY
|
||||||
tcg_iommu_init_notifier_list(cpu);
|
tcg_iommu_init_notifier_list(cpu);
|
||||||
#endif /* !CONFIG_USER_ONLY */
|
#endif /* !CONFIG_USER_ONLY */
|
||||||
|
/* qemu_plugin_vcpu_init_hook delayed until cpu_index assigned. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* undo the initializations in reverse order */
|
/* undo the initializations in reverse order */
|
||||||
void tcg_exec_unrealizefn(CPUState *cpu)
|
void tcg_exec_unrealizefn(CPUState *cpu)
|
||||||
{
|
{
|
||||||
|
qemu_plugin_vcpu_exit_hook(cpu);
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
tcg_iommu_free_notifier_list(cpu);
|
tcg_iommu_free_notifier_list(cpu);
|
||||||
#endif /* !CONFIG_USER_ONLY */
|
#endif /* !CONFIG_USER_ONLY */
|
||||||
|
|
||||||
qemu_plugin_vcpu_exit_hook(cpu);
|
|
||||||
tlb_destroy(cpu);
|
tlb_destroy(cpu);
|
||||||
|
g_free(cpu->tb_jmp_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
@ -1580,15 +1580,13 @@ void tcg_flush_jmp_cache(CPUState *cpu)
|
|||||||
{
|
{
|
||||||
CPUJumpCache *jc = cpu->tb_jmp_cache;
|
CPUJumpCache *jc = cpu->tb_jmp_cache;
|
||||||
|
|
||||||
if (likely(jc)) {
|
/* During early initialization, the cache may not yet be allocated. */
|
||||||
for (int i = 0; i < TB_JMP_CACHE_SIZE; i++) {
|
if (unlikely(jc == NULL)) {
|
||||||
qatomic_set(&jc->array[i].tb, NULL);
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
/* This should happen once during realize, and thus never race. */
|
for (int i = 0; i < TB_JMP_CACHE_SIZE; i++) {
|
||||||
jc = g_new0(CPUJumpCache, 1);
|
qatomic_set(&jc->array[i].tb, NULL);
|
||||||
jc = qatomic_xchg(&cpu->tb_jmp_cache, jc);
|
|
||||||
assert(jc == NULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
cpu.c
10
cpu.c
@ -134,15 +134,23 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
|
|||||||
/* cache the cpu class for the hotpath */
|
/* cache the cpu class for the hotpath */
|
||||||
cpu->cc = CPU_GET_CLASS(cpu);
|
cpu->cc = CPU_GET_CLASS(cpu);
|
||||||
|
|
||||||
cpu_list_add(cpu);
|
|
||||||
if (!accel_cpu_realizefn(cpu, errp)) {
|
if (!accel_cpu_realizefn(cpu, errp)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NB: errp parameter is unused currently */
|
/* NB: errp parameter is unused currently */
|
||||||
if (tcg_enabled()) {
|
if (tcg_enabled()) {
|
||||||
tcg_exec_realizefn(cpu, errp);
|
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
|
#ifdef CONFIG_USER_ONLY
|
||||||
assert(qdev_get_vmsd(DEVICE(cpu)) == NULL ||
|
assert(qdev_get_vmsd(DEVICE(cpu)) == NULL ||
|
||||||
qdev_get_vmsd(DEVICE(cpu))->unmigratable);
|
qdev_get_vmsd(DEVICE(cpu))->unmigratable);
|
||||||
|
Loading…
Reference in New Issue
Block a user