From patchwork Thu Jul 2 13:55:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: zhukeqian X-Patchwork-Id: 11638981 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 16088618 for ; Thu, 2 Jul 2020 13:58:01 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id DBDED20772 for ; Thu, 2 Jul 2020 13:58:00 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="U8MRctYs" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org DBDED20772 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=huawei.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-ID:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=LFsnT/Nt/+k0T9DqTZEVYiZ2AGlCyMtw5bp3icblC4w=; b=U8MRctYs0swUzORDw2/fwIhk4 nvZt8V6WIx2aB/9FudWTuYRCIcqIJp0IEdjEQynr7M3dy61NJ4E48b6anpL/LAIRrknaDes5ZhbxE yrORXTwEyhTXx3H15jAw2IFgJ6CR/XzMnOG4+hoRQwdq298kis3tR+S9XyaWTwPQnVGG6Hdq4vnJ4 IkTK3TUuaq8x+WCTNs84AfOOH2nxqeBqzoSd1LJSGOxFAIUOtUgYUSGs9A28sT5mQtG1CWvcOX7TU A11W6PyWm8VJvTHVphU7uAl/N62tIEgJV2QgPEce06qMCPFQ70anQGkf1xMpMA4VhmoYArl1ngrpW BhnxfVsBQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jqzhb-0001yL-4c; Thu, 02 Jul 2020 13:56:35 +0000 Received: from szxga07-in.huawei.com ([45.249.212.35] helo=huawei.com) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jqzhO-0001s1-90 for linux-arm-kernel@lists.infradead.org; Thu, 02 Jul 2020 13:56:23 +0000 Received: from DGGEMS406-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id AAE1856A3318634F4E03; Thu, 2 Jul 2020 21:56:15 +0800 (CST) Received: from DESKTOP-5IS4806.china.huawei.com (10.174.187.22) by DGGEMS406-HUB.china.huawei.com (10.3.19.206) with Microsoft SMTP Server id 14.3.487.0; Thu, 2 Jul 2020 21:56:06 +0800 From: Keqian Zhu To: , , , Subject: [PATCH v2 6/8] KVM: arm64: Add KVM_CAP_ARM_HW_DIRTY_LOG capability Date: Thu, 2 Jul 2020 21:55:54 +0800 Message-ID: <20200702135556.36896-7-zhukeqian1@huawei.com> X-Mailer: git-send-email 2.8.4.windows.1 In-Reply-To: <20200702135556.36896-1-zhukeqian1@huawei.com> References: <20200702135556.36896-1-zhukeqian1@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.174.187.22] X-CFilter-Loop: Reflected X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200702_095622_666192_9A7B4B18 X-CRM114-Status: GOOD ( 15.31 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (-2.3 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_MSPIKE_H4 RBL: Very Good reputation (+4) [45.249.212.35 listed in wl.mailspike.net] -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [45.249.212.35 listed in list.dnswl.org] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record 0.0 RCVD_IN_MSPIKE_WL Mailspike good senders X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Suzuki K Poulose , Catalin Marinas , Keqian Zhu , Sean Christopherson , Steven Price , liangpeng10@huawei.com, Alexios Zavras , zhengxiang9@huawei.com, Mark Brown , James Morse , Marc Zyngier , wanghaibin.wang@huawei.com, Thomas Gleixner , Will Deacon , Andrew Morton , Julien Thierry Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org For that using arm64 DBM to log dirty pages has the side effect of long time dirty log sync, we should give userspace opportunity to enable or disable this feature, to realize some policy. This feature is disabled by default. Signed-off-by: Keqian Zhu Signed-off-by: Peng Liang --- arch/arm64/include/asm/kvm_host.h | 1 + arch/arm64/kvm/arm.c | 35 +++++++++++++++++++++++++++++++ arch/arm64/kvm/mmu.c | 22 +++++++++++++++++++ arch/arm64/kvm/reset.c | 5 +++++ include/uapi/linux/kvm.h | 1 + tools/include/uapi/linux/kvm.h | 1 + 6 files changed, 65 insertions(+) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 86b9c210ba43..69a5317c7049 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -481,6 +481,7 @@ u64 __kvm_call_hyp(void *hypfn, ...); void force_vm_exit(const cpumask_t *mask); void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot); void kvm_mmu_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot); +void kvm_mmu_sync_dirty_log_all(struct kvm *kvm); int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, int exception_index); diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index fefa5406e037..9e3f765d5467 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -78,6 +78,11 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap) { int r; +#ifdef CONFIG_ARM64_HW_AFDBM + int i; + struct kvm_vcpu *vcpu; + bool enable_hw_dirty_log; +#endif if (cap->flags) return -EINVAL; @@ -87,6 +92,36 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm, r = 0; kvm->arch.return_nisv_io_abort_to_user = true; break; +#ifdef CONFIG_ARM64_HW_AFDBM + case KVM_CAP_ARM_HW_DIRTY_LOG: + if (!arm_mmu_hw_dbm_supported() || (cap->args[0] & ~0x1)) + r = -EINVAL; + + enable_hw_dirty_log = !!(cap->args[0] & 0x1); + if (!!(kvm->arch.vtcr & VTCR_EL2_HD) != enable_hw_dirty_log) { + if (enable_hw_dirty_log) + kvm->arch.vtcr |= VTCR_EL2_HD; + else + kvm->arch.vtcr &= ~VTCR_EL2_HD; + + /* + * We should kick vcpus out of guest mode here to + * load new vtcr value to vtcr_el2 register when + * re-enter guest mode. + */ + kvm_for_each_vcpu(i, vcpu, kvm) + kvm_vcpu_kick(vcpu); + + if (!enable_hw_dirty_log) { + mutex_lock(&kvm->slots_lock); + kvm_mmu_sync_dirty_log_all(kvm); + mutex_unlock(&kvm->slots_lock); + } + } + + r = 0; + break; +#endif default: r = -EINVAL; break; diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index adfa62f1fced..1a48554accb0 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -2590,6 +2590,28 @@ void kvm_mmu_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot) spin_unlock(&kvm->mmu_lock); srcu_read_unlock(&kvm->srcu, srcu_idx); } + +/** + * kvm_mmu_sync_dirty_log_all() - synchronize dirty log from PTEs for whole VM + * @kvm: The KVM pointer + * + * Called with kvm->slots_lock mutex acquired + */ +void kvm_mmu_sync_dirty_log_all(struct kvm *kvm) +{ + struct kvm_memslots *slots = kvm_memslots(kvm); + struct kvm_memory_slot *memslots = slots->memslots; + struct kvm_memory_slot *memslot; + int slot; + + if (unlikely(!slots->used_slots)) + return; + + for (slot = 0; slot < slots->used_slots; slot++) { + memslot = &memslots[slot]; + kvm_mmu_sync_dirty_log(kvm, memslot); + } +} #endif /* CONFIG_ARM64_HW_AFDBM */ void kvm_arch_commit_memory_region(struct kvm *kvm, diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index d3b209023727..a3be703dd54b 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -83,6 +83,11 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext) r = has_vhe() && system_supports_address_auth() && system_supports_generic_auth(); break; +#ifdef CONFIG_ARM64_HW_AFDBM + case KVM_CAP_ARM_HW_DIRTY_LOG: + r = arm_mmu_hw_dbm_supported(); + break; +#endif /* CONFIG_ARM64_HW_AFDBM */ default: r = 0; } diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 4fdf30316582..e0b12c43397b 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1031,6 +1031,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_PPC_SECURE_GUEST 181 #define KVM_CAP_HALT_POLL 182 #define KVM_CAP_ASYNC_PF_INT 183 +#define KVM_CAP_ARM_HW_DIRTY_LOG 184 #ifdef KVM_CAP_IRQ_ROUTING diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h index 4fdf30316582..e0b12c43397b 100644 --- a/tools/include/uapi/linux/kvm.h +++ b/tools/include/uapi/linux/kvm.h @@ -1031,6 +1031,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_PPC_SECURE_GUEST 181 #define KVM_CAP_HALT_POLL 182 #define KVM_CAP_ASYNC_PF_INT 183 +#define KVM_CAP_ARM_HW_DIRTY_LOG 184 #ifdef KVM_CAP_IRQ_ROUTING