Skip to content

Commit d1cd3ce

Browse files
Yu Zhangbonzini
authored andcommitted
KVM: MMU: check guest CR3 reserved bits based on its physical address width.
Currently, KVM uses CR3_L_MODE_RESERVED_BITS to check the reserved bits in CR3. Yet the length of reserved bits in guest CR3 should be based on the physical address width exposed to the VM. This patch changes CR3 check logic to calculate the reserved bits at runtime. Signed-off-by: Yu Zhang <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent e911eb3 commit d1cd3ce

File tree

4 files changed

+19
-7
lines changed

4 files changed

+19
-7
lines changed

arch/x86/include/asm/kvm_host.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@
7979
| X86_CR0_ET | X86_CR0_NE | X86_CR0_WP | X86_CR0_AM \
8080
| X86_CR0_NW | X86_CR0_CD | X86_CR0_PG))
8181

82-
#define CR3_L_MODE_RESERVED_BITS 0xFFFFFF0000000000ULL
8382
#define CR3_PCID_INVD BIT_64(63)
8483
#define CR4_RESERVED_BITS \
8584
(~(unsigned long)(X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | X86_CR4_DE\

arch/x86/kvm/emulate.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
#include "x86.h"
3030
#include "tss.h"
31+
#include "mmu.h"
3132

3233
/*
3334
* Operand types
@@ -4097,8 +4098,17 @@ static int check_cr_write(struct x86_emulate_ctxt *ctxt)
40974098
u64 rsvd = 0;
40984099

40994100
ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);
4100-
if (efer & EFER_LMA)
4101-
rsvd = CR3_L_MODE_RESERVED_BITS & ~CR3_PCID_INVD;
4101+
if (efer & EFER_LMA) {
4102+
u64 maxphyaddr;
4103+
u32 eax = 0x80000008;
4104+
4105+
if (ctxt->ops->get_cpuid(ctxt, &eax, NULL, NULL,
4106+
NULL, false))
4107+
maxphyaddr = eax & 0xff;
4108+
else
4109+
maxphyaddr = 36;
4110+
rsvd = rsvd_bits(maxphyaddr, 62);
4111+
}
41024112

41034113
if (new_val & rsvd)
41044114
return emulate_gp(ctxt, 0);

arch/x86/kvm/mmu.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@
4848

4949
static inline u64 rsvd_bits(int s, int e)
5050
{
51+
if (e < s)
52+
return 0;
53+
5154
return ((1ULL << (e - s + 1)) - 1) << s;
5255
}
5356

arch/x86/kvm/x86.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -813,10 +813,10 @@ int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
813813
return 0;
814814
}
815815

816-
if (is_long_mode(vcpu)) {
817-
if (cr3 & CR3_L_MODE_RESERVED_BITS)
818-
return 1;
819-
} else if (is_pae(vcpu) && is_paging(vcpu) &&
816+
if (is_long_mode(vcpu) &&
817+
(cr3 & rsvd_bits(cpuid_maxphyaddr(vcpu), 62)))
818+
return 1;
819+
else if (is_pae(vcpu) && is_paging(vcpu) &&
820820
!load_pdptrs(vcpu, vcpu->arch.walk_mmu, cr3))
821821
return 1;
822822

0 commit comments

Comments
 (0)