From nobody Mon Feb 9 10:29:40 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; 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=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1593704579; cv=none; d=zohomail.com; s=zohoarc; b=GZRRNXQ5NEkzEgJcRwYgc2+xqJ7S8WwS3HBzqNIZoAlzRW8nAoKb0096ET3LflhwlQynyiVbZ1E+gKxnSv4t+PaanEgfbWtbxU4qzxE53cb1Ly9MTmutaDr3/PsfMfjjXQYjmWLysZdSPLaIQY5EOpxGe6KeQYRqg2w7/chrx2w= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1593704579; 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=NUydCa7fctjP7th4rUdELWWUxIDOm37IGdKZttAnbB8=; b=DntrfBjFjKK7Rq/DzoFxdyBvaF7j9W4QvVjm7rP38FNyEHPzq+qn4BHwkVckZtxt77x3UwgbOcGvHmCbrUX/Z+NoRqeeesAX88yIqIp1gCR6uZokC/K3FiAUsvydxQ9mIXbKCVOxEq66zN4U5NPfDi+7thgDc1V/+FD4MekPIr0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; 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=fail 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 1593704579789432.2879813160537; Thu, 2 Jul 2020 08:42:59 -0700 (PDT) Received: from localhost ([::1]:43382 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jr1MY-0000Uo-Fb for importer@patchew.org; Thu, 02 Jul 2020 11:42:58 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43528) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jr17w-0001YN-FL for qemu-devel@nongnu.org; Thu, 02 Jul 2020 11:27:52 -0400 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:40000 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1jr17u-0006Rm-C1 for qemu-devel@nongnu.org; Thu, 02 Jul 2020 11:27:52 -0400 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-454-etfQ6FK0MaWgtFyW7ckfQQ-1; Thu, 02 Jul 2020 11:27:48 -0400 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 A1AB5A0C00; Thu, 2 Jul 2020 15:27:46 +0000 (UTC) Received: from laptop.redhat.com (ovpn-112-70.ams2.redhat.com [10.36.112.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id C63591D1; Thu, 2 Jul 2020 15:27:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1593703669; 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=NUydCa7fctjP7th4rUdELWWUxIDOm37IGdKZttAnbB8=; b=dQrjsgfspMZI88Z+e6DGEcb2riDNWipBJ1fOSKYu3OZCort00eAI+GZcXHUlqNg4LWJkP/ uYmeqKTzwRK1yTQKP0VtM8DmvdW7yLbOagbEaNZUJ+4MCSBoPtVdcWpaYxBnKH34WBRpi/ 47G47dq2GylpZiKmEjOvcDnU9nOMgjU= X-MC-Unique: etfQ6FK0MaWgtFyW7ckfQQ-1 From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, qemu-devel@nongnu.org, qemu-arm@nongnu.org, peter.maydell@linaro.org, peterx@redhat.com Subject: [PATCH v2 6/9] hw/arm/smmu-common: Manage IOTLB block entries Date: Thu, 2 Jul 2020 17:26:56 +0200 Message-Id: <20200702152659.8522-7-eric.auger@redhat.com> In-Reply-To: <20200702152659.8522-1-eric.auger@redhat.com> References: <20200702152659.8522-1-eric.auger@redhat.com> 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=eric.auger@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com 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=205.139.110.120; envelope-from=eric.auger@redhat.com; helo=us-smtp-1.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/02 04:00:43 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=-1, 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_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=_AUTOLEARN 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: jean-philippe@linaro.org, robh@kernel.org, robin.murphy@arm.com, mst@redhat.com, zhangfei.gao@foxmail.com, shameerali.kolothum.thodi@huawei.com, will@kernel.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" At the moment each entry in the IOTLB corresponds to a page sized mapping (4K, 16K or 64K), even if the page belongs to a mapped block. In case of block mapping this unefficiently consumes IOTLB entries. Change the value of the entry so that it reflects the actual mapping it belongs to (block or page start address and size). Also the level/tg of the entry is encoded in the key. In subsequent patches we will enable range invalidation. This latter is able to provide the level/tg of the entry. Encoding the level/tg directly in the key will allow to invalidate using g_hash_table_remove() when num_pages equals to 1. Signed-off-by: Eric Auger Reviewed-by: Peter Maydell --- v1 -> v2: - recompute starting_level --- hw/arm/smmu-internal.h | 9 ++++++ include/hw/arm/smmu-common.h | 8 +++-- hw/arm/smmu-common.c | 63 ++++++++++++++++++++++++++++-------- hw/arm/smmuv3.c | 6 ++-- hw/arm/trace-events | 2 +- 5 files changed, 67 insertions(+), 21 deletions(-) diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h index 2ecb6f1dc6..d57f5c05c2 100644 --- a/hw/arm/smmu-internal.h +++ b/hw/arm/smmu-internal.h @@ -97,7 +97,16 @@ uint64_t iova_level_offset(uint64_t iova, int inputsize, } =20 #define SMMU_IOTLB_ASID_SHIFT 40 +#define SMMU_IOTLB_LEVEL_SHIFT 56 +#define SMMU_IOTLB_TG_SHIFT 58 =20 #define SMMU_IOTLB_ASID(key) (((key) >> SMMU_IOTLB_ASID_SHIFT) & 0xFFFF) #define SMMU_IOTLB_IOVA(key) (((key) & MAKE_64BIT_MASK(0, 40)) << 12) + +typedef struct SMMUIOTLBPageInvInfo { + int asid; + uint64_t iova; + uint64_t mask; +} SMMUIOTLBPageInvInfo; + #endif diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index 0db4403e94..cc228b51b4 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -156,12 +156,14 @@ IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32= _t sid); =20 #define SMMU_IOTLB_MAX_SIZE 256 =20 -SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg, hwaddr i= ova); +SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg, + SMMUTransTableInfo *tt, hwaddr iova); void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, SMMUTLBEntry *ent= ry); -SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova); +SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova, + uint8_t tg, uint8_t level); void smmu_iotlb_inv_all(SMMUState *s); void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid); -void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t iova); +void smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova); =20 /* Unmap the range of all the notifiers registered to any IOMMU mr */ void smmu_inv_notifiers_all(SMMUState *s); diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index a3301e56e7..5c14127a24 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -42,16 +42,35 @@ static gboolean smmu_iotlb_key_equal(gconstpointer v1, = gconstpointer v2) return *((const uint64_t *)v1) =3D=3D *((const uint64_t *)v2); } =20 -SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova) +SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova, + uint8_t tg, uint8_t level) { - return iova >> 12 | (uint64_t)(asid) << SMMU_IOTLB_ASID_SHIFT; + return iova >> 12 | (uint64_t)(asid) << SMMU_IOTLB_ASID_SHIFT | + (uint64_t)(level) << SMMU_IOTLB_LEVEL_SHIFT | + (uint64_t)(tg) << SMMU_IOTLB_TG_SHIFT; } =20 SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg, - hwaddr iova) + SMMUTransTableInfo *tt, hwaddr iova) { - SMMUIOTLBKey key =3D smmu_get_iotlb_key(cfg->asid, iova); - SMMUTLBEntry *entry =3D g_hash_table_lookup(bs->iotlb, &key); + uint8_t tg =3D (tt->granule_sz - 10) / 2; + uint8_t inputsize =3D 64 - tt->tsz; + uint8_t stride =3D tt->granule_sz - 3; + uint8_t level =3D 4 - (inputsize - 4) / stride; + SMMUTLBEntry *entry =3D NULL; + + while (level <=3D 3) { + uint64_t subpage_size =3D 1ULL << level_shift(level, tt->granule_s= z); + uint64_t mask =3D subpage_size - 1; + SMMUIOTLBKey key; + + key =3D smmu_get_iotlb_key(cfg->asid, iova & ~mask, tg, level); + entry =3D g_hash_table_lookup(bs->iotlb, &key); + if (entry) { + break; + } + level++; + } =20 if (entry) { cfg->iotlb_hits++; @@ -72,13 +91,14 @@ SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTran= sCfg *cfg, void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, SMMUTLBEntry *new) { SMMUIOTLBKey *key =3D g_new0(SMMUIOTLBKey, 1); + uint8_t tg =3D (new->granule - 10) / 2; =20 if (g_hash_table_size(bs->iotlb) >=3D SMMU_IOTLB_MAX_SIZE) { smmu_iotlb_inv_all(bs); } =20 - *key =3D smmu_get_iotlb_key(cfg->asid, new->entry.iova); - trace_smmu_iotlb_insert(cfg->asid, new->entry.iova); + *key =3D smmu_get_iotlb_key(cfg->asid, new->entry.iova, tg, new->level= ); + trace_smmu_iotlb_insert(cfg->asid, new->entry.iova, tg, new->level); g_hash_table_insert(bs->iotlb, key, new); } =20 @@ -97,12 +117,28 @@ static gboolean smmu_hash_remove_by_asid(gpointer key,= gpointer value, return SMMU_IOTLB_ASID(*iotlb_key) =3D=3D asid; } =20 -inline void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t io= va) +static gboolean smmu_hash_remove_by_asid_iova(gpointer key, gpointer value, + gpointer user_data) { - SMMUIOTLBKey key =3D smmu_get_iotlb_key(asid, iova); + SMMUTLBEntry *iter =3D (SMMUTLBEntry *)value; + IOMMUTLBEntry *entry =3D &iter->entry; + SMMUIOTLBPageInvInfo *info =3D (SMMUIOTLBPageInvInfo *)user_data; + uint64_t *iotlb_key =3D (uint64_t *)key; + + if (info->asid >=3D 0) { + return (info->asid =3D=3D SMMU_IOTLB_ASID(*iotlb_key)) && + ((info->iova & ~entry->addr_mask) =3D=3D entry->iova); + } else { + return (info->iova & ~entry->addr_mask) =3D=3D entry->iova; + } +} + +inline void smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova) +{ + SMMUIOTLBPageInvInfo info =3D {.asid =3D asid, .iova =3D iova}; =20 trace_smmu_iotlb_inv_iova(asid, iova); - g_hash_table_remove(s->iotlb, &key); + g_hash_table_foreach_remove(s->iotlb, smmu_hash_remove_by_asid_iova, &= info); } =20 inline void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid) @@ -229,9 +265,6 @@ static int smmu_ptw_64(SMMUTransCfg *cfg, baseaddr =3D extract64(tt->ttb, 0, 48); baseaddr &=3D ~indexmask; =20 - tlbe->entry.iova =3D iova; - tlbe->entry.addr_mask =3D (1 << granule_sz) - 1; - while (level <=3D 3) { uint64_t subpage_size =3D 1ULL << level_shift(level, granule_sz); uint64_t mask =3D subpage_size - 1; @@ -281,7 +314,9 @@ static int smmu_ptw_64(SMMUTransCfg *cfg, goto error; } =20 - tlbe->entry.translated_addr =3D gpa + (iova & mask); + tlbe->entry.translated_addr =3D gpa; + tlbe->entry.iova =3D iova & ~mask; + tlbe->entry.addr_mask =3D mask; tlbe->entry.perm =3D PTE_AP_TO_PERM(ap); tlbe->level =3D level; tlbe->granule =3D granule_sz; diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index db74d27add..b717bde832 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -674,7 +674,7 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion= *mr, hwaddr addr, page_mask =3D (1ULL << (tt->granule_sz)) - 1; aligned_addr =3D addr & ~page_mask; =20 - cached_entry =3D smmu_iotlb_lookup(bs, cfg, aligned_addr); + cached_entry =3D smmu_iotlb_lookup(bs, cfg, tt, aligned_addr); if (cached_entry) { if ((flag & IOMMU_WO) && !(cached_entry->entry.perm & IOMMU_WO)) { status =3D SMMU_TRANS_ERROR; @@ -744,7 +744,7 @@ epilogue: case SMMU_TRANS_SUCCESS: entry.perm =3D flag; entry.translated_addr =3D cached_entry->entry.translated_addr + - (addr & page_mask); + (addr & cached_entry->entry.addr_mask); entry.addr_mask =3D cached_entry->entry.addr_mask; trace_smmuv3_translate_success(mr->parent_obj.name, sid, addr, entry.translated_addr, entry.perm); @@ -972,7 +972,7 @@ static int smmuv3_cmdq_consume(SMMUv3State *s) =20 trace_smmuv3_cmdq_tlbi_nh_vaa(vmid, addr); smmuv3_inv_notifiers_iova(bs, -1, addr); - smmu_iotlb_inv_all(bs); + smmu_iotlb_inv_iova(bs, -1, addr); break; } case SMMU_CMD_TLBI_NH_VA: diff --git a/hw/arm/trace-events b/hw/arm/trace-events index b808a1bfc1..f74d3e920f 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -16,7 +16,7 @@ smmu_iotlb_inv_iova(uint16_t asid, uint64_t addr) "IOTLB = invalidate asid=3D%d addr smmu_inv_notifiers_mr(const char *name) "iommu mr=3D%s" smmu_iotlb_lookup_hit(uint16_t asid, uint64_t addr, uint32_t hit, uint32_t= miss, uint32_t p) "IOTLB cache HIT asid=3D%d addr=3D0x%"PRIx64" hit=3D%d m= iss=3D%d hit rate=3D%d" smmu_iotlb_lookup_miss(uint16_t asid, uint64_t addr, uint32_t hit, uint32_= t miss, uint32_t p) "IOTLB cache MISS asid=3D%d addr=3D0x%"PRIx64" hit=3D%d= miss=3D%d hit rate=3D%d" -smmu_iotlb_insert(uint16_t asid, uint64_t addr) "IOTLB ++ asid=3D%d addr= =3D0x%"PRIx64 +smmu_iotlb_insert(uint16_t asid, uint64_t addr, uint8_t tg, uint8_t level)= "IOTLB ++ asid=3D%d addr=3D0x%"PRIx64" tg=3D%d level=3D%d" =20 # smmuv3.c smmuv3_read_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "= addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x(%d)" --=20 2.21.3