aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNadav Amit <namit@cs.technion.ac.il>2014-11-02 04:54:52 -0500
committerPaolo Bonzini <pbonzini@redhat.com>2014-11-07 09:44:07 -0500
commit9d88fca71a99a65c37cbfe481b4aa4e91a27ff13 (patch)
tree9e698aa68ff7b8cbabcdcda3b3d1ac46d86636b3
parent0fcc207c66a7cff024b05367b86d70d742072d61 (diff)
KVM: x86: MOV to CR3 can set bit 63
Although Intel SDM mentions bit 63 is reserved, MOV to CR3 can have bit 63 set. As Intel SDM states in section 4.10.4 "Invalidation of TLBs and Paging-Structure Caches": " MOV to CR3. ... If CR4.PCIDE = 1 and bit 63 of the instruction’s source operand is 0 ..." In other words, bit 63 is not reserved. KVM emulator currently consider bit 63 as reserved. Fix it. Signed-off-by: Nadav Amit <namit@cs.technion.ac.il> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--arch/x86/include/asm/kvm_host.h1
-rw-r--r--arch/x86/kvm/emulate.c2
-rw-r--r--arch/x86/kvm/x86.c2
3 files changed, 4 insertions, 1 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 904535fe825e..dc932d388c43 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -51,6 +51,7 @@
51 | X86_CR0_NW | X86_CR0_CD | X86_CR0_PG)) 51 | X86_CR0_NW | X86_CR0_CD | X86_CR0_PG))
52 52
53#define CR3_L_MODE_RESERVED_BITS 0xFFFFFF0000000000ULL 53#define CR3_L_MODE_RESERVED_BITS 0xFFFFFF0000000000ULL
54#define CR3_PCID_INVD (1UL << 63)
54#define CR4_RESERVED_BITS \ 55#define CR4_RESERVED_BITS \
55 (~(unsigned long)(X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | X86_CR4_DE\ 56 (~(unsigned long)(X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | X86_CR4_DE\
56 | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE \ 57 | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE \
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index a2a9c18b42e4..9f960b428bb2 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -3564,7 +3564,7 @@ static int check_cr_write(struct x86_emulate_ctxt *ctxt)
3564 3564
3565 ctxt->ops->get_msr(ctxt, MSR_EFER, &efer); 3565 ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);
3566 if (efer & EFER_LMA) 3566 if (efer & EFER_LMA)
3567 rsvd = CR3_L_MODE_RESERVED_BITS; 3567 rsvd = CR3_L_MODE_RESERVED_BITS & ~CR3_PCID_INVD;
3568 3568
3569 if (new_val & rsvd) 3569 if (new_val & rsvd)
3570 return emulate_gp(ctxt, 0); 3570 return emulate_gp(ctxt, 0);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 773c17ec42dd..641358865a0c 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -750,6 +750,8 @@ EXPORT_SYMBOL_GPL(kvm_set_cr4);
750 750
751int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) 751int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
752{ 752{
753 cr3 &= ~CR3_PCID_INVD;
754
753 if (cr3 == kvm_read_cr3(vcpu) && !pdptrs_changed(vcpu)) { 755 if (cr3 == kvm_read_cr3(vcpu) && !pdptrs_changed(vcpu)) {
754 kvm_mmu_sync_roots(vcpu); 756 kvm_mmu_sync_roots(vcpu);
755 kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu); 757 kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);