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>
This commit is contained in:
parent
a4ab9d0cf1
commit
5f7dde7bbb
2 changed files with 13 additions and 2 deletions
|
@ -88,4 +88,11 @@ static inline bool guest_cpuid_has_x2apic(struct kvm_vcpu *vcpu)
|
||||||
return best && (best->ecx & bit(X86_FEATURE_X2APIC));
|
return best && (best->ecx & bit(X86_FEATURE_X2APIC));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool guest_cpuid_has_gbpages(struct kvm_vcpu *vcpu)
|
||||||
|
{
|
||||||
|
struct kvm_cpuid_entry2 *best;
|
||||||
|
|
||||||
|
best = kvm_find_cpuid_entry(vcpu, 0x80000001, 0);
|
||||||
|
return best && (best->edx & bit(X86_FEATURE_GBPAGES));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "mmu.h"
|
#include "mmu.h"
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
#include "kvm_cache_regs.h"
|
#include "kvm_cache_regs.h"
|
||||||
|
#include "cpuid.h"
|
||||||
|
|
||||||
#include <linux/kvm_host.h>
|
#include <linux/kvm_host.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
@ -3516,11 +3517,14 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
|
||||||
{
|
{
|
||||||
int maxphyaddr = cpuid_maxphyaddr(vcpu);
|
int maxphyaddr = cpuid_maxphyaddr(vcpu);
|
||||||
u64 exb_bit_rsvd = 0;
|
u64 exb_bit_rsvd = 0;
|
||||||
|
u64 gbpages_bit_rsvd = 0;
|
||||||
|
|
||||||
context->bad_mt_xwr = 0;
|
context->bad_mt_xwr = 0;
|
||||||
|
|
||||||
if (!context->nx)
|
if (!context->nx)
|
||||||
exb_bit_rsvd = rsvd_bits(63, 63);
|
exb_bit_rsvd = rsvd_bits(63, 63);
|
||||||
|
if (!guest_cpuid_has_gbpages(vcpu))
|
||||||
|
gbpages_bit_rsvd = rsvd_bits(7, 7);
|
||||||
switch (context->root_level) {
|
switch (context->root_level) {
|
||||||
case PT32_ROOT_LEVEL:
|
case PT32_ROOT_LEVEL:
|
||||||
/* no rsvd bits for 2 level 4K page table entries */
|
/* no rsvd bits for 2 level 4K page table entries */
|
||||||
|
@ -3557,14 +3561,14 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
|
||||||
context->rsvd_bits_mask[0][3] = exb_bit_rsvd |
|
context->rsvd_bits_mask[0][3] = exb_bit_rsvd |
|
||||||
rsvd_bits(maxphyaddr, 51) | rsvd_bits(7, 7);
|
rsvd_bits(maxphyaddr, 51) | rsvd_bits(7, 7);
|
||||||
context->rsvd_bits_mask[0][2] = exb_bit_rsvd |
|
context->rsvd_bits_mask[0][2] = exb_bit_rsvd |
|
||||||
rsvd_bits(maxphyaddr, 51) | rsvd_bits(7, 7);
|
gbpages_bit_rsvd | rsvd_bits(maxphyaddr, 51);
|
||||||
context->rsvd_bits_mask[0][1] = exb_bit_rsvd |
|
context->rsvd_bits_mask[0][1] = exb_bit_rsvd |
|
||||||
rsvd_bits(maxphyaddr, 51);
|
rsvd_bits(maxphyaddr, 51);
|
||||||
context->rsvd_bits_mask[0][0] = exb_bit_rsvd |
|
context->rsvd_bits_mask[0][0] = exb_bit_rsvd |
|
||||||
rsvd_bits(maxphyaddr, 51);
|
rsvd_bits(maxphyaddr, 51);
|
||||||
context->rsvd_bits_mask[1][3] = context->rsvd_bits_mask[0][3];
|
context->rsvd_bits_mask[1][3] = context->rsvd_bits_mask[0][3];
|
||||||
context->rsvd_bits_mask[1][2] = exb_bit_rsvd |
|
context->rsvd_bits_mask[1][2] = exb_bit_rsvd |
|
||||||
rsvd_bits(maxphyaddr, 51) |
|
gbpages_bit_rsvd | rsvd_bits(maxphyaddr, 51) |
|
||||||
rsvd_bits(13, 29);
|
rsvd_bits(13, 29);
|
||||||
context->rsvd_bits_mask[1][1] = exb_bit_rsvd |
|
context->rsvd_bits_mask[1][1] = exb_bit_rsvd |
|
||||||
rsvd_bits(maxphyaddr, 51) |
|
rsvd_bits(maxphyaddr, 51) |
|
||||||
|
|
Loading…
Add table
Reference in a new issue