Make sure the APIC_ID is correctly shifted in the right bit positions when disabling x2APIC via KVM_SET_MSRS.
Signed-off-by: Emanuele Giuseppe Esposito eesposit@redhat.com --- .../selftests/kvm/x86_64/xapic_state_test.c | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+)
diff --git a/tools/testing/selftests/kvm/x86_64/xapic_state_test.c b/tools/testing/selftests/kvm/x86_64/xapic_state_test.c index d7d37dae3eeb..6ebda7162a25 100644 --- a/tools/testing/selftests/kvm/x86_64/xapic_state_test.c +++ b/tools/testing/selftests/kvm/x86_64/xapic_state_test.c @@ -132,6 +132,62 @@ static void test_icr(struct xapic_vcpu *x) __test_icr(x, -1ull & ~APIC_DM_FIXED_MASK); }
+static void _test_lapic_id(struct kvm_vcpu *vcpu, bool x2apic_enabled, + int expected_id) +{ + struct kvm_lapic_state xapic; + + vcpu_ioctl(vcpu, KVM_GET_LAPIC, &xapic); + if (x2apic_enabled) + ASSERT_EQ(xapic.regs[APIC_ID], expected_id); + else + ASSERT_EQ(xapic.regs[0x23], expected_id); + +} + +static void test_apic_id(struct kvm_vcpu *vcpu, int id) +{ + int ret; + struct { + struct kvm_msrs info; + struct kvm_msr_entry entries[1]; + } msr_data = { + .info.nmsrs = 1, + .entries[0].index = MSR_IA32_APICBASE, + }; + + /* vcpu is initialized with xAPIC enabled */ + ret = __vcpu_ioctl(vcpu, KVM_GET_MSRS, &msr_data.info); + TEST_ASSERT(ret == 1, __KVM_IOCTL_ERROR("__vcpu_ioctl", ret)); + ASSERT_EQ(msr_data.entries[0].data & MSR_IA32_APICBASE_ENABLE, + MSR_IA32_APICBASE_ENABLE); + ASSERT_EQ(msr_data.entries[0].data & X2APIC_ENABLE, 0); + _test_lapic_id(vcpu, false, id); + + /* enable x2APIC */ + msr_data.entries[0].data |= X2APIC_ENABLE; + ret = __vcpu_ioctl(vcpu, KVM_SET_MSRS, &msr_data.info); + TEST_ASSERT(ret == 1, __KVM_IOCTL_ERROR("__vcpu_ioctl", ret)); + ASSERT_EQ(msr_data.entries[0].data & MSR_IA32_APICBASE_ENABLE, + MSR_IA32_APICBASE_ENABLE); + ASSERT_EQ(msr_data.entries[0].data & X2APIC_ENABLE, X2APIC_ENABLE); + _test_lapic_id(vcpu, true, id); + + /* + * Check that disabling x2APIC correctly updates the APIC ID to the + * xAPIC format. + */ + msr_data.entries[0].data ^= X2APIC_ENABLE; + ret = __vcpu_ioctl(vcpu, KVM_SET_MSRS, &msr_data.info); + TEST_ASSERT(ret == 1, __KVM_IOCTL_ERROR("__vcpu_ioctl", ret)); + ASSERT_EQ(msr_data.entries[0].data & MSR_IA32_APICBASE_ENABLE, + MSR_IA32_APICBASE_ENABLE); + ASSERT_EQ(msr_data.entries[0].data & X2APIC_ENABLE, 0); + _test_lapic_id(vcpu, false, id); +} + +#define NCPUS 3 + int main(int argc, char *argv[]) { struct xapic_vcpu x = { @@ -139,6 +195,14 @@ int main(int argc, char *argv[]) .is_x2apic = true, }; struct kvm_vm *vm; + struct kvm_vcpu *vcpus[NCPUS] = { 0 }; + int i; + + vm = vm_create_with_vcpus(NCPUS, NULL, vcpus); + vm_enable_cap(vm, KVM_CAP_X2APIC_API, KVM_X2APIC_API_USE_32BIT_IDS); + for (i = 0; i < NCPUS; i++) + test_apic_id(vcpus[i], i); + kvm_vm_free(vm);
vm = vm_create_with_one_vcpu(&x.vcpu, x2apic_guest_code); test_icr(&x);