]> rtime.felk.cvut.cz Git - lisovros/qemu_apohw.git/commitdiff
target-i386: move cpu halted decision into x86_cpu_reset
authorIgor Mammedov <imammedo@redhat.com>
Mon, 23 Jul 2012 13:22:27 +0000 (15:22 +0200)
committerAnthony Liguori <aliguori@us.ibm.com>
Wed, 1 Aug 2012 13:45:06 +0000 (08:45 -0500)
MP initialization protocol differs between cpu families, and for P6 and
onward models it is up to CPU to decide if it will be BSP using this
protocol, so try to model this. However there is no point in implementing
MP initialization protocol in qemu. Thus first CPU is always marked as BSP.

This patch:
 - moves decision to designate BSP from board into cpu, making cpu
self-sufficient in this regard. Later it will allow to cleanup hw/pc.c
and remove cpu_reset and wrappers from there.
 - stores flag that CPU is BSP in IA32_APIC_BASE to model behavior
described in Inted SDM vol 3a part 1 chapter 8.4.1
 - uses MSR_IA32_APICBASE_BSP flag in apic_base for checking if cpu is BSP

patch is based on Jan Kiszka's proposal:
    http://thread.gmane.org/gmane.comp.emulators.qemu/100806

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
hw/apic.h
hw/apic_common.c
hw/pc.c
target-i386/cpu.c
target-i386/helper.c
target-i386/kvm.c

index a89542b231c54d938bc59b06eee35cc31a7b1ed3..1d48e027c3c17c88f1c9e4f894ef72f78d903f59 100644 (file)
--- a/hw/apic.h
+++ b/hw/apic.h
@@ -21,9 +21,12 @@ void apic_sipi(DeviceState *s);
 void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip,
                                    TPRAccess access);
 void apic_poll_irq(DeviceState *d);
+void apic_designate_bsp(DeviceState *d);
 
 /* pc.c */
-int cpu_is_bsp(CPUX86State *env);
 DeviceState *cpu_get_current_apic(void);
 
+/* cpu.c */
+bool cpu_is_bsp(X86CPU *cpu);
+
 #endif
index 60b82596e7b6f3e8701c2b3246f853cf89804c90..58e63b00da5821130bea2dd0ca7ca2cce71ffd99 100644 (file)
@@ -43,8 +43,8 @@ uint64_t cpu_get_apic_base(DeviceState *d)
         trace_cpu_get_apic_base((uint64_t)s->apicbase);
         return s->apicbase;
     } else {
-        trace_cpu_get_apic_base(0);
-        return 0;
+        trace_cpu_get_apic_base(MSR_IA32_APICBASE_BSP);
+        return MSR_IA32_APICBASE_BSP;
     }
 }
 
@@ -201,13 +201,23 @@ void apic_init_reset(DeviceState *d)
     s->timer_expiry = -1;
 }
 
+void apic_designate_bsp(DeviceState *d)
+{
+    if (d == NULL) {
+        return;
+    }
+
+    APICCommonState *s = APIC_COMMON(d);
+    s->apicbase |= MSR_IA32_APICBASE_BSP;
+}
+
 static void apic_reset_common(DeviceState *d)
 {
     APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d);
     APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
     bool bsp;
 
-    bsp = cpu_is_bsp(s->cpu_env);
+    bsp = cpu_is_bsp(x86_env_get_cpu(s->cpu_env));
     s->apicbase = 0xfee00000 |
         (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE;
 
diff --git a/hw/pc.c b/hw/pc.c
index 598267af894e5f46b7486c994bc634a58c677490..a920686cec0fca569bf4bb38346ed8136fc62808 100644 (file)
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -857,12 +857,6 @@ void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd)
     nb_ne2k++;
 }
 
-int cpu_is_bsp(CPUX86State *env)
-{
-    /* We hard-wire the BSP to the first CPU. */
-    return env->cpu_index == 0;
-}
-
 DeviceState *cpu_get_current_apic(void)
 {
     if (cpu_single_env) {
@@ -913,10 +907,7 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
 static void pc_cpu_reset(void *opaque)
 {
     X86CPU *cpu = opaque;
-    CPUX86State *env = &cpu->env;
-
     cpu_reset(CPU(cpu));
-    env->halted = !cpu_is_bsp(env);
 }
 
 static X86CPU *pc_new_cpu(const char *cpu_model)
index 6b9659f9e7064ed5a35daca28c833c3f8c8ef196..365c2ffae9db0542d5e981f4f591ade0ad15b22a 100644 (file)
@@ -1686,8 +1686,24 @@ static void x86_cpu_reset(CPUState *s)
     env->dr[7] = DR7_FIXED_1;
     cpu_breakpoint_remove_all(env, BP_CPU);
     cpu_watchpoint_remove_all(env, BP_CPU);
+
+#if !defined(CONFIG_USER_ONLY)
+    /* We hard-wire the BSP to the first CPU. */
+    if (env->cpu_index == 0) {
+        apic_designate_bsp(env->apic_state);
+    }
+
+    env->halted = !cpu_is_bsp(cpu);
+#endif
 }
 
+#ifndef CONFIG_USER_ONLY
+bool cpu_is_bsp(X86CPU *cpu)
+{
+    return cpu_get_apic_base(cpu->env.apic_state) & MSR_IA32_APICBASE_BSP;
+}
+#endif
+
 static void mce_init(X86CPU *cpu)
 {
     CPUX86State *cenv = &cpu->env;
index d3af6eaf710e67bbc17b4e68f6288700aef41153..b748d90063dfbe48054c0f0e2934127f7982adbf 100644 (file)
@@ -1191,7 +1191,6 @@ void do_cpu_init(X86CPU *cpu)
     env->interrupt_request = sipi;
     env->pat = pat;
     apic_init_reset(env->apic_state);
-    env->halted = !cpu_is_bsp(env);
 }
 
 void do_cpu_sipi(X86CPU *cpu)
index e53c2f6bdf9d586bdb176eb31b49925a4f3a7dad..4cfb3faf01b4576f9f251d1d533830cc42c41aeb 100644 (file)
@@ -584,11 +584,13 @@ int kvm_arch_init_vcpu(CPUX86State *env)
 
 void kvm_arch_reset_vcpu(CPUX86State *env)
 {
+    X86CPU *cpu = x86_env_get_cpu(env);
+
     env->exception_injected = -1;
     env->interrupt_injected = -1;
     env->xcr0 = 1;
     if (kvm_irqchip_in_kernel()) {
-        env->mp_state = cpu_is_bsp(env) ? KVM_MP_STATE_RUNNABLE :
+        env->mp_state = cpu_is_bsp(cpu) ? KVM_MP_STATE_RUNNABLE :
                                           KVM_MP_STATE_UNINITIALIZED;
     } else {
         env->mp_state = KVM_MP_STATE_RUNNABLE;