diff options
Diffstat (limited to 'drivers/kvm/svm.c')
-rw-r--r-- | drivers/kvm/svm.c | 59 |
1 files changed, 37 insertions, 22 deletions
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index fa17d6d4f0cb..bc818cc126e3 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c | |||
@@ -14,16 +14,17 @@ | |||
14 | * | 14 | * |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "kvm_svm.h" | ||
18 | #include "x86_emulate.h" | ||
19 | |||
17 | #include <linux/module.h> | 20 | #include <linux/module.h> |
18 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
19 | #include <linux/vmalloc.h> | 22 | #include <linux/vmalloc.h> |
20 | #include <linux/highmem.h> | 23 | #include <linux/highmem.h> |
21 | #include <linux/profile.h> | 24 | #include <linux/profile.h> |
22 | #include <linux/sched.h> | 25 | #include <linux/sched.h> |
23 | #include <asm/desc.h> | ||
24 | 26 | ||
25 | #include "kvm_svm.h" | 27 | #include <asm/desc.h> |
26 | #include "x86_emulate.h" | ||
27 | 28 | ||
28 | MODULE_AUTHOR("Qumranet"); | 29 | MODULE_AUTHOR("Qumranet"); |
29 | MODULE_LICENSE("GPL"); | 30 | MODULE_LICENSE("GPL"); |
@@ -378,7 +379,7 @@ static __init int svm_hardware_setup(void) | |||
378 | int cpu; | 379 | int cpu; |
379 | struct page *iopm_pages; | 380 | struct page *iopm_pages; |
380 | struct page *msrpm_pages; | 381 | struct page *msrpm_pages; |
381 | void *msrpm_va; | 382 | void *iopm_va, *msrpm_va; |
382 | int r; | 383 | int r; |
383 | 384 | ||
384 | kvm_emulator_want_group7_invlpg(); | 385 | kvm_emulator_want_group7_invlpg(); |
@@ -387,8 +388,10 @@ static __init int svm_hardware_setup(void) | |||
387 | 388 | ||
388 | if (!iopm_pages) | 389 | if (!iopm_pages) |
389 | return -ENOMEM; | 390 | return -ENOMEM; |
390 | memset(page_address(iopm_pages), 0xff, | 391 | |
391 | PAGE_SIZE * (1 << IOPM_ALLOC_ORDER)); | 392 | iopm_va = page_address(iopm_pages); |
393 | memset(iopm_va, 0xff, PAGE_SIZE * (1 << IOPM_ALLOC_ORDER)); | ||
394 | clear_bit(0x80, iopm_va); /* allow direct access to PC debug port */ | ||
392 | iopm_base = page_to_pfn(iopm_pages) << PAGE_SHIFT; | 395 | iopm_base = page_to_pfn(iopm_pages) << PAGE_SHIFT; |
393 | 396 | ||
394 | 397 | ||
@@ -579,7 +582,7 @@ static int svm_create_vcpu(struct kvm_vcpu *vcpu) | |||
579 | goto out2; | 582 | goto out2; |
580 | 583 | ||
581 | vcpu->svm->vmcb = page_address(page); | 584 | vcpu->svm->vmcb = page_address(page); |
582 | memset(vcpu->svm->vmcb, 0, PAGE_SIZE); | 585 | clear_page(vcpu->svm->vmcb); |
583 | vcpu->svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT; | 586 | vcpu->svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT; |
584 | vcpu->svm->asid_generation = 0; | 587 | vcpu->svm->asid_generation = 0; |
585 | memset(vcpu->svm->db_regs, 0, sizeof(vcpu->svm->db_regs)); | 588 | memset(vcpu->svm->db_regs, 0, sizeof(vcpu->svm->db_regs)); |
@@ -587,9 +590,9 @@ static int svm_create_vcpu(struct kvm_vcpu *vcpu) | |||
587 | 590 | ||
588 | fx_init(vcpu); | 591 | fx_init(vcpu); |
589 | vcpu->fpu_active = 1; | 592 | vcpu->fpu_active = 1; |
590 | vcpu->apic_base = 0xfee00000 | | 593 | vcpu->apic_base = 0xfee00000 | MSR_IA32_APICBASE_ENABLE; |
591 | /*for vcpu 0*/ MSR_IA32_APICBASE_BSP | | 594 | if (vcpu == &vcpu->kvm->vcpus[0]) |
592 | MSR_IA32_APICBASE_ENABLE; | 595 | vcpu->apic_base |= MSR_IA32_APICBASE_BSP; |
593 | 596 | ||
594 | return 0; | 597 | return 0; |
595 | 598 | ||
@@ -955,7 +958,7 @@ static int shutdown_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
955 | * VMCB is undefined after a SHUTDOWN intercept | 958 | * VMCB is undefined after a SHUTDOWN intercept |
956 | * so reinitialize it. | 959 | * so reinitialize it. |
957 | */ | 960 | */ |
958 | memset(vcpu->svm->vmcb, 0, PAGE_SIZE); | 961 | clear_page(vcpu->svm->vmcb); |
959 | init_vmcb(vcpu->svm->vmcb); | 962 | init_vmcb(vcpu->svm->vmcb); |
960 | 963 | ||
961 | kvm_run->exit_reason = KVM_EXIT_SHUTDOWN; | 964 | kvm_run->exit_reason = KVM_EXIT_SHUTDOWN; |
@@ -1113,12 +1116,7 @@ static int halt_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
1113 | { | 1116 | { |
1114 | vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 1; | 1117 | vcpu->svm->next_rip = vcpu->svm->vmcb->save.rip + 1; |
1115 | skip_emulated_instruction(vcpu); | 1118 | skip_emulated_instruction(vcpu); |
1116 | if (vcpu->irq_summary) | 1119 | return kvm_emulate_halt(vcpu); |
1117 | return 1; | ||
1118 | |||
1119 | kvm_run->exit_reason = KVM_EXIT_HLT; | ||
1120 | ++vcpu->stat.halt_exits; | ||
1121 | return 0; | ||
1122 | } | 1120 | } |
1123 | 1121 | ||
1124 | static int vmmcall_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | 1122 | static int vmmcall_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) |
@@ -1473,6 +1471,11 @@ static void load_db_regs(unsigned long *db_regs) | |||
1473 | asm volatile ("mov %0, %%dr3" : : "r"(db_regs[3])); | 1471 | asm volatile ("mov %0, %%dr3" : : "r"(db_regs[3])); |
1474 | } | 1472 | } |
1475 | 1473 | ||
1474 | static void svm_flush_tlb(struct kvm_vcpu *vcpu) | ||
1475 | { | ||
1476 | force_new_asid(vcpu); | ||
1477 | } | ||
1478 | |||
1476 | static int svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | 1479 | static int svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) |
1477 | { | 1480 | { |
1478 | u16 fs_selector; | 1481 | u16 fs_selector; |
@@ -1481,11 +1484,20 @@ static int svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
1481 | int r; | 1484 | int r; |
1482 | 1485 | ||
1483 | again: | 1486 | again: |
1487 | r = kvm_mmu_reload(vcpu); | ||
1488 | if (unlikely(r)) | ||
1489 | return r; | ||
1490 | |||
1484 | if (!vcpu->mmio_read_completed) | 1491 | if (!vcpu->mmio_read_completed) |
1485 | do_interrupt_requests(vcpu, kvm_run); | 1492 | do_interrupt_requests(vcpu, kvm_run); |
1486 | 1493 | ||
1487 | clgi(); | 1494 | clgi(); |
1488 | 1495 | ||
1496 | vcpu->guest_mode = 1; | ||
1497 | if (vcpu->requests) | ||
1498 | if (test_and_clear_bit(KVM_TLB_FLUSH, &vcpu->requests)) | ||
1499 | svm_flush_tlb(vcpu); | ||
1500 | |||
1489 | pre_svm_run(vcpu); | 1501 | pre_svm_run(vcpu); |
1490 | 1502 | ||
1491 | save_host_msrs(vcpu); | 1503 | save_host_msrs(vcpu); |
@@ -1617,6 +1629,8 @@ again: | |||
1617 | #endif | 1629 | #endif |
1618 | : "cc", "memory" ); | 1630 | : "cc", "memory" ); |
1619 | 1631 | ||
1632 | vcpu->guest_mode = 0; | ||
1633 | |||
1620 | if (vcpu->fpu_active) { | 1634 | if (vcpu->fpu_active) { |
1621 | fx_save(vcpu->guest_fx_image); | 1635 | fx_save(vcpu->guest_fx_image); |
1622 | fx_restore(vcpu->host_fx_image); | 1636 | fx_restore(vcpu->host_fx_image); |
@@ -1681,11 +1695,6 @@ again: | |||
1681 | return r; | 1695 | return r; |
1682 | } | 1696 | } |
1683 | 1697 | ||
1684 | static void svm_flush_tlb(struct kvm_vcpu *vcpu) | ||
1685 | { | ||
1686 | force_new_asid(vcpu); | ||
1687 | } | ||
1688 | |||
1689 | static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root) | 1698 | static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root) |
1690 | { | 1699 | { |
1691 | vcpu->svm->vmcb->save.cr3 = root; | 1700 | vcpu->svm->vmcb->save.cr3 = root; |
@@ -1727,6 +1736,12 @@ static void svm_inject_page_fault(struct kvm_vcpu *vcpu, | |||
1727 | 1736 | ||
1728 | static int is_disabled(void) | 1737 | static int is_disabled(void) |
1729 | { | 1738 | { |
1739 | u64 vm_cr; | ||
1740 | |||
1741 | rdmsrl(MSR_VM_CR, vm_cr); | ||
1742 | if (vm_cr & (1 << SVM_VM_CR_SVM_DISABLE)) | ||
1743 | return 1; | ||
1744 | |||
1730 | return 0; | 1745 | return 0; |
1731 | } | 1746 | } |
1732 | 1747 | ||