Skip to content

Commit

Permalink
target-i386: Split APIC creation from initialization in x86_cpu_reali…
Browse files Browse the repository at this point in the history
…zefn()

When APIC is hotplugged during CPU hotplug, device_set_realized()
calls device_reset() on it. And if QEMU runs in KVM mode, following
call chain will fail:
    apic_reset_common()
        -> kvm_apic_vapic_base_update()
            -> kvm_vcpu_ioctl(cpu->kvm_fd,...)
due to cpu->kvm_fd not being initialized yet.

cpu->kvm_fd is initialized during qemu_init_vcpu() but x86_cpu_apic_init()
can't be moved after it because kvm_init_vcpu() -> kvm_arch_reset_vcpu()
relies on APIC to determine if CPU is BSP for setting initial env->mp_state.

So split APIC device creation from its initialization and realize APIC
after CPU is created, when it's safe to call APIC's reset method.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: liguang <lig.fnst@cn.fujitsu.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
  • Loading branch information
Igor Mammedov authored and afaerber committed Apr 15, 2013
1 parent b28c44e commit 41590ff
Showing 1 changed file with 21 additions and 3 deletions.
24 changes: 21 additions & 3 deletions target-i386/cpu.c
Expand Up @@ -2050,9 +2050,8 @@ static void mce_init(X86CPU *cpu)
}

#ifndef CONFIG_USER_ONLY
static void x86_cpu_apic_init(X86CPU *cpu, Error **errp)
static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
{
static int apic_mapped;
CPUX86State *env = &cpu->env;
APICCommonState *apic;
const char *apic_type = "apic";
Expand All @@ -2075,6 +2074,16 @@ static void x86_cpu_apic_init(X86CPU *cpu, Error **errp)
/* TODO: convert to link<> */
apic = APIC_COMMON(env->apic_state);
apic->cpu = cpu;
}

static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
{
CPUX86State *env = &cpu->env;
static int apic_mapped;

if (env->apic_state == NULL) {
return;
}

if (qdev_init(env->apic_state)) {
error_setg(errp, "APIC device '%s' could not be initialized",
Expand All @@ -2092,6 +2101,10 @@ static void x86_cpu_apic_init(X86CPU *cpu, Error **errp)
apic_mapped = 1;
}
}
#else
static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
{
}
#endif

static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
Expand Down Expand Up @@ -2142,7 +2155,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
qemu_register_reset(x86_cpu_machine_reset_cb, cpu);

if (cpu->env.cpuid_features & CPUID_APIC || smp_cpus > 1) {
x86_cpu_apic_init(cpu, &local_err);
x86_cpu_apic_create(cpu, &local_err);
if (local_err != NULL) {
goto out;
}
Expand All @@ -2151,6 +2164,11 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)

mce_init(cpu);
qemu_init_vcpu(&cpu->env);

x86_cpu_apic_realize(cpu, &local_err);
if (local_err != NULL) {
goto out;
}
cpu_reset(CPU(cpu));

xcc->parent_realize(dev, &local_err);
Expand Down

0 comments on commit 41590ff

Please sign in to comment.