From nobody Tue Feb 10 11:17:23 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1604264974; cv=none; d=zohomail.com; s=zohoarc; b=l7LT6fieU1xdEbssI+oeztb3mIEE7/TthnBK0/NTda2EJfqctrNTa8gz4v1J0AFJ5NonCt3efVscvq2uS1dalWYhebBQyhr0vur32oRnGHRsozx57qRbHUUG0NycNFyZgDSYbiyWirSr7LwGvI2NJt8gdO68zRG7i/PvJpcd0CU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1604264974; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=bYyDd1sxB8xlVuJ9OGlB2uPqKe8tktfcGx1vV7cyw/4=; b=QnkP2iUp3XlTEHGrwuJhOGZ5tuC2pKtNKQv4D33Clak7929s0rQcHdLCq5bWoxjEc+342kyVVoLgWZtPP40L53cITdxCDGyCYVlZbv/SyNPEOQ2fRkry1E/JO2SEkN9rS9ILYxWjDZF5c864IMB6PZZwlHbLCBpGSvZIijDkobk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1604264974112795.0591769668727; Sun, 1 Nov 2020 13:09:34 -0800 (PST) Received: from localhost ([::1]:45870 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kZKbU-0000eQ-TH for importer@patchew.org; Sun, 01 Nov 2020 16:09:32 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:60428) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kZKTZ-0005vX-A6 for qemu-devel@nongnu.org; Sun, 01 Nov 2020 16:01:21 -0500 Received: from us-smtp-delivery-124.mimecast.com ([63.128.21.124]:37239) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1kZKTW-0005TU-Tx for qemu-devel@nongnu.org; Sun, 01 Nov 2020 16:01:20 -0500 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-478-OtfCbnHYNqOiut7l2IK8Rw-1; Sun, 01 Nov 2020 16:01:15 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D457E1006C83; Sun, 1 Nov 2020 21:01:14 +0000 (UTC) Received: from gimli.home (ovpn-112-213.phx2.redhat.com [10.3.112.213]) by smtp.corp.redhat.com (Postfix) with ESMTP id 828DE5D9D2; Sun, 1 Nov 2020 21:01:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1604264478; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=bYyDd1sxB8xlVuJ9OGlB2uPqKe8tktfcGx1vV7cyw/4=; b=GwU4Y4r9/kot3Jg0WYulhgmwnP+Pa4JDPxgCfTATLwDliC6cg18i8Xs3/IEX9cy7obpB6F C5CdmebCKVpA7x9SLV1LtooCJYwB3Fr09qQwgugK+SjpG6TndN4X1IfIDSLA7Fy0ftzi99 YpXJqCUsz2d4YC/CbXWz9EviokAZyOg= X-MC-Unique: OtfCbnHYNqOiut7l2IK8Rw-1 Subject: [PULL v3 14/32] vfio: Dirty page tracking when vIOMMU is enabled From: Alex Williamson To: qemu-devel@nongnu.org Date: Sun, 01 Nov 2020 14:01:11 -0700 Message-ID: <160426447125.24886.2894287896498092524.stgit@gimli.home> In-Reply-To: <160426371498.24886.12193840637250368669.stgit@gimli.home> References: <160426371498.24886.12193840637250368669.stgit@gimli.home> User-Agent: StGit/0.21-dirty MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=alex.williamson@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=63.128.21.124; envelope-from=alex.williamson@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/11/01 15:59:21 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -30 X-Spam_score: -3.1 X-Spam_bar: --- X-Spam_report: (-3.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=-1, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kirti Wankhede , Yan Zhao Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @redhat.com) From: Kirti Wankhede When vIOMMU is enabled, register MAP notifier from log_sync when all devices in container are in stop and copy phase of migration. Call replay and get dirty pages from notifier callback. Suggested-by: Alex Williamson Signed-off-by: Kirti Wankhede Reviewed-by: Yan Zhao Signed-off-by: Alex Williamson --- hw/vfio/common.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++= +--- hw/vfio/trace-events | 1 + 2 files changed, 83 insertions(+), 6 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 0a97fbfefb89..43e6e89090f2 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -442,8 +442,8 @@ static bool vfio_listener_skipped_section(MemoryRegionS= ection *section) } =20 /* Called with rcu_read_lock held. */ -static bool vfio_get_vaddr(IOMMUTLBEntry *iotlb, void **vaddr, - bool *read_only) +static bool vfio_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr, + ram_addr_t *ram_addr, bool *read_only) { MemoryRegion *mr; hwaddr xlat; @@ -474,8 +474,17 @@ static bool vfio_get_vaddr(IOMMUTLBEntry *iotlb, void = **vaddr, return false; } =20 - *vaddr =3D memory_region_get_ram_ptr(mr) + xlat; - *read_only =3D !writable || mr->readonly; + if (vaddr) { + *vaddr =3D memory_region_get_ram_ptr(mr) + xlat; + } + + if (ram_addr) { + *ram_addr =3D memory_region_get_ram_addr(mr) + xlat; + } + + if (read_only) { + *read_only =3D !writable || mr->readonly; + } =20 return true; } @@ -485,7 +494,6 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n, IOM= MUTLBEntry *iotlb) VFIOGuestIOMMU *giommu =3D container_of(n, VFIOGuestIOMMU, n); VFIOContainer *container =3D giommu->container; hwaddr iova =3D iotlb->iova + giommu->iommu_offset; - bool read_only; void *vaddr; int ret; =20 @@ -501,7 +509,9 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n, IOM= MUTLBEntry *iotlb) rcu_read_lock(); =20 if ((iotlb->perm & IOMMU_RW) !=3D IOMMU_NONE) { - if (!vfio_get_vaddr(iotlb, &vaddr, &read_only)) { + bool read_only; + + if (!vfio_get_xlat_addr(iotlb, &vaddr, NULL, &read_only)) { goto out; } /* @@ -899,11 +909,77 @@ err_out: return ret; } =20 +typedef struct { + IOMMUNotifier n; + VFIOGuestIOMMU *giommu; +} vfio_giommu_dirty_notifier; + +static void vfio_iommu_map_dirty_notify(IOMMUNotifier *n, IOMMUTLBEntry *i= otlb) +{ + vfio_giommu_dirty_notifier *gdn =3D container_of(n, + vfio_giommu_dirty_notifier= , n); + VFIOGuestIOMMU *giommu =3D gdn->giommu; + VFIOContainer *container =3D giommu->container; + hwaddr iova =3D iotlb->iova + giommu->iommu_offset; + ram_addr_t translated_addr; + + trace_vfio_iommu_map_dirty_notify(iova, iova + iotlb->addr_mask); + + if (iotlb->target_as !=3D &address_space_memory) { + error_report("Wrong target AS \"%s\", only system memory is allowe= d", + iotlb->target_as->name ? iotlb->target_as->name : "no= ne"); + return; + } + + rcu_read_lock(); + if (vfio_get_xlat_addr(iotlb, NULL, &translated_addr, NULL)) { + int ret; + + ret =3D vfio_get_dirty_bitmap(container, iova, iotlb->addr_mask + = 1, + translated_addr); + if (ret) { + error_report("vfio_iommu_map_dirty_notify(%p, 0x%"HWADDR_PRIx"= , " + "0x%"HWADDR_PRIx") =3D %d (%m)", + container, iova, + iotlb->addr_mask + 1, ret); + } + } + rcu_read_unlock(); +} + static int vfio_sync_dirty_bitmap(VFIOContainer *container, MemoryRegionSection *section) { ram_addr_t ram_addr; =20 + if (memory_region_is_iommu(section->mr)) { + VFIOGuestIOMMU *giommu; + + QLIST_FOREACH(giommu, &container->giommu_list, giommu_next) { + if (MEMORY_REGION(giommu->iommu) =3D=3D section->mr && + giommu->n.start =3D=3D section->offset_within_region) { + Int128 llend; + vfio_giommu_dirty_notifier gdn =3D { .giommu =3D giommu }; + int idx =3D memory_region_iommu_attrs_to_index(giommu->iom= mu, + MEMTXATTRS_UNSPECIF= IED); + + llend =3D int128_add(int128_make64(section->offset_within_= region), + section->size); + llend =3D int128_sub(llend, int128_one()); + + iommu_notifier_init(&gdn.n, + vfio_iommu_map_dirty_notify, + IOMMU_NOTIFIER_MAP, + section->offset_within_region, + int128_get64(llend), + idx); + memory_region_iommu_replay(giommu->iommu, &gdn.n); + break; + } + } + return 0; + } + ram_addr =3D memory_region_get_ram_addr(section->mr) + section->offset_within_region; =20 diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events index dd991bd8f265..c0e75f24b76d 100644 --- a/hw/vfio/trace-events +++ b/hw/vfio/trace-events @@ -164,3 +164,4 @@ vfio_load_state(const char *name, uint64_t data) " (%s)= data 0x%"PRIx64 vfio_load_state_device_data(const char *name, uint64_t data_offset, uint64= _t data_size) " (%s) Offset 0x%"PRIx64" size 0x%"PRIx64 vfio_load_cleanup(const char *name) " (%s)" vfio_get_dirty_bitmap(int fd, uint64_t iova, uint64_t size, uint64_t bitma= p_size, uint64_t start) "container fd=3D%d, iova=3D0x%"PRIx64" size=3D 0x%"= PRIx64" bitmap_size=3D0x%"PRIx64" start=3D0x%"PRIx64 +vfio_iommu_map_dirty_notify(uint64_t iova_start, uint64_t iova_end) "iommu= dirty @ 0x%"PRIx64" - 0x%"PRIx64