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

Commit 6de4f3ad authored by Avi Kivity's avatar Avi Kivity
Browse files

KVM: Cache pdptrs



Instead of reloading the pdptrs on every entry and exit (vmcs writes on vmx,
guest memory access on svm) extract them on demand.

Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 8f5d549f
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -120,6 +120,10 @@ enum kvm_reg {
	NR_VCPU_REGS
};

enum kvm_reg_ex {
	VCPU_EXREG_PDPTR = NR_VCPU_REGS,
};

enum {
	VCPU_SREG_ES,
	VCPU_SREG_CS,
+9 −0
Original line number Diff line number Diff line
@@ -29,4 +29,13 @@ static inline void kvm_rip_write(struct kvm_vcpu *vcpu, unsigned long val)
	kvm_register_write(vcpu, VCPU_REGS_RIP, val);
}

static inline u64 kvm_pdptr_read(struct kvm_vcpu *vcpu, int index)
{
	if (!test_bit(VCPU_EXREG_PDPTR,
		      (unsigned long *)&vcpu->arch.regs_avail))
		kvm_x86_ops->cache_reg(vcpu, VCPU_EXREG_PDPTR);

	return vcpu->arch.pdptrs[index];
}

#endif
+5 −2
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
 */

#include "mmu.h"
#include "kvm_cache_regs.h"

#include <linux/kvm_host.h>
#include <linux/types.h>
@@ -1954,6 +1955,7 @@ static int mmu_alloc_roots(struct kvm_vcpu *vcpu)
	gfn_t root_gfn;
	struct kvm_mmu_page *sp;
	int direct = 0;
	u64 pdptr;

	root_gfn = vcpu->arch.cr3 >> PAGE_SHIFT;

@@ -1981,11 +1983,12 @@ static int mmu_alloc_roots(struct kvm_vcpu *vcpu)

		ASSERT(!VALID_PAGE(root));
		if (vcpu->arch.mmu.root_level == PT32E_ROOT_LEVEL) {
			if (!is_present_pte(vcpu->arch.pdptrs[i])) {
			pdptr = kvm_pdptr_read(vcpu, i);
			if (!is_present_pte(pdptr)) {
				vcpu->arch.mmu.pae_root[i] = 0;
				continue;
			}
			root_gfn = vcpu->arch.pdptrs[i] >> PAGE_SHIFT;
			root_gfn = pdptr >> PAGE_SHIFT;
		} else if (vcpu->arch.mmu.root_level == 0)
			root_gfn = 0;
		if (mmu_check_root(vcpu, root_gfn))
+1 −1
Original line number Diff line number Diff line
@@ -131,7 +131,7 @@ static int FNAME(walk_addr)(struct guest_walker *walker,
	pte = vcpu->arch.cr3;
#if PTTYPE == 64
	if (!is_long_mode(vcpu)) {
		pte = vcpu->arch.pdptrs[(addr >> 30) & 3];
		pte = kvm_pdptr_read(vcpu, (addr >> 30) & 3);
		if (!is_present_pte(pte))
			goto not_present;
		--walker->level;
+18 −6
Original line number Diff line number Diff line
@@ -777,6 +777,18 @@ static void svm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
	to_svm(vcpu)->vmcb->save.rflags = rflags;
}

static void svm_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)
{
	switch (reg) {
	case VCPU_EXREG_PDPTR:
		BUG_ON(!npt_enabled);
		load_pdptrs(vcpu, vcpu->arch.cr3);
		break;
	default:
		BUG();
	}
}

static void svm_set_vintr(struct vcpu_svm *svm)
{
	svm->vmcb->control.intercept |= 1ULL << INTERCEPT_VINTR;
@@ -2285,12 +2297,6 @@ static int handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
		}
		vcpu->arch.cr0 = svm->vmcb->save.cr0;
		vcpu->arch.cr3 = svm->vmcb->save.cr3;
		if (is_paging(vcpu) && is_pae(vcpu) && !is_long_mode(vcpu)) {
			if (!load_pdptrs(vcpu, vcpu->arch.cr3)) {
				kvm_inject_gp(vcpu, 0);
				return 1;
			}
		}
		if (mmu_reload) {
			kvm_mmu_reset_context(vcpu);
			kvm_mmu_load(vcpu);
@@ -2641,6 +2647,11 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)

	svm->next_rip = 0;

	if (npt_enabled) {
		vcpu->arch.regs_avail &= ~(1 << VCPU_EXREG_PDPTR);
		vcpu->arch.regs_dirty &= ~(1 << VCPU_EXREG_PDPTR);
	}

	svm_complete_interrupts(svm);
}

@@ -2749,6 +2760,7 @@ static struct kvm_x86_ops svm_x86_ops = {
	.set_gdt = svm_set_gdt,
	.get_dr = svm_get_dr,
	.set_dr = svm_set_dr,
	.cache_reg = svm_cache_reg,
	.get_rflags = svm_get_rflags,
	.set_rflags = svm_set_rflags,

Loading