aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm
diff options
context:
space:
mode:
authorNadav Amit <namit@cs.technion.ac.il>2014-05-07 08:32:50 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2014-05-07 11:25:22 -0400
commit5f7dde7bbb3c628766676cbd63c0a1834035d6fa (patch)
tree39fde3ae31697b7e1ef19af9f1d3d626d0f7e909 /arch/x86/kvm
parenta4ab9d0cf1ef0bf521bb69099aa464f38c71393c (diff)
KVM: x86: Mark bit 7 in long-mode PDPTE according to 1GB pages support
In long-mode, bit 7 in the PDPTE is not reserved only if 1GB pages are supported by the CPU. Currently the bit is considered by KVM as always reserved. Signed-off-by: Nadav Amit <namit@cs.technion.ac.il> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r--arch/x86/kvm/cpuid.h7
-rw-r--r--arch/x86/kvm/mmu.c8
2 files changed, 13 insertions, 2 deletions
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index eeecbed26ac7..f9087315e0cd 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -88,4 +88,11 @@ 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_has_gbpages(struct kvm_vcpu *vcpu)
92{
93 struct kvm_cpuid_entry2 *best;
94
95 best = kvm_find_cpuid_entry(vcpu, 0x80000001, 0);
96 return best && (best->edx & bit(X86_FEATURE_GBPAGES));
97}
91#endif 98#endif
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 65f2400b8268..931467881da7 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -22,6 +22,7 @@
22#include "mmu.h" 22#include "mmu.h"
23#include "x86.h" 23#include "x86.h"
24#include "kvm_cache_regs.h" 24#include "kvm_cache_regs.h"
25#include "cpuid.h"
25 26
26#include <linux/kvm_host.h> 27#include <linux/kvm_host.h>
27#include <linux/types.h> 28#include <linux/types.h>
@@ -3516,11 +3517,14 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
3516{ 3517{
3517 int maxphyaddr = cpuid_maxphyaddr(vcpu); 3518 int maxphyaddr = cpuid_maxphyaddr(vcpu);
3518 u64 exb_bit_rsvd = 0; 3519 u64 exb_bit_rsvd = 0;
3520 u64 gbpages_bit_rsvd = 0;
3519 3521
3520 context->bad_mt_xwr = 0; 3522 context->bad_mt_xwr = 0;
3521 3523
3522 if (!context->nx) 3524 if (!context->nx)
3523 exb_bit_rsvd = rsvd_bits(63, 63); 3525 exb_bit_rsvd = rsvd_bits(63, 63);
3526 if (!guest_cpuid_has_gbpages(vcpu))
3527 gbpages_bit_rsvd = rsvd_bits(7, 7);
3524 switch (context->root_level) { 3528 switch (context->root_level) {
3525 case PT32_ROOT_LEVEL: 3529 case PT32_ROOT_LEVEL:
3526 /* no rsvd bits for 2 level 4K page table entries */ 3530 /* no rsvd bits for 2 level 4K page table entries */
@@ -3557,14 +3561,14 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
3557 context->rsvd_bits_mask[0][3] = exb_bit_rsvd | 3561 context->rsvd_bits_mask[0][3] = exb_bit_rsvd |
3558 rsvd_bits(maxphyaddr, 51) | rsvd_bits(7, 7); 3562 rsvd_bits(maxphyaddr, 51) | rsvd_bits(7, 7);
3559 context->rsvd_bits_mask[0][2] = exb_bit_rsvd | 3563 context->rsvd_bits_mask[0][2] = exb_bit_rsvd |
3560 rsvd_bits(maxphyaddr, 51) | rsvd_bits(7, 7); 3564 gbpages_bit_rsvd | rsvd_bits(maxphyaddr, 51);
3561 context->rsvd_bits_mask[0][1] = exb_bit_rsvd | 3565 context->rsvd_bits_mask[0][1] = exb_bit_rsvd |
3562 rsvd_bits(maxphyaddr, 51); 3566 rsvd_bits(maxphyaddr, 51);
3563 context->rsvd_bits_mask[0][0] = exb_bit_rsvd | 3567 context->rsvd_bits_mask[0][0] = exb_bit_rsvd |
3564 rsvd_bits(maxphyaddr, 51); 3568 rsvd_bits(maxphyaddr, 51);
3565 context->rsvd_bits_mask[1][3] = context->rsvd_bits_mask[0][3]; 3569 context->rsvd_bits_mask[1][3] = context->rsvd_bits_mask[0][3];
3566 context->rsvd_bits_mask[1][2] = exb_bit_rsvd | 3570 context->rsvd_bits_mask[1][2] = exb_bit_rsvd |
3567 rsvd_bits(maxphyaddr, 51) | 3571 gbpages_bit_rsvd | rsvd_bits(maxphyaddr, 51) |
3568 rsvd_bits(13, 29); 3572 rsvd_bits(13, 29);
3569 context->rsvd_bits_mask[1][1] = exb_bit_rsvd | 3573 context->rsvd_bits_mask[1][1] = exb_bit_rsvd |
3570 rsvd_bits(maxphyaddr, 51) | 3574 rsvd_bits(maxphyaddr, 51) |