From nobody Wed Oct 29 09:14:49 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 152463246265978.50629932470383; Tue, 24 Apr 2018 22:01:02 -0700 (PDT) Received: from localhost ([::1]:33868 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fBCY9-0001n1-Uo for importer@patchew.org; Wed, 25 Apr 2018 01:01:01 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59094) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fBCPp-0004NJ-7f for qemu-devel@nongnu.org; Wed, 25 Apr 2018 00:52:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fBCPm-0007Qb-4W for qemu-devel@nongnu.org; Wed, 25 Apr 2018 00:52:25 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:58558 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fBCPl-0007QK-VE for qemu-devel@nongnu.org; Wed, 25 Apr 2018 00:52:22 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7BC0340201AF; Wed, 25 Apr 2018 04:52:21 +0000 (UTC) Received: from xz-mi.redhat.com (ovpn-12-55.pek2.redhat.com [10.72.12.55]) by smtp.corp.redhat.com (Postfix) with ESMTP id DB9967C4A; Wed, 25 Apr 2018 04:52:12 +0000 (UTC) From: Peter Xu To: qemu-devel@nongnu.org Date: Wed, 25 Apr 2018 12:51:27 +0800 Message-Id: <20180425045129.17449-9-peterx@redhat.com> In-Reply-To: <20180425045129.17449-1-peterx@redhat.com> References: <20180425045129.17449-1-peterx@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Wed, 25 Apr 2018 04:52:21 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Wed, 25 Apr 2018 04:52:21 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'peterx@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH 08/10] intel-iommu: maintain per-device iova ranges X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jason Wang , Alex Williamson , Jintack Lim , peterx@redhat.com, "Michael S . Tsirkin" Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" For each VTDAddressSpace, now we maintain what IOVA ranges we have mapped and what we have not. With that information, now we only send MAP or UNMAP when necessary. Say, we don't send MAP notifies if we know we have already mapped the range, meanwhile we don't send UNMAP notifies if we know we never mapped the range at all. Signed-off-by: Peter Xu --- include/hw/i386/intel_iommu.h | 2 ++ hw/i386/intel_iommu.c | 28 ++++++++++++++++++++++++++++ hw/i386/trace-events | 2 ++ 3 files changed, 32 insertions(+) diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h index 486e205e79..09a2e94404 100644 --- a/include/hw/i386/intel_iommu.h +++ b/include/hw/i386/intel_iommu.h @@ -27,6 +27,7 @@ #include "hw/i386/ioapic.h" #include "hw/pci/msi.h" #include "hw/sysbus.h" +#include "qemu/interval-tree.h" =20 #define TYPE_INTEL_IOMMU_DEVICE "intel-iommu" #define INTEL_IOMMU_DEVICE(obj) \ @@ -95,6 +96,7 @@ struct VTDAddressSpace { QLIST_ENTRY(VTDAddressSpace) next; /* Superset of notifier flags that this address space has */ IOMMUNotifierFlag notifier_flags; + ITTree *iova_tree; /* Traces mapped IOVA ranges */ }; =20 struct VTDBus { diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index a19c18b8d4..8f396a5d13 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -768,12 +768,37 @@ typedef struct { static int vtd_page_walk_one(IOMMUTLBEntry *entry, int level, vtd_page_walk_info *info) { + VTDAddressSpace *as =3D info->as; vtd_page_walk_hook hook_fn =3D info->hook_fn; void *private =3D info->private; + ITRange *mapped =3D it_tree_find(as->iova_tree, entry->iova, + entry->iova + entry->addr_mask); =20 assert(hook_fn); + + /* Update local IOVA mapped ranges */ + if (entry->perm) { + if (mapped) { + /* Skip since we have already mapped this range */ + trace_vtd_page_walk_one_skip_map(entry->iova, entry->addr_mask, + mapped->start, mapped->end); + return 0; + } + it_tree_insert(as->iova_tree, entry->iova, + entry->iova + entry->addr_mask); + } else { + if (!mapped) { + /* Skip since we didn't map this range at all */ + trace_vtd_page_walk_one_skip_unmap(entry->iova, entry->addr_ma= sk); + return 0; + } + it_tree_remove(as->iova_tree, entry->iova, + entry->iova + entry->addr_mask); + } + trace_vtd_page_walk_one(level, entry->iova, entry->translated_addr, entry->addr_mask, entry->perm); + return hook_fn(entry, private); } =20 @@ -2798,6 +2823,7 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, = PCIBus *bus, int devfn) vtd_dev_as->devfn =3D (uint8_t)devfn; vtd_dev_as->iommu_state =3D s; vtd_dev_as->context_cache_entry.context_cache_gen =3D 0; + vtd_dev_as->iova_tree =3D it_tree_new(); =20 /* * Memory region relationships looks like (Address range shows @@ -2894,6 +2920,8 @@ static void vtd_address_space_unmap(VTDAddressSpace *= as, IOMMUNotifier *n) VTD_PCI_FUNC(as->devfn), entry.iova, size); =20 + it_tree_remove(as->iova_tree, entry.iova, entry.iova + entry.addr_mask= ); + memory_region_notify_one(n, &entry); } =20 diff --git a/hw/i386/trace-events b/hw/i386/trace-events index 22d44648af..677f83420d 100644 --- a/hw/i386/trace-events +++ b/hw/i386/trace-events @@ -40,6 +40,8 @@ vtd_replay_ce_valid(uint8_t bus, uint8_t dev, uint8_t fn,= uint16_t domain, uint6 vtd_replay_ce_invalid(uint8_t bus, uint8_t dev, uint8_t fn) "replay invali= d context device %02"PRIx8":%02"PRIx8".%02"PRIx8 vtd_page_walk_level(uint64_t addr, uint32_t level, uint64_t start, uint64_= t end) "walk (base=3D0x%"PRIx64", level=3D%"PRIu32") iova range 0x%"PRIx64"= - 0x%"PRIx64 vtd_page_walk_one(uint32_t level, uint64_t iova, uint64_t gpa, uint64_t ma= sk, int perm) "detected page level 0x%"PRIx32" iova 0x%"PRIx64" -> gpa 0x%"= PRIx64" mask 0x%"PRIx64" perm %d" +vtd_page_walk_one_skip_map(uint64_t iova, uint64_t mask, uint64_t start, u= int64_t end) "iova 0x%"PRIx64" mask 0x%"PRIx64" start 0x%"PRIx64" end 0x%"P= RIx64 +vtd_page_walk_one_skip_unmap(uint64_t iova, uint64_t mask) "iova 0x%"PRIx6= 4" mask 0x%"PRIx64 vtd_page_walk_skip_read(uint64_t iova, uint64_t next) "Page walk skip iova= 0x%"PRIx64" - 0x%"PRIx64" due to unable to read" vtd_page_walk_skip_perm(uint64_t iova, uint64_t next) "Page walk skip iova= 0x%"PRIx64" - 0x%"PRIx64" due to perm empty" vtd_page_walk_skip_reserve(uint64_t iova, uint64_t next) "Page walk skip i= ova 0x%"PRIx64" - 0x%"PRIx64" due to rsrv set" --=20 2.14.3