aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/svm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/kvm/svm.c')
-rw-r--r--drivers/kvm/svm.c59
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
28MODULE_AUTHOR("Qumranet"); 29MODULE_AUTHOR("Qumranet");
29MODULE_LICENSE("GPL"); 30MODULE_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
1124static int vmmcall_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 1122static 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
1474static void svm_flush_tlb(struct kvm_vcpu *vcpu)
1475{
1476 force_new_asid(vcpu);
1477}
1478
1476static int svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 1479static 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
1483again: 1486again:
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
1684static void svm_flush_tlb(struct kvm_vcpu *vcpu)
1685{
1686 force_new_asid(vcpu);
1687}
1688
1689static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root) 1698static 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
1728static int is_disabled(void) 1737static 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