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
v2:
- fix build for i386-linux-user
spotted-by: Peter Maydell <[email protected]>
v3:
- style change requested by Andreas Färber <[email protected]>
v4:
- reuse cpu_is_bsp() rather than open code check if apicbase has BSP bit set
requested by Gleb Natapov <[email protected]>
- hijacked Andreas' patch [1] to use X86CPU instead of CPUX86State in
cpu_is_bsp()
1) http://lists.gnu.org/archive/html/qemu-devel/2012-05/msg03185.html
Signed-off-by: Igor Mammedov <[email protected]>
---
hw/apic.h | 5 ++++-
hw/apic_common.c | 16 +++++++++++++---
hw/pc.c | 9 ---------
target-i386/cpu.c | 18 ++++++++++++++++++
target-i386/helper.c | 1 -
target-i386/kvm.c | 4 +++-
6 files changed, 38 insertions(+), 15 deletions(-)
diff --git a/hw/apic.h b/hw/apic.h
index 62179ce..4da10b6 100644
--- a/hw/apic.h
+++ b/hw/apic.h
@@ -20,9 +20,12 @@ void apic_init_reset(DeviceState *s);
void apic_sipi(DeviceState *s);
void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip,
TPRAccess access);
+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
diff --git a/hw/apic_common.c b/hw/apic_common.c
index 60b8259..58e63b0 100644
--- a/hw/apic_common.c
+++ b/hw/apic_common.c
@@ -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 c7e9ab3..50c1715 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -871,12 +871,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) {
@@ -927,10 +921,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)
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 5521709..0c38b7f 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -1686,6 +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)
diff --git a/target-i386/helper.c b/target-i386/helper.c
index d3af6ea..b748d90 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -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)
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 0d0d8f6..97a2cb1 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -579,11 +579,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;
--
1.7.1