KVM: x86: MOV to CR3 can set bit 63
authorNadav Amit <namit@cs.technion.ac.il>
Sun, 2 Nov 2014 09:54:52 +0000 (11:54 +0200)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 7 Nov 2014 14:44:07 +0000 (15:44 +0100)
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>
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/emulate.c
arch/x86/kvm/x86.c

index 904535fe825e7ba649e579ba7d2e00481c35bc7d..dc932d388c43ac8d8d5519183e2c549f99315e8f 100644 (file)
@@ -51,6 +51,7 @@
                          | X86_CR0_NW | X86_CR0_CD | X86_CR0_PG))
 
 #define CR3_L_MODE_RESERVED_BITS 0xFFFFFF0000000000ULL
+#define CR3_PCID_INVD           (1UL << 63)
 #define CR4_RESERVED_BITS                                               \
        (~(unsigned long)(X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | X86_CR4_DE\
                          | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE     \
index a2a9c18b42e40bd05b28ebaf6b024974a40dc9a8..9f960b428bb254cd351e110e194eaa5e15c05010 100644 (file)
@@ -3564,7 +3564,7 @@ static int check_cr_write(struct x86_emulate_ctxt *ctxt)
 
                ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);
                if (efer & EFER_LMA)
-                       rsvd = CR3_L_MODE_RESERVED_BITS;
+                       rsvd = CR3_L_MODE_RESERVED_BITS & ~CR3_PCID_INVD;
 
                if (new_val & rsvd)
                        return emulate_gp(ctxt, 0);
index 773c17ec42ddb5d08133895f2231b0d5d8ee56d5..641358865a0c98068c6c2a6f446e02fdcafd444d 100644 (file)
@@ -750,6 +750,8 @@ EXPORT_SYMBOL_GPL(kvm_set_cr4);
 
 int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 {
+       cr3 &= ~CR3_PCID_INVD;
+
        if (cr3 == kvm_read_cr3(vcpu) && !pdptrs_changed(vcpu)) {
                kvm_mmu_sync_roots(vcpu);
                kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);