On Thu, Sep 02, 2021, Sean Christopherson wrote: > On Tue, Aug 24, 2021, Lai Jiangshan wrote: > Rather than force the sync here, what about kicking all vCPUs and retrying the > page fault? The only gross part is that kvm_mmu_get_page() can now fail :-( > > --- > arch/x86/include/asm/kvm_host.h | 3 ++- > arch/x86/kvm/mmu/mmu.c | 9 +++++++-- > arch/x86/kvm/mmu/paging_tmpl.h | 4 ++++ > 3 files changed, 13 insertions(+), 3 deletions(-) > > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h > index 09b256db394a..332b9fb3454c 100644 > --- a/arch/x86/include/asm/kvm_host.h > +++ b/arch/x86/include/asm/kvm_host.h > @@ -57,7 +57,8 @@ > #define KVM_REQ_MIGRATE_TIMER KVM_ARCH_REQ(0) > #define KVM_REQ_REPORT_TPR_ACCESS KVM_ARCH_REQ(1) > #define KVM_REQ_TRIPLE_FAULT KVM_ARCH_REQ(2) > -#define KVM_REQ_MMU_SYNC KVM_ARCH_REQ(3) > +#define KVM_REQ_MMU_SYNC \ > + KVM_ARCH_REQ_FLAGS(3, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) > #define KVM_REQ_CLOCK_UPDATE KVM_ARCH_REQ(4) > #define KVM_REQ_LOAD_MMU_PGD KVM_ARCH_REQ(5) > #define KVM_REQ_EVENT KVM_ARCH_REQ(6) > diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c > index 4853c033e6ce..03293cd3c7ae 100644 > --- a/arch/x86/kvm/mmu/mmu.c > +++ b/arch/x86/kvm/mmu/mmu.c > @@ -2143,8 +2143,10 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, > kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu); > } > > - if (sp->unsync_children) > - kvm_make_request(KVM_REQ_MMU_SYNC, vcpu); > + if (sp->unsync_children) { > + kvm_make_all_cpus_request(KVM_REQ_MMU_SYNC, vcpu); > + return NULL; > + } > > __clear_sp_write_flooding_count(sp); > > @@ -2999,6 +3001,7 @@ static int __direct_map(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault) > > sp = kvm_mmu_get_page(vcpu, base_gfn, it.addr, > it.level - 1, true, ACC_ALL); > + BUG_ON(!sp); > > link_shadow_page(vcpu, it.sptep, sp); > if (fault->is_tdp && fault->huge_page_disallowed && > @@ -3383,6 +3386,8 @@ static hpa_t mmu_alloc_root(struct kvm_vcpu *vcpu, gfn_t gfn, gva_t gva, > struct kvm_mmu_page *sp; > > sp = kvm_mmu_get_page(vcpu, gfn, gva, level, direct, ACC_ALL); > + BUG_ON(!sp); Gah, this is obviously wrong when allocating an indirect root. On the happy side, it points out a cleaner approach. I think this is what we want? --- arch/x86/kvm/mmu/mmu.c | 3 --- arch/x86/kvm/mmu/paging_tmpl.h | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 4853c033e6ce..f24e8088192c 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -2143,9 +2143,6 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu); } - if (sp->unsync_children) - kvm_make_request(KVM_REQ_MMU_SYNC, vcpu); - __clear_sp_write_flooding_count(sp); trace_get_page: diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h index 50ade6450ace..5b13918a55c2 100644 --- a/arch/x86/kvm/mmu/paging_tmpl.h +++ b/arch/x86/kvm/mmu/paging_tmpl.h @@ -704,6 +704,10 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault, access = gw->pt_access[it.level - 2]; sp = kvm_mmu_get_page(vcpu, table_gfn, fault->addr, it.level-1, false, access); + if (sp->unsync_children) { + kvm_make_all_cpus_request(KVM_REQ_MMU_SYNC, vcpu); + return RET_PF_RETRY; + } } /* --