Message ID | 1ba67ddad48673feb70c7c3a8bd0b62cef9d89cb.1390578527.git.jan.kiszka@siemens.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
-----BEGIN PGP MESSAGE----- Charset: ISO-8859-15 Version: GnuPG v2.0.22 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ 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 fXe0vQUvuEXs =POu1 -----END PGP MESSAGE----- -- 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
Il 24/01/2014 16:48, Jan Kiszka ha scritto: > Check for invalid state transitions on guest-initiated updates of > MSR_IA32_APICBASE. This address both enabling of the x2APIC when it is > not supported and all invalid transitions as described in SDM section > 10.12.5. It also checks that no reserved bit is set in APICBASE by the > guest. > > Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> > --- > arch/x86/kvm/cpuid.h | 16 ++++++++++++++++ > arch/x86/kvm/lapic.h | 2 +- > arch/x86/kvm/vmx.c | 9 +++++---- > arch/x86/kvm/x86.c | 32 +++++++++++++++++++++++++------- > 4 files changed, 47 insertions(+), 12 deletions(-) > > diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h > index f1e4895..b012ad2 100644 > --- a/arch/x86/kvm/cpuid.h > +++ b/arch/x86/kvm/cpuid.h > @@ -72,4 +72,20 @@ static inline bool guest_cpuid_has_pcid(struct kvm_vcpu *vcpu) > return best && (best->ecx & bit(X86_FEATURE_PCID)); > } > > +static inline bool guest_cpuid_has_x2apic(struct kvm_vcpu *vcpu) > +{ > + struct kvm_cpuid_entry2 *best; > + > + best = kvm_find_cpuid_entry(vcpu, 1, 0); > + return best && (best->ecx & bit(X86_FEATURE_X2APIC)); > +} > + > +static inline unsigned int guest_cpuid_get_phys_bits(struct kvm_vcpu *vcpu) > +{ > + struct kvm_cpuid_entry2 *best; > + > + best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0); > + return best ? best->eax & 0xff : 36; > +} [Resending after learning that Ctrl-Shift-C does other things beyond copying to clipboard] There's already cpuid_maxphyaddr for this. I can adjust it when committing. This is applied to kvm/queue. The other three will have to wait for after the merge window. Paolo > #endif > diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h > index c8b0d0d..6a11845 100644 > --- a/arch/x86/kvm/lapic.h > +++ b/arch/x86/kvm/lapic.h > @@ -65,7 +65,7 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src, > struct kvm_lapic_irq *irq, int *r, unsigned long *dest_map); > > u64 kvm_get_apic_base(struct kvm_vcpu *vcpu); > -void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data); > +int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info); > void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu, > struct kvm_lapic_state *s); > int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu); > diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c > index 5c88791..a06f101 100644 > --- a/arch/x86/kvm/vmx.c > +++ b/arch/x86/kvm/vmx.c > @@ -4392,7 +4392,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) > static void vmx_vcpu_reset(struct kvm_vcpu *vcpu) > { > struct vcpu_vmx *vmx = to_vmx(vcpu); > - u64 msr; > + struct msr_data apic_base_msr; > > vmx->rmode.vm86_active = 0; > > @@ -4400,10 +4400,11 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu) > > vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val(); > kvm_set_cr8(&vmx->vcpu, 0); > - msr = 0xfee00000 | MSR_IA32_APICBASE_ENABLE; > + apic_base_msr.data = 0xfee00000 | MSR_IA32_APICBASE_ENABLE; > if (kvm_vcpu_is_bsp(&vmx->vcpu)) > - msr |= MSR_IA32_APICBASE_BSP; > - kvm_set_apic_base(&vmx->vcpu, msr); > + apic_base_msr.data |= MSR_IA32_APICBASE_BSP; > + apic_base_msr.host_initiated = true; > + kvm_set_apic_base(&vmx->vcpu, &apic_base_msr); > > vmx_segment_cache_clear(vmx); > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index 0c76f7c..f4b0591 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -257,10 +257,26 @@ u64 kvm_get_apic_base(struct kvm_vcpu *vcpu) > } > EXPORT_SYMBOL_GPL(kvm_get_apic_base); > > -void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data) > -{ > - /* TODO: reserve bits check */ > - kvm_lapic_set_base(vcpu, data); > +int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info) > +{ > + u64 old_state = vcpu->arch.apic_base & > + (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE); > + u64 new_state = msr_info->data & > + (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE); > + u64 reserved_bits = ((~0ULL) << guest_cpuid_get_phys_bits(vcpu)) | > + 0x2ff | (guest_cpuid_has_x2apic(vcpu) ? 0 : X2APIC_ENABLE); > + > + if (!msr_info->host_initiated && > + ((msr_info->data & reserved_bits) != 0 || > + new_state == X2APIC_ENABLE || > + (new_state == MSR_IA32_APICBASE_ENABLE && > + old_state == (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE)) || > + (new_state == (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE) && > + old_state == 0))) > + return 1; > + > + kvm_lapic_set_base(vcpu, msr_info->data); > + return 0; > } > EXPORT_SYMBOL_GPL(kvm_set_apic_base); > > @@ -2006,8 +2022,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) > case 0x200 ... 0x2ff: > return set_msr_mtrr(vcpu, msr, data); > case MSR_IA32_APICBASE: > - kvm_set_apic_base(vcpu, data); > - break; > + return kvm_set_apic_base(vcpu, msr_info); > case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff: > return kvm_x2apic_msr_write(vcpu, msr, data); > case MSR_IA32_TSCDEADLINE: > @@ -6409,6 +6424,7 @@ EXPORT_SYMBOL_GPL(kvm_task_switch); > int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, > struct kvm_sregs *sregs) > { > + struct msr_data apic_base_msr; > int mmu_reset_needed = 0; > int pending_vec, max_bits, idx; > struct desc_ptr dt; > @@ -6432,7 +6448,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, > > mmu_reset_needed |= vcpu->arch.efer != sregs->efer; > kvm_x86_ops->set_efer(vcpu, sregs->efer); > - kvm_set_apic_base(vcpu, sregs->apic_base); > + apic_base_msr.data = sregs->apic_base; > + apic_base_msr.host_initiated = true; > + kvm_set_apic_base(vcpu, &apic_base_msr); > > mmu_reset_needed |= kvm_read_cr0(vcpu) != sregs->cr0; > kvm_x86_ops->set_cr0(vcpu, sregs->cr0); > -- 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 --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index f1e4895..b012ad2 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -72,4 +72,20 @@ static inline bool guest_cpuid_has_pcid(struct kvm_vcpu *vcpu) return best && (best->ecx & bit(X86_FEATURE_PCID)); } +static inline bool guest_cpuid_has_x2apic(struct kvm_vcpu *vcpu) +{ + struct kvm_cpuid_entry2 *best; + + best = kvm_find_cpuid_entry(vcpu, 1, 0); + return best && (best->ecx & bit(X86_FEATURE_X2APIC)); +} + +static inline unsigned int guest_cpuid_get_phys_bits(struct kvm_vcpu *vcpu) +{ + struct kvm_cpuid_entry2 *best; + + best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0); + return best ? best->eax & 0xff : 36; +} + #endif diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index c8b0d0d..6a11845 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -65,7 +65,7 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src, struct kvm_lapic_irq *irq, int *r, unsigned long *dest_map); u64 kvm_get_apic_base(struct kvm_vcpu *vcpu); -void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data); +int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info); void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s); int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu); diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 5c88791..a06f101 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -4392,7 +4392,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) static void vmx_vcpu_reset(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx = to_vmx(vcpu); - u64 msr; + struct msr_data apic_base_msr; vmx->rmode.vm86_active = 0; @@ -4400,10 +4400,11 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu) vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val(); kvm_set_cr8(&vmx->vcpu, 0); - msr = 0xfee00000 | MSR_IA32_APICBASE_ENABLE; + apic_base_msr.data = 0xfee00000 | MSR_IA32_APICBASE_ENABLE; if (kvm_vcpu_is_bsp(&vmx->vcpu)) - msr |= MSR_IA32_APICBASE_BSP; - kvm_set_apic_base(&vmx->vcpu, msr); + apic_base_msr.data |= MSR_IA32_APICBASE_BSP; + apic_base_msr.host_initiated = true; + kvm_set_apic_base(&vmx->vcpu, &apic_base_msr); vmx_segment_cache_clear(vmx); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 0c76f7c..f4b0591 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -257,10 +257,26 @@ u64 kvm_get_apic_base(struct kvm_vcpu *vcpu) } EXPORT_SYMBOL_GPL(kvm_get_apic_base); -void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data) -{ - /* TODO: reserve bits check */ - kvm_lapic_set_base(vcpu, data); +int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info) +{ + u64 old_state = vcpu->arch.apic_base & + (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE); + u64 new_state = msr_info->data & + (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE); + u64 reserved_bits = ((~0ULL) << guest_cpuid_get_phys_bits(vcpu)) | + 0x2ff | (guest_cpuid_has_x2apic(vcpu) ? 0 : X2APIC_ENABLE); + + if (!msr_info->host_initiated && + ((msr_info->data & reserved_bits) != 0 || + new_state == X2APIC_ENABLE || + (new_state == MSR_IA32_APICBASE_ENABLE && + old_state == (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE)) || + (new_state == (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE) && + old_state == 0))) + return 1; + + kvm_lapic_set_base(vcpu, msr_info->data); + return 0; } EXPORT_SYMBOL_GPL(kvm_set_apic_base); @@ -2006,8 +2022,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) case 0x200 ... 0x2ff: return set_msr_mtrr(vcpu, msr, data); case MSR_IA32_APICBASE: - kvm_set_apic_base(vcpu, data); - break; + return kvm_set_apic_base(vcpu, msr_info); case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff: return kvm_x2apic_msr_write(vcpu, msr, data); case MSR_IA32_TSCDEADLINE: @@ -6409,6 +6424,7 @@ EXPORT_SYMBOL_GPL(kvm_task_switch); int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) { + struct msr_data apic_base_msr; int mmu_reset_needed = 0; int pending_vec, max_bits, idx; struct desc_ptr dt; @@ -6432,7 +6448,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, mmu_reset_needed |= vcpu->arch.efer != sregs->efer; kvm_x86_ops->set_efer(vcpu, sregs->efer); - kvm_set_apic_base(vcpu, sregs->apic_base); + apic_base_msr.data = sregs->apic_base; + apic_base_msr.host_initiated = true; + kvm_set_apic_base(vcpu, &apic_base_msr); mmu_reset_needed |= kvm_read_cr0(vcpu) != sregs->cr0; kvm_x86_ops->set_cr0(vcpu, sregs->cr0);
Check for invalid state transitions on guest-initiated updates of MSR_IA32_APICBASE. This address both enabling of the x2APIC when it is not supported and all invalid transitions as described in SDM section 10.12.5. It also checks that no reserved bit is set in APICBASE by the guest. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> --- arch/x86/kvm/cpuid.h | 16 ++++++++++++++++ arch/x86/kvm/lapic.h | 2 +- arch/x86/kvm/vmx.c | 9 +++++---- arch/x86/kvm/x86.c | 32 +++++++++++++++++++++++++------- 4 files changed, 47 insertions(+), 12 deletions(-)