summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Mammedov <imammedo@redhat.com>2016-10-19 14:05:38 +0200
committerEduardo Habkost <ehabkost@redhat.com>2016-10-24 17:29:15 -0200
commite391c00970a3fe3448b78054fb917df751847b16 (patch)
tree87ad78e1dda202037c9a51384a1d5361d2196a4d
parentfacb07cd2a3d19ebe2e15380e906eed7d5f7063c (diff)
downloadqemu-e391c00970a3fe3448b78054fb917df751847b16.tar.gz
qemu-e391c00970a3fe3448b78054fb917df751847b16.tar.bz2
qemu-e391c00970a3fe3448b78054fb917df751847b16.zip
pc: kvm_apic: Pass APIC ID depending on xAPIC/x2APIC mode
Signed-off-by: Igor Mammedov <imammedo@redhat.com> Reviewed-by: Radim Krčmář <rkrcmar@redhat.com> Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
-rw-r--r--hw/i386/kvm/apic.c12
-rw-r--r--target-i386/kvm.c13
-rw-r--r--target-i386/kvm_i386.h1
3 files changed, 21 insertions, 5 deletions
diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c
index be55102c00..39b73e7b3d 100644
--- a/hw/i386/kvm/apic.c
+++ b/hw/i386/kvm/apic.c
@@ -34,7 +34,11 @@ static void kvm_put_apic_state(APICCommonState *s, struct kvm_lapic_state *kapic
int i;
memset(kapic, 0, sizeof(*kapic));
- kvm_apic_set_reg(kapic, 0x2, s->id << 24);
+ if (kvm_has_x2apic_api() && s->apicbase & MSR_IA32_APICBASE_EXTD) {
+ kvm_apic_set_reg(kapic, 0x2, s->initial_apic_id);
+ } else {
+ kvm_apic_set_reg(kapic, 0x2, s->id << 24);
+ }
kvm_apic_set_reg(kapic, 0x8, s->tpr);
kvm_apic_set_reg(kapic, 0xd, s->log_dest << 24);
kvm_apic_set_reg(kapic, 0xe, s->dest_mode << 28 | 0x0fffffff);
@@ -59,7 +63,11 @@ void kvm_get_apic_state(DeviceState *dev, struct kvm_lapic_state *kapic)
APICCommonState *s = APIC_COMMON(dev);
int i, v;
- s->id = kvm_apic_get_reg(kapic, 0x2) >> 24;
+ if (kvm_has_x2apic_api() && s->apicbase & MSR_IA32_APICBASE_EXTD) {
+ assert(kvm_apic_get_reg(kapic, 0x2) == s->initial_apic_id);
+ } else {
+ s->id = kvm_apic_get_reg(kapic, 0x2) >> 24;
+ }
s->tpr = kvm_apic_get_reg(kapic, 0x8);
s->arb_id = kvm_apic_get_reg(kapic, 0x9);
s->log_dest = kvm_apic_get_reg(kapic, 0xd) >> 24;
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 0472f45fd0..86b41a9c21 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -129,9 +129,8 @@ static bool kvm_x2apic_api_set_flags(uint64_t flags)
return !kvm_vm_enable_cap(s, KVM_CAP_X2APIC_API, 0, flags);
}
-#define MEMORIZE(fn) \
+#define MEMORIZE(fn, _result) \
({ \
- static typeof(fn) _result; \
static bool _memorized; \
\
if (_memorized) { \
@@ -141,11 +140,19 @@ static bool kvm_x2apic_api_set_flags(uint64_t flags)
_result = fn; \
})
+static bool has_x2apic_api;
+
+bool kvm_has_x2apic_api(void)
+{
+ return has_x2apic_api;
+}
+
bool kvm_enable_x2apic(void)
{
return MEMORIZE(
kvm_x2apic_api_set_flags(KVM_X2APIC_API_USE_32BIT_IDS |
- KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK));
+ KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK),
+ has_x2apic_api);
}
static int kvm_get_tsc(CPUState *cs)
diff --git a/target-i386/kvm_i386.h b/target-i386/kvm_i386.h
index 5c369b1c5b..76079295b2 100644
--- a/target-i386/kvm_i386.h
+++ b/target-i386/kvm_i386.h
@@ -44,4 +44,5 @@ int kvm_device_msix_deassign(KVMState *s, uint32_t dev_id);
void kvm_put_apicbase(X86CPU *cpu, uint64_t value);
bool kvm_enable_x2apic(void);
+bool kvm_has_x2apic_api(void);
#endif