diff options
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 49 |
1 files changed, 17 insertions, 32 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index e46282a56565..3c4ca98ad27f 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/cpufreq.h> | 39 | #include <linux/cpufreq.h> |
40 | #include <linux/user-return-notifier.h> | 40 | #include <linux/user-return-notifier.h> |
41 | #include <linux/srcu.h> | 41 | #include <linux/srcu.h> |
42 | #include <linux/slab.h> | ||
42 | #include <trace/events/kvm.h> | 43 | #include <trace/events/kvm.h> |
43 | #undef TRACE_INCLUDE_FILE | 44 | #undef TRACE_INCLUDE_FILE |
44 | #define CREATE_TRACE_POINTS | 45 | #define CREATE_TRACE_POINTS |
@@ -432,8 +433,6 @@ void kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) | |||
432 | 433 | ||
433 | #ifdef CONFIG_X86_64 | 434 | #ifdef CONFIG_X86_64 |
434 | if (cr0 & 0xffffffff00000000UL) { | 435 | if (cr0 & 0xffffffff00000000UL) { |
435 | printk(KERN_DEBUG "set_cr0: 0x%lx #GP, reserved bits 0x%lx\n", | ||
436 | cr0, kvm_read_cr0(vcpu)); | ||
437 | kvm_inject_gp(vcpu, 0); | 436 | kvm_inject_gp(vcpu, 0); |
438 | return; | 437 | return; |
439 | } | 438 | } |
@@ -442,14 +441,11 @@ void kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) | |||
442 | cr0 &= ~CR0_RESERVED_BITS; | 441 | cr0 &= ~CR0_RESERVED_BITS; |
443 | 442 | ||
444 | if ((cr0 & X86_CR0_NW) && !(cr0 & X86_CR0_CD)) { | 443 | if ((cr0 & X86_CR0_NW) && !(cr0 & X86_CR0_CD)) { |
445 | printk(KERN_DEBUG "set_cr0: #GP, CD == 0 && NW == 1\n"); | ||
446 | kvm_inject_gp(vcpu, 0); | 444 | kvm_inject_gp(vcpu, 0); |
447 | return; | 445 | return; |
448 | } | 446 | } |
449 | 447 | ||
450 | if ((cr0 & X86_CR0_PG) && !(cr0 & X86_CR0_PE)) { | 448 | if ((cr0 & X86_CR0_PG) && !(cr0 & X86_CR0_PE)) { |
451 | printk(KERN_DEBUG "set_cr0: #GP, set PG flag " | ||
452 | "and a clear PE flag\n"); | ||
453 | kvm_inject_gp(vcpu, 0); | 449 | kvm_inject_gp(vcpu, 0); |
454 | return; | 450 | return; |
455 | } | 451 | } |
@@ -460,15 +456,11 @@ void kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) | |||
460 | int cs_db, cs_l; | 456 | int cs_db, cs_l; |
461 | 457 | ||
462 | if (!is_pae(vcpu)) { | 458 | if (!is_pae(vcpu)) { |
463 | printk(KERN_DEBUG "set_cr0: #GP, start paging " | ||
464 | "in long mode while PAE is disabled\n"); | ||
465 | kvm_inject_gp(vcpu, 0); | 459 | kvm_inject_gp(vcpu, 0); |
466 | return; | 460 | return; |
467 | } | 461 | } |
468 | kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l); | 462 | kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l); |
469 | if (cs_l) { | 463 | if (cs_l) { |
470 | printk(KERN_DEBUG "set_cr0: #GP, start paging " | ||
471 | "in long mode while CS.L == 1\n"); | ||
472 | kvm_inject_gp(vcpu, 0); | 464 | kvm_inject_gp(vcpu, 0); |
473 | return; | 465 | return; |
474 | 466 | ||
@@ -476,8 +468,6 @@ void kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) | |||
476 | } else | 468 | } else |
477 | #endif | 469 | #endif |
478 | if (is_pae(vcpu) && !load_pdptrs(vcpu, vcpu->arch.cr3)) { | 470 | if (is_pae(vcpu) && !load_pdptrs(vcpu, vcpu->arch.cr3)) { |
479 | printk(KERN_DEBUG "set_cr0: #GP, pdptrs " | ||
480 | "reserved bits\n"); | ||
481 | kvm_inject_gp(vcpu, 0); | 471 | kvm_inject_gp(vcpu, 0); |
482 | return; | 472 | return; |
483 | } | 473 | } |
@@ -504,28 +494,23 @@ void kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) | |||
504 | unsigned long pdptr_bits = X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE; | 494 | unsigned long pdptr_bits = X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE; |
505 | 495 | ||
506 | if (cr4 & CR4_RESERVED_BITS) { | 496 | if (cr4 & CR4_RESERVED_BITS) { |
507 | printk(KERN_DEBUG "set_cr4: #GP, reserved bits\n"); | ||
508 | kvm_inject_gp(vcpu, 0); | 497 | kvm_inject_gp(vcpu, 0); |
509 | return; | 498 | return; |
510 | } | 499 | } |
511 | 500 | ||
512 | if (is_long_mode(vcpu)) { | 501 | if (is_long_mode(vcpu)) { |
513 | if (!(cr4 & X86_CR4_PAE)) { | 502 | if (!(cr4 & X86_CR4_PAE)) { |
514 | printk(KERN_DEBUG "set_cr4: #GP, clearing PAE while " | ||
515 | "in long mode\n"); | ||
516 | kvm_inject_gp(vcpu, 0); | 503 | kvm_inject_gp(vcpu, 0); |
517 | return; | 504 | return; |
518 | } | 505 | } |
519 | } else if (is_paging(vcpu) && (cr4 & X86_CR4_PAE) | 506 | } else if (is_paging(vcpu) && (cr4 & X86_CR4_PAE) |
520 | && ((cr4 ^ old_cr4) & pdptr_bits) | 507 | && ((cr4 ^ old_cr4) & pdptr_bits) |
521 | && !load_pdptrs(vcpu, vcpu->arch.cr3)) { | 508 | && !load_pdptrs(vcpu, vcpu->arch.cr3)) { |
522 | printk(KERN_DEBUG "set_cr4: #GP, pdptrs reserved bits\n"); | ||
523 | kvm_inject_gp(vcpu, 0); | 509 | kvm_inject_gp(vcpu, 0); |
524 | return; | 510 | return; |
525 | } | 511 | } |
526 | 512 | ||
527 | if (cr4 & X86_CR4_VMXE) { | 513 | if (cr4 & X86_CR4_VMXE) { |
528 | printk(KERN_DEBUG "set_cr4: #GP, setting VMXE\n"); | ||
529 | kvm_inject_gp(vcpu, 0); | 514 | kvm_inject_gp(vcpu, 0); |
530 | return; | 515 | return; |
531 | } | 516 | } |
@@ -546,21 +531,16 @@ void kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) | |||
546 | 531 | ||
547 | if (is_long_mode(vcpu)) { | 532 | if (is_long_mode(vcpu)) { |
548 | if (cr3 & CR3_L_MODE_RESERVED_BITS) { | 533 | if (cr3 & CR3_L_MODE_RESERVED_BITS) { |
549 | printk(KERN_DEBUG "set_cr3: #GP, reserved bits\n"); | ||
550 | kvm_inject_gp(vcpu, 0); | 534 | kvm_inject_gp(vcpu, 0); |
551 | return; | 535 | return; |
552 | } | 536 | } |
553 | } else { | 537 | } else { |
554 | if (is_pae(vcpu)) { | 538 | if (is_pae(vcpu)) { |
555 | if (cr3 & CR3_PAE_RESERVED_BITS) { | 539 | if (cr3 & CR3_PAE_RESERVED_BITS) { |
556 | printk(KERN_DEBUG | ||
557 | "set_cr3: #GP, reserved bits\n"); | ||
558 | kvm_inject_gp(vcpu, 0); | 540 | kvm_inject_gp(vcpu, 0); |
559 | return; | 541 | return; |
560 | } | 542 | } |
561 | if (is_paging(vcpu) && !load_pdptrs(vcpu, cr3)) { | 543 | if (is_paging(vcpu) && !load_pdptrs(vcpu, cr3)) { |
562 | printk(KERN_DEBUG "set_cr3: #GP, pdptrs " | ||
563 | "reserved bits\n"); | ||
564 | kvm_inject_gp(vcpu, 0); | 544 | kvm_inject_gp(vcpu, 0); |
565 | return; | 545 | return; |
566 | } | 546 | } |
@@ -592,7 +572,6 @@ EXPORT_SYMBOL_GPL(kvm_set_cr3); | |||
592 | void kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8) | 572 | void kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8) |
593 | { | 573 | { |
594 | if (cr8 & CR8_RESERVED_BITS) { | 574 | if (cr8 & CR8_RESERVED_BITS) { |
595 | printk(KERN_DEBUG "set_cr8: #GP, reserved bits 0x%lx\n", cr8); | ||
596 | kvm_inject_gp(vcpu, 0); | 575 | kvm_inject_gp(vcpu, 0); |
597 | return; | 576 | return; |
598 | } | 577 | } |
@@ -648,15 +627,12 @@ static u32 emulated_msrs[] = { | |||
648 | static void set_efer(struct kvm_vcpu *vcpu, u64 efer) | 627 | static void set_efer(struct kvm_vcpu *vcpu, u64 efer) |
649 | { | 628 | { |
650 | if (efer & efer_reserved_bits) { | 629 | if (efer & efer_reserved_bits) { |
651 | printk(KERN_DEBUG "set_efer: 0x%llx #GP, reserved bits\n", | ||
652 | efer); | ||
653 | kvm_inject_gp(vcpu, 0); | 630 | kvm_inject_gp(vcpu, 0); |
654 | return; | 631 | return; |
655 | } | 632 | } |
656 | 633 | ||
657 | if (is_paging(vcpu) | 634 | if (is_paging(vcpu) |
658 | && (vcpu->arch.efer & EFER_LME) != (efer & EFER_LME)) { | 635 | && (vcpu->arch.efer & EFER_LME) != (efer & EFER_LME)) { |
659 | printk(KERN_DEBUG "set_efer: #GP, change LME while paging\n"); | ||
660 | kvm_inject_gp(vcpu, 0); | 636 | kvm_inject_gp(vcpu, 0); |
661 | return; | 637 | return; |
662 | } | 638 | } |
@@ -666,7 +642,6 @@ static void set_efer(struct kvm_vcpu *vcpu, u64 efer) | |||
666 | 642 | ||
667 | feat = kvm_find_cpuid_entry(vcpu, 0x80000001, 0); | 643 | feat = kvm_find_cpuid_entry(vcpu, 0x80000001, 0); |
668 | if (!feat || !(feat->edx & bit(X86_FEATURE_FXSR_OPT))) { | 644 | if (!feat || !(feat->edx & bit(X86_FEATURE_FXSR_OPT))) { |
669 | printk(KERN_DEBUG "set_efer: #GP, enable FFXSR w/o CPUID capability\n"); | ||
670 | kvm_inject_gp(vcpu, 0); | 645 | kvm_inject_gp(vcpu, 0); |
671 | return; | 646 | return; |
672 | } | 647 | } |
@@ -677,7 +652,6 @@ static void set_efer(struct kvm_vcpu *vcpu, u64 efer) | |||
677 | 652 | ||
678 | feat = kvm_find_cpuid_entry(vcpu, 0x80000001, 0); | 653 | feat = kvm_find_cpuid_entry(vcpu, 0x80000001, 0); |
679 | if (!feat || !(feat->ecx & bit(X86_FEATURE_SVM))) { | 654 | if (!feat || !(feat->ecx & bit(X86_FEATURE_SVM))) { |
680 | printk(KERN_DEBUG "set_efer: #GP, enable SVM w/o SVM\n"); | ||
681 | kvm_inject_gp(vcpu, 0); | 655 | kvm_inject_gp(vcpu, 0); |
682 | return; | 656 | return; |
683 | } | 657 | } |
@@ -966,9 +940,13 @@ static int set_msr_mce(struct kvm_vcpu *vcpu, u32 msr, u64 data) | |||
966 | if (msr >= MSR_IA32_MC0_CTL && | 940 | if (msr >= MSR_IA32_MC0_CTL && |
967 | msr < MSR_IA32_MC0_CTL + 4 * bank_num) { | 941 | msr < MSR_IA32_MC0_CTL + 4 * bank_num) { |
968 | u32 offset = msr - MSR_IA32_MC0_CTL; | 942 | u32 offset = msr - MSR_IA32_MC0_CTL; |
969 | /* only 0 or all 1s can be written to IA32_MCi_CTL */ | 943 | /* only 0 or all 1s can be written to IA32_MCi_CTL |
944 | * some Linux kernels though clear bit 10 in bank 4 to | ||
945 | * workaround a BIOS/GART TBL issue on AMD K8s, ignore | ||
946 | * this to avoid an uncatched #GP in the guest | ||
947 | */ | ||
970 | if ((offset & 0x3) == 0 && | 948 | if ((offset & 0x3) == 0 && |
971 | data != 0 && data != ~(u64)0) | 949 | data != 0 && (data | (1 << 10)) != ~(u64)0) |
972 | return -1; | 950 | return -1; |
973 | vcpu->arch.mce_banks[offset] = data; | 951 | vcpu->arch.mce_banks[offset] = data; |
974 | break; | 952 | break; |
@@ -2634,8 +2612,9 @@ static int kvm_vm_ioctl_reinject(struct kvm *kvm, | |||
2634 | int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, | 2612 | int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, |
2635 | struct kvm_dirty_log *log) | 2613 | struct kvm_dirty_log *log) |
2636 | { | 2614 | { |
2637 | int r, n, i; | 2615 | int r, i; |
2638 | struct kvm_memory_slot *memslot; | 2616 | struct kvm_memory_slot *memslot; |
2617 | unsigned long n; | ||
2639 | unsigned long is_dirty = 0; | 2618 | unsigned long is_dirty = 0; |
2640 | unsigned long *dirty_bitmap = NULL; | 2619 | unsigned long *dirty_bitmap = NULL; |
2641 | 2620 | ||
@@ -2650,7 +2629,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, | |||
2650 | if (!memslot->dirty_bitmap) | 2629 | if (!memslot->dirty_bitmap) |
2651 | goto out; | 2630 | goto out; |
2652 | 2631 | ||
2653 | n = ALIGN(memslot->npages, BITS_PER_LONG) / 8; | 2632 | n = kvm_dirty_bitmap_bytes(memslot); |
2654 | 2633 | ||
2655 | r = -ENOMEM; | 2634 | r = -ENOMEM; |
2656 | dirty_bitmap = vmalloc(n); | 2635 | dirty_bitmap = vmalloc(n); |
@@ -4482,7 +4461,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
4482 | kvm_set_cr8(vcpu, kvm_run->cr8); | 4461 | kvm_set_cr8(vcpu, kvm_run->cr8); |
4483 | 4462 | ||
4484 | if (vcpu->arch.pio.cur_count) { | 4463 | if (vcpu->arch.pio.cur_count) { |
4464 | vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); | ||
4485 | r = complete_pio(vcpu); | 4465 | r = complete_pio(vcpu); |
4466 | srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); | ||
4486 | if (r) | 4467 | if (r) |
4487 | goto out; | 4468 | goto out; |
4488 | } | 4469 | } |
@@ -5145,6 +5126,7 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason) | |||
5145 | int ret = 0; | 5126 | int ret = 0; |
5146 | u32 old_tss_base = get_segment_base(vcpu, VCPU_SREG_TR); | 5127 | u32 old_tss_base = get_segment_base(vcpu, VCPU_SREG_TR); |
5147 | u16 old_tss_sel = get_segment_selector(vcpu, VCPU_SREG_TR); | 5128 | u16 old_tss_sel = get_segment_selector(vcpu, VCPU_SREG_TR); |
5129 | u32 desc_limit; | ||
5148 | 5130 | ||
5149 | old_tss_base = kvm_mmu_gva_to_gpa_write(vcpu, old_tss_base, NULL); | 5131 | old_tss_base = kvm_mmu_gva_to_gpa_write(vcpu, old_tss_base, NULL); |
5150 | 5132 | ||
@@ -5167,7 +5149,10 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason) | |||
5167 | } | 5149 | } |
5168 | } | 5150 | } |
5169 | 5151 | ||
5170 | if (!nseg_desc.p || get_desc_limit(&nseg_desc) < 0x67) { | 5152 | desc_limit = get_desc_limit(&nseg_desc); |
5153 | if (!nseg_desc.p || | ||
5154 | ((desc_limit < 0x67 && (nseg_desc.type & 8)) || | ||
5155 | desc_limit < 0x2b)) { | ||
5171 | kvm_queue_exception_e(vcpu, TS_VECTOR, tss_selector & 0xfffc); | 5156 | kvm_queue_exception_e(vcpu, TS_VECTOR, tss_selector & 0xfffc); |
5172 | return 1; | 5157 | return 1; |
5173 | } | 5158 | } |