Loading arch/x86/include/asm/kvm_host.h +4 −0 Original line number Diff line number Diff line Loading @@ -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, Loading arch/x86/kvm/kvm_cache_regs.h +9 −0 Original line number Diff line number Diff line Loading @@ -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 arch/x86/kvm/mmu.c +5 −2 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ */ #include "mmu.h" #include "kvm_cache_regs.h" #include <linux/kvm_host.h> #include <linux/types.h> Loading Loading @@ -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; Loading Loading @@ -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)) Loading arch/x86/kvm/paging_tmpl.h +1 −1 Original line number Diff line number Diff line Loading @@ -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; Loading arch/x86/kvm/svm.c +18 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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); } Loading Loading @@ -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 Loading
arch/x86/include/asm/kvm_host.h +4 −0 Original line number Diff line number Diff line Loading @@ -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, Loading
arch/x86/kvm/kvm_cache_regs.h +9 −0 Original line number Diff line number Diff line Loading @@ -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
arch/x86/kvm/mmu.c +5 −2 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ */ #include "mmu.h" #include "kvm_cache_regs.h" #include <linux/kvm_host.h> #include <linux/types.h> Loading Loading @@ -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; Loading Loading @@ -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)) Loading
arch/x86/kvm/paging_tmpl.h +1 −1 Original line number Diff line number Diff line Loading @@ -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; Loading
arch/x86/kvm/svm.c +18 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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); } Loading Loading @@ -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