From nobody Wed Nov 5 09:21:55 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1499633789479341.0533273751323; Sun, 9 Jul 2017 13:56:29 -0700 (PDT) Received: from localhost ([::1]:37450 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dUJFk-00058s-7f for importer@patchew.org; Sun, 09 Jul 2017 16:56:28 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59015) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dUJCk-0002Ze-Hc for qemu-devel@nongnu.org; Sun, 09 Jul 2017 16:53:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dUJCj-0006OO-7Q for qemu-devel@nongnu.org; Sun, 09 Jul 2017 16:53:22 -0400 Received: from mx1.redhat.com ([209.132.183.28]:50238) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dUJCc-0006Lg-6W; Sun, 09 Jul 2017 16:53:14 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 024CB61B82; Sun, 9 Jul 2017 20:53:13 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-31.ams2.redhat.com [10.36.116.31]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9F50D17DC6; Sun, 9 Jul 2017 20:52:59 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 024CB61B82 Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=eric.auger@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 024CB61B82 From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, peter.maydell@linaro.org, qemu-arm@nongnu.org, qemu-devel@nongnu.org, alex.williamson@redhat.com, prem.mallappa@gmail.com Date: Sun, 9 Jul 2017 22:51:33 +0200 Message-Id: <1499633493-19865-9-git-send-email-eric.auger@redhat.com> In-Reply-To: <1499633493-19865-1-git-send-email-eric.auger@redhat.com> References: <1499633493-19865-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Sun, 09 Jul 2017 20:53:13 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC v5 8/8] hw/arm/smmuv3: VFIO integration 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: mohun106@gmail.com, drjones@redhat.com, tcain@qti.qualcomm.com, Radha.Chintakuntla@cavium.com, Sunil.Goutham@cavium.com, mst@redhat.com, jean-philippe.brucker@arm.com, tn@semihalf.com, will.deacon@arm.com, robin.murphy@arm.com, peterx@redhat.com, edgar.iglesias@gmail.com, bharat.bhushan@nxp.com, christoffer.dall@linaro.org 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" This patch allows doing PCIe passthrough with a guest exposed with a vSMMUv3. It implements the replay and notify_flag_changed iommu ops. Also on TLB and data structure invalidation commands, we replay the mappings so that the physical IOMMU implements updated stage 1 settings (Guest IOVA -> Guest PA) + stage 2 settings. This works only if the guest smmuv3 driver implements the "tlbi-on-map" option. Signed-off-by: Eric Auger --- at the moment the "tlbi-on-map" option only is set in DT mode. --- hw/arm/smmuv3.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++= ++++ hw/arm/trace-events | 6 +++ 2 files changed, 129 insertions(+) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 639f682..1ff77f7 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -143,6 +143,32 @@ static MemTxResult smmu_read_cmdq(SMMUV3State *s, Cmd = *cmd) return ret; } =20 +static void smmu_replay_all(SMMUState *s) +{ + SMMUNotifierNode *node; + + QLIST_FOREACH(node, &s->notifiers_list, next) { + memory_region_iommu_replay_all(&node->sdev->iommu); + } +} + +static void smmuv3_replay_single(MemoryRegion *mr, IOMMUNotifier *n, + uint64_t iova); + +static void smmu_notify_all(SMMUState *s, uint64_t iova) +{ + SMMUNotifierNode *node; + + QLIST_FOREACH(node, &s->notifiers_list, next) { + MemoryRegion *mr =3D &node->sdev->iommu; + IOMMUNotifier *n; + + IOMMU_NOTIFIER_FOREACH(n, mr) { + smmuv3_replay_single(mr, n, iova); + } + } +} + static int smmu_cmdq_consume(SMMUV3State *s) { uint32_t error =3D SMMU_CMD_ERR_NONE; @@ -183,6 +209,7 @@ static int smmu_cmdq_consume(SMMUV3State *s) uint32_t streamid =3D cmd.word[1]; =20 trace_smmuv3_cmdq_cfgi_ste(streamid); + smmu_replay_all(&s->smmu_state); break; } case SMMU_CMD_CFGI_STE_RANGE: /* same as SMMU_CMD_CFGI_ALL */ @@ -192,14 +219,17 @@ static int smmu_cmdq_consume(SMMUV3State *s) range =3D extract32(cmd.word[2], 0, 5); end =3D start + (1 << (range + 1)) - 1; trace_smmuv3_cmdq_cfgi_ste_range(start, end); + smmu_replay_all(&s->smmu_state); break; } case SMMU_CMD_CFGI_CD: case SMMU_CMD_CFGI_CD_ALL: + smmu_replay_all(&s->smmu_state); break; case SMMU_CMD_TLBI_NH_ALL: case SMMU_CMD_TLBI_NH_ASID: printf("%s TLBI* replay\n", __func__); + smmu_replay_all(&s->smmu_state); break; case SMMU_CMD_TLBI_NH_VA: { @@ -210,6 +240,7 @@ static int smmu_cmdq_consume(SMMUV3State *s) uint64_t addr =3D high << 32 | (low << 12); =20 trace_smmuv3_cmdq_tlbi_nh_va(asid, vmid, addr); + smmu_notify_all(&s->smmu_state, addr); break; } case SMMU_CMD_TLBI_NH_VAA: @@ -222,6 +253,7 @@ static int smmu_cmdq_consume(SMMUV3State *s) case SMMU_CMD_TLBI_S12_VMALL: case SMMU_CMD_TLBI_S2_IPA: case SMMU_CMD_TLBI_NSNH_ALL: + smmu_replay_all(&s->smmu_state); break; case SMMU_CMD_ATC_INV: case SMMU_CMD_PRI_RESP: @@ -804,6 +836,95 @@ out: return entry; } =20 +static int smmuv3_replay_hook(IOMMUTLBEntry *entry, void *private) +{ + int perm =3D entry->perm; + + trace_smmuv3_replay_hook(entry->iova, entry->translated_addr, + entry->addr_mask, entry->perm); + entry->perm =3D IOMMU_NONE; + memory_region_notify_one((IOMMUNotifier *)private, entry); + entry->perm =3D perm; + memory_region_notify_one((IOMMUNotifier *)private, entry); + return 0; +} + +static void smmuv3_replay(MemoryRegion *mr, IOMMUNotifier *n) +{ + SMMUDevice *sdev =3D container_of(mr, SMMUDevice, iommu); + SMMUV3State *s =3D sdev->smmu; + SMMUBaseClass *sbc =3D SMMU_DEVICE_GET_CLASS(s); + SMMUTransCfg cfg =3D {}; + int ret; + + ret =3D smmuv3_decode_config(mr, &cfg); + if (ret) { + error_report("%s error decoding the configuration for iommu mr=3D%= s", + __func__, mr->name); + } + + if (cfg.disabled || cfg.bypassed) { + return; + } + /* is the smmu enabled */ + sbc->page_walk_64(&cfg, 0, (1ULL << (64 - cfg.tsz)) - 1, false, + smmuv3_replay_hook, n); +} + +static void smmuv3_replay_single(MemoryRegion *mr, IOMMUNotifier *n, + uint64_t iova) +{ + SMMUDevice *sdev =3D container_of(mr, SMMUDevice, iommu); + SMMUV3State *s =3D sdev->smmu; + SMMUBaseClass *sbc =3D SMMU_DEVICE_GET_CLASS(s); + SMMUTransCfg cfg =3D {}; + int ret; + + trace_smmuv3_replay_single(mr->name, iova, n); + ret =3D smmuv3_decode_config(mr, &cfg); + if (ret) { + error_report("%s error decoding the configuration for iommu mr=3D%= s", + __func__, mr->name); + } + + if (cfg.disabled || cfg.bypassed) { + return; + } + /* is the smmu enabled */ + sbc->page_walk_64(&cfg, iova, iova + 1, false, + smmuv3_replay_hook, n); +} + +static void smmuv3_notify_flag_changed(MemoryRegion *iommu, + IOMMUNotifierFlag old, + IOMMUNotifierFlag new) +{ + SMMUDevice *sdev =3D container_of(iommu, SMMUDevice, iommu); + SMMUV3State *s3 =3D sdev->smmu; + SMMUState *s =3D &(s3->smmu_state); + SMMUNotifierNode *node =3D NULL; + SMMUNotifierNode *next_node =3D NULL; + + if (old =3D=3D IOMMU_NOTIFIER_NONE) { + trace_smmuv3_notify_flag_add(iommu->name); + node =3D g_malloc0(sizeof(*node)); + node->sdev =3D sdev; + QLIST_INSERT_HEAD(&s->notifiers_list, node, next); + return; + } + + /* update notifier node with new flags */ + QLIST_FOREACH_SAFE(node, &s->notifiers_list, next, next_node) { + if (node->sdev =3D=3D sdev) { + if (new =3D=3D IOMMU_NOTIFIER_NONE) { + trace_smmuv3_notify_flag_del(iommu->name); + QLIST_REMOVE(node, next); + g_free(node); + } + return; + } + } +} =20 static inline void smmu_update_base_reg(SMMUV3State *s, uint64_t *base, uint64_t val) @@ -1072,6 +1193,8 @@ static void smmu_realize(DeviceState *d, Error **errp) SysBusDevice *dev =3D SYS_BUS_DEVICE(d); =20 sys->iommu_ops.translate =3D smmuv3_translate; + sys->iommu_ops.notify_flag_changed =3D smmuv3_notify_flag_changed; + sys->iommu_ops.replay =3D smmuv3_replay; /* Register Access */ memset(sys->smmu_as_by_bus_num, 0, sizeof(sys->smmu_as_by_bus_num)); memory_region_init_io(&sys->iomem, OBJECT(s), diff --git a/hw/arm/trace-events b/hw/arm/trace-events index 30a817b..6c143be 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -50,3 +50,9 @@ smmuv3_dump_ste(int i, uint32_t word0, int j, uint32_t w= ord1) "STE[%2d]: %#010x smmuv3_dump_cd(int i, uint32_t word0, int j, uint32_t word1) "CD[%2d]: %#= 010x\t CD[%2d]: %#010x" smmuv3_dump_cmd(int i, uint32_t word0, int j, uint32_t word1) "CMD[%2d]: = %#010x\t CMD[%2d]: %#010x" smmuv3_cfg_stage(int s, uint32_t oas, uint32_t tsz, uint64_t ttbr, bool aa= 64, uint32_t granule_sz, int initial_level) "TransCFG stage:%d oas:%d tsz:%= d ttbr:0x%"PRIx64" aa64:%d granule_sz:%d, initial_level =3D %d" + +smmuv3_replay(uint16_t sid, bool enabled) "sid=3D%d, enabled=3D%d" +smmuv3_replay_hook(hwaddr iova, hwaddr pa, hwaddr mask, int perm) "iova=3D= 0x%"PRIx64" pa=3D0x%" PRIx64" mask=3D0x%"PRIx64" perm=3D%d" +smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu= mr=3D%s" +smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu= mr=3D%s" +smmuv3_replay_single(const char *name, uint64_t iova, void *n) "iommu mr= =3D%s iova=3D0x%"PRIx64" n=3D%p" --=20 2.5.5