aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2014-09-02 07:24:12 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2014-09-03 04:04:11 -0400
commita0c0feb57992c5caed170feab8a68c51306eb7c3 (patch)
tree03865eccb27cbc1a2604d6e83ae3f8ecff9b355c
parentd143148383d0395539073dd6c2f25ddf6656bdcc (diff)
KVM: x86: reserve bit 8 of non-leaf PDPEs and PML4Es in 64-bit mode on AMD
Bit 8 would be the "global" bit, which does not quite make sense for non-leaf page table entries. Intel ignores it; AMD ignores it in PDEs, but reserves it in PDPEs and PML4Es. The SVM test is relying on this behavior, so enforce it. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--arch/x86/kvm/cpuid.h8
-rw-r--r--arch/x86/kvm/mmu.c13
2 files changed, 19 insertions, 2 deletions
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index a5380590ab0e..43b33e301e68 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -88,6 +88,14 @@ static inline bool guest_cpuid_has_x2apic(struct kvm_vcpu *vcpu)
88 return best && (best->ecx & bit(X86_FEATURE_X2APIC)); 88 return best && (best->ecx & bit(X86_FEATURE_X2APIC));
89} 89}
90 90
91static inline bool guest_cpuid_is_amd(struct kvm_vcpu *vcpu)
92{
93 struct kvm_cpuid_entry2 *best;
94
95 best = kvm_find_cpuid_entry(vcpu, 0, 0);
96 return best && best->ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx;
97}
98
91static inline bool guest_cpuid_has_gbpages(struct kvm_vcpu *vcpu) 99static inline bool guest_cpuid_has_gbpages(struct kvm_vcpu *vcpu)
92{ 100{
93 struct kvm_cpuid_entry2 *best; 101 struct kvm_cpuid_entry2 *best;
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 6b6df0c5be3d..5b93a597e0c8 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3512,6 +3512,7 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
3512 int maxphyaddr = cpuid_maxphyaddr(vcpu); 3512 int maxphyaddr = cpuid_maxphyaddr(vcpu);
3513 u64 exb_bit_rsvd = 0; 3513 u64 exb_bit_rsvd = 0;
3514 u64 gbpages_bit_rsvd = 0; 3514 u64 gbpages_bit_rsvd = 0;
3515 u64 nonleaf_bit8_rsvd = 0;
3515 3516
3516 context->bad_mt_xwr = 0; 3517 context->bad_mt_xwr = 0;
3517 3518
@@ -3519,6 +3520,14 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
3519 exb_bit_rsvd = rsvd_bits(63, 63); 3520 exb_bit_rsvd = rsvd_bits(63, 63);
3520 if (!guest_cpuid_has_gbpages(vcpu)) 3521 if (!guest_cpuid_has_gbpages(vcpu))
3521 gbpages_bit_rsvd = rsvd_bits(7, 7); 3522 gbpages_bit_rsvd = rsvd_bits(7, 7);
3523
3524 /*
3525 * Non-leaf PML4Es and PDPEs reserve bit 8 (which would be the G bit for
3526 * leaf entries) on AMD CPUs only.
3527 */
3528 if (guest_cpuid_is_amd(vcpu))
3529 nonleaf_bit8_rsvd = rsvd_bits(8, 8);
3530
3522 switch (context->root_level) { 3531 switch (context->root_level) {
3523 case PT32_ROOT_LEVEL: 3532 case PT32_ROOT_LEVEL:
3524 /* no rsvd bits for 2 level 4K page table entries */ 3533 /* no rsvd bits for 2 level 4K page table entries */
@@ -3553,9 +3562,9 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
3553 break; 3562 break;
3554 case PT64_ROOT_LEVEL: 3563 case PT64_ROOT_LEVEL:
3555 context->rsvd_bits_mask[0][3] = exb_bit_rsvd | 3564 context->rsvd_bits_mask[0][3] = exb_bit_rsvd |
3556 rsvd_bits(maxphyaddr, 51) | rsvd_bits(7, 7); 3565 nonleaf_bit8_rsvd | rsvd_bits(7, 7) | rsvd_bits(maxphyaddr, 51);
3557 context->rsvd_bits_mask[0][2] = exb_bit_rsvd | 3566 context->rsvd_bits_mask[0][2] = exb_bit_rsvd |
3558 gbpages_bit_rsvd | rsvd_bits(maxphyaddr, 51); 3567 nonleaf_bit8_rsvd | gbpages_bit_rsvd | rsvd_bits(maxphyaddr, 51);
3559 context->rsvd_bits_mask[0][1] = exb_bit_rsvd | 3568 context->rsvd_bits_mask[0][1] = exb_bit_rsvd |
3560 rsvd_bits(maxphyaddr, 51); 3569 rsvd_bits(maxphyaddr, 51);
3561 context->rsvd_bits_mask[0][0] = exb_bit_rsvd | 3570 context->rsvd_bits_mask[0][0] = exb_bit_rsvd |