Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a0c0feb5 authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

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: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent d1431483
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -88,6 +88,14 @@ static inline bool guest_cpuid_has_x2apic(struct kvm_vcpu *vcpu)
	return best && (best->ecx & bit(X86_FEATURE_X2APIC));
}

static inline bool guest_cpuid_is_amd(struct kvm_vcpu *vcpu)
{
	struct kvm_cpuid_entry2 *best;

	best = kvm_find_cpuid_entry(vcpu, 0, 0);
	return best && best->ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx;
}

static inline bool guest_cpuid_has_gbpages(struct kvm_vcpu *vcpu)
{
	struct kvm_cpuid_entry2 *best;
+11 −2
Original line number Diff line number Diff line
@@ -3512,6 +3512,7 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
	int maxphyaddr = cpuid_maxphyaddr(vcpu);
	u64 exb_bit_rsvd = 0;
	u64 gbpages_bit_rsvd = 0;
	u64 nonleaf_bit8_rsvd = 0;

	context->bad_mt_xwr = 0;

@@ -3519,6 +3520,14 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
		exb_bit_rsvd = rsvd_bits(63, 63);
	if (!guest_cpuid_has_gbpages(vcpu))
		gbpages_bit_rsvd = rsvd_bits(7, 7);

	/*
	 * Non-leaf PML4Es and PDPEs reserve bit 8 (which would be the G bit for
	 * leaf entries) on AMD CPUs only.
	 */
	if (guest_cpuid_is_amd(vcpu))
		nonleaf_bit8_rsvd = rsvd_bits(8, 8);

	switch (context->root_level) {
	case PT32_ROOT_LEVEL:
		/* no rsvd bits for 2 level 4K page table entries */
@@ -3553,9 +3562,9 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
		break;
	case PT64_ROOT_LEVEL:
		context->rsvd_bits_mask[0][3] = exb_bit_rsvd |
			rsvd_bits(maxphyaddr, 51) | rsvd_bits(7, 7);
			nonleaf_bit8_rsvd | rsvd_bits(7, 7) | rsvd_bits(maxphyaddr, 51);
		context->rsvd_bits_mask[0][2] = exb_bit_rsvd |
			gbpages_bit_rsvd | rsvd_bits(maxphyaddr, 51);
			nonleaf_bit8_rsvd | gbpages_bit_rsvd | rsvd_bits(maxphyaddr, 51);
		context->rsvd_bits_mask[0][1] = exb_bit_rsvd |
			rsvd_bits(maxphyaddr, 51);
		context->rsvd_bits_mask[0][0] = exb_bit_rsvd |