From: Hou Wenlong <houwenlong.hwl@xxxxxxxxxxxx> PVM uses pfncache to share the PVCS structure between the guest and host. The flag of pfncache of PVCS is initialized as KVM_GUEST_AND_HOST_USE_PFN because the PVCS is used inside the vcpu_run() callback, even in the switcher, where the vcpu is in guest mode. However, there is no real usage for GUEST_USE_PFN, so the request in mmu_notifier only kicks the vcpu out of guest mode and no refresh is done before the next vcpu_run(). Therefore, a new request type is introduced to request the refresh, and a new callback is used to service the request. Suggested-by: Lai Jiangshan <jiangshan.ljs@xxxxxxxxxxxx> Signed-off-by: Hou Wenlong <houwenlong.hwl@xxxxxxxxxxxx> Signed-off-by: Lai Jiangshan <jiangshan.ljs@xxxxxxxxxxxx> --- arch/x86/include/asm/kvm-x86-ops.h | 1 + arch/x86/include/asm/kvm_host.h | 3 +++ arch/x86/kvm/mmu/mmu.c | 1 + arch/x86/kvm/x86.c | 3 +++ include/linux/kvm_host.h | 10 ++++++++++ virt/kvm/pfncache.c | 2 +- 6 files changed, 19 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-x86-ops.h index 32e5473b499d..0d9b21988943 100644 --- a/arch/x86/include/asm/kvm-x86-ops.h +++ b/arch/x86/include/asm/kvm-x86-ops.h @@ -94,6 +94,7 @@ KVM_X86_OP_OPTIONAL_RET0(set_identity_map_addr) KVM_X86_OP_OPTIONAL_RET0(get_mt_mask) KVM_X86_OP(load_mmu_pgd) KVM_X86_OP_OPTIONAL_RET0(disallowed_va) +KVM_X86_OP_OPTIONAL(vcpu_gpc_refresh); KVM_X86_OP(has_wbinvd_exit) KVM_X86_OP(get_l2_tsc_offset) KVM_X86_OP(get_l2_tsc_multiplier) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index d17d85106d6f..9223d34cb8e3 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1683,6 +1683,8 @@ struct kvm_x86_ops { bool (*disallowed_va)(struct kvm_vcpu *vcpu, u64 la); + void (*vcpu_gpc_refresh)(struct kvm_vcpu *vcpu); + bool (*has_wbinvd_exit)(void); u64 (*get_l2_tsc_offset)(struct kvm_vcpu *vcpu); @@ -1839,6 +1841,7 @@ static inline int kvm_arch_flush_remote_tlbs(struct kvm *kvm) } #define __KVM_HAVE_ARCH_FLUSH_REMOTE_TLBS_RANGE +#define __KVM_HAVE_GUEST_USE_PFN_USAGE #define kvm_arch_pmi_in_guest(vcpu) \ ((vcpu) && (vcpu)->arch.handling_intr_from_guest) diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 80406666d7da..7bd88f7ace51 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -6741,6 +6741,7 @@ void kvm_arch_flush_shadow_memslot(struct kvm *kvm, struct kvm_memory_slot *slot) { kvm_mmu_zap_all_fast(kvm); + kvm_make_all_cpus_request(kvm, KVM_REQ_GPC_REFRESH); } void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm, u64 gen) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index be8fdae942d1..89bf368085a9 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -10786,6 +10786,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) if (kvm_check_request(KVM_REQ_UPDATE_CPU_DIRTY_LOGGING, vcpu)) static_call(kvm_x86_update_cpu_dirty_logging)(vcpu); + + if (kvm_check_request(KVM_REQ_GPC_REFRESH, vcpu)) + static_call_cond(kvm_x86_vcpu_gpc_refresh)(vcpu); } if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win || diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 4944136efaa2..b7c490e74704 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -167,6 +167,7 @@ static inline bool is_error_page(struct page *page) #define KVM_REQ_VM_DEAD (1 | KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) #define KVM_REQ_UNBLOCK 2 #define KVM_REQ_DIRTY_RING_SOFT_FULL 3 +#define KVM_REQ_GPC_REFRESH (5 | KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) #define KVM_REQUEST_ARCH_BASE 8 /* @@ -1367,6 +1368,15 @@ int kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, unsigned long len); */ void kvm_gpc_deactivate(struct gfn_to_pfn_cache *gpc); +static inline unsigned int kvm_gpc_refresh_request(void) +{ +#ifdef __KVM_HAVE_GUEST_USE_PFN_USAGE + return KVM_REQ_GPC_REFRESH; +#else + return KVM_REQ_OUTSIDE_GUEST_MODE; +#endif +} + void kvm_sigset_activate(struct kvm_vcpu *vcpu); void kvm_sigset_deactivate(struct kvm_vcpu *vcpu); diff --git a/virt/kvm/pfncache.c b/virt/kvm/pfncache.c index 2d6aba677830..f7b7a2f75ec7 100644 --- a/virt/kvm/pfncache.c +++ b/virt/kvm/pfncache.c @@ -59,7 +59,7 @@ void gfn_to_pfn_cache_invalidate_start(struct kvm *kvm, unsigned long start, * KVM needs to ensure the vCPU is fully out of guest context * before allowing the invalidation to continue. */ - unsigned int req = KVM_REQ_OUTSIDE_GUEST_MODE; + unsigned int req = kvm_gpc_refresh_request(); bool called; /* -- 2.19.1.6.gb485710b