diff options
| -rw-r--r-- | arch/x86/kvm/cpuid.h | 8 | ||||
| -rw-r--r-- | arch/x86/kvm/lapic.h | 2 | ||||
| -rw-r--r-- | arch/x86/kvm/vmx.c | 9 | ||||
| -rw-r--r-- | arch/x86/kvm/x86.c | 32 |
4 files changed, 39 insertions, 12 deletions
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index f1e4895174b2..a2a1bb7ed8c1 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h | |||
| @@ -72,4 +72,12 @@ static inline bool guest_cpuid_has_pcid(struct kvm_vcpu *vcpu) | |||
| 72 | return best && (best->ecx & bit(X86_FEATURE_PCID)); | 72 | return best && (best->ecx & bit(X86_FEATURE_PCID)); |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | static inline bool guest_cpuid_has_x2apic(struct kvm_vcpu *vcpu) | ||
| 76 | { | ||
| 77 | struct kvm_cpuid_entry2 *best; | ||
| 78 | |||
| 79 | best = kvm_find_cpuid_entry(vcpu, 1, 0); | ||
| 80 | return best && (best->ecx & bit(X86_FEATURE_X2APIC)); | ||
| 81 | } | ||
| 82 | |||
| 75 | #endif | 83 | #endif |
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index c8b0d0d2da5c..6a11845fd8b9 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, | |||
| 65 | struct kvm_lapic_irq *irq, int *r, unsigned long *dest_map); | 65 | struct kvm_lapic_irq *irq, int *r, unsigned long *dest_map); |
| 66 | 66 | ||
| 67 | u64 kvm_get_apic_base(struct kvm_vcpu *vcpu); | 67 | u64 kvm_get_apic_base(struct kvm_vcpu *vcpu); |
| 68 | void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data); | 68 | int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info); |
| 69 | void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu, | 69 | void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu, |
| 70 | struct kvm_lapic_state *s); | 70 | struct kvm_lapic_state *s); |
| 71 | int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu); | 71 | 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 5c8879127cfa..a06f101ef64b 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) | |||
| 4392 | static void vmx_vcpu_reset(struct kvm_vcpu *vcpu) | 4392 | static void vmx_vcpu_reset(struct kvm_vcpu *vcpu) |
| 4393 | { | 4393 | { |
| 4394 | struct vcpu_vmx *vmx = to_vmx(vcpu); | 4394 | struct vcpu_vmx *vmx = to_vmx(vcpu); |
| 4395 | u64 msr; | 4395 | struct msr_data apic_base_msr; |
| 4396 | 4396 | ||
| 4397 | vmx->rmode.vm86_active = 0; | 4397 | vmx->rmode.vm86_active = 0; |
| 4398 | 4398 | ||
| @@ -4400,10 +4400,11 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu) | |||
| 4400 | 4400 | ||
| 4401 | vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val(); | 4401 | vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val(); |
| 4402 | kvm_set_cr8(&vmx->vcpu, 0); | 4402 | kvm_set_cr8(&vmx->vcpu, 0); |
| 4403 | msr = 0xfee00000 | MSR_IA32_APICBASE_ENABLE; | 4403 | apic_base_msr.data = 0xfee00000 | MSR_IA32_APICBASE_ENABLE; |
| 4404 | if (kvm_vcpu_is_bsp(&vmx->vcpu)) | 4404 | if (kvm_vcpu_is_bsp(&vmx->vcpu)) |
| 4405 | msr |= MSR_IA32_APICBASE_BSP; | 4405 | apic_base_msr.data |= MSR_IA32_APICBASE_BSP; |
| 4406 | kvm_set_apic_base(&vmx->vcpu, msr); | 4406 | apic_base_msr.host_initiated = true; |
| 4407 | kvm_set_apic_base(&vmx->vcpu, &apic_base_msr); | ||
| 4407 | 4408 | ||
| 4408 | vmx_segment_cache_clear(vmx); | 4409 | vmx_segment_cache_clear(vmx); |
| 4409 | 4410 | ||
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index dc11b4f98577..34d0d610aa8a 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) | |||
| 257 | } | 257 | } |
| 258 | EXPORT_SYMBOL_GPL(kvm_get_apic_base); | 258 | EXPORT_SYMBOL_GPL(kvm_get_apic_base); |
| 259 | 259 | ||
| 260 | void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data) | 260 | int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info) |
| 261 | { | 261 | { |
| 262 | /* TODO: reserve bits check */ | 262 | u64 old_state = vcpu->arch.apic_base & |
| 263 | kvm_lapic_set_base(vcpu, data); | 263 | (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE); |
| 264 | u64 new_state = msr_info->data & | ||
| 265 | (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE); | ||
| 266 | u64 reserved_bits = ((~0ULL) << cpuid_maxphyaddr(vcpu)) | | ||
| 267 | 0x2ff | (guest_cpuid_has_x2apic(vcpu) ? 0 : X2APIC_ENABLE); | ||
| 268 | |||
| 269 | if (!msr_info->host_initiated && | ||
| 270 | ((msr_info->data & reserved_bits) != 0 || | ||
| 271 | new_state == X2APIC_ENABLE || | ||
| 272 | (new_state == MSR_IA32_APICBASE_ENABLE && | ||
| 273 | old_state == (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE)) || | ||
| 274 | (new_state == (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE) && | ||
| 275 | old_state == 0))) | ||
| 276 | return 1; | ||
| 277 | |||
| 278 | kvm_lapic_set_base(vcpu, msr_info->data); | ||
| 279 | return 0; | ||
| 264 | } | 280 | } |
| 265 | EXPORT_SYMBOL_GPL(kvm_set_apic_base); | 281 | EXPORT_SYMBOL_GPL(kvm_set_apic_base); |
| 266 | 282 | ||
| @@ -2009,8 +2025,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) | |||
| 2009 | case 0x200 ... 0x2ff: | 2025 | case 0x200 ... 0x2ff: |
| 2010 | return set_msr_mtrr(vcpu, msr, data); | 2026 | return set_msr_mtrr(vcpu, msr, data); |
| 2011 | case MSR_IA32_APICBASE: | 2027 | case MSR_IA32_APICBASE: |
| 2012 | kvm_set_apic_base(vcpu, data); | 2028 | return kvm_set_apic_base(vcpu, msr_info); |
| 2013 | break; | ||
| 2014 | case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff: | 2029 | case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff: |
| 2015 | return kvm_x2apic_msr_write(vcpu, msr, data); | 2030 | return kvm_x2apic_msr_write(vcpu, msr, data); |
| 2016 | case MSR_IA32_TSCDEADLINE: | 2031 | case MSR_IA32_TSCDEADLINE: |
| @@ -6412,6 +6427,7 @@ EXPORT_SYMBOL_GPL(kvm_task_switch); | |||
| 6412 | int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, | 6427 | int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, |
| 6413 | struct kvm_sregs *sregs) | 6428 | struct kvm_sregs *sregs) |
| 6414 | { | 6429 | { |
| 6430 | struct msr_data apic_base_msr; | ||
| 6415 | int mmu_reset_needed = 0; | 6431 | int mmu_reset_needed = 0; |
| 6416 | int pending_vec, max_bits, idx; | 6432 | int pending_vec, max_bits, idx; |
| 6417 | struct desc_ptr dt; | 6433 | struct desc_ptr dt; |
| @@ -6435,7 +6451,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, | |||
| 6435 | 6451 | ||
| 6436 | mmu_reset_needed |= vcpu->arch.efer != sregs->efer; | 6452 | mmu_reset_needed |= vcpu->arch.efer != sregs->efer; |
| 6437 | kvm_x86_ops->set_efer(vcpu, sregs->efer); | 6453 | kvm_x86_ops->set_efer(vcpu, sregs->efer); |
| 6438 | kvm_set_apic_base(vcpu, sregs->apic_base); | 6454 | apic_base_msr.data = sregs->apic_base; |
| 6455 | apic_base_msr.host_initiated = true; | ||
| 6456 | kvm_set_apic_base(vcpu, &apic_base_msr); | ||
| 6439 | 6457 | ||
| 6440 | mmu_reset_needed |= kvm_read_cr0(vcpu) != sregs->cr0; | 6458 | mmu_reset_needed |= kvm_read_cr0(vcpu) != sregs->cr0; |
| 6441 | kvm_x86_ops->set_cr0(vcpu, sregs->cr0); | 6459 | kvm_x86_ops->set_cr0(vcpu, sregs->cr0); |
