diff mbox

kvm: nVMX: CPUID.01H:EDX.APIC[bit 9] should mirror IA32_APIC_BASE[11]

Message ID 1478296802-23291-1-git-send-email-jmattson@google.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jim Mattson Nov. 4, 2016, 10 p.m. UTC
From the Intel SDM, volume 3, section 10.4.3, "Enabling or Disabling the
Local APIC,"

  When IA32_APIC_BASE[11] is 0, the processor is functionally equivalent
  to an IA-32 processor without an on-chip APIC. The CPUID feature flag
  for the APIC (see Section 10.4.2, "Presence of the Local APIC") is
  also set to 0.

Signed-off-by: Jim Mattson <jmattson@google.com>
Reviewed-by: Ben Serebrin <serebrin@google.com>
Reviewed-by: David Matlack <dmatlack@google.com>
---
 arch/x86/kvm/cpuid.c | 3 +++
 arch/x86/kvm/lapic.c | 1 +
 2 files changed, 4 insertions(+)

Comments

Radim Krčmář Nov. 8, 2016, 4:33 p.m. UTC | #1
2016-11-04 15:00-0700, Jim Mattson:
> From the Intel SDM, volume 3, section 10.4.3, "Enabling or Disabling the
> Local APIC,"
> 
>   When IA32_APIC_BASE[11] is 0, the processor is functionally equivalent
>   to an IA-32 processor without an on-chip APIC. The CPUID feature flag
>   for the APIC (see Section 10.4.2, "Presence of the Local APIC") is
>   also set to 0.
> 
> Signed-off-by: Jim Mattson <jmattson@google.com>
> Reviewed-by: Ben Serebrin <serebrin@google.com>
> Reviewed-by: David Matlack <dmatlack@google.com>
> ---
> diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
> @@ -81,7 +81,10 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu)
>  			best->ecx |= F(OSXSAVE);
>  	}
>  
> +	best->edx &= ~F(APIC);

This might prevent userspace LAPIC from working.
(The bit will always be zero.)

>  	if (apic) {
> +		if (vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE)
> +			best->edx |= F(APIC);

vcpu->arch.apic_base should be correct regardless of lapic_in_kernel().
Userspace can update CPUID when it changes MSR_IA32_APICBASE_ENABLE, so
not handling CPUID update in KVM is fine, but KVM must not touch the
CPUID bit in that case.

>  		if (best->ecx & F(TSC_DEADLINE_TIMER))
>  			apic->lapic_timer.timer_mode_mask = 3 << 17;
>  		else
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jim Mattson Nov. 9, 2016, 4:53 p.m. UTC | #2
Oops. I missed the subtlety of the "if (apic)" test. I thought it was
testing for the existence of an APIC, rather than where the APIC was
implemented.

On Tue, Nov 8, 2016 at 8:33 AM, Radim Krčmář <rkrcmar@redhat.com> wrote:
> 2016-11-04 15:00-0700, Jim Mattson:
>> From the Intel SDM, volume 3, section 10.4.3, "Enabling or Disabling the
>> Local APIC,"
>>
>>   When IA32_APIC_BASE[11] is 0, the processor is functionally equivalent
>>   to an IA-32 processor without an on-chip APIC. The CPUID feature flag
>>   for the APIC (see Section 10.4.2, "Presence of the Local APIC") is
>>   also set to 0.
>>
>> Signed-off-by: Jim Mattson <jmattson@google.com>
>> Reviewed-by: Ben Serebrin <serebrin@google.com>
>> Reviewed-by: David Matlack <dmatlack@google.com>
>> ---
>> diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
>> @@ -81,7 +81,10 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu)
>>                       best->ecx |= F(OSXSAVE);
>>       }
>>
>> +     best->edx &= ~F(APIC);
>
> This might prevent userspace LAPIC from working.
> (The bit will always be zero.)
>
>>       if (apic) {
>> +             if (vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE)
>> +                     best->edx |= F(APIC);
>
> vcpu->arch.apic_base should be correct regardless of lapic_in_kernel().
> Userspace can update CPUID when it changes MSR_IA32_APICBASE_ENABLE, so
> not handling CPUID update in KVM is fine, but KVM must not touch the
> CPUID bit in that case.
>
>>               if (best->ecx & F(TSC_DEADLINE_TIMER))
>>                       apic->lapic_timer.timer_mode_mask = 3 << 17;
>>               else
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index afa7bbb..0a49fd2 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -81,7 +81,10 @@  int kvm_update_cpuid(struct kvm_vcpu *vcpu)
 			best->ecx |= F(OSXSAVE);
 	}
 
+	best->edx &= ~F(APIC);
 	if (apic) {
+		if (vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE)
+			best->edx |= F(APIC);
 		if (best->ecx & F(TSC_DEADLINE_TIMER))
 			apic->lapic_timer.timer_mode_mask = 3 << 17;
 		else
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 23b99f3..eda4284e 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1758,6 +1758,7 @@  void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
 
 	/* update jump label if enable bit changes */
 	if ((old_value ^ value) & MSR_IA32_APICBASE_ENABLE) {
+		kvm_update_cpuid(vcpu);
 		if (value & MSR_IA32_APICBASE_ENABLE) {
 			kvm_apic_set_xapic_id(apic, vcpu->vcpu_id);
 			static_key_slow_dec_deferred(&apic_hw_disabled);